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 /* 23*78323854SJudy Chen * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24ae115bc7Smrj * Use is subject to license terms. 25ae115bc7Smrj */ 26ae115bc7Smrj 27ae115bc7Smrj /* 28ae115bc7Smrj * isa-specific console configuration routines 29ae115bc7Smrj */ 30ae115bc7Smrj 31ae115bc7Smrj #include <sys/types.h> 32ae115bc7Smrj #include <sys/param.h> 33ae115bc7Smrj #include <sys/cmn_err.h> 34ae115bc7Smrj #include <sys/systm.h> 35ae115bc7Smrj #include <sys/conf.h> 36ae115bc7Smrj #include <sys/debug.h> 37ae115bc7Smrj #include <sys/ddi.h> 38ae115bc7Smrj #include <sys/sunddi.h> 39ae115bc7Smrj #include <sys/sunndi.h> 40ae115bc7Smrj #include <sys/esunddi.h> 41ae115bc7Smrj #include <sys/ddi_impldefs.h> 42ae115bc7Smrj #include <sys/promif.h> 43ae115bc7Smrj #include <sys/modctl.h> 44ae115bc7Smrj #include <sys/termios.h> 45843e1988Sjohnlev #if defined(__xpv) 46843e1988Sjohnlev #include <sys/hypervisor.h> 47843e1988Sjohnlev #include <sys/boot_console.h> 48843e1988Sjohnlev #endif 49ae115bc7Smrj 50*78323854SJudy Chen extern int pseudo_isa; 51*78323854SJudy Chen 52ae115bc7Smrj /* The names of currently supported graphics drivers on x86 */ 53ae115bc7Smrj static char * 54ae115bc7Smrj gfxdrv_name[] = { 55e57b9183Scg149915 "radeon", 56ae115bc7Smrj "vgatext", 57ae115bc7Smrj "i915", 582df1fe9cSrandyf "atiatom", 592df1fe9cSrandyf "nvidia", 60ae115bc7Smrj }; 61ae115bc7Smrj 62ae115bc7Smrj int 63ae115bc7Smrj plat_use_polled_debug() { 64ae115bc7Smrj return (0); 65ae115bc7Smrj } 66ae115bc7Smrj 67ae115bc7Smrj int 68ae115bc7Smrj plat_support_serial_kbd_and_ms() { 69ae115bc7Smrj return (0); 70ae115bc7Smrj } 71ae115bc7Smrj 72843e1988Sjohnlev #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0])) 73843e1988Sjohnlev 74ae115bc7Smrj #define CONS_INVALID -1 75ae115bc7Smrj #define CONS_SCREEN 0 76ae115bc7Smrj #define CONS_TTYA 1 77ae115bc7Smrj #define CONS_TTYB 2 78ae115bc7Smrj #define CONS_USBSER 3 79843e1988Sjohnlev #define CONS_HYPERVISOR 4 80ae115bc7Smrj 81583da248Srz201010 char *plat_fbpath(void); 82583da248Srz201010 83ae115bc7Smrj static int 84ae115bc7Smrj console_type() 85ae115bc7Smrj { 86ae115bc7Smrj static int boot_console = CONS_INVALID; 87ae115bc7Smrj 88ae115bc7Smrj char *cons; 89ae115bc7Smrj dev_info_t *root; 90ae115bc7Smrj 91ae115bc7Smrj if (boot_console != CONS_INVALID) 92ae115bc7Smrj return (boot_console); 93ae115bc7Smrj 94843e1988Sjohnlev #if defined(__xpv) 95843e1988Sjohnlev if (!DOMAIN_IS_INITDOMAIN(xen_info) || bcons_hypervisor_redirect()) { 96843e1988Sjohnlev boot_console = CONS_HYPERVISOR; 97843e1988Sjohnlev return (boot_console); 98843e1988Sjohnlev } 99843e1988Sjohnlev #endif /* __xpv */ 100843e1988Sjohnlev 101ae115bc7Smrj /* 102ae115bc7Smrj * console is defined by "console" property, with 103ae115bc7Smrj * fallback on the old "input-device" property. 104583da248Srz201010 * If "input-device" is not defined either, also check "output-device". 105ae115bc7Smrj */ 106ae115bc7Smrj boot_console = CONS_SCREEN; /* default is screen/kb */ 107ae115bc7Smrj root = ddi_root_node(); 108ae115bc7Smrj if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root, 109ae115bc7Smrj DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) || 110ae115bc7Smrj (ddi_prop_lookup_string(DDI_DEV_T_ANY, root, 111583da248Srz201010 DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS) || 112583da248Srz201010 (ddi_prop_lookup_string(DDI_DEV_T_ANY, root, 113583da248Srz201010 DDI_PROP_DONTPASS, "output-device", &cons) == DDI_SUCCESS)) { 114843e1988Sjohnlev if (strcmp(cons, "ttya") == 0) { 115ae115bc7Smrj boot_console = CONS_TTYA; 116843e1988Sjohnlev } else if (strcmp(cons, "ttyb") == 0) { 117ae115bc7Smrj boot_console = CONS_TTYB; 118843e1988Sjohnlev } else if (strcmp(cons, "usb-serial") == 0) { 119ae115bc7Smrj (void) i_ddi_attach_hw_nodes("ehci"); 120ae115bc7Smrj (void) i_ddi_attach_hw_nodes("uhci"); 121ae115bc7Smrj (void) i_ddi_attach_hw_nodes("ohci"); 122ae115bc7Smrj /* 123ae115bc7Smrj * USB device enumerate asynchronously. 124ae115bc7Smrj * Wait 2 seconds for USB serial devices to attach. 125ae115bc7Smrj */ 126ae115bc7Smrj delay(drv_usectohz(2000000)); 127ae115bc7Smrj boot_console = CONS_USBSER; 128843e1988Sjohnlev #if defined(__xpv) 129843e1988Sjohnlev } else if (strcmp(cons, "hypervisor") == 0) { 130843e1988Sjohnlev boot_console = CONS_HYPERVISOR; 131843e1988Sjohnlev #endif /* __xpv */ 132ae115bc7Smrj } 133ae115bc7Smrj ddi_prop_free(cons); 134ae115bc7Smrj } 135583da248Srz201010 136583da248Srz201010 /* 137583da248Srz201010 * If the console is configured to use a framebuffer but none 138583da248Srz201010 * could be found, fallback to "ttya" since it's likely to exist 139583da248Srz201010 * and it matches longstanding behavior on SPARC. 140583da248Srz201010 */ 141583da248Srz201010 if (boot_console == CONS_SCREEN && plat_fbpath() == NULL) 142583da248Srz201010 boot_console = CONS_TTYA; 143583da248Srz201010 144ae115bc7Smrj return (boot_console); 145ae115bc7Smrj } 146ae115bc7Smrj 147ae115bc7Smrj int 148ae115bc7Smrj plat_stdin_is_keyboard(void) 149ae115bc7Smrj { 150ae115bc7Smrj return (console_type() == CONS_SCREEN); 151ae115bc7Smrj } 152ae115bc7Smrj 153ae115bc7Smrj int 154ae115bc7Smrj plat_stdout_is_framebuffer(void) 155ae115bc7Smrj { 156ae115bc7Smrj return (console_type() == CONS_SCREEN); 157ae115bc7Smrj } 158ae115bc7Smrj 159*78323854SJudy Chen static char * 160*78323854SJudy Chen plat_devpath(char *name, char *path) 161*78323854SJudy Chen { 162*78323854SJudy Chen major_t major; 163*78323854SJudy Chen dev_info_t *dip, *pdip; 164*78323854SJudy Chen 165*78323854SJudy Chen if ((major = ddi_name_to_major(name)) == (major_t)-1) 166*78323854SJudy Chen return (NULL); 167*78323854SJudy Chen 168*78323854SJudy Chen if ((dip = devnamesp[major].dn_head) == NULL) 169*78323854SJudy Chen return (NULL); 170*78323854SJudy Chen 171*78323854SJudy Chen pdip = ddi_get_parent(dip); 172*78323854SJudy Chen if (i_ddi_attach_node_hierarchy(pdip) != DDI_SUCCESS) 173*78323854SJudy Chen return (NULL); 174*78323854SJudy Chen if (ddi_initchild(pdip, dip) != DDI_SUCCESS) 175*78323854SJudy Chen return (NULL); 176*78323854SJudy Chen 177*78323854SJudy Chen (void) ddi_pathname(dip, path); 178*78323854SJudy Chen 179*78323854SJudy Chen return (path); 180*78323854SJudy Chen } 181*78323854SJudy Chen 182ae115bc7Smrj /* 183ae115bc7Smrj * Return generic path to keyboard device from the alias. 184ae115bc7Smrj */ 185ae115bc7Smrj char * 186ae115bc7Smrj plat_kbdpath(void) 187ae115bc7Smrj { 188*78323854SJudy Chen static char kbpath[MAXPATHLEN]; 189*78323854SJudy Chen 190ae115bc7Smrj /* 191ae115bc7Smrj * Hardcode to isa keyboard path 192ae115bc7Smrj * XXX make it settable via bootprop? 193ae115bc7Smrj */ 194*78323854SJudy Chen if (pseudo_isa) 195ae115bc7Smrj return ("/isa/i8042@1,60/keyboard@0"); 196*78323854SJudy Chen 197*78323854SJudy Chen if (plat_devpath("kb8042", kbpath) == NULL) 198*78323854SJudy Chen return (NULL); 199*78323854SJudy Chen 200*78323854SJudy Chen return (kbpath); 201ae115bc7Smrj } 202ae115bc7Smrj 203ae115bc7Smrj /* 204ae115bc7Smrj * Return generic path to display device from the alias. 205ae115bc7Smrj */ 206ae115bc7Smrj char * 207ae115bc7Smrj plat_fbpath(void) 208ae115bc7Smrj { 209ae115bc7Smrj static char *fbpath = NULL; 210ae115bc7Smrj static char fbpath_buf[MAXPATHLEN]; 211ae115bc7Smrj major_t major; 212843e1988Sjohnlev dev_info_t *dip, *dip_pseudo = NULL; 213ae115bc7Smrj int i; 214ae115bc7Smrj 215843e1988Sjohnlev /* lookup the dip for the pseudo device */ 216843e1988Sjohnlev (void) resolve_pathname("/pseudo", &dip_pseudo, NULL, NULL); 217843e1988Sjohnlev 218843e1988Sjohnlev for (i = 0; i < A_CNT(gfxdrv_name); i++) { 219ae115bc7Smrj /* 220ae115bc7Smrj * look for first instance of each driver 221ae115bc7Smrj */ 222843e1988Sjohnlev if ((major = ddi_name_to_major(gfxdrv_name[i])) == (major_t)-1) 223843e1988Sjohnlev continue; 224843e1988Sjohnlev 225843e1988Sjohnlev if ((dip = devnamesp[major].dn_head) == NULL) 226843e1988Sjohnlev continue; 227843e1988Sjohnlev 228843e1988Sjohnlev /* 229843e1988Sjohnlev * We're looking for a real hardware device here so skip 230843e1988Sjohnlev * any pseudo devices. When could a framebuffer hardware 231843e1988Sjohnlev * driver also have a pseudo node? Well, some framebuffer 232843e1988Sjohnlev * hardware drivers (nvidia) also create pseudo nodes for 233843e1988Sjohnlev * administration purposes, and these nodes will exist 234843e1988Sjohnlev * regardless of if the actual associated hardware 235843e1988Sjohnlev * is present or not. 236843e1988Sjohnlev */ 237843e1988Sjohnlev if (ddi_get_parent(dip) == dip_pseudo) 238843e1988Sjohnlev continue; 239843e1988Sjohnlev 240843e1988Sjohnlev if (i_ddi_attach_node_hierarchy(dip) == DDI_SUCCESS) { 241ae115bc7Smrj (void) ddi_pathname(dip, fbpath_buf); 242ae115bc7Smrj fbpath = fbpath_buf; 243ae115bc7Smrj } 244ae115bc7Smrj 245ae115bc7Smrj if (fbpath) 246843e1988Sjohnlev break; 247ae115bc7Smrj } 248ae115bc7Smrj 249843e1988Sjohnlev if (dip_pseudo != NULL) 250843e1988Sjohnlev ddi_release_devi(dip_pseudo); 251843e1988Sjohnlev 252ae115bc7Smrj /* No screen found */ 253843e1988Sjohnlev return (fbpath); 254ae115bc7Smrj } 255ae115bc7Smrj 256ae115bc7Smrj char * 257ae115bc7Smrj plat_mousepath(void) 258ae115bc7Smrj { 259*78323854SJudy Chen static char mpath[MAXPATHLEN]; 260*78323854SJudy Chen 261ae115bc7Smrj /* 262ae115bc7Smrj * Hardcode to isa mouse path 263ae115bc7Smrj * XXX make it settable via bootprop? 264ae115bc7Smrj */ 265*78323854SJudy Chen if (pseudo_isa) 266ae115bc7Smrj return ("/isa/i8042@1,60/mouse@1"); 267*78323854SJudy Chen 268*78323854SJudy Chen if (plat_devpath("mouse8042", mpath) == NULL) 269*78323854SJudy Chen return (NULL); 270*78323854SJudy Chen 271*78323854SJudy Chen return (mpath); 272ae115bc7Smrj } 273ae115bc7Smrj 274ae115bc7Smrj /* return path of first usb serial device */ 275ae115bc7Smrj static char * 276ae115bc7Smrj plat_usbser_path(void) 277ae115bc7Smrj { 278ae115bc7Smrj extern dev_info_t *usbser_first_device(void); 279ae115bc7Smrj 280ae115bc7Smrj dev_info_t *us_dip; 281ae115bc7Smrj static char *us_path = NULL; 282ae115bc7Smrj 283ae115bc7Smrj if (us_path) 284ae115bc7Smrj return (us_path); 285ae115bc7Smrj 286ae115bc7Smrj us_dip = usbser_first_device(); 287ae115bc7Smrj if (us_dip == NULL) 288ae115bc7Smrj return (NULL); 289ae115bc7Smrj 290ae115bc7Smrj us_path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 291ae115bc7Smrj (void) ddi_pathname(us_dip, us_path); 292ae115bc7Smrj ndi_rele_devi(us_dip); /* held from usbser_first_device */ 293ae115bc7Smrj return (us_path); 294ae115bc7Smrj } 295ae115bc7Smrj 296*78323854SJudy Chen static char * 297*78323854SJudy Chen plat_ttypath(int inum) 298*78323854SJudy Chen { 299*78323854SJudy Chen static char *defaultpath[] = { 300*78323854SJudy Chen "/isa/asy@1,3f8:a", 301*78323854SJudy Chen "/isa/asy@1,2f8:b" 302*78323854SJudy Chen }; 303*78323854SJudy Chen static char path[MAXPATHLEN]; 304*78323854SJudy Chen char *bp; 305*78323854SJudy Chen major_t major; 306*78323854SJudy Chen dev_info_t *dip; 307*78323854SJudy Chen 308*78323854SJudy Chen if (pseudo_isa) 309*78323854SJudy Chen return (defaultpath[inum]); 310*78323854SJudy Chen 311*78323854SJudy Chen if ((major = ddi_name_to_major("asy")) == (major_t)-1) 312*78323854SJudy Chen return (NULL); 313*78323854SJudy Chen 314*78323854SJudy Chen if ((dip = devnamesp[major].dn_head) == NULL) 315*78323854SJudy Chen return (NULL); 316*78323854SJudy Chen 317*78323854SJudy Chen while (inum-- > 0) { 318*78323854SJudy Chen if ((dip = ddi_get_next(dip)) == NULL) 319*78323854SJudy Chen return (NULL); 320*78323854SJudy Chen } 321*78323854SJudy Chen 322*78323854SJudy Chen if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS) 323*78323854SJudy Chen return (NULL); 324*78323854SJudy Chen 325*78323854SJudy Chen (void) ddi_pathname(dip, path); 326*78323854SJudy Chen bp = path + strlen(path); 327*78323854SJudy Chen (void) snprintf(bp, 3, ":%s", DEVI(dip)->devi_minor->ddm_name); 328*78323854SJudy Chen 329*78323854SJudy Chen return (path); 330*78323854SJudy Chen } 331*78323854SJudy Chen 332ae115bc7Smrj /* 333ae115bc7Smrj * Lacking support for com2 and com3, if that matters. 334ae115bc7Smrj * Another possible enhancement could be to use properties 335ae115bc7Smrj * for the port mapping rather than simply hard-code them. 336ae115bc7Smrj */ 337ae115bc7Smrj char * 338ae115bc7Smrj plat_stdinpath(void) 339ae115bc7Smrj { 340ae115bc7Smrj switch (console_type()) { 341843e1988Sjohnlev #if defined(__xpv) 342843e1988Sjohnlev case CONS_HYPERVISOR: 343843e1988Sjohnlev return ("/xpvd/xencons@0"); 344843e1988Sjohnlev #endif /* __xpv */ 345ae115bc7Smrj case CONS_TTYA: 346*78323854SJudy Chen return (plat_ttypath(0)); 347ae115bc7Smrj case CONS_TTYB: 348*78323854SJudy Chen return (plat_ttypath(1)); 349ae115bc7Smrj case CONS_USBSER: 350ae115bc7Smrj return (plat_usbser_path()); 351ae115bc7Smrj case CONS_SCREEN: 352ae115bc7Smrj default: 353ae115bc7Smrj break; 354ae115bc7Smrj }; 355ae115bc7Smrj return (plat_kbdpath()); 356ae115bc7Smrj } 357ae115bc7Smrj 358ae115bc7Smrj char * 359ae115bc7Smrj plat_stdoutpath(void) 360ae115bc7Smrj { 361ae115bc7Smrj switch (console_type()) { 362843e1988Sjohnlev #if defined(__xpv) 363843e1988Sjohnlev case CONS_HYPERVISOR: 364843e1988Sjohnlev return ("/xpvd/xencons@0"); 365843e1988Sjohnlev #endif /* __xpv */ 366ae115bc7Smrj case CONS_TTYA: 367*78323854SJudy Chen return (plat_ttypath(0)); 368ae115bc7Smrj case CONS_TTYB: 369*78323854SJudy Chen return (plat_ttypath(1)); 370ae115bc7Smrj case CONS_USBSER: 371ae115bc7Smrj return (plat_usbser_path()); 372ae115bc7Smrj case CONS_SCREEN: 373ae115bc7Smrj default: 374ae115bc7Smrj break; 375ae115bc7Smrj }; 376ae115bc7Smrj return (plat_fbpath()); 377ae115bc7Smrj } 378ae115bc7Smrj 379ae115bc7Smrj /* 380ae115bc7Smrj * If VIS_PIXEL mode will be implemented on x86, these following 381ae115bc7Smrj * functions should be re-considered. Now these functions are 382ae115bc7Smrj * unused on x86. 383ae115bc7Smrj */ 384ae115bc7Smrj void 385c9503a49Slq150181 plat_tem_get_inverses(int *inverse, int *inverse_screen) 386c9503a49Slq150181 { 387c9503a49Slq150181 *inverse = 0; 388c9503a49Slq150181 *inverse_screen = 0; 389c9503a49Slq150181 } 390c9503a49Slq150181 391c9503a49Slq150181 void 392ae115bc7Smrj plat_tem_get_prom_font_size(int *charheight, int *windowtop) 393ae115bc7Smrj { 394ae115bc7Smrj *charheight = 0; 395ae115bc7Smrj *windowtop = 0; 396ae115bc7Smrj } 397ae115bc7Smrj 398843e1988Sjohnlev /*ARGSUSED*/ 399ae115bc7Smrj void 400ae115bc7Smrj plat_tem_get_prom_size(size_t *height, size_t *width) 401ae115bc7Smrj { 402843e1988Sjohnlev panic("unimplemented at line %d of %s", __LINE__, __FILE__); 403ae115bc7Smrj } 404ae115bc7Smrj 405ae115bc7Smrj void 406ae115bc7Smrj plat_tem_hide_prom_cursor(void) 407ae115bc7Smrj { 408843e1988Sjohnlev panic("unimplemented at line %d of %s", __LINE__, __FILE__); 409ae115bc7Smrj } 410ae115bc7Smrj 411843e1988Sjohnlev /*ARGSUSED*/ 412ae115bc7Smrj void 413ae115bc7Smrj plat_tem_get_prom_pos(uint32_t *row, uint32_t *col) 414ae115bc7Smrj { 415843e1988Sjohnlev panic("unimplemented at line %d of %s", __LINE__, __FILE__); 416ae115bc7Smrj } 417