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 /* 220d928757SGary Mills * Copyright (c) 2012 Gary Mills 230d928757SGary 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; 610d928757SGary Mills static int console = CONS_SCREEN_TEXT; 620d928757SGary Mills static int tty_num = 0; 630d928757SGary Mills static int tty_addr[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8}; 64*b9a86732SToomas Soome static char *boot_line; 65*b9a86732SToomas Soome static struct boot_env { 66*b9a86732SToomas Soome char *be_env; /* ends with double ascii nul */ 67*b9a86732SToomas Soome size_t be_size; /* size of the environment, including nul */ 68*b9a86732SToomas Soome } boot_env; 69*b9a86732SToomas Soome 70*b9a86732SToomas Soome static int serial_ischar(void); 71*b9a86732SToomas Soome static int serial_getchar(void); 72*b9a86732SToomas Soome static void serial_putchar(int); 73*b9a86732SToomas Soome static void serial_adjust_prop(void); 74*b9a86732SToomas Soome 75*b9a86732SToomas Soome #if !defined(_BOOT) 76*b9a86732SToomas Soome /* Set if the console or mode are expressed in the boot line */ 77*b9a86732SToomas Soome static int console_set, console_mode_set; 78*b9a86732SToomas Soome #endif 79*b9a86732SToomas Soome 80843e1988Sjohnlev #if defined(__xpv) 81843e1988Sjohnlev static int console_hypervisor_redirect = B_FALSE; 820d928757SGary Mills static int console_hypervisor_device = CONS_INVALID; 830d928757SGary Mills static int console_hypervisor_tty_num = 0; 840d928757SGary Mills 850d928757SGary Mills /* Obtain the hypervisor console type */ 860d928757SGary Mills int 870d928757SGary Mills console_hypervisor_dev_type(int *tnum) 880d928757SGary Mills { 890d928757SGary Mills if (tnum != NULL) 900d928757SGary Mills *tnum = console_hypervisor_tty_num; 910d928757SGary Mills return (console_hypervisor_device); 920d928757SGary Mills } 93843e1988Sjohnlev #endif /* __xpv */ 94843e1988Sjohnlev 95ae115bc7Smrj /* Clear the screen and initialize VIDEO, XPOS and YPOS. */ 96843e1988Sjohnlev void 97ae115bc7Smrj clear_screen(void) 98ae115bc7Smrj { 99ae115bc7Smrj /* 100ae115bc7Smrj * XXX should set vga mode so we don't depend on the 101843e1988Sjohnlev * state left by the boot loader. Note that we have to 102843e1988Sjohnlev * enable the cursor before clearing the screen since 103843e1988Sjohnlev * the cursor position is dependant upon the cursor 104843e1988Sjohnlev * skew, which is initialized by vga_cursor_display() 105ae115bc7Smrj */ 106843e1988Sjohnlev vga_cursor_display(); 107ae115bc7Smrj vga_clear(cons_color); 108ae115bc7Smrj vga_setpos(0, 0); 109ae115bc7Smrj } 110ae115bc7Smrj 111ae115bc7Smrj /* Put the character C on the screen. */ 112ae115bc7Smrj static void 113ae115bc7Smrj screen_putchar(int c) 114ae115bc7Smrj { 115ae115bc7Smrj int row, col; 116ae115bc7Smrj 117ae115bc7Smrj vga_getpos(&row, &col); 118ae115bc7Smrj switch (c) { 119ae115bc7Smrj case '\t': 120ae115bc7Smrj col += 8 - (col % 8); 121ae115bc7Smrj if (col == VGA_TEXT_COLS) 122ae115bc7Smrj col = 79; 123ae115bc7Smrj vga_setpos(row, col); 124ae115bc7Smrj break; 125ae115bc7Smrj 126ae115bc7Smrj case '\r': 127ae115bc7Smrj vga_setpos(row, 0); 128ae115bc7Smrj break; 129ae115bc7Smrj 130ae115bc7Smrj case '\b': 131ae115bc7Smrj if (col > 0) 132ae115bc7Smrj vga_setpos(row, col - 1); 133ae115bc7Smrj break; 134ae115bc7Smrj 135ae115bc7Smrj case '\n': 136ae115bc7Smrj if (row < VGA_TEXT_ROWS - 1) 137ae115bc7Smrj vga_setpos(row + 1, col); 138ae115bc7Smrj else 139ae115bc7Smrj vga_scroll(cons_color); 140ae115bc7Smrj break; 141ae115bc7Smrj 142ae115bc7Smrj default: 143ae115bc7Smrj vga_drawc(c, cons_color); 144ae115bc7Smrj if (col < VGA_TEXT_COLS -1) 145ae115bc7Smrj vga_setpos(row, col + 1); 146ae115bc7Smrj else if (row < VGA_TEXT_ROWS - 1) 147ae115bc7Smrj vga_setpos(row + 1, 0); 148ae115bc7Smrj else { 149ae115bc7Smrj vga_setpos(row, 0); 150ae115bc7Smrj vga_scroll(cons_color); 151ae115bc7Smrj } 152ae115bc7Smrj break; 153ae115bc7Smrj } 154ae115bc7Smrj } 155ae115bc7Smrj 156ae115bc7Smrj static int port; 157ae115bc7Smrj 158ae115bc7Smrj static void 159ae115bc7Smrj serial_init(void) 160ae115bc7Smrj { 1610d928757SGary Mills port = tty_addr[tty_num]; 162ae115bc7Smrj 163ae115bc7Smrj outb(port + ISR, 0x20); 164ae115bc7Smrj if (inb(port + ISR) & 0x20) { 165ae115bc7Smrj /* 166ae115bc7Smrj * 82510 chip is present 167ae115bc7Smrj */ 168ae115bc7Smrj outb(port + DAT+7, 0x04); /* clear status */ 169ae115bc7Smrj outb(port + ISR, 0x40); /* set to bank 2 */ 170ae115bc7Smrj outb(port + MCR, 0x08); /* IMD */ 171ae115bc7Smrj outb(port + DAT, 0x21); /* FMD */ 172ae115bc7Smrj outb(port + ISR, 0x00); /* set to bank 0 */ 173ae115bc7Smrj } else { 174ae115bc7Smrj /* 175ae115bc7Smrj * set the UART in FIFO mode if it has FIFO buffers. 176ae115bc7Smrj * use 16550 fifo reset sequence specified in NS 177ae115bc7Smrj * application note. disable fifos until chip is 178ae115bc7Smrj * initialized. 179ae115bc7Smrj */ 180ae115bc7Smrj outb(port + FIFOR, 0x00); /* clear */ 181ae115bc7Smrj outb(port + FIFOR, FIFO_ON); /* enable */ 182ae115bc7Smrj outb(port + FIFOR, FIFO_ON|FIFORXFLSH); /* reset */ 183ae115bc7Smrj outb(port + FIFOR, 184ae115bc7Smrj FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80); 185ae115bc7Smrj if ((inb(port + ISR) & 0xc0) != 0xc0) { 186ae115bc7Smrj /* 187ae115bc7Smrj * no fifo buffers so disable fifos. 188ae115bc7Smrj * this is true for 8250's 189ae115bc7Smrj */ 190ae115bc7Smrj outb(port + FIFOR, 0x00); 191ae115bc7Smrj } 192ae115bc7Smrj } 193ae115bc7Smrj 194ae115bc7Smrj /* disable interrupts */ 195ae115bc7Smrj outb(port + ICR, 0); 196ae115bc7Smrj 197843e1988Sjohnlev #if !defined(_BOOT) 198843e1988Sjohnlev if (IN_XPV_PANIC()) 199843e1988Sjohnlev return; 200843e1988Sjohnlev #endif 201843e1988Sjohnlev 202ae115bc7Smrj /* adjust setting based on tty properties */ 203ae115bc7Smrj serial_adjust_prop(); 204ae115bc7Smrj 205ae115bc7Smrj #if defined(_BOOT) 206ae115bc7Smrj /* 207ae115bc7Smrj * Do a full reset to match console behavior. 208ae115bc7Smrj * 0x1B + c - reset everything 209ae115bc7Smrj */ 210ae115bc7Smrj serial_putchar(0x1B); 211ae115bc7Smrj serial_putchar('c'); 212ae115bc7Smrj #endif 213ae115bc7Smrj } 214ae115bc7Smrj 215adb91f47Srscott /* Advance str pointer past white space */ 216adb91f47Srscott #define EAT_WHITE_SPACE(str) { \ 217adb91f47Srscott while ((*str != '\0') && ISSPACE(*str)) \ 218adb91f47Srscott str++; \ 219adb91f47Srscott } 220adb91f47Srscott 221adb91f47Srscott /* 222adb91f47Srscott * boot_line is set when we call here. Search it for the argument name, 223adb91f47Srscott * and if found, return a pointer to it. 224adb91f47Srscott */ 225adb91f47Srscott static char * 226adb91f47Srscott find_boot_line_prop(const char *name) 227adb91f47Srscott { 228adb91f47Srscott char *ptr; 229c6d6228cSEnrico Perla - Sun Microsystems char *ret = NULL; 230adb91f47Srscott char end_char; 231adb91f47Srscott size_t len; 232adb91f47Srscott 233adb91f47Srscott if (boot_line == NULL) 234adb91f47Srscott return (NULL); 235adb91f47Srscott 236adb91f47Srscott len = strlen(name); 237adb91f47Srscott 238adb91f47Srscott /* 239adb91f47Srscott * We have two nested loops here: the outer loop discards all options 240adb91f47Srscott * except -B, and the inner loop parses the -B options looking for 241adb91f47Srscott * the one we're interested in. 242adb91f47Srscott */ 243adb91f47Srscott for (ptr = boot_line; *ptr != '\0'; ptr++) { 244adb91f47Srscott EAT_WHITE_SPACE(ptr); 245adb91f47Srscott 246adb91f47Srscott if (*ptr == '-') { 247adb91f47Srscott ptr++; 248adb91f47Srscott while ((*ptr != '\0') && (*ptr != 'B') && 249adb91f47Srscott !ISSPACE(*ptr)) 250adb91f47Srscott ptr++; 251adb91f47Srscott if (*ptr == '\0') 252c6d6228cSEnrico Perla - Sun Microsystems goto out; 253adb91f47Srscott else if (*ptr != 'B') 254adb91f47Srscott continue; 255adb91f47Srscott } else { 256adb91f47Srscott while ((*ptr != '\0') && !ISSPACE(*ptr)) 257adb91f47Srscott ptr++; 258adb91f47Srscott if (*ptr == '\0') 259c6d6228cSEnrico Perla - Sun Microsystems goto out; 260adb91f47Srscott continue; 261adb91f47Srscott } 262adb91f47Srscott 263adb91f47Srscott do { 264adb91f47Srscott ptr++; 265adb91f47Srscott EAT_WHITE_SPACE(ptr); 266adb91f47Srscott 267adb91f47Srscott if ((strncmp(ptr, name, len) == 0) && 268adb91f47Srscott (ptr[len] == '=')) { 269adb91f47Srscott ptr += len + 1; 270c6d6228cSEnrico Perla - Sun Microsystems if ((*ptr == '\'') || (*ptr == '"')) { 271c6d6228cSEnrico Perla - Sun Microsystems ret = ptr + 1; 272c6d6228cSEnrico Perla - Sun Microsystems end_char = *ptr; 273c6d6228cSEnrico Perla - Sun Microsystems ptr++; 274c6d6228cSEnrico Perla - Sun Microsystems } else { 275c6d6228cSEnrico Perla - Sun Microsystems ret = ptr; 276c6d6228cSEnrico Perla - Sun Microsystems end_char = ','; 277c6d6228cSEnrico Perla - Sun Microsystems } 278c6d6228cSEnrico Perla - Sun Microsystems goto consume_property; 279adb91f47Srscott } 280adb91f47Srscott 281adb91f47Srscott /* 282adb91f47Srscott * We have a property, and it's not the one we're 283adb91f47Srscott * interested in. Skip the property name. A name 284adb91f47Srscott * can end with '=', a comma, or white space. 285adb91f47Srscott */ 286adb91f47Srscott while ((*ptr != '\0') && (*ptr != '=') && 287adb91f47Srscott (*ptr != ',') && (!ISSPACE(*ptr))) 288adb91f47Srscott ptr++; 289adb91f47Srscott 290adb91f47Srscott /* 291adb91f47Srscott * We only want to go through the rest of the inner 292adb91f47Srscott * loop if we have a comma. If we have a property 293adb91f47Srscott * name without a value, either continue or break. 294adb91f47Srscott */ 295adb91f47Srscott if (*ptr == '\0') 296c6d6228cSEnrico Perla - Sun Microsystems goto out; 297adb91f47Srscott else if (*ptr == ',') 298adb91f47Srscott continue; 299adb91f47Srscott else if (ISSPACE(*ptr)) 300adb91f47Srscott break; 301adb91f47Srscott ptr++; 302adb91f47Srscott 303adb91f47Srscott /* 304adb91f47Srscott * Is the property quoted? 305adb91f47Srscott */ 306adb91f47Srscott if ((*ptr == '\'') || (*ptr == '"')) { 307adb91f47Srscott end_char = *ptr; 308c6d6228cSEnrico Perla - Sun Microsystems ptr++; 309adb91f47Srscott } else { 310adb91f47Srscott /* 311adb91f47Srscott * Not quoted, so the string ends at a comma 312adb91f47Srscott * or at white space. Deal with white space 313adb91f47Srscott * later. 314adb91f47Srscott */ 315adb91f47Srscott end_char = ','; 316adb91f47Srscott } 317adb91f47Srscott 318adb91f47Srscott /* 319adb91f47Srscott * Now, we can ignore any characters until we find 320adb91f47Srscott * end_char. 321adb91f47Srscott */ 322c6d6228cSEnrico Perla - Sun Microsystems consume_property: 323adb91f47Srscott for (; (*ptr != '\0') && (*ptr != end_char); ptr++) { 324adb91f47Srscott if ((end_char == ',') && ISSPACE(*ptr)) 325adb91f47Srscott break; 326adb91f47Srscott } 327c6d6228cSEnrico Perla - Sun Microsystems if (*ptr && (*ptr != ',') && !ISSPACE(*ptr)) 328adb91f47Srscott ptr++; 329adb91f47Srscott } while (*ptr == ','); 330adb91f47Srscott } 331c6d6228cSEnrico Perla - Sun Microsystems out: 332c6d6228cSEnrico Perla - Sun Microsystems return (ret); 333adb91f47Srscott } 334adb91f47Srscott 335*b9a86732SToomas Soome /* 336*b9a86732SToomas Soome * Find prop from boot env module. The data in module is list of C strings 337*b9a86732SToomas Soome * name=value, the list is terminated by double nul. 338*b9a86732SToomas Soome */ 339*b9a86732SToomas Soome static const char * 340*b9a86732SToomas Soome find_boot_env_prop(const char *name) 341*b9a86732SToomas Soome { 342*b9a86732SToomas Soome char *ptr; 343*b9a86732SToomas Soome size_t len; 344*b9a86732SToomas Soome uintptr_t size; 345*b9a86732SToomas Soome 346*b9a86732SToomas Soome if (boot_env.be_env == NULL) 347*b9a86732SToomas Soome return (NULL); 348*b9a86732SToomas Soome 349*b9a86732SToomas Soome ptr = boot_env.be_env; 350*b9a86732SToomas Soome len = strlen(name); 351*b9a86732SToomas Soome 352*b9a86732SToomas Soome /* 353*b9a86732SToomas Soome * Make sure we have at least len + 2 bytes in the environment. 354*b9a86732SToomas Soome * We are looking for name=value\0 constructs, and the environment 355*b9a86732SToomas Soome * itself is terminated by '\0'. 356*b9a86732SToomas Soome */ 357*b9a86732SToomas Soome if (boot_env.be_size < len + 2) 358*b9a86732SToomas Soome return (NULL); 359*b9a86732SToomas Soome 360*b9a86732SToomas Soome do { 361*b9a86732SToomas Soome if ((strncmp(ptr, name, len) == 0) && (ptr[len] == '=')) { 362*b9a86732SToomas Soome ptr += len + 1; 363*b9a86732SToomas Soome return (ptr); 364*b9a86732SToomas Soome } 365*b9a86732SToomas Soome /* find the first '\0' */ 366*b9a86732SToomas Soome while (*ptr != '\0') { 367*b9a86732SToomas Soome ptr++; 368*b9a86732SToomas Soome size = (uintptr_t)ptr - (uintptr_t)boot_env.be_env; 369*b9a86732SToomas Soome if (size > boot_env.be_size) 370*b9a86732SToomas Soome return (NULL); 371*b9a86732SToomas Soome } 372*b9a86732SToomas Soome ptr++; 373*b9a86732SToomas Soome 374*b9a86732SToomas Soome /* If the remainder is shorter than name + 2, get out. */ 375*b9a86732SToomas Soome size = (uintptr_t)ptr - (uintptr_t)boot_env.be_env; 376*b9a86732SToomas Soome if (boot_env.be_size - size < len + 2) 377*b9a86732SToomas Soome return (NULL); 378*b9a86732SToomas Soome } while (*ptr != '\0'); 379*b9a86732SToomas Soome return (NULL); 380*b9a86732SToomas Soome } 381*b9a86732SToomas Soome 382*b9a86732SToomas Soome /* 383*b9a86732SToomas Soome * Get prop value from either command line or boot environment. 384*b9a86732SToomas Soome * We always check kernel command line first, as this will keep the 385*b9a86732SToomas Soome * functionality and will allow user to override the values in environment. 386*b9a86732SToomas Soome */ 387*b9a86732SToomas Soome const char * 388*b9a86732SToomas Soome find_boot_prop(const char *name) 389*b9a86732SToomas Soome { 390*b9a86732SToomas Soome const char *value = find_boot_line_prop(name); 391*b9a86732SToomas Soome 392*b9a86732SToomas Soome if (value == NULL) 393*b9a86732SToomas Soome value = find_boot_env_prop(name); 394*b9a86732SToomas Soome return (value); 395*b9a86732SToomas Soome } 396ae115bc7Smrj 397ae115bc7Smrj #define MATCHES(p, pat) \ 398ae115bc7Smrj (strncmp(p, pat, strlen(pat)) == 0 ? (p += strlen(pat), 1) : 0) 399ae115bc7Smrj 400ae115bc7Smrj #define SKIP(p, c) \ 401ae115bc7Smrj while (*(p) != 0 && *p != (c)) \ 402ae115bc7Smrj ++(p); \ 403ae115bc7Smrj if (*(p) == (c)) \ 404ae115bc7Smrj ++(p); 405ae115bc7Smrj 406ae115bc7Smrj /* 407ae115bc7Smrj * find a tty mode property either from cmdline or from boot properties 408ae115bc7Smrj */ 409*b9a86732SToomas Soome static const char * 410ae115bc7Smrj get_mode_value(char *name) 411ae115bc7Smrj { 412ae115bc7Smrj /* 413ae115bc7Smrj * when specified on boot line it looks like "name" "=".... 414ae115bc7Smrj */ 415ae115bc7Smrj if (boot_line != NULL) { 416*b9a86732SToomas Soome return (find_boot_prop(name)); 417ae115bc7Smrj } 418ae115bc7Smrj 419ae115bc7Smrj #if defined(_BOOT) 420ae115bc7Smrj return (NULL); 421ae115bc7Smrj #else 422ae115bc7Smrj /* 423ae115bc7Smrj * if we're running in the full kernel we check the bootenv.rc settings 424ae115bc7Smrj */ 425ae115bc7Smrj { 426ae115bc7Smrj static char propval[20]; 427ae115bc7Smrj 428ae115bc7Smrj propval[0] = 0; 429adb91f47Srscott if (do_bsys_getproplen(NULL, name) <= 0) 430ae115bc7Smrj return (NULL); 431adb91f47Srscott (void) do_bsys_getprop(NULL, name, propval); 432ae115bc7Smrj return (propval); 433ae115bc7Smrj } 434ae115bc7Smrj #endif 435ae115bc7Smrj } 436ae115bc7Smrj 437ae115bc7Smrj /* 438ae115bc7Smrj * adjust serial port based on properties 439ae115bc7Smrj * These come either from the cmdline or from boot properties. 440ae115bc7Smrj */ 441ae115bc7Smrj static void 442ae115bc7Smrj serial_adjust_prop(void) 443ae115bc7Smrj { 444ae115bc7Smrj char propname[20]; 445*b9a86732SToomas Soome const char *propval; 446*b9a86732SToomas Soome const char *p; 447ae115bc7Smrj ulong_t baud; 448ae115bc7Smrj uchar_t lcr = 0; 449ae115bc7Smrj uchar_t mcr = DTR | RTS; 450ae115bc7Smrj 451ae115bc7Smrj (void) strcpy(propname, "ttyX-mode"); 4520d928757SGary Mills propname[3] = 'a' + tty_num; 453ae115bc7Smrj propval = get_mode_value(propname); 454ae115bc7Smrj if (propval == NULL) 455ae115bc7Smrj propval = "9600,8,n,1,-"; 456843e1988Sjohnlev #if !defined(_BOOT) 457adb91f47Srscott else 458adb91f47Srscott console_mode_set = 1; 459843e1988Sjohnlev #endif 460ae115bc7Smrj 461ae115bc7Smrj /* property is of the form: "9600,8,n,1,-" */ 462ae115bc7Smrj p = propval; 463ae115bc7Smrj if (MATCHES(p, "110,")) 464ae115bc7Smrj baud = ASY110; 465ae115bc7Smrj else if (MATCHES(p, "150,")) 466ae115bc7Smrj baud = ASY150; 467ae115bc7Smrj else if (MATCHES(p, "300,")) 468ae115bc7Smrj baud = ASY300; 469ae115bc7Smrj else if (MATCHES(p, "600,")) 470ae115bc7Smrj baud = ASY600; 471ae115bc7Smrj else if (MATCHES(p, "1200,")) 472ae115bc7Smrj baud = ASY1200; 473ae115bc7Smrj else if (MATCHES(p, "2400,")) 474ae115bc7Smrj baud = ASY2400; 475ae115bc7Smrj else if (MATCHES(p, "4800,")) 476ae115bc7Smrj baud = ASY4800; 477ae115bc7Smrj else if (MATCHES(p, "19200,")) 478ae115bc7Smrj baud = ASY19200; 479ae115bc7Smrj else if (MATCHES(p, "38400,")) 480ae115bc7Smrj baud = ASY38400; 481ae115bc7Smrj else if (MATCHES(p, "57600,")) 482ae115bc7Smrj baud = ASY57600; 483ae115bc7Smrj else if (MATCHES(p, "115200,")) 484ae115bc7Smrj baud = ASY115200; 485ae115bc7Smrj else { 486ae115bc7Smrj baud = ASY9600; 487ae115bc7Smrj SKIP(p, ','); 488ae115bc7Smrj } 489ae115bc7Smrj outb(port + LCR, DLAB); 490ae115bc7Smrj outb(port + DAT + DLL, baud & 0xff); 491ae115bc7Smrj outb(port + DAT + DLH, (baud >> 8) & 0xff); 492ae115bc7Smrj 493ae115bc7Smrj switch (*p) { 494ae115bc7Smrj case '5': 495ae115bc7Smrj lcr |= BITS5; 496ae115bc7Smrj ++p; 497ae115bc7Smrj break; 498ae115bc7Smrj case '6': 499ae115bc7Smrj lcr |= BITS6; 500ae115bc7Smrj ++p; 501ae115bc7Smrj break; 502ae115bc7Smrj case '7': 503ae115bc7Smrj lcr |= BITS7; 504ae115bc7Smrj ++p; 505ae115bc7Smrj break; 506ae115bc7Smrj case '8': 507ae115bc7Smrj ++p; 508ae115bc7Smrj default: 509ae115bc7Smrj lcr |= BITS8; 510ae115bc7Smrj break; 511ae115bc7Smrj } 512ae115bc7Smrj 513ae115bc7Smrj SKIP(p, ','); 514ae115bc7Smrj 515ae115bc7Smrj switch (*p) { 516ae115bc7Smrj case 'n': 517ae115bc7Smrj lcr |= PARITY_NONE; 518ae115bc7Smrj ++p; 519ae115bc7Smrj break; 520ae115bc7Smrj case 'o': 521ae115bc7Smrj lcr |= PARITY_ODD; 522ae115bc7Smrj ++p; 523ae115bc7Smrj break; 524ae115bc7Smrj case 'e': 525ae115bc7Smrj ++p; 526ae115bc7Smrj default: 527ae115bc7Smrj lcr |= PARITY_EVEN; 528ae115bc7Smrj break; 529ae115bc7Smrj } 530ae115bc7Smrj 531ae115bc7Smrj 532ae115bc7Smrj SKIP(p, ','); 533ae115bc7Smrj 534ae115bc7Smrj switch (*p) { 535ae115bc7Smrj case '1': 536ae115bc7Smrj /* STOP1 is 0 */ 537ae115bc7Smrj ++p; 538ae115bc7Smrj break; 539ae115bc7Smrj default: 540ae115bc7Smrj lcr |= STOP2; 541ae115bc7Smrj break; 542ae115bc7Smrj } 543ae115bc7Smrj /* set parity bits */ 544ae115bc7Smrj outb(port + LCR, lcr); 545ae115bc7Smrj 546ae115bc7Smrj (void) strcpy(propname, "ttyX-rts-dtr-off"); 5470d928757SGary Mills propname[3] = 'a' + tty_num; 548ae115bc7Smrj propval = get_mode_value(propname); 549ae115bc7Smrj if (propval == NULL) 550ae115bc7Smrj propval = "false"; 551ae115bc7Smrj if (propval[0] != 'f' && propval[0] != 'F') 552ae115bc7Smrj mcr = 0; 553ae115bc7Smrj /* set modem control bits */ 554ae115bc7Smrj outb(port + MCR, mcr | OUT2); 555ae115bc7Smrj } 556ae115bc7Smrj 5570d928757SGary Mills /* Obtain the console type */ 5580d928757SGary Mills int 5590d928757SGary Mills boot_console_type(int *tnum) 5600d928757SGary Mills { 5610d928757SGary Mills if (tnum != NULL) 5620d928757SGary Mills *tnum = tty_num; 5630d928757SGary Mills return (console); 5640d928757SGary Mills } 5650d928757SGary Mills 566adb91f47Srscott /* 567adb91f47Srscott * A structure to map console names to values. 568adb91f47Srscott */ 569adb91f47Srscott typedef struct { 570adb91f47Srscott char *name; 571adb91f47Srscott int value; 572adb91f47Srscott } console_value_t; 573adb91f47Srscott 574adb91f47Srscott console_value_t console_devices[] = { 5750d928757SGary Mills { "ttya", CONS_TTY }, /* 0 */ 5760d928757SGary Mills { "ttyb", CONS_TTY }, /* 1 */ 5770d928757SGary Mills { "ttyc", CONS_TTY }, /* 2 */ 5780d928757SGary Mills { "ttyd", CONS_TTY }, /* 3 */ 579adb91f47Srscott { "text", CONS_SCREEN_TEXT }, 58067ce1dadSJan Setje-Eilers { "graphics", CONS_SCREEN_GRAPHICS }, 581843e1988Sjohnlev #if defined(__xpv) 582843e1988Sjohnlev { "hypervisor", CONS_HYPERVISOR }, 583843e1988Sjohnlev #endif 584adb91f47Srscott #if !defined(_BOOT) 585adb91f47Srscott { "usb-serial", CONS_USBSER }, 586adb91f47Srscott #endif 5870d928757SGary Mills { NULL, CONS_INVALID } 588adb91f47Srscott }; 589adb91f47Srscott 590*b9a86732SToomas Soome static void 591*b9a86732SToomas Soome bcons_init_env(struct xboot_info *xbi) 592*b9a86732SToomas Soome { 593*b9a86732SToomas Soome uint32_t i; 594*b9a86732SToomas Soome struct boot_modules *modules; 595*b9a86732SToomas Soome 596*b9a86732SToomas Soome modules = (struct boot_modules *)(uintptr_t)xbi->bi_modules; 597*b9a86732SToomas Soome for (i = 0; i < xbi->bi_module_cnt; i++) { 598*b9a86732SToomas Soome if (modules[i].bm_type == BMT_ENV) 599*b9a86732SToomas Soome break; 600*b9a86732SToomas Soome } 601*b9a86732SToomas Soome if (i == xbi->bi_module_cnt) 602*b9a86732SToomas Soome return; 603*b9a86732SToomas Soome 604*b9a86732SToomas Soome boot_env.be_env = (char *)(uintptr_t)modules[i].bm_addr; 605*b9a86732SToomas Soome boot_env.be_size = modules[i].bm_size; 606*b9a86732SToomas Soome } 607*b9a86732SToomas Soome 608ae115bc7Smrj void 609*b9a86732SToomas Soome bcons_init(struct xboot_info *xbi) 610ae115bc7Smrj { 611adb91f47Srscott console_value_t *consolep; 612adb91f47Srscott size_t len, cons_len; 613*b9a86732SToomas Soome const char *cons_str; 6149db7147eSSherry Moore #if !defined(_BOOT) 6159db7147eSSherry Moore static char console_text[] = "text"; 6169db7147eSSherry Moore extern int post_fastreboot; 6179db7147eSSherry Moore #endif 618adb91f47Srscott 619*b9a86732SToomas Soome /* Set up data to fetch properties from commad line and boot env. */ 620*b9a86732SToomas Soome boot_line = (char *)(uintptr_t)xbi->bi_cmdline; 621*b9a86732SToomas Soome bcons_init_env(xbi); 622ae115bc7Smrj console = CONS_INVALID; 623ae115bc7Smrj 624843e1988Sjohnlev #if defined(__xpv) 625*b9a86732SToomas Soome bcons_init_xen(boot_line); 626843e1988Sjohnlev #endif /* __xpv */ 627843e1988Sjohnlev 628*b9a86732SToomas Soome cons_str = find_boot_prop("console"); 629adb91f47Srscott if (cons_str == NULL) 630*b9a86732SToomas Soome cons_str = find_boot_prop("output-device"); 631adb91f47Srscott 6329db7147eSSherry Moore #if !defined(_BOOT) 6339db7147eSSherry Moore if (post_fastreboot && strcmp(cons_str, "graphics") == 0) 6349db7147eSSherry Moore cons_str = console_text; 6359db7147eSSherry Moore #endif 6369db7147eSSherry Moore 637adb91f47Srscott /* 638adb91f47Srscott * Go through the console_devices array trying to match the string 639adb91f47Srscott * we were given. The string on the command line must end with 640adb91f47Srscott * a comma or white space. 641adb91f47Srscott */ 642adb91f47Srscott if (cons_str != NULL) { 6430d928757SGary Mills int n; 6440d928757SGary Mills 645adb91f47Srscott cons_len = strlen(cons_str); 6460d928757SGary Mills for (n = 0; console_devices[n].name != NULL; n++) { 6470d928757SGary Mills consolep = &console_devices[n]; 648adb91f47Srscott len = strlen(consolep->name); 649adb91f47Srscott if ((len <= cons_len) && ((cons_str[len] == '\0') || 650adb91f47Srscott (cons_str[len] == ',') || (cons_str[len] == '\'') || 651adb91f47Srscott (cons_str[len] == '"') || ISSPACE(cons_str[len])) && 652adb91f47Srscott (strncmp(cons_str, consolep->name, len) == 0)) { 653adb91f47Srscott console = consolep->value; 6540d928757SGary Mills if (console == CONS_TTY) 6550d928757SGary Mills tty_num = n; 656adb91f47Srscott break; 657adb91f47Srscott } 658adb91f47Srscott } 659adb91f47Srscott } 660ae115bc7Smrj 661843e1988Sjohnlev #if defined(__xpv) 662843e1988Sjohnlev /* 663843e1988Sjohnlev * domU's always use the hypervisor regardless of what 664843e1988Sjohnlev * the console variable may be set to. 665843e1988Sjohnlev */ 666843e1988Sjohnlev if (!DOMAIN_IS_INITDOMAIN(xen_info)) { 667843e1988Sjohnlev console = CONS_HYPERVISOR; 668843e1988Sjohnlev console_hypervisor_redirect = B_TRUE; 669843e1988Sjohnlev } 670843e1988Sjohnlev #endif /* __xpv */ 671843e1988Sjohnlev 672ae115bc7Smrj /* 673ae115bc7Smrj * If no console device specified, default to text. 674ae115bc7Smrj * Remember what was specified for second phase. 675ae115bc7Smrj */ 676ae115bc7Smrj if (console == CONS_INVALID) 677ae115bc7Smrj console = CONS_SCREEN_TEXT; 678843e1988Sjohnlev #if !defined(_BOOT) 679adb91f47Srscott else 680adb91f47Srscott console_set = 1; 681843e1988Sjohnlev #endif 682843e1988Sjohnlev 683843e1988Sjohnlev #if defined(__xpv) 684843e1988Sjohnlev if (DOMAIN_IS_INITDOMAIN(xen_info)) { 685843e1988Sjohnlev switch (HYPERVISOR_console_io(CONSOLEIO_get_device, 0, NULL)) { 686843e1988Sjohnlev case XEN_CONSOLE_COM1: 687843e1988Sjohnlev case XEN_CONSOLE_COM2: 6880d928757SGary Mills console_hypervisor_device = CONS_TTY; 6890d928757SGary Mills console_hypervisor_tty_num = tty_num; 690843e1988Sjohnlev break; 691843e1988Sjohnlev case XEN_CONSOLE_VGA: 692843e1988Sjohnlev /* 693843e1988Sjohnlev * Currently xen doesn't really support 694843e1988Sjohnlev * keyboard/display console devices. 695843e1988Sjohnlev * What this setting means is that 696843e1988Sjohnlev * "vga=keep" has been enabled, which is 697843e1988Sjohnlev * more of a xen debugging tool that a 698843e1988Sjohnlev * true console mode. Hence, we're going 699843e1988Sjohnlev * to ignore this xen "console" setting. 700843e1988Sjohnlev */ 701843e1988Sjohnlev /*FALLTHROUGH*/ 702843e1988Sjohnlev default: 703843e1988Sjohnlev console_hypervisor_device = CONS_INVALID; 704843e1988Sjohnlev } 705843e1988Sjohnlev } 706843e1988Sjohnlev 707843e1988Sjohnlev /* 708843e1988Sjohnlev * if the hypervisor is using the currently selected serial 709843e1988Sjohnlev * port then default to using the hypervisor as the console 710843e1988Sjohnlev * device. 711843e1988Sjohnlev */ 712843e1988Sjohnlev if (console == console_hypervisor_device) { 713843e1988Sjohnlev console = CONS_HYPERVISOR; 714843e1988Sjohnlev console_hypervisor_redirect = B_TRUE; 715843e1988Sjohnlev } 716843e1988Sjohnlev #endif /* __xpv */ 717ae115bc7Smrj 718ae115bc7Smrj switch (console) { 7190d928757SGary Mills case CONS_TTY: 720ae115bc7Smrj serial_init(); 721ae115bc7Smrj break; 722ae115bc7Smrj 723843e1988Sjohnlev case CONS_HYPERVISOR: 724843e1988Sjohnlev break; 725843e1988Sjohnlev 726adb91f47Srscott #if !defined(_BOOT) 727adb91f47Srscott case CONS_USBSER: 728adb91f47Srscott /* 729adb91f47Srscott * We can't do anything with the usb serial 730adb91f47Srscott * until we have memory management. 731adb91f47Srscott */ 732adb91f47Srscott break; 733adb91f47Srscott #endif 73467ce1dadSJan Setje-Eilers case CONS_SCREEN_GRAPHICS: 73567ce1dadSJan Setje-Eilers kb_init(); 73667ce1dadSJan Setje-Eilers break; 737ae115bc7Smrj case CONS_SCREEN_TEXT: 738ae115bc7Smrj default: 739ae115bc7Smrj #if defined(_BOOT) 740843e1988Sjohnlev clear_screen(); /* clears the grub or xen screen */ 741843e1988Sjohnlev #endif /* _BOOT */ 742ae115bc7Smrj kb_init(); 743ae115bc7Smrj break; 744ae115bc7Smrj } 745ae115bc7Smrj } 746ae115bc7Smrj 747843e1988Sjohnlev #if !defined(_BOOT) 748ae115bc7Smrj /* 749ae115bc7Smrj * 2nd part of console initialization. 750ae115bc7Smrj * In the kernel (ie. fakebop), this can be used only to switch to 751ae115bc7Smrj * using a serial port instead of screen based on the contents 752ae115bc7Smrj * of the bootenv.rc file. 753ae115bc7Smrj */ 754ae115bc7Smrj /*ARGSUSED*/ 755ae115bc7Smrj void 756ae115bc7Smrj bcons_init2(char *inputdev, char *outputdev, char *consoledev) 757ae115bc7Smrj { 758ae115bc7Smrj int cons = CONS_INVALID; 7590d928757SGary Mills int ttyn; 760adb91f47Srscott char *devnames[] = { consoledev, outputdev, inputdev, NULL }; 761adb91f47Srscott console_value_t *consolep; 762adb91f47Srscott int i; 7639db7147eSSherry Moore extern int post_fastreboot; 7649db7147eSSherry Moore 7659db7147eSSherry Moore if (post_fastreboot && console == CONS_SCREEN_GRAPHICS) 7669db7147eSSherry Moore console = CONS_SCREEN_TEXT; 767ae115bc7Smrj 768c6d6228cSEnrico Perla - Sun Microsystems if (console != CONS_USBSER && console != CONS_SCREEN_GRAPHICS) { 769adb91f47Srscott if (console_set) { 770adb91f47Srscott /* 771adb91f47Srscott * If the console was set on the command line, 772adb91f47Srscott * but the ttyX-mode was not, we only need to 773adb91f47Srscott * check bootenv.rc for that setting. 774adb91f47Srscott */ 7750d928757SGary Mills if ((!console_mode_set) && (console == CONS_TTY)) 776adb91f47Srscott serial_init(); 777adb91f47Srscott return; 778ae115bc7Smrj } 779ae115bc7Smrj 780adb91f47Srscott for (i = 0; devnames[i] != NULL; i++) { 7810d928757SGary Mills int n; 7820d928757SGary Mills 7830d928757SGary Mills for (n = 0; console_devices[n].name != NULL; n++) { 7840d928757SGary Mills consolep = &console_devices[n]; 785adb91f47Srscott if (strcmp(devnames[i], consolep->name) == 0) { 786adb91f47Srscott cons = consolep->value; 7870d928757SGary Mills if (cons == CONS_TTY) 7880d928757SGary Mills ttyn = n; 789ae115bc7Smrj } 790adb91f47Srscott } 791adb91f47Srscott if (cons != CONS_INVALID) 792adb91f47Srscott break; 793ae115bc7Smrj } 794ae115bc7Smrj 795843e1988Sjohnlev #if defined(__xpv) 796843e1988Sjohnlev /* 797843e1988Sjohnlev * if the hypervisor is using the currently selected console 798843e1988Sjohnlev * device then default to using the hypervisor as the console 799843e1988Sjohnlev * device. 800843e1988Sjohnlev */ 801843e1988Sjohnlev if (cons == console_hypervisor_device) { 802843e1988Sjohnlev cons = CONS_HYPERVISOR; 803843e1988Sjohnlev console_hypervisor_redirect = B_TRUE; 804843e1988Sjohnlev } 805843e1988Sjohnlev #endif /* __xpv */ 806843e1988Sjohnlev 807843e1988Sjohnlev if ((cons == CONS_INVALID) || (cons == console)) { 808843e1988Sjohnlev /* 809843e1988Sjohnlev * we're sticking with whatever the current setting is 810843e1988Sjohnlev */ 811ae115bc7Smrj return; 812843e1988Sjohnlev } 813ae115bc7Smrj 814ae115bc7Smrj console = cons; 8150d928757SGary Mills if (cons == CONS_TTY) { 8160d928757SGary Mills tty_num = ttyn; 817ae115bc7Smrj serial_init(); 818ae115bc7Smrj return; 819ae115bc7Smrj } 820c6d6228cSEnrico Perla - Sun Microsystems } else { 821ae115bc7Smrj /* 822c6d6228cSEnrico Perla - Sun Microsystems * USB serial and GRAPHICS console 823c6d6228cSEnrico Perla - Sun Microsystems * we just collect data into a buffer 824ae115bc7Smrj */ 82548633f18SJan Setje-Eilers extern void *defcons_init(size_t); 82648633f18SJan Setje-Eilers defcons_buf = defcons_cur = defcons_init(MMU_PAGESIZE); 827ae115bc7Smrj } 828ae115bc7Smrj } 829ae115bc7Smrj 830843e1988Sjohnlev #if defined(__xpv) 831843e1988Sjohnlev boolean_t 832843e1988Sjohnlev bcons_hypervisor_redirect(void) 833843e1988Sjohnlev { 834843e1988Sjohnlev return (console_hypervisor_redirect); 835843e1988Sjohnlev } 836843e1988Sjohnlev 837843e1988Sjohnlev void 838843e1988Sjohnlev bcons_device_change(int new_console) 839843e1988Sjohnlev { 840843e1988Sjohnlev if (new_console < CONS_MIN || new_console > CONS_MAX) 841843e1988Sjohnlev return; 842843e1988Sjohnlev 843843e1988Sjohnlev /* 844843e1988Sjohnlev * If we are asked to switch the console to the hypervisor, that 845843e1988Sjohnlev * really means to switch the console to whichever device the 846843e1988Sjohnlev * hypervisor is/was using. 847843e1988Sjohnlev */ 848843e1988Sjohnlev if (new_console == CONS_HYPERVISOR) 849843e1988Sjohnlev new_console = console_hypervisor_device; 850843e1988Sjohnlev 851843e1988Sjohnlev console = new_console; 852843e1988Sjohnlev 8530d928757SGary Mills if (new_console == CONS_TTY) { 8540d928757SGary Mills tty_num = console_hypervisor_tty_num; 855843e1988Sjohnlev serial_init(); 856843e1988Sjohnlev } 8570d928757SGary Mills } 858843e1988Sjohnlev #endif /* __xpv */ 859843e1988Sjohnlev 860ae115bc7Smrj static void 86148633f18SJan Setje-Eilers defcons_putchar(int c) 862ae115bc7Smrj { 863c6d6228cSEnrico Perla - Sun Microsystems if (defcons_buf != NULL && 864c6d6228cSEnrico Perla - Sun Microsystems defcons_cur + 1 - defcons_buf < MMU_PAGESIZE) { 86548633f18SJan Setje-Eilers *defcons_cur++ = c; 86663dd072cSJan Setje-Eilers *defcons_cur = 0; 86763dd072cSJan Setje-Eilers } 868ae115bc7Smrj } 869ae115bc7Smrj #endif /* _BOOT */ 870ae115bc7Smrj 871ae115bc7Smrj static void 872ae115bc7Smrj serial_putchar(int c) 873ae115bc7Smrj { 874ae115bc7Smrj int checks = 10000; 875ae115bc7Smrj 876ae115bc7Smrj while (((inb(port + LSR) & XHRE) == 0) && checks--) 877ae115bc7Smrj ; 878ae115bc7Smrj outb(port + DAT, (char)c); 879ae115bc7Smrj } 880ae115bc7Smrj 881ae115bc7Smrj static int 882ae115bc7Smrj serial_getchar(void) 883ae115bc7Smrj { 884ae115bc7Smrj uchar_t lsr; 885ae115bc7Smrj 886ae115bc7Smrj while (serial_ischar() == 0) 887ae115bc7Smrj ; 888ae115bc7Smrj 889ae115bc7Smrj lsr = inb(port + LSR); 890ae115bc7Smrj if (lsr & (SERIAL_BREAK | SERIAL_FRAME | 891ae115bc7Smrj SERIAL_PARITY | SERIAL_OVERRUN)) { 892ae115bc7Smrj if (lsr & SERIAL_OVERRUN) { 893ae115bc7Smrj return (inb(port + DAT)); 894ae115bc7Smrj } else { 895ae115bc7Smrj /* Toss the garbage */ 896ae115bc7Smrj (void) inb(port + DAT); 897ae115bc7Smrj return (0); 898ae115bc7Smrj } 899ae115bc7Smrj } 900ae115bc7Smrj return (inb(port + DAT)); 901ae115bc7Smrj } 902ae115bc7Smrj 903ae115bc7Smrj static int 904ae115bc7Smrj serial_ischar(void) 905ae115bc7Smrj { 906ae115bc7Smrj return (inb(port + LSR) & RCA); 907ae115bc7Smrj } 908ae115bc7Smrj 909ae115bc7Smrj static void 910ae115bc7Smrj _doputchar(int c) 911ae115bc7Smrj { 912ae115bc7Smrj switch (console) { 9130d928757SGary Mills case CONS_TTY: 914ae115bc7Smrj serial_putchar(c); 915ae115bc7Smrj return; 916ae115bc7Smrj case CONS_SCREEN_TEXT: 917ae115bc7Smrj screen_putchar(c); 918ae115bc7Smrj return; 91967ce1dadSJan Setje-Eilers case CONS_SCREEN_GRAPHICS: 920ae115bc7Smrj #if !defined(_BOOT) 921ae115bc7Smrj case CONS_USBSER: 92248633f18SJan Setje-Eilers defcons_putchar(c); 923ae115bc7Smrj #endif /* _BOOT */ 92448633f18SJan Setje-Eilers return; 925ae115bc7Smrj } 926ae115bc7Smrj } 927ae115bc7Smrj 928ae115bc7Smrj void 929ae115bc7Smrj bcons_putchar(int c) 930ae115bc7Smrj { 931ae115bc7Smrj static int bhcharpos = 0; 932ae115bc7Smrj 933843e1988Sjohnlev #if defined(__xpv) 934843e1988Sjohnlev if (!DOMAIN_IS_INITDOMAIN(xen_info) || 935843e1988Sjohnlev console == CONS_HYPERVISOR) { 936843e1988Sjohnlev bcons_putchar_xen(c); 937843e1988Sjohnlev return; 938843e1988Sjohnlev } 939843e1988Sjohnlev #endif /* __xpv */ 940843e1988Sjohnlev 941ae115bc7Smrj if (c == '\t') { 942ae115bc7Smrj do { 943ae115bc7Smrj _doputchar(' '); 944ae115bc7Smrj } while (++bhcharpos % 8); 945ae115bc7Smrj return; 946ae115bc7Smrj } else if (c == '\n' || c == '\r') { 947ae115bc7Smrj bhcharpos = 0; 948ae115bc7Smrj _doputchar('\r'); 949ae115bc7Smrj _doputchar(c); 950ae115bc7Smrj return; 951ae115bc7Smrj } else if (c == '\b') { 952ae115bc7Smrj if (bhcharpos) 953ae115bc7Smrj bhcharpos--; 954ae115bc7Smrj _doputchar(c); 955ae115bc7Smrj return; 956ae115bc7Smrj } 957ae115bc7Smrj 958ae115bc7Smrj bhcharpos++; 959ae115bc7Smrj _doputchar(c); 960ae115bc7Smrj } 961ae115bc7Smrj 962ae115bc7Smrj /* 963ae115bc7Smrj * kernel character input functions 964ae115bc7Smrj */ 965ae115bc7Smrj int 966ae115bc7Smrj bcons_getchar(void) 967ae115bc7Smrj { 968843e1988Sjohnlev #if defined(__xpv) 969843e1988Sjohnlev if (!DOMAIN_IS_INITDOMAIN(xen_info) || 970843e1988Sjohnlev console == CONS_HYPERVISOR) 971843e1988Sjohnlev return (bcons_getchar_xen()); 972843e1988Sjohnlev #endif /* __xpv */ 973843e1988Sjohnlev 974ae115bc7Smrj switch (console) { 9750d928757SGary Mills case CONS_TTY: 976ae115bc7Smrj return (serial_getchar()); 977ae115bc7Smrj default: 978ae115bc7Smrj return (kb_getchar()); 979ae115bc7Smrj } 980ae115bc7Smrj } 981ae115bc7Smrj 982ae115bc7Smrj #if !defined(_BOOT) 983ae115bc7Smrj 984ae115bc7Smrj int 985ae115bc7Smrj bcons_ischar(void) 986ae115bc7Smrj { 987843e1988Sjohnlev 988843e1988Sjohnlev #if defined(__xpv) 989843e1988Sjohnlev if (!DOMAIN_IS_INITDOMAIN(xen_info) || 990843e1988Sjohnlev console == CONS_HYPERVISOR) 991843e1988Sjohnlev return (bcons_ischar_xen()); 992843e1988Sjohnlev #endif /* __xpv */ 993843e1988Sjohnlev 994ae115bc7Smrj switch (console) { 9950d928757SGary Mills case CONS_TTY: 996ae115bc7Smrj return (serial_ischar()); 997ae115bc7Smrj default: 998ae115bc7Smrj return (kb_ischar()); 999ae115bc7Smrj } 1000ae115bc7Smrj } 1001ae115bc7Smrj 1002ae115bc7Smrj #endif /* _BOOT */ 1003