xref: /titanic_44/usr/src/uts/i86pc/boot/boot_console.c (revision 0d928757379972073af9fb22bdc827b74e8ba6ac)
1ae115bc7Smrj /*
2ae115bc7Smrj  * CDDL HEADER START
3ae115bc7Smrj  *
4ae115bc7Smrj  * The contents of this file are subject to the terms of the
5ae115bc7Smrj  * Common Development and Distribution License (the "License").
6ae115bc7Smrj  * You may not use this file except in compliance with the License.
7ae115bc7Smrj  *
8ae115bc7Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ae115bc7Smrj  * or http://www.opensolaris.org/os/licensing.
10ae115bc7Smrj  * See the License for the specific language governing permissions
11ae115bc7Smrj  * and limitations under the License.
12ae115bc7Smrj  *
13ae115bc7Smrj  * When distributing Covered Code, include this CDDL HEADER in each
14ae115bc7Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ae115bc7Smrj  * If applicable, add the following below this CDDL HEADER, with the
16ae115bc7Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
17ae115bc7Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
18ae115bc7Smrj  *
19ae115bc7Smrj  * CDDL HEADER END
20ae115bc7Smrj  */
21ae115bc7Smrj /*
22*0d928757SGary Mills  * Copyright (c) 2012 Gary Mills
23*0d928757SGary Mills  *
2448633f18SJan Setje-Eilers  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25ae115bc7Smrj  * Use is subject to license terms.
26ae115bc7Smrj  */
27ae115bc7Smrj 
28ae115bc7Smrj #include <sys/types.h>
29ae115bc7Smrj #include <sys/systm.h>
30ae115bc7Smrj #include <sys/archsystm.h>
31ae115bc7Smrj #include <sys/boot_console.h>
32843e1988Sjohnlev #include <sys/panic.h>
33adb91f47Srscott #include <sys/ctype.h>
34843e1988Sjohnlev #if defined(__xpv)
35843e1988Sjohnlev #include <sys/hypervisor.h>
36843e1988Sjohnlev #endif /* __xpv */
37ae115bc7Smrj 
38ae115bc7Smrj #include "boot_serial.h"
39ae115bc7Smrj #include "boot_vga.h"
40ae115bc7Smrj 
41ae115bc7Smrj #if defined(_BOOT)
42843e1988Sjohnlev #include <dboot/dboot_asm.h>
43adb91f47Srscott #include <dboot/dboot_xboot.h>
44843e1988Sjohnlev #else /* _BOOT */
45ae115bc7Smrj #include <sys/bootconf.h>
46843e1988Sjohnlev #if defined(__xpv)
47843e1988Sjohnlev #include <sys/evtchn_impl.h>
48843e1988Sjohnlev #endif /* __xpv */
4948633f18SJan Setje-Eilers static char *defcons_buf;
5048633f18SJan Setje-Eilers static char *defcons_cur;
51843e1988Sjohnlev #endif /* _BOOT */
52843e1988Sjohnlev 
53843e1988Sjohnlev #if defined(__xpv)
54843e1988Sjohnlev extern void bcons_init_xen(char *);
55843e1988Sjohnlev extern void bcons_putchar_xen(int);
56843e1988Sjohnlev extern int bcons_getchar_xen(void);
57843e1988Sjohnlev extern int bcons_ischar_xen(void);
58843e1988Sjohnlev #endif /* __xpv */
59ae115bc7Smrj 
60ae115bc7Smrj static int cons_color = CONS_COLOR;
61*0d928757SGary Mills static int console = CONS_SCREEN_TEXT;
62*0d928757SGary Mills static int tty_num = 0;
63*0d928757SGary Mills static int tty_addr[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
64843e1988Sjohnlev #if defined(__xpv)
65843e1988Sjohnlev static int console_hypervisor_redirect = B_FALSE;
66*0d928757SGary Mills static int console_hypervisor_device = CONS_INVALID;
67*0d928757SGary Mills static int console_hypervisor_tty_num = 0;
68*0d928757SGary Mills 
69*0d928757SGary Mills /* Obtain the hypervisor console type */
70*0d928757SGary Mills int
console_hypervisor_dev_type(int * tnum)71*0d928757SGary Mills console_hypervisor_dev_type(int *tnum)
72*0d928757SGary Mills {
73*0d928757SGary Mills 	if (tnum != NULL)
74*0d928757SGary Mills 		*tnum = console_hypervisor_tty_num;
75*0d928757SGary Mills 	return (console_hypervisor_device);
76*0d928757SGary Mills }
77843e1988Sjohnlev #endif /* __xpv */
78843e1988Sjohnlev 
79ae115bc7Smrj static int serial_ischar(void);
80ae115bc7Smrj static int serial_getchar(void);
81ae115bc7Smrj static void serial_putchar(int);
82ae115bc7Smrj static void serial_adjust_prop(void);
83ae115bc7Smrj 
84ae115bc7Smrj static char *boot_line = NULL;
85ae115bc7Smrj 
86843e1988Sjohnlev #if !defined(_BOOT)
87adb91f47Srscott /* Set if the console or mode are expressed in the boot line */
88adb91f47Srscott static int console_set, console_mode_set;
89843e1988Sjohnlev #endif
90adb91f47Srscott 
91ae115bc7Smrj /* Clear the screen and initialize VIDEO, XPOS and YPOS. */
92843e1988Sjohnlev void
clear_screen(void)93ae115bc7Smrj clear_screen(void)
94ae115bc7Smrj {
95ae115bc7Smrj 	/*
96ae115bc7Smrj 	 * XXX should set vga mode so we don't depend on the
97843e1988Sjohnlev 	 * state left by the boot loader.  Note that we have to
98843e1988Sjohnlev 	 * enable the cursor before clearing the screen since
99843e1988Sjohnlev 	 * the cursor position is dependant upon the cursor
100843e1988Sjohnlev 	 * skew, which is initialized by vga_cursor_display()
101ae115bc7Smrj 	 */
102843e1988Sjohnlev 	vga_cursor_display();
103ae115bc7Smrj 	vga_clear(cons_color);
104ae115bc7Smrj 	vga_setpos(0, 0);
105ae115bc7Smrj }
106ae115bc7Smrj 
107ae115bc7Smrj /* Put the character C on the screen. */
108ae115bc7Smrj static void
screen_putchar(int c)109ae115bc7Smrj screen_putchar(int c)
110ae115bc7Smrj {
111ae115bc7Smrj 	int row, col;
112ae115bc7Smrj 
113ae115bc7Smrj 	vga_getpos(&row, &col);
114ae115bc7Smrj 	switch (c) {
115ae115bc7Smrj 	case '\t':
116ae115bc7Smrj 		col += 8 - (col % 8);
117ae115bc7Smrj 		if (col == VGA_TEXT_COLS)
118ae115bc7Smrj 			col = 79;
119ae115bc7Smrj 		vga_setpos(row, col);
120ae115bc7Smrj 		break;
121ae115bc7Smrj 
122ae115bc7Smrj 	case '\r':
123ae115bc7Smrj 		vga_setpos(row, 0);
124ae115bc7Smrj 		break;
125ae115bc7Smrj 
126ae115bc7Smrj 	case '\b':
127ae115bc7Smrj 		if (col > 0)
128ae115bc7Smrj 			vga_setpos(row, col - 1);
129ae115bc7Smrj 		break;
130ae115bc7Smrj 
131ae115bc7Smrj 	case '\n':
132ae115bc7Smrj 		if (row < VGA_TEXT_ROWS - 1)
133ae115bc7Smrj 			vga_setpos(row + 1, col);
134ae115bc7Smrj 		else
135ae115bc7Smrj 			vga_scroll(cons_color);
136ae115bc7Smrj 		break;
137ae115bc7Smrj 
138ae115bc7Smrj 	default:
139ae115bc7Smrj 		vga_drawc(c, cons_color);
140ae115bc7Smrj 		if (col < VGA_TEXT_COLS -1)
141ae115bc7Smrj 			vga_setpos(row, col + 1);
142ae115bc7Smrj 		else if (row < VGA_TEXT_ROWS - 1)
143ae115bc7Smrj 			vga_setpos(row + 1, 0);
144ae115bc7Smrj 		else {
145ae115bc7Smrj 			vga_setpos(row, 0);
146ae115bc7Smrj 			vga_scroll(cons_color);
147ae115bc7Smrj 		}
148ae115bc7Smrj 		break;
149ae115bc7Smrj 	}
150ae115bc7Smrj }
151ae115bc7Smrj 
152ae115bc7Smrj static int port;
153ae115bc7Smrj 
154ae115bc7Smrj static void
serial_init(void)155ae115bc7Smrj serial_init(void)
156ae115bc7Smrj {
157*0d928757SGary Mills 	port = tty_addr[tty_num];
158ae115bc7Smrj 
159ae115bc7Smrj 	outb(port + ISR, 0x20);
160ae115bc7Smrj 	if (inb(port + ISR) & 0x20) {
161ae115bc7Smrj 		/*
162ae115bc7Smrj 		 * 82510 chip is present
163ae115bc7Smrj 		 */
164ae115bc7Smrj 		outb(port + DAT+7, 0x04);	/* clear status */
165ae115bc7Smrj 		outb(port + ISR, 0x40);  /* set to bank 2 */
166ae115bc7Smrj 		outb(port + MCR, 0x08);  /* IMD */
167ae115bc7Smrj 		outb(port + DAT, 0x21);  /* FMD */
168ae115bc7Smrj 		outb(port + ISR, 0x00);  /* set to bank 0 */
169ae115bc7Smrj 	} else {
170ae115bc7Smrj 		/*
171ae115bc7Smrj 		 * set the UART in FIFO mode if it has FIFO buffers.
172ae115bc7Smrj 		 * use 16550 fifo reset sequence specified in NS
173ae115bc7Smrj 		 * application note. disable fifos until chip is
174ae115bc7Smrj 		 * initialized.
175ae115bc7Smrj 		 */
176ae115bc7Smrj 		outb(port + FIFOR, 0x00);		/* clear */
177ae115bc7Smrj 		outb(port + FIFOR, FIFO_ON);		/* enable */
178ae115bc7Smrj 		outb(port + FIFOR, FIFO_ON|FIFORXFLSH);  /* reset */
179ae115bc7Smrj 		outb(port + FIFOR,
180ae115bc7Smrj 		    FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80);
181ae115bc7Smrj 		if ((inb(port + ISR) & 0xc0) != 0xc0) {
182ae115bc7Smrj 			/*
183ae115bc7Smrj 			 * no fifo buffers so disable fifos.
184ae115bc7Smrj 			 * this is true for 8250's
185ae115bc7Smrj 			 */
186ae115bc7Smrj 			outb(port + FIFOR, 0x00);
187ae115bc7Smrj 		}
188ae115bc7Smrj 	}
189ae115bc7Smrj 
190ae115bc7Smrj 	/* disable interrupts */
191ae115bc7Smrj 	outb(port + ICR, 0);
192ae115bc7Smrj 
193843e1988Sjohnlev #if !defined(_BOOT)
194843e1988Sjohnlev 	if (IN_XPV_PANIC())
195843e1988Sjohnlev 		return;
196843e1988Sjohnlev #endif
197843e1988Sjohnlev 
198ae115bc7Smrj 	/* adjust setting based on tty properties */
199ae115bc7Smrj 	serial_adjust_prop();
200ae115bc7Smrj 
201ae115bc7Smrj #if defined(_BOOT)
202ae115bc7Smrj 	/*
203ae115bc7Smrj 	 * Do a full reset to match console behavior.
204ae115bc7Smrj 	 * 0x1B + c - reset everything
205ae115bc7Smrj 	 */
206ae115bc7Smrj 	serial_putchar(0x1B);
207ae115bc7Smrj 	serial_putchar('c');
208ae115bc7Smrj #endif
209ae115bc7Smrj }
210ae115bc7Smrj 
211adb91f47Srscott /* Advance str pointer past white space */
212adb91f47Srscott #define	EAT_WHITE_SPACE(str)	{			\
213adb91f47Srscott 	while ((*str != '\0') && ISSPACE(*str))		\
214adb91f47Srscott 		str++;					\
215adb91f47Srscott }
216adb91f47Srscott 
217adb91f47Srscott /*
218adb91f47Srscott  * boot_line is set when we call here.  Search it for the argument name,
219adb91f47Srscott  * and if found, return a pointer to it.
220adb91f47Srscott  */
221adb91f47Srscott static char *
find_boot_line_prop(const char * name)222adb91f47Srscott find_boot_line_prop(const char *name)
223adb91f47Srscott {
224adb91f47Srscott 	char *ptr;
225c6d6228cSEnrico Perla - Sun Microsystems 	char *ret = NULL;
226adb91f47Srscott 	char end_char;
227adb91f47Srscott 	size_t len;
228adb91f47Srscott 
229adb91f47Srscott 	if (boot_line == NULL)
230adb91f47Srscott 		return (NULL);
231adb91f47Srscott 
232adb91f47Srscott 	len = strlen(name);
233adb91f47Srscott 
234adb91f47Srscott 	/*
235adb91f47Srscott 	 * We have two nested loops here: the outer loop discards all options
236adb91f47Srscott 	 * except -B, and the inner loop parses the -B options looking for
237adb91f47Srscott 	 * the one we're interested in.
238adb91f47Srscott 	 */
239adb91f47Srscott 	for (ptr = boot_line; *ptr != '\0'; ptr++) {
240adb91f47Srscott 		EAT_WHITE_SPACE(ptr);
241adb91f47Srscott 
242adb91f47Srscott 		if (*ptr == '-') {
243adb91f47Srscott 			ptr++;
244adb91f47Srscott 			while ((*ptr != '\0') && (*ptr != 'B') &&
245adb91f47Srscott 			    !ISSPACE(*ptr))
246adb91f47Srscott 				ptr++;
247adb91f47Srscott 			if (*ptr == '\0')
248c6d6228cSEnrico Perla - Sun Microsystems 				goto out;
249adb91f47Srscott 			else if (*ptr != 'B')
250adb91f47Srscott 				continue;
251adb91f47Srscott 		} else {
252adb91f47Srscott 			while ((*ptr != '\0') && !ISSPACE(*ptr))
253adb91f47Srscott 				ptr++;
254adb91f47Srscott 			if (*ptr == '\0')
255c6d6228cSEnrico Perla - Sun Microsystems 				goto out;
256adb91f47Srscott 			continue;
257adb91f47Srscott 		}
258adb91f47Srscott 
259adb91f47Srscott 		do {
260adb91f47Srscott 			ptr++;
261adb91f47Srscott 			EAT_WHITE_SPACE(ptr);
262adb91f47Srscott 
263adb91f47Srscott 			if ((strncmp(ptr, name, len) == 0) &&
264adb91f47Srscott 			    (ptr[len] == '=')) {
265adb91f47Srscott 				ptr += len + 1;
266c6d6228cSEnrico Perla - Sun Microsystems 				if ((*ptr == '\'') || (*ptr == '"')) {
267c6d6228cSEnrico Perla - Sun Microsystems 					ret = ptr + 1;
268c6d6228cSEnrico Perla - Sun Microsystems 					end_char = *ptr;
269c6d6228cSEnrico Perla - Sun Microsystems 					ptr++;
270c6d6228cSEnrico Perla - Sun Microsystems 				} else {
271c6d6228cSEnrico Perla - Sun Microsystems 					ret = ptr;
272c6d6228cSEnrico Perla - Sun Microsystems 					end_char = ',';
273c6d6228cSEnrico Perla - Sun Microsystems 				}
274c6d6228cSEnrico Perla - Sun Microsystems 				goto consume_property;
275adb91f47Srscott 			}
276adb91f47Srscott 
277adb91f47Srscott 			/*
278adb91f47Srscott 			 * We have a property, and it's not the one we're
279adb91f47Srscott 			 * interested in.  Skip the property name.  A name
280adb91f47Srscott 			 * can end with '=', a comma, or white space.
281adb91f47Srscott 			 */
282adb91f47Srscott 			while ((*ptr != '\0') && (*ptr != '=') &&
283adb91f47Srscott 			    (*ptr != ',') && (!ISSPACE(*ptr)))
284adb91f47Srscott 				ptr++;
285adb91f47Srscott 
286adb91f47Srscott 			/*
287adb91f47Srscott 			 * We only want to go through the rest of the inner
288adb91f47Srscott 			 * loop if we have a comma.  If we have a property
289adb91f47Srscott 			 * name without a value, either continue or break.
290adb91f47Srscott 			 */
291adb91f47Srscott 			if (*ptr == '\0')
292c6d6228cSEnrico Perla - Sun Microsystems 				goto out;
293adb91f47Srscott 			else if (*ptr == ',')
294adb91f47Srscott 				continue;
295adb91f47Srscott 			else if (ISSPACE(*ptr))
296adb91f47Srscott 				break;
297adb91f47Srscott 			ptr++;
298adb91f47Srscott 
299adb91f47Srscott 			/*
300adb91f47Srscott 			 * Is the property quoted?
301adb91f47Srscott 			 */
302adb91f47Srscott 			if ((*ptr == '\'') || (*ptr == '"')) {
303adb91f47Srscott 				end_char = *ptr;
304c6d6228cSEnrico Perla - Sun Microsystems 				ptr++;
305adb91f47Srscott 			} else {
306adb91f47Srscott 				/*
307adb91f47Srscott 				 * Not quoted, so the string ends at a comma
308adb91f47Srscott 				 * or at white space.  Deal with white space
309adb91f47Srscott 				 * later.
310adb91f47Srscott 				 */
311adb91f47Srscott 				end_char = ',';
312adb91f47Srscott 			}
313adb91f47Srscott 
314adb91f47Srscott 			/*
315adb91f47Srscott 			 * Now, we can ignore any characters until we find
316adb91f47Srscott 			 * end_char.
317adb91f47Srscott 			 */
318c6d6228cSEnrico Perla - Sun Microsystems consume_property:
319adb91f47Srscott 			for (; (*ptr != '\0') && (*ptr != end_char); ptr++) {
320adb91f47Srscott 				if ((end_char == ',') && ISSPACE(*ptr))
321adb91f47Srscott 					break;
322adb91f47Srscott 			}
323c6d6228cSEnrico Perla - Sun Microsystems 			if (*ptr && (*ptr != ',') && !ISSPACE(*ptr))
324adb91f47Srscott 				ptr++;
325adb91f47Srscott 		} while (*ptr == ',');
326adb91f47Srscott 	}
327c6d6228cSEnrico Perla - Sun Microsystems out:
328c6d6228cSEnrico Perla - Sun Microsystems 	return (ret);
329adb91f47Srscott }
330adb91f47Srscott 
331ae115bc7Smrj 
332ae115bc7Smrj #define	MATCHES(p, pat)	\
333ae115bc7Smrj 	(strncmp(p, pat, strlen(pat)) == 0 ? (p += strlen(pat), 1) : 0)
334ae115bc7Smrj 
335ae115bc7Smrj #define	SKIP(p, c)				\
336ae115bc7Smrj 	while (*(p) != 0 && *p != (c))		\
337ae115bc7Smrj 		++(p);				\
338ae115bc7Smrj 	if (*(p) == (c))			\
339ae115bc7Smrj 		++(p);
340ae115bc7Smrj 
341ae115bc7Smrj /*
342ae115bc7Smrj  * find a tty mode property either from cmdline or from boot properties
343ae115bc7Smrj  */
344ae115bc7Smrj static char *
get_mode_value(char * name)345ae115bc7Smrj get_mode_value(char *name)
346ae115bc7Smrj {
347ae115bc7Smrj 	/*
348ae115bc7Smrj 	 * when specified on boot line it looks like "name" "="....
349ae115bc7Smrj 	 */
350ae115bc7Smrj 	if (boot_line != NULL) {
351adb91f47Srscott 		return (find_boot_line_prop(name));
352ae115bc7Smrj 	}
353ae115bc7Smrj 
354ae115bc7Smrj #if defined(_BOOT)
355ae115bc7Smrj 	return (NULL);
356ae115bc7Smrj #else
357ae115bc7Smrj 	/*
358ae115bc7Smrj 	 * if we're running in the full kernel we check the bootenv.rc settings
359ae115bc7Smrj 	 */
360ae115bc7Smrj 	{
361ae115bc7Smrj 		static char propval[20];
362ae115bc7Smrj 
363ae115bc7Smrj 		propval[0] = 0;
364adb91f47Srscott 		if (do_bsys_getproplen(NULL, name) <= 0)
365ae115bc7Smrj 			return (NULL);
366adb91f47Srscott 		(void) do_bsys_getprop(NULL, name, propval);
367ae115bc7Smrj 		return (propval);
368ae115bc7Smrj 	}
369ae115bc7Smrj #endif
370ae115bc7Smrj }
371ae115bc7Smrj 
372ae115bc7Smrj /*
373ae115bc7Smrj  * adjust serial port based on properties
374ae115bc7Smrj  * These come either from the cmdline or from boot properties.
375ae115bc7Smrj  */
376ae115bc7Smrj static void
serial_adjust_prop(void)377ae115bc7Smrj serial_adjust_prop(void)
378ae115bc7Smrj {
379ae115bc7Smrj 	char propname[20];
380ae115bc7Smrj 	char *propval;
381ae115bc7Smrj 	char *p;
382ae115bc7Smrj 	ulong_t baud;
383ae115bc7Smrj 	uchar_t lcr = 0;
384ae115bc7Smrj 	uchar_t mcr = DTR | RTS;
385ae115bc7Smrj 
386ae115bc7Smrj 	(void) strcpy(propname, "ttyX-mode");
387*0d928757SGary Mills 	propname[3] = 'a' + tty_num;
388ae115bc7Smrj 	propval = get_mode_value(propname);
389ae115bc7Smrj 	if (propval == NULL)
390ae115bc7Smrj 		propval = "9600,8,n,1,-";
391843e1988Sjohnlev #if !defined(_BOOT)
392adb91f47Srscott 	else
393adb91f47Srscott 		console_mode_set = 1;
394843e1988Sjohnlev #endif
395ae115bc7Smrj 
396ae115bc7Smrj 	/* property is of the form: "9600,8,n,1,-" */
397ae115bc7Smrj 	p = propval;
398ae115bc7Smrj 	if (MATCHES(p, "110,"))
399ae115bc7Smrj 		baud = ASY110;
400ae115bc7Smrj 	else if (MATCHES(p, "150,"))
401ae115bc7Smrj 		baud = ASY150;
402ae115bc7Smrj 	else if (MATCHES(p, "300,"))
403ae115bc7Smrj 		baud = ASY300;
404ae115bc7Smrj 	else if (MATCHES(p, "600,"))
405ae115bc7Smrj 		baud = ASY600;
406ae115bc7Smrj 	else if (MATCHES(p, "1200,"))
407ae115bc7Smrj 		baud = ASY1200;
408ae115bc7Smrj 	else if (MATCHES(p, "2400,"))
409ae115bc7Smrj 		baud = ASY2400;
410ae115bc7Smrj 	else if (MATCHES(p, "4800,"))
411ae115bc7Smrj 		baud = ASY4800;
412ae115bc7Smrj 	else if (MATCHES(p, "19200,"))
413ae115bc7Smrj 		baud = ASY19200;
414ae115bc7Smrj 	else if (MATCHES(p, "38400,"))
415ae115bc7Smrj 		baud = ASY38400;
416ae115bc7Smrj 	else if (MATCHES(p, "57600,"))
417ae115bc7Smrj 		baud = ASY57600;
418ae115bc7Smrj 	else if (MATCHES(p, "115200,"))
419ae115bc7Smrj 		baud = ASY115200;
420ae115bc7Smrj 	else {
421ae115bc7Smrj 		baud = ASY9600;
422ae115bc7Smrj 		SKIP(p, ',');
423ae115bc7Smrj 	}
424ae115bc7Smrj 	outb(port + LCR, DLAB);
425ae115bc7Smrj 	outb(port + DAT + DLL, baud & 0xff);
426ae115bc7Smrj 	outb(port + DAT + DLH, (baud >> 8) & 0xff);
427ae115bc7Smrj 
428ae115bc7Smrj 	switch (*p) {
429ae115bc7Smrj 	case '5':
430ae115bc7Smrj 		lcr |= BITS5;
431ae115bc7Smrj 		++p;
432ae115bc7Smrj 		break;
433ae115bc7Smrj 	case '6':
434ae115bc7Smrj 		lcr |= BITS6;
435ae115bc7Smrj 		++p;
436ae115bc7Smrj 		break;
437ae115bc7Smrj 	case '7':
438ae115bc7Smrj 		lcr |= BITS7;
439ae115bc7Smrj 		++p;
440ae115bc7Smrj 		break;
441ae115bc7Smrj 	case '8':
442ae115bc7Smrj 		++p;
443ae115bc7Smrj 	default:
444ae115bc7Smrj 		lcr |= BITS8;
445ae115bc7Smrj 		break;
446ae115bc7Smrj 	}
447ae115bc7Smrj 
448ae115bc7Smrj 	SKIP(p, ',');
449ae115bc7Smrj 
450ae115bc7Smrj 	switch (*p) {
451ae115bc7Smrj 	case 'n':
452ae115bc7Smrj 		lcr |= PARITY_NONE;
453ae115bc7Smrj 		++p;
454ae115bc7Smrj 		break;
455ae115bc7Smrj 	case 'o':
456ae115bc7Smrj 		lcr |= PARITY_ODD;
457ae115bc7Smrj 		++p;
458ae115bc7Smrj 		break;
459ae115bc7Smrj 	case 'e':
460ae115bc7Smrj 		++p;
461ae115bc7Smrj 	default:
462ae115bc7Smrj 		lcr |= PARITY_EVEN;
463ae115bc7Smrj 		break;
464ae115bc7Smrj 	}
465ae115bc7Smrj 
466ae115bc7Smrj 
467ae115bc7Smrj 	SKIP(p, ',');
468ae115bc7Smrj 
469ae115bc7Smrj 	switch (*p) {
470ae115bc7Smrj 	case '1':
471ae115bc7Smrj 		/* STOP1 is 0 */
472ae115bc7Smrj 		++p;
473ae115bc7Smrj 		break;
474ae115bc7Smrj 	default:
475ae115bc7Smrj 		lcr |= STOP2;
476ae115bc7Smrj 		break;
477ae115bc7Smrj 	}
478ae115bc7Smrj 	/* set parity bits */
479ae115bc7Smrj 	outb(port + LCR, lcr);
480ae115bc7Smrj 
481ae115bc7Smrj 	(void) strcpy(propname, "ttyX-rts-dtr-off");
482*0d928757SGary Mills 	propname[3] = 'a' + tty_num;
483ae115bc7Smrj 	propval = get_mode_value(propname);
484ae115bc7Smrj 	if (propval == NULL)
485ae115bc7Smrj 		propval = "false";
486ae115bc7Smrj 	if (propval[0] != 'f' && propval[0] != 'F')
487ae115bc7Smrj 		mcr = 0;
488ae115bc7Smrj 	/* set modem control bits */
489ae115bc7Smrj 	outb(port + MCR, mcr | OUT2);
490ae115bc7Smrj }
491ae115bc7Smrj 
492*0d928757SGary Mills /* Obtain the console type */
493*0d928757SGary Mills int
boot_console_type(int * tnum)494*0d928757SGary Mills boot_console_type(int *tnum)
495*0d928757SGary Mills {
496*0d928757SGary Mills 	if (tnum != NULL)
497*0d928757SGary Mills 		*tnum = tty_num;
498*0d928757SGary Mills 	return (console);
499*0d928757SGary Mills }
500*0d928757SGary Mills 
501adb91f47Srscott /*
502adb91f47Srscott  * A structure to map console names to values.
503adb91f47Srscott  */
504adb91f47Srscott typedef struct {
505adb91f47Srscott 	char *name;
506adb91f47Srscott 	int value;
507adb91f47Srscott } console_value_t;
508adb91f47Srscott 
509adb91f47Srscott console_value_t console_devices[] = {
510*0d928757SGary Mills 	{ "ttya", CONS_TTY },	/* 0 */
511*0d928757SGary Mills 	{ "ttyb", CONS_TTY },	/* 1 */
512*0d928757SGary Mills 	{ "ttyc", CONS_TTY },	/* 2 */
513*0d928757SGary Mills 	{ "ttyd", CONS_TTY },	/* 3 */
514adb91f47Srscott 	{ "text", CONS_SCREEN_TEXT },
51567ce1dadSJan Setje-Eilers 	{ "graphics", CONS_SCREEN_GRAPHICS },
516843e1988Sjohnlev #if defined(__xpv)
517843e1988Sjohnlev 	{ "hypervisor", CONS_HYPERVISOR },
518843e1988Sjohnlev #endif
519adb91f47Srscott #if !defined(_BOOT)
520adb91f47Srscott 	{ "usb-serial", CONS_USBSER },
521adb91f47Srscott #endif
522*0d928757SGary Mills 	{ NULL, CONS_INVALID }
523adb91f47Srscott };
524adb91f47Srscott 
525ae115bc7Smrj void
bcons_init(char * bootstr)526ae115bc7Smrj bcons_init(char *bootstr)
527ae115bc7Smrj {
528adb91f47Srscott 	console_value_t *consolep;
529adb91f47Srscott 	size_t len, cons_len;
530adb91f47Srscott 	char *cons_str;
5319db7147eSSherry Moore #if !defined(_BOOT)
5329db7147eSSherry Moore 	static char console_text[] = "text";
5339db7147eSSherry Moore 	extern int post_fastreboot;
5349db7147eSSherry Moore #endif
535adb91f47Srscott 
536ae115bc7Smrj 	boot_line = bootstr;
537ae115bc7Smrj 	console = CONS_INVALID;
538ae115bc7Smrj 
539843e1988Sjohnlev #if defined(__xpv)
540843e1988Sjohnlev 	bcons_init_xen(bootstr);
541843e1988Sjohnlev #endif /* __xpv */
542843e1988Sjohnlev 
543adb91f47Srscott 	cons_str = find_boot_line_prop("console");
544adb91f47Srscott 	if (cons_str == NULL)
545adb91f47Srscott 		cons_str = find_boot_line_prop("output-device");
546adb91f47Srscott 
5479db7147eSSherry Moore #if !defined(_BOOT)
5489db7147eSSherry Moore 	if (post_fastreboot && strcmp(cons_str, "graphics") == 0)
5499db7147eSSherry Moore 		cons_str = console_text;
5509db7147eSSherry Moore #endif
5519db7147eSSherry Moore 
552adb91f47Srscott 	/*
553adb91f47Srscott 	 * Go through the console_devices array trying to match the string
554adb91f47Srscott 	 * we were given.  The string on the command line must end with
555adb91f47Srscott 	 * a comma or white space.
556adb91f47Srscott 	 */
557adb91f47Srscott 	if (cons_str != NULL) {
558*0d928757SGary Mills 		int n;
559*0d928757SGary Mills 
560adb91f47Srscott 		cons_len = strlen(cons_str);
561*0d928757SGary Mills 		for (n = 0; console_devices[n].name != NULL; n++) {
562*0d928757SGary Mills 			consolep = &console_devices[n];
563adb91f47Srscott 			len = strlen(consolep->name);
564adb91f47Srscott 			if ((len <= cons_len) && ((cons_str[len] == '\0') ||
565adb91f47Srscott 			    (cons_str[len] == ',') || (cons_str[len] == '\'') ||
566adb91f47Srscott 			    (cons_str[len] == '"') || ISSPACE(cons_str[len])) &&
567adb91f47Srscott 			    (strncmp(cons_str, consolep->name, len) == 0)) {
568adb91f47Srscott 				console = consolep->value;
569*0d928757SGary Mills 				if (console == CONS_TTY)
570*0d928757SGary Mills 					tty_num = n;
571adb91f47Srscott 				break;
572adb91f47Srscott 			}
573adb91f47Srscott 		}
574adb91f47Srscott 	}
575ae115bc7Smrj 
576843e1988Sjohnlev #if defined(__xpv)
577843e1988Sjohnlev 	/*
578843e1988Sjohnlev 	 * domU's always use the hypervisor regardless of what
579843e1988Sjohnlev 	 * the console variable may be set to.
580843e1988Sjohnlev 	 */
581843e1988Sjohnlev 	if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
582843e1988Sjohnlev 		console = CONS_HYPERVISOR;
583843e1988Sjohnlev 		console_hypervisor_redirect = B_TRUE;
584843e1988Sjohnlev 	}
585843e1988Sjohnlev #endif /* __xpv */
586843e1988Sjohnlev 
587ae115bc7Smrj 	/*
588ae115bc7Smrj 	 * If no console device specified, default to text.
589ae115bc7Smrj 	 * Remember what was specified for second phase.
590ae115bc7Smrj 	 */
591ae115bc7Smrj 	if (console == CONS_INVALID)
592ae115bc7Smrj 		console = CONS_SCREEN_TEXT;
593843e1988Sjohnlev #if !defined(_BOOT)
594adb91f47Srscott 	else
595adb91f47Srscott 		console_set = 1;
596843e1988Sjohnlev #endif
597843e1988Sjohnlev 
598843e1988Sjohnlev #if defined(__xpv)
599843e1988Sjohnlev 	if (DOMAIN_IS_INITDOMAIN(xen_info)) {
600843e1988Sjohnlev 		switch (HYPERVISOR_console_io(CONSOLEIO_get_device, 0, NULL)) {
601843e1988Sjohnlev 			case XEN_CONSOLE_COM1:
602843e1988Sjohnlev 			case XEN_CONSOLE_COM2:
603*0d928757SGary Mills 				console_hypervisor_device = CONS_TTY;
604*0d928757SGary Mills 				console_hypervisor_tty_num = tty_num;
605843e1988Sjohnlev 				break;
606843e1988Sjohnlev 			case XEN_CONSOLE_VGA:
607843e1988Sjohnlev 				/*
608843e1988Sjohnlev 				 * Currently xen doesn't really support
609843e1988Sjohnlev 				 * keyboard/display console devices.
610843e1988Sjohnlev 				 * What this setting means is that
611843e1988Sjohnlev 				 * "vga=keep" has been enabled, which is
612843e1988Sjohnlev 				 * more of a xen debugging tool that a
613843e1988Sjohnlev 				 * true console mode.  Hence, we're going
614843e1988Sjohnlev 				 * to ignore this xen "console" setting.
615843e1988Sjohnlev 				 */
616843e1988Sjohnlev 				/*FALLTHROUGH*/
617843e1988Sjohnlev 			default:
618843e1988Sjohnlev 				console_hypervisor_device = CONS_INVALID;
619843e1988Sjohnlev 		}
620843e1988Sjohnlev 	}
621843e1988Sjohnlev 
622843e1988Sjohnlev 	/*
623843e1988Sjohnlev 	 * if the hypervisor is using the currently selected serial
624843e1988Sjohnlev 	 * port then default to using the hypervisor as the console
625843e1988Sjohnlev 	 * device.
626843e1988Sjohnlev 	 */
627843e1988Sjohnlev 	if (console == console_hypervisor_device) {
628843e1988Sjohnlev 		console = CONS_HYPERVISOR;
629843e1988Sjohnlev 		console_hypervisor_redirect = B_TRUE;
630843e1988Sjohnlev 	}
631843e1988Sjohnlev #endif /* __xpv */
632ae115bc7Smrj 
633ae115bc7Smrj 	switch (console) {
634*0d928757SGary Mills 	case CONS_TTY:
635ae115bc7Smrj 		serial_init();
636ae115bc7Smrj 		break;
637ae115bc7Smrj 
638843e1988Sjohnlev 	case CONS_HYPERVISOR:
639843e1988Sjohnlev 		break;
640843e1988Sjohnlev 
641adb91f47Srscott #if !defined(_BOOT)
642adb91f47Srscott 	case CONS_USBSER:
643adb91f47Srscott 		/*
644adb91f47Srscott 		 * We can't do anything with the usb serial
645adb91f47Srscott 		 * until we have memory management.
646adb91f47Srscott 		 */
647adb91f47Srscott 		break;
648adb91f47Srscott #endif
64967ce1dadSJan Setje-Eilers 	case CONS_SCREEN_GRAPHICS:
65067ce1dadSJan Setje-Eilers 		kb_init();
65167ce1dadSJan Setje-Eilers 		break;
652ae115bc7Smrj 	case CONS_SCREEN_TEXT:
653ae115bc7Smrj 	default:
654ae115bc7Smrj #if defined(_BOOT)
655843e1988Sjohnlev 		clear_screen();	/* clears the grub or xen screen */
656843e1988Sjohnlev #endif /* _BOOT */
657ae115bc7Smrj 		kb_init();
658ae115bc7Smrj 		break;
659ae115bc7Smrj 	}
660ae115bc7Smrj 	boot_line = NULL;
661ae115bc7Smrj }
662ae115bc7Smrj 
663843e1988Sjohnlev #if !defined(_BOOT)
664ae115bc7Smrj /*
665ae115bc7Smrj  * 2nd part of console initialization.
666ae115bc7Smrj  * In the kernel (ie. fakebop), this can be used only to switch to
667ae115bc7Smrj  * using a serial port instead of screen based on the contents
668ae115bc7Smrj  * of the bootenv.rc file.
669ae115bc7Smrj  */
670ae115bc7Smrj /*ARGSUSED*/
671ae115bc7Smrj void
bcons_init2(char * inputdev,char * outputdev,char * consoledev)672ae115bc7Smrj bcons_init2(char *inputdev, char *outputdev, char *consoledev)
673ae115bc7Smrj {
674ae115bc7Smrj 	int cons = CONS_INVALID;
675*0d928757SGary Mills 	int ttyn;
676adb91f47Srscott 	char *devnames[] = { consoledev, outputdev, inputdev, NULL };
677adb91f47Srscott 	console_value_t *consolep;
678adb91f47Srscott 	int i;
6799db7147eSSherry Moore 	extern int post_fastreboot;
6809db7147eSSherry Moore 
6819db7147eSSherry Moore 	if (post_fastreboot && console == CONS_SCREEN_GRAPHICS)
6829db7147eSSherry Moore 		console = CONS_SCREEN_TEXT;
683ae115bc7Smrj 
684c6d6228cSEnrico Perla - Sun Microsystems 	if (console != CONS_USBSER && console != CONS_SCREEN_GRAPHICS) {
685adb91f47Srscott 		if (console_set) {
686adb91f47Srscott 			/*
687adb91f47Srscott 			 * If the console was set on the command line,
688adb91f47Srscott 			 * but the ttyX-mode was not, we only need to
689adb91f47Srscott 			 * check bootenv.rc for that setting.
690adb91f47Srscott 			 */
691*0d928757SGary Mills 			if ((!console_mode_set) && (console == CONS_TTY))
692adb91f47Srscott 				serial_init();
693adb91f47Srscott 			return;
694ae115bc7Smrj 		}
695ae115bc7Smrj 
696adb91f47Srscott 		for (i = 0; devnames[i] != NULL; i++) {
697*0d928757SGary Mills 			int n;
698*0d928757SGary Mills 
699*0d928757SGary Mills 			for (n = 0; console_devices[n].name != NULL; n++) {
700*0d928757SGary Mills 				consolep = &console_devices[n];
701adb91f47Srscott 				if (strcmp(devnames[i], consolep->name) == 0) {
702adb91f47Srscott 					cons = consolep->value;
703*0d928757SGary Mills 					if (cons == CONS_TTY)
704*0d928757SGary Mills 						ttyn = n;
705ae115bc7Smrj 				}
706adb91f47Srscott 			}
707adb91f47Srscott 			if (cons != CONS_INVALID)
708adb91f47Srscott 				break;
709ae115bc7Smrj 		}
710ae115bc7Smrj 
711843e1988Sjohnlev #if defined(__xpv)
712843e1988Sjohnlev 		/*
713843e1988Sjohnlev 		 * if the hypervisor is using the currently selected console
714843e1988Sjohnlev 		 * device then default to using the hypervisor as the console
715843e1988Sjohnlev 		 * device.
716843e1988Sjohnlev 		 */
717843e1988Sjohnlev 		if (cons == console_hypervisor_device) {
718843e1988Sjohnlev 			cons = CONS_HYPERVISOR;
719843e1988Sjohnlev 			console_hypervisor_redirect = B_TRUE;
720843e1988Sjohnlev 		}
721843e1988Sjohnlev #endif /* __xpv */
722843e1988Sjohnlev 
723843e1988Sjohnlev 		if ((cons == CONS_INVALID) || (cons == console)) {
724843e1988Sjohnlev 			/*
725843e1988Sjohnlev 			 * we're sticking with whatever the current setting is
726843e1988Sjohnlev 			 */
727ae115bc7Smrj 			return;
728843e1988Sjohnlev 		}
729ae115bc7Smrj 
730ae115bc7Smrj 		console = cons;
731*0d928757SGary Mills 		if (cons == CONS_TTY) {
732*0d928757SGary Mills 			tty_num = ttyn;
733ae115bc7Smrj 			serial_init();
734ae115bc7Smrj 			return;
735ae115bc7Smrj 		}
736c6d6228cSEnrico Perla - Sun Microsystems 	} else {
737ae115bc7Smrj 		/*
738c6d6228cSEnrico Perla - Sun Microsystems 		 * USB serial and GRAPHICS console
739c6d6228cSEnrico Perla - Sun Microsystems 		 * we just collect data into a buffer
740ae115bc7Smrj 		 */
74148633f18SJan Setje-Eilers 		extern void *defcons_init(size_t);
74248633f18SJan Setje-Eilers 		defcons_buf = defcons_cur = defcons_init(MMU_PAGESIZE);
743ae115bc7Smrj 	}
744ae115bc7Smrj }
745ae115bc7Smrj 
746843e1988Sjohnlev #if defined(__xpv)
747843e1988Sjohnlev boolean_t
bcons_hypervisor_redirect(void)748843e1988Sjohnlev bcons_hypervisor_redirect(void)
749843e1988Sjohnlev {
750843e1988Sjohnlev 	return (console_hypervisor_redirect);
751843e1988Sjohnlev }
752843e1988Sjohnlev 
753843e1988Sjohnlev void
bcons_device_change(int new_console)754843e1988Sjohnlev bcons_device_change(int new_console)
755843e1988Sjohnlev {
756843e1988Sjohnlev 	if (new_console < CONS_MIN || new_console > CONS_MAX)
757843e1988Sjohnlev 		return;
758843e1988Sjohnlev 
759843e1988Sjohnlev 	/*
760843e1988Sjohnlev 	 * If we are asked to switch the console to the hypervisor, that
761843e1988Sjohnlev 	 * really means to switch the console to whichever device the
762843e1988Sjohnlev 	 * hypervisor is/was using.
763843e1988Sjohnlev 	 */
764843e1988Sjohnlev 	if (new_console == CONS_HYPERVISOR)
765843e1988Sjohnlev 		new_console = console_hypervisor_device;
766843e1988Sjohnlev 
767843e1988Sjohnlev 	console = new_console;
768843e1988Sjohnlev 
769*0d928757SGary Mills 	if (new_console == CONS_TTY) {
770*0d928757SGary Mills 		tty_num = console_hypervisor_tty_num;
771843e1988Sjohnlev 		serial_init();
772843e1988Sjohnlev 	}
773*0d928757SGary Mills }
774843e1988Sjohnlev #endif /* __xpv */
775843e1988Sjohnlev 
776ae115bc7Smrj static void
defcons_putchar(int c)77748633f18SJan Setje-Eilers defcons_putchar(int c)
778ae115bc7Smrj {
779c6d6228cSEnrico Perla - Sun Microsystems 	if (defcons_buf != NULL &&
780c6d6228cSEnrico Perla - Sun Microsystems 	    defcons_cur + 1 - defcons_buf < MMU_PAGESIZE) {
78148633f18SJan Setje-Eilers 		*defcons_cur++ = c;
78263dd072cSJan Setje-Eilers 		*defcons_cur = 0;
78363dd072cSJan Setje-Eilers 	}
784ae115bc7Smrj }
785ae115bc7Smrj #endif	/* _BOOT */
786ae115bc7Smrj 
787ae115bc7Smrj static void
serial_putchar(int c)788ae115bc7Smrj serial_putchar(int c)
789ae115bc7Smrj {
790ae115bc7Smrj 	int checks = 10000;
791ae115bc7Smrj 
792ae115bc7Smrj 	while (((inb(port + LSR) & XHRE) == 0) && checks--)
793ae115bc7Smrj 		;
794ae115bc7Smrj 	outb(port + DAT, (char)c);
795ae115bc7Smrj }
796ae115bc7Smrj 
797ae115bc7Smrj static int
serial_getchar(void)798ae115bc7Smrj serial_getchar(void)
799ae115bc7Smrj {
800ae115bc7Smrj 	uchar_t lsr;
801ae115bc7Smrj 
802ae115bc7Smrj 	while (serial_ischar() == 0)
803ae115bc7Smrj 		;
804ae115bc7Smrj 
805ae115bc7Smrj 	lsr = inb(port + LSR);
806ae115bc7Smrj 	if (lsr & (SERIAL_BREAK | SERIAL_FRAME |
807ae115bc7Smrj 	    SERIAL_PARITY | SERIAL_OVERRUN)) {
808ae115bc7Smrj 		if (lsr & SERIAL_OVERRUN) {
809ae115bc7Smrj 			return (inb(port + DAT));
810ae115bc7Smrj 		} else {
811ae115bc7Smrj 			/* Toss the garbage */
812ae115bc7Smrj 			(void) inb(port + DAT);
813ae115bc7Smrj 			return (0);
814ae115bc7Smrj 		}
815ae115bc7Smrj 	}
816ae115bc7Smrj 	return (inb(port + DAT));
817ae115bc7Smrj }
818ae115bc7Smrj 
819ae115bc7Smrj static int
serial_ischar(void)820ae115bc7Smrj serial_ischar(void)
821ae115bc7Smrj {
822ae115bc7Smrj 	return (inb(port + LSR) & RCA);
823ae115bc7Smrj }
824ae115bc7Smrj 
825ae115bc7Smrj static void
_doputchar(int c)826ae115bc7Smrj _doputchar(int c)
827ae115bc7Smrj {
828ae115bc7Smrj 	switch (console) {
829*0d928757SGary Mills 	case CONS_TTY:
830ae115bc7Smrj 		serial_putchar(c);
831ae115bc7Smrj 		return;
832ae115bc7Smrj 	case CONS_SCREEN_TEXT:
833ae115bc7Smrj 		screen_putchar(c);
834ae115bc7Smrj 		return;
83567ce1dadSJan Setje-Eilers 	case CONS_SCREEN_GRAPHICS:
836ae115bc7Smrj #if !defined(_BOOT)
837ae115bc7Smrj 	case CONS_USBSER:
83848633f18SJan Setje-Eilers 		defcons_putchar(c);
839ae115bc7Smrj #endif /* _BOOT */
84048633f18SJan Setje-Eilers 		return;
841ae115bc7Smrj 	}
842ae115bc7Smrj }
843ae115bc7Smrj 
844ae115bc7Smrj void
bcons_putchar(int c)845ae115bc7Smrj bcons_putchar(int c)
846ae115bc7Smrj {
847ae115bc7Smrj 	static int bhcharpos = 0;
848ae115bc7Smrj 
849843e1988Sjohnlev #if defined(__xpv)
850843e1988Sjohnlev 	if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
851843e1988Sjohnlev 	    console == CONS_HYPERVISOR) {
852843e1988Sjohnlev 		bcons_putchar_xen(c);
853843e1988Sjohnlev 		return;
854843e1988Sjohnlev 	}
855843e1988Sjohnlev #endif /* __xpv */
856843e1988Sjohnlev 
857ae115bc7Smrj 	if (c == '\t') {
858ae115bc7Smrj 		do {
859ae115bc7Smrj 			_doputchar(' ');
860ae115bc7Smrj 		} while (++bhcharpos % 8);
861ae115bc7Smrj 		return;
862ae115bc7Smrj 	} else  if (c == '\n' || c == '\r') {
863ae115bc7Smrj 		bhcharpos = 0;
864ae115bc7Smrj 		_doputchar('\r');
865ae115bc7Smrj 		_doputchar(c);
866ae115bc7Smrj 		return;
867ae115bc7Smrj 	} else if (c == '\b') {
868ae115bc7Smrj 		if (bhcharpos)
869ae115bc7Smrj 			bhcharpos--;
870ae115bc7Smrj 		_doputchar(c);
871ae115bc7Smrj 		return;
872ae115bc7Smrj 	}
873ae115bc7Smrj 
874ae115bc7Smrj 	bhcharpos++;
875ae115bc7Smrj 	_doputchar(c);
876ae115bc7Smrj }
877ae115bc7Smrj 
878ae115bc7Smrj /*
879ae115bc7Smrj  * kernel character input functions
880ae115bc7Smrj  */
881ae115bc7Smrj int
bcons_getchar(void)882ae115bc7Smrj bcons_getchar(void)
883ae115bc7Smrj {
884843e1988Sjohnlev #if defined(__xpv)
885843e1988Sjohnlev 	if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
886843e1988Sjohnlev 	    console == CONS_HYPERVISOR)
887843e1988Sjohnlev 		return (bcons_getchar_xen());
888843e1988Sjohnlev #endif /* __xpv */
889843e1988Sjohnlev 
890ae115bc7Smrj 	switch (console) {
891*0d928757SGary Mills 	case CONS_TTY:
892ae115bc7Smrj 		return (serial_getchar());
893ae115bc7Smrj 	default:
894ae115bc7Smrj 		return (kb_getchar());
895ae115bc7Smrj 	}
896ae115bc7Smrj }
897ae115bc7Smrj 
898ae115bc7Smrj #if !defined(_BOOT)
899ae115bc7Smrj 
900ae115bc7Smrj int
bcons_ischar(void)901ae115bc7Smrj bcons_ischar(void)
902ae115bc7Smrj {
903843e1988Sjohnlev 
904843e1988Sjohnlev #if defined(__xpv)
905843e1988Sjohnlev 	if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
906843e1988Sjohnlev 	    console == CONS_HYPERVISOR)
907843e1988Sjohnlev 		return (bcons_ischar_xen());
908843e1988Sjohnlev #endif /* __xpv */
909843e1988Sjohnlev 
910ae115bc7Smrj 	switch (console) {
911*0d928757SGary Mills 	case CONS_TTY:
912ae115bc7Smrj 		return (serial_ischar());
913ae115bc7Smrj 	default:
914ae115bc7Smrj 		return (kb_ischar());
915ae115bc7Smrj 	}
916ae115bc7Smrj }
917ae115bc7Smrj 
918ae115bc7Smrj #endif /* _BOOT */
919