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