sd: remove 'ssd' driver support
[unleashed/tickless.git] / arch / x86 / kernel / platform / i86pc / boot / boot_console.c
blobc706e4eb4735d083ec8441a8ee03a1546b545456
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2012 Gary Mills
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/archsystm.h>
31 #include <sys/boot_console.h>
32 #include <sys/panic.h>
33 #include <sys/ctype.h>
34 #if defined(__xpv)
35 #include <sys/hypervisor.h>
36 #endif /* __xpv */
38 #include "boot_serial.h"
39 #include "boot_vga.h"
41 #if defined(_BOOT)
42 #include <dboot_asm.h>
43 #include <dboot_xboot.h>
44 #else /* _BOOT */
45 #include <sys/bootconf.h>
46 #if defined(__xpv)
47 #include <sys/evtchn_impl.h>
48 #endif /* __xpv */
49 static char *defcons_buf;
50 static char *defcons_cur;
51 #endif /* _BOOT */
53 #if defined(__xpv)
54 extern void bcons_init_xen(char *);
55 extern void bcons_putchar_xen(int);
56 extern int bcons_getchar_xen(void);
57 extern int bcons_ischar_xen(void);
58 #endif /* __xpv */
60 static int cons_color = CONS_COLOR;
61 static int console = CONS_SCREEN_TEXT;
62 static int tty_num = 0;
63 static int tty_addr[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
64 static char *boot_line;
65 static struct boot_env {
66 char *be_env; /* ends with double ascii nul */
67 size_t be_size; /* size of the environment, including nul */
68 } boot_env;
70 static int serial_ischar(void);
71 static int serial_getchar(void);
72 static void serial_putchar(int);
73 static void serial_adjust_prop(void);
75 #if !defined(_BOOT)
76 /* Set if the console or mode are expressed in the boot line */
77 static int console_set, console_mode_set;
78 #endif
80 #if defined(__xpv)
81 static int console_hypervisor_redirect = B_FALSE;
82 static int console_hypervisor_device = CONS_INVALID;
83 static int console_hypervisor_tty_num = 0;
85 /* Obtain the hypervisor console type */
86 int
87 console_hypervisor_dev_type(int *tnum)
89 if (tnum != NULL)
90 *tnum = console_hypervisor_tty_num;
91 return (console_hypervisor_device);
93 #endif /* __xpv */
95 /* Clear the screen and initialize VIDEO, XPOS and YPOS. */
96 void
97 clear_screen(void)
100 * XXX should set vga mode so we don't depend on the
101 * state left by the boot loader. Note that we have to
102 * enable the cursor before clearing the screen since
103 * the cursor position is dependant upon the cursor
104 * skew, which is initialized by vga_cursor_display()
106 vga_cursor_display();
107 vga_clear(cons_color);
108 vga_setpos(0, 0);
111 /* Put the character C on the screen. */
112 static void
113 screen_putchar(int c)
115 int row, col;
117 vga_getpos(&row, &col);
118 switch (c) {
119 case '\t':
120 col += 8 - (col % 8);
121 if (col == VGA_TEXT_COLS)
122 col = 79;
123 vga_setpos(row, col);
124 break;
126 case '\r':
127 vga_setpos(row, 0);
128 break;
130 case '\b':
131 if (col > 0)
132 vga_setpos(row, col - 1);
133 break;
135 case '\n':
136 if (row < VGA_TEXT_ROWS - 1)
137 vga_setpos(row + 1, col);
138 else
139 vga_scroll(cons_color);
140 break;
142 default:
143 vga_drawc(c, cons_color);
144 if (col < VGA_TEXT_COLS -1)
145 vga_setpos(row, col + 1);
146 else if (row < VGA_TEXT_ROWS - 1)
147 vga_setpos(row + 1, 0);
148 else {
149 vga_setpos(row, 0);
150 vga_scroll(cons_color);
152 break;
156 static int port;
158 static void
159 serial_init(void)
161 port = tty_addr[tty_num];
163 outb(port + ISR, 0x20);
164 if (inb(port + ISR) & 0x20) {
166 * 82510 chip is present
168 outb(port + DAT+7, 0x04); /* clear status */
169 outb(port + ISR, 0x40); /* set to bank 2 */
170 outb(port + MCR, 0x08); /* IMD */
171 outb(port + DAT, 0x21); /* FMD */
172 outb(port + ISR, 0x00); /* set to bank 0 */
173 } else {
175 * set the UART in FIFO mode if it has FIFO buffers.
176 * use 16550 fifo reset sequence specified in NS
177 * application note. disable fifos until chip is
178 * initialized.
180 outb(port + FIFOR, 0x00); /* clear */
181 outb(port + FIFOR, FIFO_ON); /* enable */
182 outb(port + FIFOR, FIFO_ON|FIFORXFLSH); /* reset */
183 outb(port + FIFOR,
184 FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80);
185 if ((inb(port + ISR) & 0xc0) != 0xc0) {
187 * no fifo buffers so disable fifos.
188 * this is true for 8250's
190 outb(port + FIFOR, 0x00);
194 /* disable interrupts */
195 outb(port + ICR, 0);
197 #if !defined(_BOOT)
198 if (IN_XPV_PANIC())
199 return;
200 #endif
202 /* adjust setting based on tty properties */
203 serial_adjust_prop();
205 #if defined(_BOOT)
207 * Do a full reset to match console behavior.
208 * 0x1B + c - reset everything
210 serial_putchar(0x1B);
211 serial_putchar('c');
212 #endif
215 /* Advance str pointer past white space */
216 #define EAT_WHITE_SPACE(str) { \
217 while ((*str != '\0') && ISSPACE(*str)) \
218 str++; \
222 * boot_line is set when we call here. Search it for the argument name,
223 * and if found, return a pointer to it.
225 static char *
226 find_boot_line_prop(const char *name)
228 char *ptr;
229 char *ret = NULL;
230 char end_char;
231 size_t len;
233 if (boot_line == NULL)
234 return (NULL);
236 len = strlen(name);
239 * We have two nested loops here: the outer loop discards all options
240 * except -B, and the inner loop parses the -B options looking for
241 * the one we're interested in.
243 for (ptr = boot_line; *ptr != '\0'; ptr++) {
244 EAT_WHITE_SPACE(ptr);
246 if (*ptr == '-') {
247 ptr++;
248 while ((*ptr != '\0') && (*ptr != 'B') &&
249 !ISSPACE(*ptr))
250 ptr++;
251 if (*ptr == '\0')
252 goto out;
253 else if (*ptr != 'B')
254 continue;
255 } else {
256 while ((*ptr != '\0') && !ISSPACE(*ptr))
257 ptr++;
258 if (*ptr == '\0')
259 goto out;
260 continue;
263 do {
264 ptr++;
265 EAT_WHITE_SPACE(ptr);
267 if ((strncmp(ptr, name, len) == 0) &&
268 (ptr[len] == '=')) {
269 ptr += len + 1;
270 if ((*ptr == '\'') || (*ptr == '"')) {
271 ret = ptr + 1;
272 end_char = *ptr;
273 ptr++;
274 } else {
275 ret = ptr;
276 end_char = ',';
278 goto consume_property;
282 * We have a property, and it's not the one we're
283 * interested in. Skip the property name. A name
284 * can end with '=', a comma, or white space.
286 while ((*ptr != '\0') && (*ptr != '=') &&
287 (*ptr != ',') && (!ISSPACE(*ptr)))
288 ptr++;
291 * We only want to go through the rest of the inner
292 * loop if we have a comma. If we have a property
293 * name without a value, either continue or break.
295 if (*ptr == '\0')
296 goto out;
297 else if (*ptr == ',')
298 continue;
299 else if (ISSPACE(*ptr))
300 break;
301 ptr++;
304 * Is the property quoted?
306 if ((*ptr == '\'') || (*ptr == '"')) {
307 end_char = *ptr;
308 ptr++;
309 } else {
311 * Not quoted, so the string ends at a comma
312 * or at white space. Deal with white space
313 * later.
315 end_char = ',';
319 * Now, we can ignore any characters until we find
320 * end_char.
322 consume_property:
323 for (; (*ptr != '\0') && (*ptr != end_char); ptr++) {
324 if ((end_char == ',') && ISSPACE(*ptr))
325 break;
327 if (*ptr && (*ptr != ',') && !ISSPACE(*ptr))
328 ptr++;
329 } while (*ptr == ',');
331 out:
332 return (ret);
336 * Find prop from boot env module. The data in module is list of C strings
337 * name=value, the list is terminated by double nul.
339 static const char *
340 find_boot_env_prop(const char *name)
342 char *ptr;
343 size_t len;
344 uintptr_t size;
346 if (boot_env.be_env == NULL)
347 return (NULL);
349 ptr = boot_env.be_env;
350 len = strlen(name);
353 * Make sure we have at least len + 2 bytes in the environment.
354 * We are looking for name=value\0 constructs, and the environment
355 * itself is terminated by '\0'.
357 if (boot_env.be_size < len + 2)
358 return (NULL);
360 do {
361 if ((strncmp(ptr, name, len) == 0) && (ptr[len] == '=')) {
362 ptr += len + 1;
363 return (ptr);
365 /* find the first '\0' */
366 while (*ptr != '\0') {
367 ptr++;
368 size = (uintptr_t)ptr - (uintptr_t)boot_env.be_env;
369 if (size > boot_env.be_size)
370 return (NULL);
372 ptr++;
374 /* If the remainder is shorter than name + 2, get out. */
375 size = (uintptr_t)ptr - (uintptr_t)boot_env.be_env;
376 if (boot_env.be_size - size < len + 2)
377 return (NULL);
378 } while (*ptr != '\0');
379 return (NULL);
383 * Get prop value from either command line or boot environment.
384 * We always check kernel command line first, as this will keep the
385 * functionality and will allow user to override the values in environment.
387 const char *
388 find_boot_prop(const char *name)
390 const char *value = find_boot_line_prop(name);
392 if (value == NULL)
393 value = find_boot_env_prop(name);
394 return (value);
397 #define MATCHES(p, pat) \
398 (strncmp(p, pat, strlen(pat)) == 0 ? (p += strlen(pat), 1) : 0)
400 #define SKIP(p, c) \
401 while (*(p) != 0 && *p != (c)) \
402 ++(p); \
403 if (*(p) == (c)) \
404 ++(p);
407 * find a tty mode property either from cmdline or from boot properties
409 static const char *
410 get_mode_value(char *name)
413 * when specified on boot line it looks like "name" "="....
415 if (boot_line != NULL) {
416 return (find_boot_prop(name));
419 #if defined(_BOOT)
420 return (NULL);
421 #else
423 * if we're running in the full kernel we check the bootenv.rc settings
426 static char propval[20];
428 propval[0] = 0;
429 if (do_bsys_getproplen(NULL, name) <= 0)
430 return (NULL);
431 (void) do_bsys_getprop(NULL, name, propval);
432 return (propval);
434 #endif
438 * adjust serial port based on properties
439 * These come either from the cmdline or from boot properties.
441 static void
442 serial_adjust_prop(void)
444 char propname[20];
445 const char *propval;
446 const char *p;
447 ulong_t baud;
448 uchar_t lcr = 0;
449 uchar_t mcr = DTR | RTS;
451 (void) strcpy(propname, "ttyX-mode");
452 propname[3] = 'a' + tty_num;
453 propval = get_mode_value(propname);
454 if (propval == NULL)
455 propval = "9600,8,n,1,-";
456 #if !defined(_BOOT)
457 else
458 console_mode_set = 1;
459 #endif
461 /* property is of the form: "9600,8,n,1,-" */
462 p = propval;
463 if (MATCHES(p, "110,"))
464 baud = ASY110;
465 else if (MATCHES(p, "150,"))
466 baud = ASY150;
467 else if (MATCHES(p, "300,"))
468 baud = ASY300;
469 else if (MATCHES(p, "600,"))
470 baud = ASY600;
471 else if (MATCHES(p, "1200,"))
472 baud = ASY1200;
473 else if (MATCHES(p, "2400,"))
474 baud = ASY2400;
475 else if (MATCHES(p, "4800,"))
476 baud = ASY4800;
477 else if (MATCHES(p, "19200,"))
478 baud = ASY19200;
479 else if (MATCHES(p, "38400,"))
480 baud = ASY38400;
481 else if (MATCHES(p, "57600,"))
482 baud = ASY57600;
483 else if (MATCHES(p, "115200,"))
484 baud = ASY115200;
485 else {
486 baud = ASY9600;
487 SKIP(p, ',');
489 outb(port + LCR, DLAB);
490 outb(port + DAT + DLL, baud & 0xff);
491 outb(port + DAT + DLH, (baud >> 8) & 0xff);
493 switch (*p) {
494 case '5':
495 lcr |= BITS5;
496 ++p;
497 break;
498 case '6':
499 lcr |= BITS6;
500 ++p;
501 break;
502 case '7':
503 lcr |= BITS7;
504 ++p;
505 break;
506 case '8':
507 ++p;
508 default:
509 lcr |= BITS8;
510 break;
513 SKIP(p, ',');
515 switch (*p) {
516 case 'n':
517 lcr |= PARITY_NONE;
518 ++p;
519 break;
520 case 'o':
521 lcr |= PARITY_ODD;
522 ++p;
523 break;
524 case 'e':
525 ++p;
526 default:
527 lcr |= PARITY_EVEN;
528 break;
532 SKIP(p, ',');
534 switch (*p) {
535 case '1':
536 /* STOP1 is 0 */
537 ++p;
538 break;
539 default:
540 lcr |= STOP2;
541 break;
543 /* set parity bits */
544 outb(port + LCR, lcr);
546 (void) strcpy(propname, "ttyX-rts-dtr-off");
547 propname[3] = 'a' + tty_num;
548 propval = get_mode_value(propname);
549 if (propval == NULL)
550 propval = "false";
551 if (propval[0] != 'f' && propval[0] != 'F')
552 mcr = 0;
553 /* set modem control bits */
554 outb(port + MCR, mcr | OUT2);
557 /* Obtain the console type */
559 boot_console_type(int *tnum)
561 if (tnum != NULL)
562 *tnum = tty_num;
563 return (console);
567 * A structure to map console names to values.
569 typedef struct {
570 char *name;
571 int value;
572 } console_value_t;
574 console_value_t console_devices[] = {
575 { "ttya", CONS_TTY }, /* 0 */
576 { "ttyb", CONS_TTY }, /* 1 */
577 { "ttyc", CONS_TTY }, /* 2 */
578 { "ttyd", CONS_TTY }, /* 3 */
579 { "text", CONS_SCREEN_TEXT },
580 { "graphics", CONS_SCREEN_GRAPHICS },
581 #if defined(__xpv)
582 { "hypervisor", CONS_HYPERVISOR },
583 #endif
584 #if !defined(_BOOT)
585 { "usb-serial", CONS_USBSER },
586 #endif
587 { NULL, CONS_INVALID }
590 static void
591 bcons_init_env(struct xboot_info *xbi)
593 uint32_t i;
594 struct boot_modules *modules;
596 modules = (struct boot_modules *)(uintptr_t)xbi->bi_modules;
597 for (i = 0; i < xbi->bi_module_cnt; i++) {
598 if (modules[i].bm_type == BMT_ENV)
599 break;
601 if (i == xbi->bi_module_cnt)
602 return;
604 boot_env.be_env = (char *)(uintptr_t)modules[i].bm_addr;
605 boot_env.be_size = modules[i].bm_size;
608 void
609 bcons_init(struct xboot_info *xbi)
611 console_value_t *consolep;
612 size_t len, cons_len;
613 const char *cons_str;
614 #if !defined(_BOOT)
615 static char console_text[] = "text";
616 extern int post_fastreboot;
617 #endif
619 /* Set up data to fetch properties from commad line and boot env. */
620 boot_line = (char *)(uintptr_t)xbi->bi_cmdline;
621 bcons_init_env(xbi);
622 console = CONS_INVALID;
624 #if defined(__xpv)
625 bcons_init_xen(boot_line);
626 #endif /* __xpv */
628 cons_str = find_boot_prop("console");
629 if (cons_str == NULL)
630 cons_str = find_boot_prop("output-device");
632 #if !defined(_BOOT)
633 if (post_fastreboot && strcmp(cons_str, "graphics") == 0)
634 cons_str = console_text;
635 #endif
638 * Go through the console_devices array trying to match the string
639 * we were given. The string on the command line must end with
640 * a comma or white space.
642 if (cons_str != NULL) {
643 int n;
645 cons_len = strlen(cons_str);
646 for (n = 0; console_devices[n].name != NULL; n++) {
647 consolep = &console_devices[n];
648 len = strlen(consolep->name);
649 if ((len <= cons_len) && ((cons_str[len] == '\0') ||
650 (cons_str[len] == ',') || (cons_str[len] == '\'') ||
651 (cons_str[len] == '"') || ISSPACE(cons_str[len])) &&
652 (strncmp(cons_str, consolep->name, len) == 0)) {
653 console = consolep->value;
654 if (console == CONS_TTY)
655 tty_num = n;
656 break;
661 #if defined(__xpv)
663 * domU's always use the hypervisor regardless of what
664 * the console variable may be set to.
666 if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
667 console = CONS_HYPERVISOR;
668 console_hypervisor_redirect = B_TRUE;
670 #endif /* __xpv */
673 * If no console device specified, default to text.
674 * Remember what was specified for second phase.
676 if (console == CONS_INVALID)
677 console = CONS_SCREEN_TEXT;
678 #if !defined(_BOOT)
679 else
680 console_set = 1;
681 #endif
683 #if defined(__xpv)
684 if (DOMAIN_IS_INITDOMAIN(xen_info)) {
685 switch (HYPERVISOR_console_io(CONSOLEIO_get_device, 0, NULL)) {
686 case XEN_CONSOLE_COM1:
687 case XEN_CONSOLE_COM2:
688 console_hypervisor_device = CONS_TTY;
689 console_hypervisor_tty_num = tty_num;
690 break;
691 case XEN_CONSOLE_VGA:
693 * Currently xen doesn't really support
694 * keyboard/display console devices.
695 * What this setting means is that
696 * "vga=keep" has been enabled, which is
697 * more of a xen debugging tool that a
698 * true console mode. Hence, we're going
699 * to ignore this xen "console" setting.
701 /*FALLTHROUGH*/
702 default:
703 console_hypervisor_device = CONS_INVALID;
708 * if the hypervisor is using the currently selected serial
709 * port then default to using the hypervisor as the console
710 * device.
712 if (console == console_hypervisor_device) {
713 console = CONS_HYPERVISOR;
714 console_hypervisor_redirect = B_TRUE;
716 #endif /* __xpv */
718 switch (console) {
719 case CONS_TTY:
720 serial_init();
721 break;
723 case CONS_HYPERVISOR:
724 break;
726 #if !defined(_BOOT)
727 case CONS_USBSER:
729 * We can't do anything with the usb serial
730 * until we have memory management.
732 break;
733 #endif
734 case CONS_SCREEN_GRAPHICS:
735 kb_init();
736 break;
737 case CONS_SCREEN_TEXT:
738 default:
739 #if defined(_BOOT)
740 clear_screen(); /* clears the grub or xen screen */
741 #endif /* _BOOT */
742 kb_init();
743 break;
747 #if !defined(_BOOT)
749 * 2nd part of console initialization.
750 * In the kernel (ie. fakebop), this can be used only to switch to
751 * using a serial port instead of screen based on the contents
752 * of the bootenv.rc file.
754 /*ARGSUSED*/
755 void
756 bcons_init2(char *inputdev, char *outputdev, char *consoledev)
758 int cons = CONS_INVALID;
759 int ttyn;
760 char *devnames[] = { consoledev, outputdev, inputdev, NULL };
761 console_value_t *consolep;
762 int i;
763 extern int post_fastreboot;
765 if (post_fastreboot && console == CONS_SCREEN_GRAPHICS)
766 console = CONS_SCREEN_TEXT;
768 if (console != CONS_USBSER && console != CONS_SCREEN_GRAPHICS) {
769 if (console_set) {
771 * If the console was set on the command line,
772 * but the ttyX-mode was not, we only need to
773 * check bootenv.rc for that setting.
775 if ((!console_mode_set) && (console == CONS_TTY))
776 serial_init();
777 return;
780 for (i = 0; devnames[i] != NULL; i++) {
781 int n;
783 for (n = 0; console_devices[n].name != NULL; n++) {
784 consolep = &console_devices[n];
785 if (strcmp(devnames[i], consolep->name) == 0) {
786 cons = consolep->value;
787 if (cons == CONS_TTY)
788 ttyn = n;
791 if (cons != CONS_INVALID)
792 break;
795 #if defined(__xpv)
797 * if the hypervisor is using the currently selected console
798 * device then default to using the hypervisor as the console
799 * device.
801 if (cons == console_hypervisor_device) {
802 cons = CONS_HYPERVISOR;
803 console_hypervisor_redirect = B_TRUE;
805 #endif /* __xpv */
807 if ((cons == CONS_INVALID) || (cons == console)) {
809 * we're sticking with whatever the current setting is
811 return;
814 console = cons;
815 if (cons == CONS_TTY) {
816 tty_num = ttyn;
817 serial_init();
818 return;
820 } else {
822 * USB serial and GRAPHICS console
823 * we just collect data into a buffer
825 extern void *defcons_init(size_t);
826 defcons_buf = defcons_cur = defcons_init(MMU_PAGESIZE);
830 #if defined(__xpv)
831 boolean_t
832 bcons_hypervisor_redirect(void)
834 return (console_hypervisor_redirect);
837 void
838 bcons_device_change(int new_console)
840 if (new_console < CONS_MIN || new_console > CONS_MAX)
841 return;
844 * If we are asked to switch the console to the hypervisor, that
845 * really means to switch the console to whichever device the
846 * hypervisor is/was using.
848 if (new_console == CONS_HYPERVISOR)
849 new_console = console_hypervisor_device;
851 console = new_console;
853 if (new_console == CONS_TTY) {
854 tty_num = console_hypervisor_tty_num;
855 serial_init();
858 #endif /* __xpv */
860 static void
861 defcons_putchar(int c)
863 if (defcons_buf != NULL &&
864 defcons_cur + 1 - defcons_buf < MMU_PAGESIZE) {
865 *defcons_cur++ = c;
866 *defcons_cur = 0;
869 #endif /* _BOOT */
871 static void
872 serial_putchar(int c)
874 int checks = 10000;
876 while (((inb(port + LSR) & XHRE) == 0) && checks--)
878 outb(port + DAT, (char)c);
881 static int
882 serial_getchar(void)
884 uchar_t lsr;
886 while (serial_ischar() == 0)
889 lsr = inb(port + LSR);
890 if (lsr & (SERIAL_BREAK | SERIAL_FRAME |
891 SERIAL_PARITY | SERIAL_OVERRUN)) {
892 if (lsr & SERIAL_OVERRUN) {
893 return (inb(port + DAT));
894 } else {
895 /* Toss the garbage */
896 (void) inb(port + DAT);
897 return (0);
900 return (inb(port + DAT));
903 static int
904 serial_ischar(void)
906 return (inb(port + LSR) & RCA);
909 static void
910 _doputchar(int c)
912 switch (console) {
913 case CONS_TTY:
914 serial_putchar(c);
915 return;
916 case CONS_SCREEN_TEXT:
917 screen_putchar(c);
918 return;
919 case CONS_SCREEN_GRAPHICS:
920 #if !defined(_BOOT)
921 case CONS_USBSER:
922 defcons_putchar(c);
923 #endif /* _BOOT */
924 return;
928 void
929 bcons_putchar(int c)
931 static int bhcharpos = 0;
933 #if defined(__xpv)
934 if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
935 console == CONS_HYPERVISOR) {
936 bcons_putchar_xen(c);
937 return;
939 #endif /* __xpv */
941 if (c == '\t') {
942 do {
943 _doputchar(' ');
944 } while (++bhcharpos % 8);
945 return;
946 } else if (c == '\n' || c == '\r') {
947 bhcharpos = 0;
948 _doputchar('\r');
949 _doputchar(c);
950 return;
951 } else if (c == '\b') {
952 if (bhcharpos)
953 bhcharpos--;
954 _doputchar(c);
955 return;
958 bhcharpos++;
959 _doputchar(c);
963 * kernel character input functions
966 bcons_getchar(void)
968 #if defined(__xpv)
969 if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
970 console == CONS_HYPERVISOR)
971 return (bcons_getchar_xen());
972 #endif /* __xpv */
974 switch (console) {
975 case CONS_TTY:
976 return (serial_getchar());
977 default:
978 return (kb_getchar());
982 #if !defined(_BOOT)
985 bcons_ischar(void)
988 #if defined(__xpv)
989 if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
990 console == CONS_HYPERVISOR)
991 return (bcons_ischar_xen());
992 #endif /* __xpv */
994 switch (console) {
995 case CONS_TTY:
996 return (serial_ischar());
997 default:
998 return (kb_ischar());
1002 #endif /* _BOOT */