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 22ae115bc7Smrj /* 23c9503a49Slq150181 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24ae115bc7Smrj * Use is subject to license terms. 25ae115bc7Smrj */ 26ae115bc7Smrj 27ae115bc7Smrj #pragma ident "%Z%%M% %I% %E% SMI" 28ae115bc7Smrj 29ae115bc7Smrj /* 30ae115bc7Smrj * isa-specific console configuration routines 31ae115bc7Smrj */ 32ae115bc7Smrj 33ae115bc7Smrj #include <sys/types.h> 34ae115bc7Smrj #include <sys/param.h> 35ae115bc7Smrj #include <sys/cmn_err.h> 36ae115bc7Smrj #include <sys/systm.h> 37ae115bc7Smrj #include <sys/conf.h> 38ae115bc7Smrj #include <sys/debug.h> 39ae115bc7Smrj #include <sys/ddi.h> 40ae115bc7Smrj #include <sys/sunddi.h> 41ae115bc7Smrj #include <sys/sunndi.h> 42ae115bc7Smrj #include <sys/esunddi.h> 43ae115bc7Smrj #include <sys/ddi_impldefs.h> 44ae115bc7Smrj #include <sys/promif.h> 45ae115bc7Smrj #include <sys/modctl.h> 46ae115bc7Smrj #include <sys/termios.h> 47843e1988Sjohnlev #if defined(__xpv) 48843e1988Sjohnlev #include <sys/hypervisor.h> 49843e1988Sjohnlev #include <sys/boot_console.h> 50843e1988Sjohnlev #endif 51ae115bc7Smrj 52ae115bc7Smrj /* The names of currently supported graphics drivers on x86 */ 53ae115bc7Smrj static char * 54ae115bc7Smrj gfxdrv_name[] = { 55ae115bc7Smrj "vgatext", 56ae115bc7Smrj "i915", 572df1fe9cSrandyf "atiatom", 582df1fe9cSrandyf "nvidia", 59ae115bc7Smrj }; 60ae115bc7Smrj 61ae115bc7Smrj int 62ae115bc7Smrj plat_use_polled_debug() { 63ae115bc7Smrj return (0); 64ae115bc7Smrj } 65ae115bc7Smrj 66ae115bc7Smrj int 67ae115bc7Smrj plat_support_serial_kbd_and_ms() { 68ae115bc7Smrj return (0); 69ae115bc7Smrj } 70ae115bc7Smrj 71843e1988Sjohnlev #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0])) 72843e1988Sjohnlev 73ae115bc7Smrj #define CONS_INVALID -1 74ae115bc7Smrj #define CONS_SCREEN 0 75ae115bc7Smrj #define CONS_TTYA 1 76ae115bc7Smrj #define CONS_TTYB 2 77ae115bc7Smrj #define CONS_USBSER 3 78843e1988Sjohnlev #define CONS_HYPERVISOR 4 79ae115bc7Smrj 80*583da248Srz201010 char *plat_fbpath(void); 81*583da248Srz201010 82ae115bc7Smrj static int 83ae115bc7Smrj console_type() 84ae115bc7Smrj { 85ae115bc7Smrj static int boot_console = CONS_INVALID; 86ae115bc7Smrj 87ae115bc7Smrj char *cons; 88ae115bc7Smrj dev_info_t *root; 89ae115bc7Smrj 90ae115bc7Smrj if (boot_console != CONS_INVALID) 91ae115bc7Smrj return (boot_console); 92ae115bc7Smrj 93843e1988Sjohnlev #if defined(__xpv) 94843e1988Sjohnlev if (!DOMAIN_IS_INITDOMAIN(xen_info) || bcons_hypervisor_redirect()) { 95843e1988Sjohnlev boot_console = CONS_HYPERVISOR; 96843e1988Sjohnlev return (boot_console); 97843e1988Sjohnlev } 98843e1988Sjohnlev #endif /* __xpv */ 99843e1988Sjohnlev 100ae115bc7Smrj /* 101ae115bc7Smrj * console is defined by "console" property, with 102ae115bc7Smrj * fallback on the old "input-device" property. 103*583da248Srz201010 * If "input-device" is not defined either, also check "output-device". 104ae115bc7Smrj */ 105ae115bc7Smrj boot_console = CONS_SCREEN; /* default is screen/kb */ 106ae115bc7Smrj root = ddi_root_node(); 107ae115bc7Smrj if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root, 108ae115bc7Smrj DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) || 109ae115bc7Smrj (ddi_prop_lookup_string(DDI_DEV_T_ANY, root, 110*583da248Srz201010 DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS) || 111*583da248Srz201010 (ddi_prop_lookup_string(DDI_DEV_T_ANY, root, 112*583da248Srz201010 DDI_PROP_DONTPASS, "output-device", &cons) == DDI_SUCCESS)) { 113843e1988Sjohnlev if (strcmp(cons, "ttya") == 0) { 114ae115bc7Smrj boot_console = CONS_TTYA; 115843e1988Sjohnlev } else if (strcmp(cons, "ttyb") == 0) { 116ae115bc7Smrj boot_console = CONS_TTYB; 117843e1988Sjohnlev } else if (strcmp(cons, "usb-serial") == 0) { 118ae115bc7Smrj (void) i_ddi_attach_hw_nodes("ehci"); 119ae115bc7Smrj (void) i_ddi_attach_hw_nodes("uhci"); 120ae115bc7Smrj (void) i_ddi_attach_hw_nodes("ohci"); 121ae115bc7Smrj /* 122ae115bc7Smrj * USB device enumerate asynchronously. 123ae115bc7Smrj * Wait 2 seconds for USB serial devices to attach. 124ae115bc7Smrj */ 125ae115bc7Smrj delay(drv_usectohz(2000000)); 126ae115bc7Smrj boot_console = CONS_USBSER; 127843e1988Sjohnlev #if defined(__xpv) 128843e1988Sjohnlev } else if (strcmp(cons, "hypervisor") == 0) { 129843e1988Sjohnlev boot_console = CONS_HYPERVISOR; 130843e1988Sjohnlev #endif /* __xpv */ 131ae115bc7Smrj } 132ae115bc7Smrj ddi_prop_free(cons); 133ae115bc7Smrj } 134*583da248Srz201010 135*583da248Srz201010 /* 136*583da248Srz201010 * If the console is configured to use a framebuffer but none 137*583da248Srz201010 * could be found, fallback to "ttya" since it's likely to exist 138*583da248Srz201010 * and it matches longstanding behavior on SPARC. 139*583da248Srz201010 */ 140*583da248Srz201010 if (boot_console == CONS_SCREEN && plat_fbpath() == NULL) 141*583da248Srz201010 boot_console = CONS_TTYA; 142*583da248Srz201010 143ae115bc7Smrj return (boot_console); 144ae115bc7Smrj } 145ae115bc7Smrj 146ae115bc7Smrj int 147ae115bc7Smrj plat_stdin_is_keyboard(void) 148ae115bc7Smrj { 149ae115bc7Smrj return (console_type() == CONS_SCREEN); 150ae115bc7Smrj } 151ae115bc7Smrj 152ae115bc7Smrj int 153ae115bc7Smrj plat_stdout_is_framebuffer(void) 154ae115bc7Smrj { 155ae115bc7Smrj return (console_type() == CONS_SCREEN); 156ae115bc7Smrj } 157ae115bc7Smrj 158ae115bc7Smrj /* 159ae115bc7Smrj * Return generic path to keyboard device from the alias. 160ae115bc7Smrj */ 161ae115bc7Smrj char * 162ae115bc7Smrj plat_kbdpath(void) 163ae115bc7Smrj { 164ae115bc7Smrj /* 165ae115bc7Smrj * Hardcode to isa keyboard path 166ae115bc7Smrj * XXX make it settable via bootprop? 167ae115bc7Smrj */ 168ae115bc7Smrj return ("/isa/i8042@1,60/keyboard@0"); 169ae115bc7Smrj } 170ae115bc7Smrj 171ae115bc7Smrj /* 172ae115bc7Smrj * Return generic path to display device from the alias. 173ae115bc7Smrj */ 174ae115bc7Smrj char * 175ae115bc7Smrj plat_fbpath(void) 176ae115bc7Smrj { 177ae115bc7Smrj static char *fbpath = NULL; 178ae115bc7Smrj static char fbpath_buf[MAXPATHLEN]; 179ae115bc7Smrj major_t major; 180843e1988Sjohnlev dev_info_t *dip, *dip_pseudo = NULL; 181ae115bc7Smrj int i; 182ae115bc7Smrj 183843e1988Sjohnlev /* lookup the dip for the pseudo device */ 184843e1988Sjohnlev (void) resolve_pathname("/pseudo", &dip_pseudo, NULL, NULL); 185843e1988Sjohnlev 186843e1988Sjohnlev for (i = 0; i < A_CNT(gfxdrv_name); i++) { 187ae115bc7Smrj /* 188ae115bc7Smrj * look for first instance of each driver 189ae115bc7Smrj */ 190843e1988Sjohnlev if ((major = ddi_name_to_major(gfxdrv_name[i])) == (major_t)-1) 191843e1988Sjohnlev continue; 192843e1988Sjohnlev 193843e1988Sjohnlev if ((dip = devnamesp[major].dn_head) == NULL) 194843e1988Sjohnlev continue; 195843e1988Sjohnlev 196843e1988Sjohnlev /* 197843e1988Sjohnlev * We're looking for a real hardware device here so skip 198843e1988Sjohnlev * any pseudo devices. When could a framebuffer hardware 199843e1988Sjohnlev * driver also have a pseudo node? Well, some framebuffer 200843e1988Sjohnlev * hardware drivers (nvidia) also create pseudo nodes for 201843e1988Sjohnlev * administration purposes, and these nodes will exist 202843e1988Sjohnlev * regardless of if the actual associated hardware 203843e1988Sjohnlev * is present or not. 204843e1988Sjohnlev */ 205843e1988Sjohnlev if (ddi_get_parent(dip) == dip_pseudo) 206843e1988Sjohnlev continue; 207843e1988Sjohnlev 208843e1988Sjohnlev if (i_ddi_attach_node_hierarchy(dip) == DDI_SUCCESS) { 209ae115bc7Smrj (void) ddi_pathname(dip, fbpath_buf); 210ae115bc7Smrj fbpath = fbpath_buf; 211ae115bc7Smrj } 212ae115bc7Smrj 213ae115bc7Smrj if (fbpath) 214843e1988Sjohnlev break; 215ae115bc7Smrj } 216ae115bc7Smrj 217843e1988Sjohnlev if (dip_pseudo != NULL) 218843e1988Sjohnlev ddi_release_devi(dip_pseudo); 219843e1988Sjohnlev 220ae115bc7Smrj /* No screen found */ 221843e1988Sjohnlev return (fbpath); 222ae115bc7Smrj } 223ae115bc7Smrj 224ae115bc7Smrj char * 225ae115bc7Smrj plat_mousepath(void) 226ae115bc7Smrj { 227ae115bc7Smrj /* 228ae115bc7Smrj * Hardcode to isa mouse path 229ae115bc7Smrj * XXX make it settable via bootprop? 230ae115bc7Smrj */ 231ae115bc7Smrj return ("/isa/i8042@1,60/mouse@1"); 232ae115bc7Smrj } 233ae115bc7Smrj 234ae115bc7Smrj /* return path of first usb serial device */ 235ae115bc7Smrj static char * 236ae115bc7Smrj plat_usbser_path(void) 237ae115bc7Smrj { 238ae115bc7Smrj extern dev_info_t *usbser_first_device(void); 239ae115bc7Smrj 240ae115bc7Smrj dev_info_t *us_dip; 241ae115bc7Smrj static char *us_path = NULL; 242ae115bc7Smrj 243ae115bc7Smrj if (us_path) 244ae115bc7Smrj return (us_path); 245ae115bc7Smrj 246ae115bc7Smrj us_dip = usbser_first_device(); 247ae115bc7Smrj if (us_dip == NULL) 248ae115bc7Smrj return (NULL); 249ae115bc7Smrj 250ae115bc7Smrj us_path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 251ae115bc7Smrj (void) ddi_pathname(us_dip, us_path); 252ae115bc7Smrj ndi_rele_devi(us_dip); /* held from usbser_first_device */ 253ae115bc7Smrj return (us_path); 254ae115bc7Smrj } 255ae115bc7Smrj 256ae115bc7Smrj /* 257ae115bc7Smrj * Lacking support for com2 and com3, if that matters. 258ae115bc7Smrj * Another possible enhancement could be to use properties 259ae115bc7Smrj * for the port mapping rather than simply hard-code them. 260ae115bc7Smrj */ 261ae115bc7Smrj char * 262ae115bc7Smrj plat_stdinpath(void) 263ae115bc7Smrj { 264ae115bc7Smrj switch (console_type()) { 265843e1988Sjohnlev #if defined(__xpv) 266843e1988Sjohnlev case CONS_HYPERVISOR: 267843e1988Sjohnlev return ("/xpvd/xencons@0"); 268843e1988Sjohnlev #endif /* __xpv */ 269ae115bc7Smrj case CONS_TTYA: 270ae115bc7Smrj return ("/isa/asy@1,3f8:a"); 271ae115bc7Smrj case CONS_TTYB: 272ae115bc7Smrj return ("/isa/asy@1,2f8:b"); 273ae115bc7Smrj case CONS_USBSER: 274ae115bc7Smrj return (plat_usbser_path()); 275ae115bc7Smrj case CONS_SCREEN: 276ae115bc7Smrj default: 277ae115bc7Smrj break; 278ae115bc7Smrj }; 279ae115bc7Smrj return (plat_kbdpath()); 280ae115bc7Smrj } 281ae115bc7Smrj 282ae115bc7Smrj char * 283ae115bc7Smrj plat_stdoutpath(void) 284ae115bc7Smrj { 285ae115bc7Smrj switch (console_type()) { 286843e1988Sjohnlev #if defined(__xpv) 287843e1988Sjohnlev case CONS_HYPERVISOR: 288843e1988Sjohnlev return ("/xpvd/xencons@0"); 289843e1988Sjohnlev #endif /* __xpv */ 290ae115bc7Smrj case CONS_TTYA: 291ae115bc7Smrj return ("/isa/asy@1,3f8:a"); 292ae115bc7Smrj case CONS_TTYB: 293ae115bc7Smrj return ("/isa/asy@1,2f8:b"); 294ae115bc7Smrj case CONS_USBSER: 295ae115bc7Smrj return (plat_usbser_path()); 296ae115bc7Smrj case CONS_SCREEN: 297ae115bc7Smrj default: 298ae115bc7Smrj break; 299ae115bc7Smrj }; 300ae115bc7Smrj return (plat_fbpath()); 301ae115bc7Smrj } 302ae115bc7Smrj 303ae115bc7Smrj /* 304ae115bc7Smrj * If VIS_PIXEL mode will be implemented on x86, these following 305ae115bc7Smrj * functions should be re-considered. Now these functions are 306ae115bc7Smrj * unused on x86. 307ae115bc7Smrj */ 308ae115bc7Smrj void 309c9503a49Slq150181 plat_tem_get_inverses(int *inverse, int *inverse_screen) 310c9503a49Slq150181 { 311c9503a49Slq150181 *inverse = 0; 312c9503a49Slq150181 *inverse_screen = 0; 313c9503a49Slq150181 } 314c9503a49Slq150181 315c9503a49Slq150181 void 316ae115bc7Smrj plat_tem_get_prom_font_size(int *charheight, int *windowtop) 317ae115bc7Smrj { 318ae115bc7Smrj *charheight = 0; 319ae115bc7Smrj *windowtop = 0; 320ae115bc7Smrj } 321ae115bc7Smrj 322843e1988Sjohnlev /*ARGSUSED*/ 323ae115bc7Smrj void 324ae115bc7Smrj plat_tem_get_prom_size(size_t *height, size_t *width) 325ae115bc7Smrj { 326843e1988Sjohnlev panic("unimplemented at line %d of %s", __LINE__, __FILE__); 327ae115bc7Smrj } 328ae115bc7Smrj 329ae115bc7Smrj void 330ae115bc7Smrj plat_tem_hide_prom_cursor(void) 331ae115bc7Smrj { 332843e1988Sjohnlev panic("unimplemented at line %d of %s", __LINE__, __FILE__); 333ae115bc7Smrj } 334ae115bc7Smrj 335843e1988Sjohnlev /*ARGSUSED*/ 336ae115bc7Smrj void 337ae115bc7Smrj plat_tem_get_prom_pos(uint32_t *row, uint32_t *col) 338ae115bc7Smrj { 339843e1988Sjohnlev panic("unimplemented at line %d of %s", __LINE__, __FILE__); 340ae115bc7Smrj } 341