17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5fea9cb91Slq150181 * Common Development and Distribution License (the "License"). 6fea9cb91Slq150181 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21fea9cb91Slq150181 227c478bd9Sstevel@tonic-gate /* 23*018afb24SVincent Wang * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * This module performs two functions. First, it kicks off the driver loading 297c478bd9Sstevel@tonic-gate * of the console devices during boot in dynamic_console_config(). 307c478bd9Sstevel@tonic-gate * The loading of the drivers for the console devices triggers the 317c478bd9Sstevel@tonic-gate * additional device autoconfiguration to link the drivers into the keyboard 327c478bd9Sstevel@tonic-gate * and mouse console streams. 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * The second function of this module is to provide the dacf functions 357c478bd9Sstevel@tonic-gate * to be called after a driver has attached and before it detaches. For 367c478bd9Sstevel@tonic-gate * example, a driver associated with the keyboard will have kb_config called 377c478bd9Sstevel@tonic-gate * after the driver attaches and kb_unconfig before it detaches. Similar 387c478bd9Sstevel@tonic-gate * configuration actions are performed on behalf of minor nodes representing 397c478bd9Sstevel@tonic-gate * mice. The configuration functions for the attach case take a module 407c478bd9Sstevel@tonic-gate * name as a parameter. The module is pushed on top of the driver during 417c478bd9Sstevel@tonic-gate * the configuration. 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * Although the dacf framework is used to configure all keyboards and mice, 447c478bd9Sstevel@tonic-gate * its primary function is to allow keyboard and mouse hotplugging. 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * This module supports multiple keyboards and mice at the same time. 477c478bd9Sstevel@tonic-gate * 487c478bd9Sstevel@tonic-gate * From the kernel perspective, there are roughly three different possible 497c478bd9Sstevel@tonic-gate * console configurations. Across these three configurations, the following 507c478bd9Sstevel@tonic-gate * elements are constant: 517c478bd9Sstevel@tonic-gate * wsconsvp = IWSCN_PATH 527c478bd9Sstevel@tonic-gate * rwsconsvp = WC_PATH 537c478bd9Sstevel@tonic-gate * consms -> msdev 547c478bd9Sstevel@tonic-gate * 557c478bd9Sstevel@tonic-gate * The "->" syntax indicates that the streams device on the right is 567c478bd9Sstevel@tonic-gate * linked under the streams device on the left. 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * The following lists how the system is configured for different setups: 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * stdin is a local keyboard. use stdin and stdout as the console. 617c478bd9Sstevel@tonic-gate * sp->cons_input_type = CONSOLE_LOCAL 627c478bd9Sstevel@tonic-gate * rconsvp = IWSCN_PATH 637c478bd9Sstevel@tonic-gate * wc -> conskbd -> kbddev 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * stdin is not a keyboard and stdin is the same as stdout. 667c478bd9Sstevel@tonic-gate * assume we running on a tip line and use stdin/stdout as the console. 677c478bd9Sstevel@tonic-gate * sp->cons_input_type = CONSOLE_TIP 687c478bd9Sstevel@tonic-gate * rconsvp = (stdindev/stdoutdev) 697c478bd9Sstevel@tonic-gate * wc -> conskbd -> kbddev 707c478bd9Sstevel@tonic-gate * 717c478bd9Sstevel@tonic-gate * stdin is not a keyboard device and it's not the same as stdout. 727c478bd9Sstevel@tonic-gate * assume we have a serial keyboard hooked up and use it along with 737c478bd9Sstevel@tonic-gate * stdout as the console. 747c478bd9Sstevel@tonic-gate * sp->cons_input_type = CONSOLE_SERIAL_KEYBOARD 757c478bd9Sstevel@tonic-gate * rconsvp = IWSCN_PATH 767c478bd9Sstevel@tonic-gate * wc -> stdindev 777c478bd9Sstevel@tonic-gate * conskbd -> kbddev 787c478bd9Sstevel@tonic-gate * 797c478bd9Sstevel@tonic-gate * CAVEAT: 807c478bd9Sstevel@tonic-gate * The above is all true except for one possible Intel configuration. 817c478bd9Sstevel@tonic-gate * If stdin is set to a local keyboard but stdout is set to something 827c478bd9Sstevel@tonic-gate * other than the local display (a tip port for example) stdout will 837c478bd9Sstevel@tonic-gate * still go to the local display. This is an artifact of the console 847c478bd9Sstevel@tonic-gate * implementation on intel. 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #include <sys/types.h> 887c478bd9Sstevel@tonic-gate #include <sys/param.h> 897c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 907c478bd9Sstevel@tonic-gate #include <sys/user.h> 917c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 927c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 937c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 947c478bd9Sstevel@tonic-gate #include <sys/systm.h> 957c478bd9Sstevel@tonic-gate #include <sys/file.h> 967c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 977c478bd9Sstevel@tonic-gate #include <sys/stream.h> 987c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 101fea9cb91Slq150181 #include <sys/console.h> 102fea9cb91Slq150181 #include <sys/wscons.h> 1037c478bd9Sstevel@tonic-gate #include <sys/kbio.h> 1047c478bd9Sstevel@tonic-gate #include <sys/debug.h> 1057c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 1067c478bd9Sstevel@tonic-gate #include <sys/termios.h> 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 1097c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 1107c478bd9Sstevel@tonic-gate #include <sys/sunldi.h> 1117c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 1127c478bd9Sstevel@tonic-gate #include <sys/ndi_impldefs.h> 1137c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 1147c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 1157c478bd9Sstevel@tonic-gate #include <sys/ddi_implfuncs.h> 1167c478bd9Sstevel@tonic-gate #include <sys/promif.h> 1177c478bd9Sstevel@tonic-gate #include <sys/fs/snode.h> 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate #include <sys/errno.h> 1207c478bd9Sstevel@tonic-gate #include <sys/devops.h> 1217c478bd9Sstevel@tonic-gate #include <sys/note.h> 1227c478bd9Sstevel@tonic-gate 123fea9cb91Slq150181 #include <sys/tem_impl.h> 1247c478bd9Sstevel@tonic-gate #include <sys/polled_io.h> 1257c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 1267c478bd9Sstevel@tonic-gate #include <sys/dacf.h> 1277c478bd9Sstevel@tonic-gate #include <sys/consconfig_dacf.h> 128b52fe415Slipeng sang - Sun Microsystems - Beijing China #include <sys/consplat.h> 12928cdc3d7Sszhou #include <sys/log.h> 13028cdc3d7Sszhou #include <sys/disp.h> 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * External global variables 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate extern vnode_t *rconsvp; 1367c478bd9Sstevel@tonic-gate extern dev_t rwsconsdev; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * External functions 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate extern uintptr_t space_fetch(char *key); 1427c478bd9Sstevel@tonic-gate extern int space_store(char *key, uintptr_t ptr); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Tasks 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate static int kb_config(dacf_infohdl_t, dacf_arghdl_t, int); 1487c478bd9Sstevel@tonic-gate static int kb_unconfig(dacf_infohdl_t, dacf_arghdl_t, int); 1497c478bd9Sstevel@tonic-gate static int ms_config(dacf_infohdl_t, dacf_arghdl_t, int); 1507c478bd9Sstevel@tonic-gate static int ms_unconfig(dacf_infohdl_t, dacf_arghdl_t, int); 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * Internal functions 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate static int consconfig_setmodes(dev_t dev, struct termios *termiosp); 1567c478bd9Sstevel@tonic-gate static void consconfig_check_phys_kbd(cons_state_t *); 1577c478bd9Sstevel@tonic-gate static void consconfig_rem_dev(cons_state_t *, dev_t); 1587c478bd9Sstevel@tonic-gate static void consconfig_add_dev(cons_state_t *, cons_prop_t *); 1597c478bd9Sstevel@tonic-gate static cons_prop_t *consconfig_find_dev(cons_state_t *, dev_t); 1607c478bd9Sstevel@tonic-gate static void consconfig_free_prop(cons_prop_t *prop); 16148633f18SJan Setje-Eilers static void flush_deferred_console_buf(void); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * On supported configurations, the firmware defines the keyboard and mouse 1667c478bd9Sstevel@tonic-gate * paths. However, during USB development, it is useful to be able to use 1677c478bd9Sstevel@tonic-gate * the USB keyboard and mouse on machines without full USB firmware support. 1687c478bd9Sstevel@tonic-gate * These variables may be set in /etc/system according to a machine's 1697c478bd9Sstevel@tonic-gate * USB configuration. This module will override the firmware's values 1707c478bd9Sstevel@tonic-gate * with these. 1717c478bd9Sstevel@tonic-gate * 1727c478bd9Sstevel@tonic-gate * NOTE: 1737c478bd9Sstevel@tonic-gate * The master copies of these variables in the misc/consconfig module. 1747c478bd9Sstevel@tonic-gate * The reason for this is historic. In versions of solaris up to and 1757c478bd9Sstevel@tonic-gate * including solaris 9 the conscole configuration code was split into a 1767c478bd9Sstevel@tonic-gate * seperate sparc and intel version. These variables were defined 1777c478bd9Sstevel@tonic-gate * in misc/consconfig on sparc and dacf/consconfig_dacf on intel. 1787c478bd9Sstevel@tonic-gate * 1797c478bd9Sstevel@tonic-gate * Unfortunatly the sparc variables were well documented. 1807c478bd9Sstevel@tonic-gate * So to aviod breaking either sparc or intel we'll declare the variables 1817c478bd9Sstevel@tonic-gate * in both modules. This will allow any /etc/system entries that 1827c478bd9Sstevel@tonic-gate * users may have to continue working. 1837c478bd9Sstevel@tonic-gate * 1847c478bd9Sstevel@tonic-gate * The variables in misc/consconfig will take precedence over the variables 1857c478bd9Sstevel@tonic-gate * found in this file. Since we eventually want to remove the variables 1867c478bd9Sstevel@tonic-gate * local to this this file, if the user set them we'll emmit an error 1877c478bd9Sstevel@tonic-gate * message telling them they need to set the variables in misc/consconfig 1887c478bd9Sstevel@tonic-gate * instead. 1897c478bd9Sstevel@tonic-gate */ 1907c478bd9Sstevel@tonic-gate static char *usb_kb_path = NULL; 1917c478bd9Sstevel@tonic-gate static char *usb_ms_path = NULL; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* 1947c478bd9Sstevel@tonic-gate * Access functions in the misc/consconfig module used to retrieve the 1957c478bd9Sstevel@tonic-gate * values of it local usb_kb_path and usb_ms_path variables 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate extern char *consconfig_get_usb_kb_path(); 1987c478bd9Sstevel@tonic-gate extern char *consconfig_get_usb_ms_path(); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * Local variables used to store the value of the usb_kb_path and 2027c478bd9Sstevel@tonic-gate * usb_ms_path variables found in misc/consconfig 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate static char *consconfig_usb_kb_path = NULL; 2057c478bd9Sstevel@tonic-gate static char *consconfig_usb_ms_path = NULL; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * Internal variables 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate static dev_t stdoutdev; 211ae115bc7Smrj static cons_state_t *consconfig_sp; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * consconfig_errlevel: debug verbosity; smaller numbers are more 2157c478bd9Sstevel@tonic-gate * verbose. 2167c478bd9Sstevel@tonic-gate */ 217ae115bc7Smrj int consconfig_errlevel = DPRINT_L3; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Baud rate table 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate static struct speed { 2237c478bd9Sstevel@tonic-gate char *name; 2247c478bd9Sstevel@tonic-gate int code; 225de81e71eSTim Marsland } speedtab[] = { 2267c478bd9Sstevel@tonic-gate {"0", B0}, {"50", B50}, {"75", B75}, 2277c478bd9Sstevel@tonic-gate {"110", B110}, {"134", B134}, {"150", B150}, 2287c478bd9Sstevel@tonic-gate {"200", B200}, {"300", B300}, {"600", B600}, 2297c478bd9Sstevel@tonic-gate {"1200", B1200}, {"1800", B1800}, {"2400", B2400}, 2307c478bd9Sstevel@tonic-gate {"4800", B4800}, {"9600", B9600}, {"19200", B19200}, 2317c478bd9Sstevel@tonic-gate {"38400", B38400}, {"57600", B57600}, {"76800", B76800}, 2327c478bd9Sstevel@tonic-gate {"115200", B115200}, {"153600", B153600}, {"230400", B230400}, 233de81e71eSTim Marsland {"307200", B307200}, {"460800", B460800}, {"921600", B921600}, 234de81e71eSTim Marsland {"", 0} 2357c478bd9Sstevel@tonic-gate }; 2367c478bd9Sstevel@tonic-gate 237de81e71eSTim Marsland static const int MAX_SPEEDS = sizeof (speedtab) / sizeof (speedtab[0]); 238de81e71eSTim Marsland 2397c478bd9Sstevel@tonic-gate static dacf_op_t kbconfig_op[] = { 2407c478bd9Sstevel@tonic-gate { DACF_OPID_POSTATTACH, kb_config }, 2417c478bd9Sstevel@tonic-gate { DACF_OPID_PREDETACH, kb_unconfig }, 2427c478bd9Sstevel@tonic-gate { DACF_OPID_END, NULL }, 2437c478bd9Sstevel@tonic-gate }; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate static dacf_op_t msconfig_op[] = { 2467c478bd9Sstevel@tonic-gate { DACF_OPID_POSTATTACH, ms_config }, 2477c478bd9Sstevel@tonic-gate { DACF_OPID_PREDETACH, ms_unconfig }, 2487c478bd9Sstevel@tonic-gate { DACF_OPID_END, NULL }, 2497c478bd9Sstevel@tonic-gate }; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate static dacf_opset_t opsets[] = { 2527c478bd9Sstevel@tonic-gate { "kb_config", kbconfig_op }, 2537c478bd9Sstevel@tonic-gate { "ms_config", msconfig_op }, 2547c478bd9Sstevel@tonic-gate { NULL, NULL } 2557c478bd9Sstevel@tonic-gate }; 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate struct dacfsw dacfsw = { 2587c478bd9Sstevel@tonic-gate DACF_MODREV_1, 2597c478bd9Sstevel@tonic-gate opsets, 2607c478bd9Sstevel@tonic-gate }; 2617c478bd9Sstevel@tonic-gate 262e8ed0869SJohn Beck static struct modldacf modldacf = { 2637c478bd9Sstevel@tonic-gate &mod_dacfops, /* Type of module */ 264b52fe415Slipeng sang - Sun Microsystems - Beijing China "Consconfig DACF", 2657c478bd9Sstevel@tonic-gate &dacfsw 2667c478bd9Sstevel@tonic-gate }; 2677c478bd9Sstevel@tonic-gate 268e8ed0869SJohn Beck static struct modlinkage modlinkage = { 2697c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldacf, NULL 2707c478bd9Sstevel@tonic-gate }; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate int 2737c478bd9Sstevel@tonic-gate _init(void) { 2747c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate int 2787c478bd9Sstevel@tonic-gate _fini(void) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * This modules state is held in the kernel by space.c 2827c478bd9Sstevel@tonic-gate * allowing this module to be unloaded. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate int 2887c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 2947c478bd9Sstevel@tonic-gate static void consconfig_dprintf(int, const char *, ...) 2957c478bd9Sstevel@tonic-gate __KPRINTFLIKE(2); 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate static void 2987c478bd9Sstevel@tonic-gate consconfig_dprintf(int l, const char *fmt, ...) 2997c478bd9Sstevel@tonic-gate { 3007c478bd9Sstevel@tonic-gate va_list ap; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate #ifndef DEBUG 3037c478bd9Sstevel@tonic-gate if (!l) { 3047c478bd9Sstevel@tonic-gate return; 3057c478bd9Sstevel@tonic-gate } 306fea9cb91Slq150181 #endif /* DEBUG */ 3077c478bd9Sstevel@tonic-gate if (l < consconfig_errlevel) { 3087c478bd9Sstevel@tonic-gate return; 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate va_start(ap, fmt); 3127c478bd9Sstevel@tonic-gate (void) vprintf(fmt, ap); 3137c478bd9Sstevel@tonic-gate va_end(ap); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 317d0495a01Sedp * Return a property value for the specified alias in /aliases. 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate char * 3207c478bd9Sstevel@tonic-gate get_alias(char *alias, char *buf) 3217c478bd9Sstevel@tonic-gate { 322fa9e4066Sahrens pnode_t node; 323d0495a01Sedp int len; 3247c478bd9Sstevel@tonic-gate 325d0495a01Sedp /* The /aliases node only exists in OBP >= 2.4. */ 3267c478bd9Sstevel@tonic-gate if ((node = prom_alias_node()) == OBP_BADNODE) 3277c478bd9Sstevel@tonic-gate return (NULL); 3287c478bd9Sstevel@tonic-gate 329d0495a01Sedp if ((len = prom_getproplen(node, (caddr_t)alias)) <= 0) 3307c478bd9Sstevel@tonic-gate return (NULL); 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate (void) prom_getprop(node, (caddr_t)alias, (caddr_t)buf); 333d0495a01Sedp 334d0495a01Sedp /* 335d0495a01Sedp * The IEEE 1275 standard specifies that /aliases string property 336d0495a01Sedp * values should be null-terminated. Unfortunatly the reality 337d0495a01Sedp * is that most aren't and the OBP can't easily be modified to 338d0495a01Sedp * add null termination to these strings. So we'll add the 339d0495a01Sedp * null termination here. If the string already contains a 340d0495a01Sedp * null termination character then that's ok too because we'll 341d0495a01Sedp * just be adding a second one. 342d0495a01Sedp */ 343d0495a01Sedp buf[len] = '\0'; 344d0495a01Sedp 3457c478bd9Sstevel@tonic-gate prom_pathname(buf); 3467c478bd9Sstevel@tonic-gate return (buf); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * i_consconfig_createvp: 3517c478bd9Sstevel@tonic-gate * This routine is a convenience routine that is passed a path and returns 3527c478bd9Sstevel@tonic-gate * a vnode. 3537c478bd9Sstevel@tonic-gate */ 3547c478bd9Sstevel@tonic-gate static vnode_t * 3557c478bd9Sstevel@tonic-gate i_consconfig_createvp(char *path) 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate int error; 3587c478bd9Sstevel@tonic-gate vnode_t *vp; 3597c478bd9Sstevel@tonic-gate char *buf = NULL, *fullpath; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "i_consconfig_createvp: %s\n", path); 3627c478bd9Sstevel@tonic-gate fullpath = kmem_alloc(MAXPATHLEN, KM_SLEEP); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if (strchr(path, ':') == NULL) { 3657c478bd9Sstevel@tonic-gate /* convert an OBP path to a /devices path */ 3667c478bd9Sstevel@tonic-gate buf = kmem_alloc(MAXPATHLEN, KM_SLEEP); 3677c478bd9Sstevel@tonic-gate if (i_ddi_prompath_to_devfspath(path, buf) != DDI_SUCCESS) { 3687c478bd9Sstevel@tonic-gate kmem_free(buf, MAXPATHLEN); 3697c478bd9Sstevel@tonic-gate kmem_free(fullpath, MAXPATHLEN); 3707c478bd9Sstevel@tonic-gate return (NULL); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate (void) snprintf(fullpath, MAXPATHLEN, "/devices%s", buf); 3737c478bd9Sstevel@tonic-gate kmem_free(buf, MAXPATHLEN); 3747c478bd9Sstevel@tonic-gate } else { 3757c478bd9Sstevel@tonic-gate /* convert a devfs path to a /devices path */ 3767c478bd9Sstevel@tonic-gate (void) snprintf(fullpath, MAXPATHLEN, "/devices%s", path); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "lookupname(%s)\n", fullpath); 3807c478bd9Sstevel@tonic-gate error = lookupname(fullpath, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp); 3817c478bd9Sstevel@tonic-gate kmem_free(fullpath, MAXPATHLEN); 3827c478bd9Sstevel@tonic-gate if (error) 3837c478bd9Sstevel@tonic-gate return (NULL); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "create vnode = 0x%p - dev 0x%lx\n", vp, vp->v_rdev); 3867c478bd9Sstevel@tonic-gate ASSERT(vn_matchops(vp, spec_getvnodeops())); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate return (vp); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate /* 3927c478bd9Sstevel@tonic-gate * consconfig_print_paths: 3937c478bd9Sstevel@tonic-gate * Function to print out the various paths 3947c478bd9Sstevel@tonic-gate */ 3957c478bd9Sstevel@tonic-gate static void 3967c478bd9Sstevel@tonic-gate consconfig_print_paths(void) 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate char *path; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate if (usb_kb_path != NULL) 4017c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4027c478bd9Sstevel@tonic-gate "consconfig_dacf:usb_kb_path has been deprecated, " 4037c478bd9Sstevel@tonic-gate "use consconfig:usb_kb_path instead"); 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if (usb_ms_path != NULL) 4067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4077c478bd9Sstevel@tonic-gate "consconfig_dacf:usb_ms_path has been deprecated, " 4087c478bd9Sstevel@tonic-gate "use consconfig:usb_ms_path instead"); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if (consconfig_errlevel > DPRINT_L0) 4117c478bd9Sstevel@tonic-gate return; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate path = NULL; 4147c478bd9Sstevel@tonic-gate if (consconfig_usb_kb_path != NULL) 4157c478bd9Sstevel@tonic-gate path = consconfig_usb_kb_path; 4167c478bd9Sstevel@tonic-gate else if (usb_kb_path != NULL) 4177c478bd9Sstevel@tonic-gate path = usb_kb_path; 4187c478bd9Sstevel@tonic-gate if (path != NULL) 4197c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "usb keyboard path = %s\n", path); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate path = plat_kbdpath(); 4227c478bd9Sstevel@tonic-gate if (path != NULL) 4237c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "keyboard path = %s\n", path); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate path = NULL; 4267c478bd9Sstevel@tonic-gate if (consconfig_usb_ms_path != NULL) 4277c478bd9Sstevel@tonic-gate path = consconfig_usb_ms_path; 4287c478bd9Sstevel@tonic-gate else if (usb_ms_path != NULL) 4297c478bd9Sstevel@tonic-gate path = usb_ms_path; 4307c478bd9Sstevel@tonic-gate if (path != NULL) 4317c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "usb mouse path = %s\n", path); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate path = plat_mousepath(); 4347c478bd9Sstevel@tonic-gate if (path != NULL) 4357c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "mouse path = %s\n", path); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate path = plat_stdinpath(); 4387c478bd9Sstevel@tonic-gate if (path != NULL) 4397c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "stdin path = %s\n", path); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate path = plat_stdoutpath(); 4427c478bd9Sstevel@tonic-gate if (path != NULL) 4437c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "stdout path = %s\n", path); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate path = plat_fbpath(); 4467c478bd9Sstevel@tonic-gate if (path != NULL) 4477c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "fb path = %s\n", path); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * consconfig_kbd_abort_enable: 4527c478bd9Sstevel@tonic-gate * Send the CONSSETABORTENABLE ioctl to the lower layers. This ioctl 4537c478bd9Sstevel@tonic-gate * will only be sent to the device if it is the console device. 4547c478bd9Sstevel@tonic-gate * This ioctl tells the device to pay attention to abort sequences. 4557c478bd9Sstevel@tonic-gate * In the case of kbtrans, this would tell the driver to pay attention 4567c478bd9Sstevel@tonic-gate * to the two key abort sequences like STOP-A. In the case of the 4577c478bd9Sstevel@tonic-gate * serial keyboard, it would be an abort sequence like a break. 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate static int 4607c478bd9Sstevel@tonic-gate consconfig_kbd_abort_enable(ldi_handle_t lh) 4617c478bd9Sstevel@tonic-gate { 4627c478bd9Sstevel@tonic-gate int err, rval; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "consconfig_kbd_abort_enable\n"); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate err = ldi_ioctl(lh, CONSSETABORTENABLE, (uintptr_t)B_TRUE, 4677c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 4687c478bd9Sstevel@tonic-gate return (err); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate /* 4727c478bd9Sstevel@tonic-gate * consconfig_kbd_abort_disable: 4737c478bd9Sstevel@tonic-gate * Send CONSSETABORTENABLE ioctl to lower layers. This ioctl 4747c478bd9Sstevel@tonic-gate * will only be sent to the device if it is the console device. 4757c478bd9Sstevel@tonic-gate * This ioctl tells the physical device to ignore abort sequences, 4767c478bd9Sstevel@tonic-gate * and send the sequences up to virtual keyboard(conskbd) so that 4777c478bd9Sstevel@tonic-gate * STOP and A (or F1 and A) can be combined. 4787c478bd9Sstevel@tonic-gate */ 4797c478bd9Sstevel@tonic-gate static int 4807c478bd9Sstevel@tonic-gate consconfig_kbd_abort_disable(ldi_handle_t lh) 4817c478bd9Sstevel@tonic-gate { 4827c478bd9Sstevel@tonic-gate int err, rval; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "consconfig_kbd_abort_disable\n"); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate err = ldi_ioctl(lh, CONSSETABORTENABLE, (uintptr_t)B_FALSE, 4877c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 4887c478bd9Sstevel@tonic-gate return (err); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4911b83305cSjm22469 #ifdef _HAVE_TEM_FIRMWARE 4921b83305cSjm22469 static int 4931b83305cSjm22469 consconfig_tem_supported(cons_state_t *sp) 4941b83305cSjm22469 { 4951b83305cSjm22469 dev_t dev; 4961b83305cSjm22469 dev_info_t *dip; 4971b83305cSjm22469 int *int_array; 4981b83305cSjm22469 uint_t nint; 4991b83305cSjm22469 int rv = 0; 5001b83305cSjm22469 501aecfc01dSrui zang - Sun Microsystems - Beijing China if (sp->cons_fb_path == NULL) 502aecfc01dSrui zang - Sun Microsystems - Beijing China return (0); 503aecfc01dSrui zang - Sun Microsystems - Beijing China 5041b83305cSjm22469 if ((dev = ddi_pathname_to_dev_t(sp->cons_fb_path)) == NODEV) 5051b83305cSjm22469 return (0); /* warning printed later by common code */ 5061b83305cSjm22469 5071b83305cSjm22469 /* 5081b83305cSjm22469 * Here we hold the driver and check "tem-support" property. 5091b83305cSjm22469 * We're doing this with e_ddi_hold_devi_by_dev and 5101b83305cSjm22469 * ddi_prop_lookup_int_array without opening the driver since 5111b83305cSjm22469 * some video cards that don't support the kernel terminal 5121b83305cSjm22469 * emulator could hang or crash if opened too early during 5131b83305cSjm22469 * boot. 5141b83305cSjm22469 */ 5151b83305cSjm22469 if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) { 5161b83305cSjm22469 cmn_err(CE_WARN, "consconfig: cannot hold fb dev %s", 5171b83305cSjm22469 sp->cons_fb_path); 5181b83305cSjm22469 return (0); 5191b83305cSjm22469 } 5201b83305cSjm22469 5211b83305cSjm22469 /* 5221b83305cSjm22469 * Check that the tem-support property exists AND that 5231b83305cSjm22469 * it is equal to 1. 5241b83305cSjm22469 */ 5251b83305cSjm22469 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 5261b83305cSjm22469 DDI_PROP_DONTPASS, "tem-support", &int_array, &nint) == 5271b83305cSjm22469 DDI_SUCCESS) { 5281b83305cSjm22469 if (nint > 0) 5291b83305cSjm22469 rv = int_array[0] == 1; 5301b83305cSjm22469 ddi_prop_free(int_array); 5311b83305cSjm22469 } 5321b83305cSjm22469 5331b83305cSjm22469 ddi_release_devi(dip); 5341b83305cSjm22469 5351b83305cSjm22469 return (rv); 5361b83305cSjm22469 } 5371b83305cSjm22469 #endif /* _HAVE_TEM_FIRMWARE */ 5381b83305cSjm22469 5397c478bd9Sstevel@tonic-gate /* 5407c478bd9Sstevel@tonic-gate * consconfig_get_polledio: 5417c478bd9Sstevel@tonic-gate * Query the console with the CONSPOLLEDIO ioctl. 5427c478bd9Sstevel@tonic-gate * The polled I/O routines are used by debuggers to perform I/O while 5437c478bd9Sstevel@tonic-gate * interrupts and normal kernel services are disabled. 5447c478bd9Sstevel@tonic-gate */ 5457c478bd9Sstevel@tonic-gate static cons_polledio_t * 5467c478bd9Sstevel@tonic-gate consconfig_get_polledio(ldi_handle_t lh) 5477c478bd9Sstevel@tonic-gate { 5487c478bd9Sstevel@tonic-gate int err, rval; 5497c478bd9Sstevel@tonic-gate struct strioctl strioc; 5507c478bd9Sstevel@tonic-gate cons_polledio_t *polled_io; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* 5537c478bd9Sstevel@tonic-gate * Setup the ioctl to be sent down to the lower driver. 5547c478bd9Sstevel@tonic-gate */ 5557c478bd9Sstevel@tonic-gate strioc.ic_cmd = CONSOPENPOLLEDIO; 5567c478bd9Sstevel@tonic-gate strioc.ic_timout = INFTIM; 5577c478bd9Sstevel@tonic-gate strioc.ic_len = sizeof (polled_io); 5587c478bd9Sstevel@tonic-gate strioc.ic_dp = (char *)&polled_io; 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate /* 5617c478bd9Sstevel@tonic-gate * Send the ioctl to the driver. The ioctl will wait for 5627c478bd9Sstevel@tonic-gate * the response to come back from wc. wc has already issued 5637c478bd9Sstevel@tonic-gate * the CONSOPENPOLLEDIO to the lower layer driver. 5647c478bd9Sstevel@tonic-gate */ 5657c478bd9Sstevel@tonic-gate err = ldi_ioctl(lh, I_STR, (intptr_t)&strioc, FKIOCTL, kcred, &rval); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate if (err != 0) { 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * If the lower driver does not support polled I/O, then 5707c478bd9Sstevel@tonic-gate * return NULL. This will be the case if the driver does 5717c478bd9Sstevel@tonic-gate * not handle polled I/O, or OBP is going to handle polled 5727c478bd9Sstevel@tonic-gate * I/O for the device. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate return (NULL); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * Return the polled I/O structure. 5807c478bd9Sstevel@tonic-gate */ 5817c478bd9Sstevel@tonic-gate return (polled_io); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* 5857c478bd9Sstevel@tonic-gate * consconfig_setup_polledio: 5867c478bd9Sstevel@tonic-gate * This routine does the setup work for polled I/O. First we get 5877c478bd9Sstevel@tonic-gate * the polled_io structure from the lower layers 5887c478bd9Sstevel@tonic-gate * and then we register the polled I/O 5897c478bd9Sstevel@tonic-gate * callbacks with the debugger that will be using them. 5907c478bd9Sstevel@tonic-gate */ 5917c478bd9Sstevel@tonic-gate static void 5927c478bd9Sstevel@tonic-gate consconfig_setup_polledio(cons_state_t *sp, dev_t dev) 5937c478bd9Sstevel@tonic-gate { 5947c478bd9Sstevel@tonic-gate cons_polledio_t *polled_io; 5957c478bd9Sstevel@tonic-gate ldi_handle_t lh; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "consconfig_setup_polledio: start\n"); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (ldi_open_by_dev(&dev, OTYP_CHR, 6017c478bd9Sstevel@tonic-gate FREAD|FWRITE|FNOCTTY, kcred, &lh, sp->cons_li) != 0) 6027c478bd9Sstevel@tonic-gate return; 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate /* 6067c478bd9Sstevel@tonic-gate * Get the polled io routines so that we can use this 6077c478bd9Sstevel@tonic-gate * device with the debuggers. 6087c478bd9Sstevel@tonic-gate */ 6097c478bd9Sstevel@tonic-gate polled_io = consconfig_get_polledio(lh); 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * If the get polledio failed, then we do not want to throw 6137c478bd9Sstevel@tonic-gate * the polled I/O switch. 6147c478bd9Sstevel@tonic-gate */ 6157c478bd9Sstevel@tonic-gate if (polled_io == NULL) { 6167c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, 6177c478bd9Sstevel@tonic-gate "consconfig_setup_polledio: get_polledio failed\n"); 6187c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, kcred); 6197c478bd9Sstevel@tonic-gate return; 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate /* Initialize the polled input */ 6237c478bd9Sstevel@tonic-gate polled_io_init(); 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate /* Register the callbacks */ 6267c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, 6277c478bd9Sstevel@tonic-gate "consconfig_setup_polledio: registering callbacks\n"); 6287c478bd9Sstevel@tonic-gate (void) polled_io_register_callbacks(polled_io, 0); 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, kcred); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "consconfig_setup_polledio: end\n"); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate static cons_state_t * 6367c478bd9Sstevel@tonic-gate consconfig_state_init(void) 6377c478bd9Sstevel@tonic-gate { 6387c478bd9Sstevel@tonic-gate cons_state_t *sp; 6397c478bd9Sstevel@tonic-gate int rval; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate /* Initialize console information */ 6427c478bd9Sstevel@tonic-gate sp = kmem_zalloc(sizeof (cons_state_t), KM_SLEEP); 6437c478bd9Sstevel@tonic-gate sp->cons_keyboard_problem = B_FALSE; 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate mutex_init(&sp->cons_lock, NULL, MUTEX_DRIVER, NULL); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate /* check if consconfig:usb_kb_path is set in /etc/system */ 6487c478bd9Sstevel@tonic-gate consconfig_usb_kb_path = consconfig_get_usb_kb_path(); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate /* check if consconfig:usb_ms_path is set in /etc/system */ 6517c478bd9Sstevel@tonic-gate consconfig_usb_ms_path = consconfig_get_usb_ms_path(); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate consconfig_print_paths(); 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate /* init external globals */ 6567c478bd9Sstevel@tonic-gate stdoutdev = NODEV; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate /* 6597c478bd9Sstevel@tonic-gate * Find keyboard, mouse, stdin and stdout devices, if they 6607c478bd9Sstevel@tonic-gate * exist on this platform. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (consconfig_usb_kb_path != NULL) { 6647c478bd9Sstevel@tonic-gate sp->cons_keyboard_path = consconfig_usb_kb_path; 6657c478bd9Sstevel@tonic-gate } else if (usb_kb_path != NULL) { 6667c478bd9Sstevel@tonic-gate sp->cons_keyboard_path = usb_kb_path; 6677c478bd9Sstevel@tonic-gate } else { 6687c478bd9Sstevel@tonic-gate sp->cons_keyboard_path = plat_kbdpath(); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (consconfig_usb_ms_path != NULL) { 6727c478bd9Sstevel@tonic-gate sp->cons_mouse_path = consconfig_usb_ms_path; 6737c478bd9Sstevel@tonic-gate } else if (usb_ms_path != NULL) { 6747c478bd9Sstevel@tonic-gate sp->cons_mouse_path = usb_ms_path; 6757c478bd9Sstevel@tonic-gate } else { 6767c478bd9Sstevel@tonic-gate sp->cons_mouse_path = plat_mousepath(); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* Identify the stdout driver */ 6807c478bd9Sstevel@tonic-gate sp->cons_stdout_path = plat_stdoutpath(); 6811b83305cSjm22469 sp->cons_stdout_is_fb = plat_stdout_is_framebuffer(); 6827c478bd9Sstevel@tonic-gate 6831b83305cSjm22469 sp->cons_stdin_is_kbd = plat_stdin_is_keyboard(); 6841b83305cSjm22469 6851b83305cSjm22469 if (sp->cons_stdin_is_kbd && 686f65f434dSry162471 (usb_kb_path != NULL || consconfig_usb_kb_path != NULL)) { 6877c478bd9Sstevel@tonic-gate sp->cons_stdin_path = sp->cons_keyboard_path; 6887c478bd9Sstevel@tonic-gate } else { 6897c478bd9Sstevel@tonic-gate /* 6907c478bd9Sstevel@tonic-gate * The standard in device may or may not be the same as 6917c478bd9Sstevel@tonic-gate * the keyboard. Even if the keyboard is not the 6927c478bd9Sstevel@tonic-gate * standard input, the keyboard console stream will 6937c478bd9Sstevel@tonic-gate * still be built if the keyboard alias provided by the 6947c478bd9Sstevel@tonic-gate * firmware exists and is valid. 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate sp->cons_stdin_path = plat_stdinpath(); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6991b83305cSjm22469 if (sp->cons_stdout_is_fb) { 7001b83305cSjm22469 sp->cons_fb_path = sp->cons_stdout_path; 7011b83305cSjm22469 7021b83305cSjm22469 #ifdef _HAVE_TEM_FIRMWARE 7031b83305cSjm22469 sp->cons_tem_supported = consconfig_tem_supported(sp); 7041b83305cSjm22469 7051b83305cSjm22469 /* 7061b83305cSjm22469 * Systems which offer a virtual console must use that 7071b83305cSjm22469 * as a fallback whenever the fb doesn't support tem. 7081b83305cSjm22469 * Such systems cannot render characters to the screen 7091b83305cSjm22469 * using OBP. 7101b83305cSjm22469 */ 7111b83305cSjm22469 if (!sp->cons_tem_supported) { 7121b83305cSjm22469 char *path; 7131b83305cSjm22469 7141b83305cSjm22469 if (plat_virtual_console_path(&path) >= 0) { 7151b83305cSjm22469 sp->cons_stdin_is_kbd = 0; 7161b83305cSjm22469 sp->cons_stdout_is_fb = 0; 7171b83305cSjm22469 sp->cons_stdin_path = path; 7181b83305cSjm22469 sp->cons_stdout_path = path; 7191b83305cSjm22469 sp->cons_fb_path = plat_fbpath(); 7201b83305cSjm22469 7211b83305cSjm22469 cmn_err(CE_WARN, 7221b83305cSjm22469 "%s doesn't support terminal emulation " 7231b83305cSjm22469 "mode; switching to virtual console.", 7241b83305cSjm22469 sp->cons_fb_path); 7251b83305cSjm22469 } 7261b83305cSjm22469 } 7271b83305cSjm22469 #endif /* _HAVE_TEM_FIRMWARE */ 7281b83305cSjm22469 } else { 7291b83305cSjm22469 sp->cons_fb_path = plat_fbpath(); 730aecfc01dSrui zang - Sun Microsystems - Beijing China #ifdef _HAVE_TEM_FIRMWARE 731aecfc01dSrui zang - Sun Microsystems - Beijing China sp->cons_tem_supported = consconfig_tem_supported(sp); 732aecfc01dSrui zang - Sun Microsystems - Beijing China #endif /* _HAVE_TEM_FIRMWARE */ 7331b83305cSjm22469 } 7341b83305cSjm22469 7357c478bd9Sstevel@tonic-gate sp->cons_li = ldi_ident_from_anon(); 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* Save the pointer for retrieval by the dacf functions */ 7387c478bd9Sstevel@tonic-gate rval = space_store("consconfig", (uintptr_t)sp); 7397c478bd9Sstevel@tonic-gate ASSERT(rval == 0); 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate return (sp); 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate static int 7457c478bd9Sstevel@tonic-gate consconfig_relink_wc(cons_state_t *sp, ldi_handle_t new_lh, int *muxid) 7467c478bd9Sstevel@tonic-gate { 7477c478bd9Sstevel@tonic-gate int err, rval; 7487c478bd9Sstevel@tonic-gate ldi_handle_t wc_lh; 7497c478bd9Sstevel@tonic-gate dev_t wc_dev; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate ASSERT(muxid != NULL); 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate /* 7547c478bd9Sstevel@tonic-gate * NOTE: we could be in a dacf callback context right now. normally 7557c478bd9Sstevel@tonic-gate * it's not legal to call any ldi_open_*() function from this context 7567c478bd9Sstevel@tonic-gate * because we're currently holding device tree locks and if the 7577c478bd9Sstevel@tonic-gate * ldi_open_*() call could try to acquire other device tree locks 7587c478bd9Sstevel@tonic-gate * (to attach the device we're trying to open.) if this happens then 7597c478bd9Sstevel@tonic-gate * we could deadlock. To avoid this situation, during initialization 7607c478bd9Sstevel@tonic-gate * we made sure to grab a hold on the dip of the device we plan to 7617c478bd9Sstevel@tonic-gate * open so that it can never be detached. Then we use 7627c478bd9Sstevel@tonic-gate * ldi_open_by_dev() to actually open the device since it will see 7637c478bd9Sstevel@tonic-gate * that the device is already attached and held and instead of 7647c478bd9Sstevel@tonic-gate * acquire any locks it will only increase the reference count 7657c478bd9Sstevel@tonic-gate * on the device. 7667c478bd9Sstevel@tonic-gate */ 7677c478bd9Sstevel@tonic-gate wc_dev = sp->cons_wc_vp->v_rdev; 7687c478bd9Sstevel@tonic-gate err = ldi_open_by_dev(&wc_dev, OTYP_CHR, FREAD|FWRITE|FNOCTTY, 7697c478bd9Sstevel@tonic-gate kcred, &wc_lh, sp->cons_li); 7707c478bd9Sstevel@tonic-gate ASSERT(wc_dev == sp->cons_wc_vp->v_rdev); 7717c478bd9Sstevel@tonic-gate if (err) { 7727c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_wc: " 7737c478bd9Sstevel@tonic-gate "unable to open wc device"); 7747c478bd9Sstevel@tonic-gate return (err); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate if (new_lh != NULL) { 7787c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "linking stream under wc\n"); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate err = ldi_ioctl(wc_lh, I_PLINK, (uintptr_t)new_lh, 7817c478bd9Sstevel@tonic-gate FKIOCTL, kcred, muxid); 7827c478bd9Sstevel@tonic-gate if (err != 0) { 7837c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_wc: " 7847c478bd9Sstevel@tonic-gate "wc link failed, error %d", err); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate } else { 7877c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "unlinking stream from under wc\n"); 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate err = ldi_ioctl(wc_lh, I_PUNLINK, *muxid, 7907c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 7917c478bd9Sstevel@tonic-gate if (err != 0) { 7927c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_wc: " 7937c478bd9Sstevel@tonic-gate "wc unlink failed, error %d", err); 7947c478bd9Sstevel@tonic-gate } else { 7957c478bd9Sstevel@tonic-gate *muxid = -1; 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate } 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate (void) ldi_close(wc_lh, FREAD|FWRITE, kcred); 8007c478bd9Sstevel@tonic-gate return (err); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate static void 8047c478bd9Sstevel@tonic-gate cons_build_upper_layer(cons_state_t *sp) 8057c478bd9Sstevel@tonic-gate { 806fea9cb91Slq150181 ldi_handle_t wc_lh; 807fea9cb91Slq150181 struct strioctl strioc; 808fea9cb91Slq150181 int rval; 809fea9cb91Slq150181 dev_t dev; 8101b83305cSjm22469 dev_t wc_dev; 811fea9cb91Slq150181 8127c478bd9Sstevel@tonic-gate /* 8137c478bd9Sstevel@tonic-gate * Build the wc->conskbd portion of the keyboard console stream. 8147c478bd9Sstevel@tonic-gate * Even if no keyboard is attached to the system, the upper 8157c478bd9Sstevel@tonic-gate * layer of the stream will be built. If the user attaches 8167c478bd9Sstevel@tonic-gate * a keyboard after the system is booted, the keyboard driver 8177c478bd9Sstevel@tonic-gate * and module will be linked under conskbd. 8187c478bd9Sstevel@tonic-gate * 8197c478bd9Sstevel@tonic-gate * Errors are generally ignored here because conskbd and wc 8207c478bd9Sstevel@tonic-gate * are pseudo drivers and should be present on the system. 8217c478bd9Sstevel@tonic-gate */ 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate /* open the console keyboard device. will never be closed */ 824ae115bc7Smrj if (ldi_open_by_name(CONSKBD_PATH, FREAD|FWRITE|FNOCTTY, 825ae115bc7Smrj kcred, &sp->conskbd_lh, sp->cons_li) != 0) { 826ae115bc7Smrj panic("consconfig: unable to open conskbd device"); 827ae115bc7Smrj /*NOTREACHED*/ 828ae115bc7Smrj } 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "conskbd_lh = %p\n", sp->conskbd_lh); 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate /* open the console mouse device. will never be closed */ 833ae115bc7Smrj if (ldi_open_by_name(CONSMS_PATH, FREAD|FWRITE|FNOCTTY, 834ae115bc7Smrj kcred, &sp->consms_lh, sp->cons_li) != 0) { 835ae115bc7Smrj panic("consconfig: unable to open consms device"); 836ae115bc7Smrj /*NOTREACHED*/ 837ae115bc7Smrj } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "consms_lh = %p\n", sp->consms_lh); 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate /* 8427c478bd9Sstevel@tonic-gate * Get a vnode for the wc device and then grab a hold on the 8437c478bd9Sstevel@tonic-gate * device dip so it can never detach. We need to do this now 8447c478bd9Sstevel@tonic-gate * because later we'll have to open the wc device in a context 8457c478bd9Sstevel@tonic-gate * were it isn't safe to acquire any device tree locks (ie, during 8467c478bd9Sstevel@tonic-gate * a dacf callback.) 8477c478bd9Sstevel@tonic-gate */ 8487c478bd9Sstevel@tonic-gate sp->cons_wc_vp = i_consconfig_createvp(WC_PATH); 8497c478bd9Sstevel@tonic-gate if (sp->cons_wc_vp == NULL) 8507c478bd9Sstevel@tonic-gate panic("consconfig: unable to find wc device"); 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate if (e_ddi_hold_devi_by_dev(sp->cons_wc_vp->v_rdev, 0) == NULL) 8537c478bd9Sstevel@tonic-gate panic("consconfig: unable to hold wc device"); 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate /* 8567c478bd9Sstevel@tonic-gate * Build the wc->conskbd portion of the keyboard console stream. 8577c478bd9Sstevel@tonic-gate * Even if no keyboard is attached to the system, the upper 8587c478bd9Sstevel@tonic-gate * layer of the stream will be built. If the user attaches 8597c478bd9Sstevel@tonic-gate * a keyboard after the system is booted, the keyboard driver 8607c478bd9Sstevel@tonic-gate * and module will be linked under conskbd. 8617c478bd9Sstevel@tonic-gate * 8627c478bd9Sstevel@tonic-gate * The act of linking conskbd under wc will cause wc to 8637c478bd9Sstevel@tonic-gate * query the lower layers about their polled I/O routines 8647c478bd9Sstevel@tonic-gate * using CONSOPENPOLLEDIO. This will fail on this link because 8657c478bd9Sstevel@tonic-gate * there is not a physical keyboard linked under conskbd. 8667c478bd9Sstevel@tonic-gate * 8677c478bd9Sstevel@tonic-gate * Since conskbd and wc are pseudo drivers, errors are 8687c478bd9Sstevel@tonic-gate * generally ignored when linking and unlinking them. 8697c478bd9Sstevel@tonic-gate */ 8707c478bd9Sstevel@tonic-gate (void) consconfig_relink_wc(sp, sp->conskbd_lh, &sp->conskbd_muxid); 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate /* 8737c478bd9Sstevel@tonic-gate * Get a vnode for the redirection device. (It has the 8747c478bd9Sstevel@tonic-gate * connection to the workstation console device wired into it, 8757c478bd9Sstevel@tonic-gate * so that it's not necessary to establish the connection 8767c478bd9Sstevel@tonic-gate * here. If the redirection device is ever generalized to 8777c478bd9Sstevel@tonic-gate * handle multiple client devices, it won't be able to 8787c478bd9Sstevel@tonic-gate * establish the connection itself, and we'll have to do it 8797c478bd9Sstevel@tonic-gate * here.) 8807c478bd9Sstevel@tonic-gate */ 8817c478bd9Sstevel@tonic-gate wsconsvp = i_consconfig_createvp(IWSCN_PATH); 882ae115bc7Smrj if (wsconsvp == NULL) { 883ae115bc7Smrj panic("consconfig: unable to find iwscn device"); 884ae115bc7Smrj /*NOTREACHED*/ 885ae115bc7Smrj } 8867c478bd9Sstevel@tonic-gate 887fea9cb91Slq150181 if (cons_tem_disable) 8887c478bd9Sstevel@tonic-gate return; 889fea9cb91Slq150181 890fea9cb91Slq150181 if (sp->cons_fb_path == NULL) { 891ae115bc7Smrj #if defined(__x86) 8921b83305cSjm22469 if (sp->cons_stdout_is_fb) 893fea9cb91Slq150181 cmn_err(CE_WARN, "consconfig: no screen found"); 894ae115bc7Smrj #endif 895fea9cb91Slq150181 return; 896fea9cb91Slq150181 } 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate /* make sure the frame buffer device exists */ 899fea9cb91Slq150181 dev = ddi_pathname_to_dev_t(sp->cons_fb_path); 900fea9cb91Slq150181 if (dev == NODEV) { 901fea9cb91Slq150181 cmn_err(CE_WARN, "consconfig: " 9027c478bd9Sstevel@tonic-gate "cannot find driver for screen device %s", 9037c478bd9Sstevel@tonic-gate sp->cons_fb_path); 9047c478bd9Sstevel@tonic-gate return; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate 907fea9cb91Slq150181 #ifdef _HAVE_TEM_FIRMWARE 908fea9cb91Slq150181 /* 9091b83305cSjm22469 * If the underlying fb device doesn't support terminal emulation, 9101b83305cSjm22469 * we don't want to open the wc device (below) because it depends 9111b83305cSjm22469 * on features which aren't available (polled mode io). 912fea9cb91Slq150181 */ 9131b83305cSjm22469 if (!sp->cons_tem_supported) 914fea9cb91Slq150181 return; 915fea9cb91Slq150181 #endif /* _HAVE_TEM_FIRMWARE */ 916fea9cb91Slq150181 9177c478bd9Sstevel@tonic-gate /* tell wc to open the frame buffer device */ 9187c478bd9Sstevel@tonic-gate wc_dev = sp->cons_wc_vp->v_rdev; 919fea9cb91Slq150181 if (ldi_open_by_dev(&wc_dev, OTYP_CHR, FREAD|FWRITE|FNOCTTY, kcred, 920fea9cb91Slq150181 &wc_lh, sp->cons_li)) { 921fea9cb91Slq150181 cmn_err(CE_PANIC, "cons_build_upper_layer: " 9227c478bd9Sstevel@tonic-gate "unable to open wc device"); 923fea9cb91Slq150181 return; 9247c478bd9Sstevel@tonic-gate } 925fea9cb91Slq150181 ASSERT(wc_dev == sp->cons_wc_vp->v_rdev); 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate strioc.ic_cmd = WC_OPEN_FB; 9287c478bd9Sstevel@tonic-gate strioc.ic_timout = INFTIM; 9297c478bd9Sstevel@tonic-gate strioc.ic_len = strlen(sp->cons_fb_path) + 1; 9307c478bd9Sstevel@tonic-gate strioc.ic_dp = sp->cons_fb_path; 9317c478bd9Sstevel@tonic-gate 932fea9cb91Slq150181 if (ldi_ioctl(wc_lh, I_STR, (intptr_t)&strioc, 933fea9cb91Slq150181 FKIOCTL, kcred, &rval) == 0) 934fea9cb91Slq150181 consmode = CONS_KFB; 935fea9cb91Slq150181 else 936fea9cb91Slq150181 cmn_err(CE_WARN, 937fea9cb91Slq150181 "consconfig: terminal emulator failed to initialize"); 9387c478bd9Sstevel@tonic-gate (void) ldi_close(wc_lh, FREAD|FWRITE, kcred); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate static void 9427c478bd9Sstevel@tonic-gate consconfig_load_drivers(cons_state_t *sp) 9437c478bd9Sstevel@tonic-gate { 9447c478bd9Sstevel@tonic-gate /* 945*018afb24SVincent Wang * Calling ddi_pathname_to_dev_t may cause the USB Host Controller 946*018afb24SVincent Wang * drivers to be loaded. Here we make sure that EHCI is loaded 947*018afb24SVincent Wang * earlier than {U, O}HCI. The order here is important. As 948*018afb24SVincent Wang * we have observed many systems on which hangs occur if the 949*018afb24SVincent Wang * {U,O}HCI companion controllers take over control from the BIOS 950*018afb24SVincent Wang * before EHCI does. These hangs are also caused by BIOSes leaving 951*018afb24SVincent Wang * interrupt-on-port-change enabled in the ehci controller, so that 952*018afb24SVincent Wang * when uhci/ohci reset themselves, it induces a port change on 953*018afb24SVincent Wang * the ehci companion controller. Since there's no interrupt handler 954*018afb24SVincent Wang * installed at the time, the moment that interrupt is unmasked, an 955*018afb24SVincent Wang * interrupt storm will occur. All this is averted when ehci is 956*018afb24SVincent Wang * loaded first. And now you know..... the REST of the story. 957*018afb24SVincent Wang * 958*018afb24SVincent Wang * Regardless of platform, ehci needs to initialize first to avoid 959*018afb24SVincent Wang * unnecessary connects and disconnects on the companion controller 960*018afb24SVincent Wang * when ehci sets up the routing. 961*018afb24SVincent Wang */ 962*018afb24SVincent Wang (void) ddi_hold_installed_driver(ddi_name_to_major("ehci")); 963*018afb24SVincent Wang (void) ddi_hold_installed_driver(ddi_name_to_major("uhci")); 964*018afb24SVincent Wang (void) ddi_hold_installed_driver(ddi_name_to_major("ohci")); 965*018afb24SVincent Wang 966*018afb24SVincent Wang /* 9677c478bd9Sstevel@tonic-gate * The attaching of the drivers will cause the creation of the 9687c478bd9Sstevel@tonic-gate * keyboard and mouse minor nodes, which will in turn trigger the 9697c478bd9Sstevel@tonic-gate * dacf framework to call the keyboard and mouse configuration 9707c478bd9Sstevel@tonic-gate * tasks. See PSARC/1998/212 for more details about the dacf 9717c478bd9Sstevel@tonic-gate * framework. 9727c478bd9Sstevel@tonic-gate * 9737c478bd9Sstevel@tonic-gate * on sparc, when the console is ttya, zs0 is stdin/stdout, and zs1 9747c478bd9Sstevel@tonic-gate * is kb/mouse. zs0 must be attached before zs1. The zs driver 9757c478bd9Sstevel@tonic-gate * is written this way and the hardware may depend on this, too. 9767c478bd9Sstevel@tonic-gate * It would be better to enforce this by attaching zs in sibling 9777c478bd9Sstevel@tonic-gate * order with a driver property, such as ddi-attachall. 9787c478bd9Sstevel@tonic-gate */ 9797c478bd9Sstevel@tonic-gate if (sp->cons_stdin_path != NULL) 9807c478bd9Sstevel@tonic-gate stdindev = ddi_pathname_to_dev_t(sp->cons_stdin_path); 9817c478bd9Sstevel@tonic-gate if (stdindev == NODEV) { 9827c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, 9837c478bd9Sstevel@tonic-gate "!fail to attach stdin: %s\n", sp->cons_stdin_path); 9847c478bd9Sstevel@tonic-gate } 9857c478bd9Sstevel@tonic-gate if (sp->cons_stdout_path != NULL) 9867c478bd9Sstevel@tonic-gate stdoutdev = ddi_pathname_to_dev_t(sp->cons_stdout_path); 9877c478bd9Sstevel@tonic-gate if (sp->cons_keyboard_path != NULL) 9887c478bd9Sstevel@tonic-gate kbddev = ddi_pathname_to_dev_t(sp->cons_keyboard_path); 9897c478bd9Sstevel@tonic-gate if (sp->cons_mouse_path != NULL) 9907c478bd9Sstevel@tonic-gate mousedev = ddi_pathname_to_dev_t(sp->cons_mouse_path); 991ae115bc7Smrj 992ae115bc7Smrj /* 993ae115bc7Smrj * On x86, make sure the fb driver is loaded even if we don't use it 994ae115bc7Smrj * for the console. This will ensure that we create a /dev/fb link 995ae115bc7Smrj * which is required to start Xorg. 996ae115bc7Smrj */ 997ae115bc7Smrj #if defined(__x86) 998ae115bc7Smrj if (sp->cons_fb_path != NULL) 999ae115bc7Smrj fbdev = ddi_pathname_to_dev_t(sp->cons_fb_path); 1000ae115bc7Smrj #endif 1001ae115bc7Smrj 10027c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "stdindev %lx, stdoutdev %lx, kbddev %lx, " 10037c478bd9Sstevel@tonic-gate "mousedev %lx\n", stdindev, stdoutdev, kbddev, mousedev); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 1006361ed64aSJames Anderson #if !defined(__x86) 1007361ed64aSJames Anderson void 1008361ed64aSJames Anderson consconfig_virtual_console_vp(cons_state_t *sp) 1009361ed64aSJames Anderson { 1010361ed64aSJames Anderson char *virtual_cons_path; 1011361ed64aSJames Anderson 1012361ed64aSJames Anderson if (plat_virtual_console_path(&virtual_cons_path) < 0) 1013361ed64aSJames Anderson return; 1014361ed64aSJames Anderson 1015361ed64aSJames Anderson DPRINTF(DPRINT_L0, "consconfig_virtual_console_vp: " 1016361ed64aSJames Anderson "virtual console device path %s\n", virtual_cons_path); 1017361ed64aSJames Anderson 1018361ed64aSJames Anderson ASSERT(sp->cons_stdout_path != NULL); 1019361ed64aSJames Anderson if (strcmp(virtual_cons_path, sp->cons_stdout_path) == 0) { 1020361ed64aSJames Anderson /* virtual console already in use */ 1021361ed64aSJames Anderson return; 1022361ed64aSJames Anderson } 1023361ed64aSJames Anderson 1024361ed64aSJames Anderson vsconsvp = i_consconfig_createvp(virtual_cons_path); 1025361ed64aSJames Anderson if (vsconsvp == NULL) { 1026361ed64aSJames Anderson cmn_err(CE_WARN, "consconfig_virtual_console_vp: " 1027361ed64aSJames Anderson "unable to find serial virtual console device %s", 1028361ed64aSJames Anderson virtual_cons_path); 1029361ed64aSJames Anderson return; 1030361ed64aSJames Anderson } 1031361ed64aSJames Anderson 1032361ed64aSJames Anderson (void) e_ddi_hold_devi_by_dev(vsconsvp->v_rdev, 0); 1033361ed64aSJames Anderson } 1034361ed64aSJames Anderson #endif 1035361ed64aSJames Anderson 10367c478bd9Sstevel@tonic-gate static void 10377c478bd9Sstevel@tonic-gate consconfig_init_framebuffer(cons_state_t *sp) 10387c478bd9Sstevel@tonic-gate { 10391b83305cSjm22469 if (!sp->cons_stdout_is_fb) 10407c478bd9Sstevel@tonic-gate return; 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "stdout is framebuffer\n"); 10437c478bd9Sstevel@tonic-gate ASSERT(strcmp(sp->cons_fb_path, sp->cons_stdout_path) == 0); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * Console output is a framebuffer. 10477c478bd9Sstevel@tonic-gate * Find the framebuffer driver if we can, and make 10487c478bd9Sstevel@tonic-gate * ourselves a shadow vnode to track it with. 10497c478bd9Sstevel@tonic-gate */ 10507c478bd9Sstevel@tonic-gate fbdev = stdoutdev; 10517c478bd9Sstevel@tonic-gate if (fbdev == NODEV) { 10527c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L3, 10537c478bd9Sstevel@tonic-gate "Can't find driver for console framebuffer\n"); 10547c478bd9Sstevel@tonic-gate } else { 10557c478bd9Sstevel@tonic-gate /* stdoutdev is valid, of fbvp should exist */ 10567c478bd9Sstevel@tonic-gate fbvp = i_consconfig_createvp(sp->cons_stdout_path); 10577c478bd9Sstevel@tonic-gate if (fbvp == NULL) { 1058361ed64aSJames Anderson panic("consconfig_init_framebuffer: " 10597c478bd9Sstevel@tonic-gate "unable to find frame buffer device"); 10607c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate ASSERT(fbvp->v_rdev == fbdev); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate /* console device is never released */ 10657c478bd9Sstevel@tonic-gate fbdip = e_ddi_hold_devi_by_dev(fbdev, 0); 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate pm_cfb_setup(sp->cons_stdout_path); 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate /* 10717c478bd9Sstevel@tonic-gate * consconfig_prepare_dev: 10727c478bd9Sstevel@tonic-gate * Flush the stream, push "pushmod" onto the stream. 10737c478bd9Sstevel@tonic-gate * for keyboard, issue the KIOCTRANSABLE ioctl, and 10747c478bd9Sstevel@tonic-gate * possible enable abort. 10757c478bd9Sstevel@tonic-gate */ 10767c478bd9Sstevel@tonic-gate static void 10777c478bd9Sstevel@tonic-gate consconfig_prepare_dev( 10787c478bd9Sstevel@tonic-gate ldi_handle_t new_lh, 10797c478bd9Sstevel@tonic-gate const char *pushmod, 10807c478bd9Sstevel@tonic-gate int kbdtranslatable, 10817c478bd9Sstevel@tonic-gate int input_type, 10827c478bd9Sstevel@tonic-gate int dev_type) 10837c478bd9Sstevel@tonic-gate { 10847c478bd9Sstevel@tonic-gate int err, rval; 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate /* send a flush down the stream to the keyboard driver */ 10877c478bd9Sstevel@tonic-gate (void) ldi_ioctl(new_lh, I_FLUSH, (intptr_t)FLUSHRW, 10887c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate if (pushmod) { 10917c478bd9Sstevel@tonic-gate err = ldi_ioctl(new_lh, I_PUSH, (intptr_t)pushmod, 10927c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 10937c478bd9Sstevel@tonic-gate if (err) { 10947c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_prepare_dev: " 10957c478bd9Sstevel@tonic-gate "can't push streams module \"%s\", error %d", 10967c478bd9Sstevel@tonic-gate pushmod, err); 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate } 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate if (dev_type == CONS_MS) 11017c478bd9Sstevel@tonic-gate return; 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate ASSERT(dev_type == CONS_KBD); 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate err = ldi_ioctl(new_lh, KIOCTRANSABLE, 11067c478bd9Sstevel@tonic-gate (intptr_t)&kbdtranslatable, FKIOCTL, kcred, &rval); 11077c478bd9Sstevel@tonic-gate if (err) { 11087c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_prepare_dev: " 11097c478bd9Sstevel@tonic-gate "KIOCTRANSABLE failed, error: %d", err); 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate /* 11137c478bd9Sstevel@tonic-gate * During boot, dynamic_console_config() will call the 11147c478bd9Sstevel@tonic-gate * function to enable abort on the console. If the 11157c478bd9Sstevel@tonic-gate * keyboard is hotplugged after boot, check to see if 11167c478bd9Sstevel@tonic-gate * the keyboard is the console input. If it is 11177c478bd9Sstevel@tonic-gate * enable abort on it. 11187c478bd9Sstevel@tonic-gate */ 11197c478bd9Sstevel@tonic-gate if (input_type == CONSOLE_LOCAL) 11207c478bd9Sstevel@tonic-gate (void) consconfig_kbd_abort_enable(new_lh); 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate /* 11247c478bd9Sstevel@tonic-gate * consconfig_relink_conskbd: 11257c478bd9Sstevel@tonic-gate * If new_lh is not NULL it should represent a driver with a 11267c478bd9Sstevel@tonic-gate * keyboard module pushed on top of it. The driver is then linked 11277c478bd9Sstevel@tonic-gate * underneath conskbd. the resulting stream will be 11287c478bd9Sstevel@tonic-gate * wc->conskbd->"new_lh driver". 11297c478bd9Sstevel@tonic-gate * 11307c478bd9Sstevel@tonic-gate * If new_lh is NULL, then an unlink operation is done on conskbd 11317c478bd9Sstevel@tonic-gate * that attempts to unlink the stream specified by *muxid. 11327c478bd9Sstevel@tonic-gate * the resulting stream will be wc->conskbd. 11337c478bd9Sstevel@tonic-gate */ 11347c478bd9Sstevel@tonic-gate static int 11357c478bd9Sstevel@tonic-gate consconfig_relink_conskbd(cons_state_t *sp, ldi_handle_t new_lh, int *muxid) 11367c478bd9Sstevel@tonic-gate { 11377c478bd9Sstevel@tonic-gate int err, rval; 11387c478bd9Sstevel@tonic-gate int conskbd_relink = 0; 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate ASSERT(muxid != NULL); 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "consconfig_relink_conskbd: " 11437c478bd9Sstevel@tonic-gate "conskbd_lh = %p, new_lh = %p, muxid = %x\n", 11447c478bd9Sstevel@tonic-gate sp->conskbd_lh, new_lh, *muxid); 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate /* 11477c478bd9Sstevel@tonic-gate * If conskbd is linked under wc then temporarily unlink it 11487c478bd9Sstevel@tonic-gate * from under wc so that the new_lh stream may be linked under 11497c478bd9Sstevel@tonic-gate * conskbd. This has to be done because streams are built bottom 11507c478bd9Sstevel@tonic-gate * up and linking a stream under conskbd isn't allowed when 11517c478bd9Sstevel@tonic-gate * conskbd is linked under wc. 11527c478bd9Sstevel@tonic-gate */ 11537c478bd9Sstevel@tonic-gate if (sp->conskbd_muxid != -1) { 11547c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "unlinking conskbd from under wc\n"); 11557c478bd9Sstevel@tonic-gate conskbd_relink = 1; 11567c478bd9Sstevel@tonic-gate err = consconfig_relink_wc(sp, NULL, &sp->conskbd_muxid); 11577c478bd9Sstevel@tonic-gate if (err) { 11587c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_conskbd: " 11597c478bd9Sstevel@tonic-gate "wc unlink failed, error %d", err); 11607c478bd9Sstevel@tonic-gate return (err); 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate if (new_lh != NULL) { 11657c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "linking keyboard under conskbd\n"); 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate /* Link the stream represented by new_lh under conskbd */ 11687c478bd9Sstevel@tonic-gate err = ldi_ioctl(sp->conskbd_lh, I_PLINK, (uintptr_t)new_lh, 11697c478bd9Sstevel@tonic-gate FKIOCTL, kcred, muxid); 11707c478bd9Sstevel@tonic-gate if (err != 0) { 11717c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_conskbd: " 11727c478bd9Sstevel@tonic-gate "conskbd link failed, error %d", err); 11737c478bd9Sstevel@tonic-gate goto relink_failed; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate } else { 11767c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "unlinking keyboard from under conskbd\n"); 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate /* 11797c478bd9Sstevel@tonic-gate * This will cause the keyboard driver to be closed, 11807c478bd9Sstevel@tonic-gate * all modules to be popped, and the keyboard vnode released. 11817c478bd9Sstevel@tonic-gate */ 11827c478bd9Sstevel@tonic-gate err = ldi_ioctl(sp->conskbd_lh, I_PUNLINK, *muxid, 11837c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 11847c478bd9Sstevel@tonic-gate if (err != 0) { 11857c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_conskbd: " 11867c478bd9Sstevel@tonic-gate "conskbd unlink failed, error %d", err); 11877c478bd9Sstevel@tonic-gate goto relink_failed; 11887c478bd9Sstevel@tonic-gate } else { 11897c478bd9Sstevel@tonic-gate *muxid = -1; 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate consconfig_check_phys_kbd(sp); 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate if (!conskbd_relink) 11967c478bd9Sstevel@tonic-gate return (err); 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate /* 11997c478bd9Sstevel@tonic-gate * Link consbkd back under wc. 12007c478bd9Sstevel@tonic-gate * 12017c478bd9Sstevel@tonic-gate * The act of linking conskbd back under wc will cause wc 12027c478bd9Sstevel@tonic-gate * to query the lower lower layers about their polled I/O 12037c478bd9Sstevel@tonic-gate * routines. This time the request will succeed because there 12047c478bd9Sstevel@tonic-gate * is a physical keyboard linked under conskbd. 12057c478bd9Sstevel@tonic-gate */ 12067c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "re-linking conskbd under wc\n"); 12077c478bd9Sstevel@tonic-gate err = consconfig_relink_wc(sp, sp->conskbd_lh, &sp->conskbd_muxid); 12087c478bd9Sstevel@tonic-gate if (err) { 12097c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_conskbd: " 12107c478bd9Sstevel@tonic-gate "wc link failed, error %d", err); 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate return (err); 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate relink_failed: 12157c478bd9Sstevel@tonic-gate if (!conskbd_relink) 12167c478bd9Sstevel@tonic-gate return (err); 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate /* something went wrong, try to reconnect conskbd back under wc */ 12197c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "re-linking conskbd under wc\n"); 12207c478bd9Sstevel@tonic-gate (void) consconfig_relink_wc(sp, sp->conskbd_lh, &sp->conskbd_muxid); 12217c478bd9Sstevel@tonic-gate return (err); 12227c478bd9Sstevel@tonic-gate } 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate /* 12257c478bd9Sstevel@tonic-gate * consconfig_relink_consms: 12267c478bd9Sstevel@tonic-gate * If new_lh is not NULL it should represent a driver with a 12277c478bd9Sstevel@tonic-gate * mouse module pushed on top of it. The driver is then linked 12287c478bd9Sstevel@tonic-gate * underneath consms. the resulting stream will be 12297c478bd9Sstevel@tonic-gate * consms->"new_lh driver". 12307c478bd9Sstevel@tonic-gate * 12317c478bd9Sstevel@tonic-gate * If new_lh is NULL, then an unlink operation is done on consms 12327c478bd9Sstevel@tonic-gate * that attempts to unlink the stream specified by *muxid. 12337c478bd9Sstevel@tonic-gate */ 12347c478bd9Sstevel@tonic-gate static int 12357c478bd9Sstevel@tonic-gate consconfig_relink_consms(cons_state_t *sp, ldi_handle_t new_lh, int *muxid) 12367c478bd9Sstevel@tonic-gate { 12377c478bd9Sstevel@tonic-gate int err, rval; 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "consconfig_relink_consms: " 12407c478bd9Sstevel@tonic-gate "consms_lh = %p, new_lh = %p, muxid = %x\n", 12417c478bd9Sstevel@tonic-gate (void *)sp->consms_lh, (void *)new_lh, *muxid); 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate if (new_lh != NULL) { 12447c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "linking mouse under consms\n"); 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate /* Link ms/usbms stream underneath consms multiplexor. */ 12477c478bd9Sstevel@tonic-gate err = ldi_ioctl(sp->consms_lh, I_PLINK, (uintptr_t)new_lh, 12487c478bd9Sstevel@tonic-gate FKIOCTL, kcred, muxid); 12497c478bd9Sstevel@tonic-gate if (err != 0) { 12507c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_consms: " 12517c478bd9Sstevel@tonic-gate "mouse link failed, error %d", err); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate } else { 12547c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "unlinking mouse from under consms\n"); 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate /* Tear down the mouse stream */ 12577c478bd9Sstevel@tonic-gate err = ldi_ioctl(sp->consms_lh, I_PUNLINK, *muxid, 12587c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 12597c478bd9Sstevel@tonic-gate if (err != 0) { 12607c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_relink_consms: " 12617c478bd9Sstevel@tonic-gate "mouse unlink failed, error %d", err); 12627c478bd9Sstevel@tonic-gate } else { 12637c478bd9Sstevel@tonic-gate *muxid = -1; 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate return (err); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate static int 12701b83305cSjm22469 cons_get_input_type(cons_state_t *sp) 12717c478bd9Sstevel@tonic-gate { 12727c478bd9Sstevel@tonic-gate int type; 12731b83305cSjm22469 12747c478bd9Sstevel@tonic-gate /* 12757c478bd9Sstevel@tonic-gate * Now that we know what all the devices are, we can figure out 12767c478bd9Sstevel@tonic-gate * what kind of console we have. 12777c478bd9Sstevel@tonic-gate */ 12781b83305cSjm22469 if (sp->cons_stdin_is_kbd) { 12797c478bd9Sstevel@tonic-gate /* Stdin is from the system keyboard */ 12807c478bd9Sstevel@tonic-gate type = CONSOLE_LOCAL; 12817c478bd9Sstevel@tonic-gate } else if ((stdindev != NODEV) && (stdindev == stdoutdev)) { 12827c478bd9Sstevel@tonic-gate /* 12837c478bd9Sstevel@tonic-gate * A reliable indicator that we are doing a remote console 12847c478bd9Sstevel@tonic-gate * is that stdin and stdout are the same. 12857c478bd9Sstevel@tonic-gate * This is probably a tip line. 12867c478bd9Sstevel@tonic-gate */ 12877c478bd9Sstevel@tonic-gate type = CONSOLE_TIP; 12887c478bd9Sstevel@tonic-gate } else { 12897c478bd9Sstevel@tonic-gate type = CONSOLE_SERIAL_KEYBOARD; 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate return (type); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate static void 12967c478bd9Sstevel@tonic-gate consconfig_init_input(cons_state_t *sp) 12977c478bd9Sstevel@tonic-gate { 12987c478bd9Sstevel@tonic-gate ldi_handle_t new_lh; 12997c478bd9Sstevel@tonic-gate dev_t cons_final_dev; 13007c478bd9Sstevel@tonic-gate int err; 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate cons_final_dev = NODEV; 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate switch (sp->cons_input_type) { 13057c478bd9Sstevel@tonic-gate case CONSOLE_LOCAL: 13067c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "stdin is keyboard\n"); 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate /* 13097c478bd9Sstevel@tonic-gate * The machine is allowed to boot without a keyboard. 13107c478bd9Sstevel@tonic-gate * If a user attaches a keyboard later, the keyboard 13117c478bd9Sstevel@tonic-gate * will be hooked into the console stream with the dacf 13127c478bd9Sstevel@tonic-gate * functions. 13137c478bd9Sstevel@tonic-gate * 13147c478bd9Sstevel@tonic-gate * The only drivers that look at kbbdev are the 13157c478bd9Sstevel@tonic-gate * serial drivers, which looks at kbdev to see if 13167c478bd9Sstevel@tonic-gate * they should allow abort on a break. In the absence 13177c478bd9Sstevel@tonic-gate * of keyboard, the serial drivers won't be attached 13187c478bd9Sstevel@tonic-gate * for any keyboard instance. 13197c478bd9Sstevel@tonic-gate */ 13207c478bd9Sstevel@tonic-gate if (kbddev == NODEV) { 13217c478bd9Sstevel@tonic-gate /* 13227c478bd9Sstevel@tonic-gate * If there is a problem with the keyboard 13237c478bd9Sstevel@tonic-gate * during the driver loading, then the polled 13247c478bd9Sstevel@tonic-gate * input won't get setup properly if polled 13257c478bd9Sstevel@tonic-gate * input is needed. This means that if the 13267c478bd9Sstevel@tonic-gate * keyboard is hotplugged, the keyboard would 13277c478bd9Sstevel@tonic-gate * work normally, but going down to the 13287c478bd9Sstevel@tonic-gate * debugger would not work if polled input is 13297c478bd9Sstevel@tonic-gate * required. This field is set here. The next 13307c478bd9Sstevel@tonic-gate * time a keyboard is plugged in, the field is 13317c478bd9Sstevel@tonic-gate * checked in order to give the next keyboard a 13327c478bd9Sstevel@tonic-gate * chance at being registered for console 13337c478bd9Sstevel@tonic-gate * input. 13347c478bd9Sstevel@tonic-gate * 13357c478bd9Sstevel@tonic-gate * Although this code will rarely be needed, 13367c478bd9Sstevel@tonic-gate * USB keyboards can be flaky, so this code 13377c478bd9Sstevel@tonic-gate * will be useful on the occasion that the 13387c478bd9Sstevel@tonic-gate * keyboard doesn't enumerate when the drivers 13397c478bd9Sstevel@tonic-gate * are loaded. 13407c478bd9Sstevel@tonic-gate */ 13417c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L2, "Error with console keyboard\n"); 13427c478bd9Sstevel@tonic-gate sp->cons_keyboard_problem = B_TRUE; 13437c478bd9Sstevel@tonic-gate } 13447c478bd9Sstevel@tonic-gate stdindev = kbddev; 13457c478bd9Sstevel@tonic-gate cons_final_dev = sp->cons_wc_vp->v_rdev; 13467c478bd9Sstevel@tonic-gate break; 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate case CONSOLE_TIP: 13497c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "console input is tty (%s)\n", 13507c478bd9Sstevel@tonic-gate sp->cons_stdin_path); 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate /* 13537c478bd9Sstevel@tonic-gate * Console device drivers must be able to output 13547c478bd9Sstevel@tonic-gate * after being closed. 13557c478bd9Sstevel@tonic-gate */ 13567c478bd9Sstevel@tonic-gate rconsvp = i_consconfig_createvp(sp->cons_stdin_path); 1357ae115bc7Smrj if (rconsvp == NULL) { 1358ae115bc7Smrj panic("consconfig_init_input: " 13597c478bd9Sstevel@tonic-gate "unable to find stdin device (%s)", 13607c478bd9Sstevel@tonic-gate sp->cons_stdin_path); 1361ae115bc7Smrj /*NOTREACHED*/ 1362ae115bc7Smrj } 13637c478bd9Sstevel@tonic-gate rconsdev = rconsvp->v_rdev; 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate ASSERT(rconsdev == stdindev); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate cons_final_dev = rconsdev; 13687c478bd9Sstevel@tonic-gate break; 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate case CONSOLE_SERIAL_KEYBOARD: 13717c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "stdin is serial keyboard\n"); 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate /* 13747c478bd9Sstevel@tonic-gate * Non-keyboard input device, but not rconsdev. 13757c478bd9Sstevel@tonic-gate * This is known as the "serial keyboard" case - the 13767c478bd9Sstevel@tonic-gate * most likely use is someone has a keyboard attached 13777c478bd9Sstevel@tonic-gate * to a serial port (tip) and still has output on a 13787c478bd9Sstevel@tonic-gate * framebuffer. 13797c478bd9Sstevel@tonic-gate * 13807c478bd9Sstevel@tonic-gate * In this case, the serial driver must be linked 13817c478bd9Sstevel@tonic-gate * directly beneath wc. Since conskbd was linked 13827c478bd9Sstevel@tonic-gate * underneath wc above, first we unlink conskbd. 13837c478bd9Sstevel@tonic-gate */ 13847c478bd9Sstevel@tonic-gate (void) consconfig_relink_wc(sp, NULL, &sp->conskbd_muxid); 13857c478bd9Sstevel@tonic-gate sp->conskbd_muxid = -1; 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate /* 13887c478bd9Sstevel@tonic-gate * Open the serial keyboard, configure it, 13897c478bd9Sstevel@tonic-gate * and link it underneath wc. 13907c478bd9Sstevel@tonic-gate */ 13917c478bd9Sstevel@tonic-gate err = ldi_open_by_name(sp->cons_stdin_path, 13927c478bd9Sstevel@tonic-gate FREAD|FWRITE|FNOCTTY, kcred, &new_lh, sp->cons_li); 13937c478bd9Sstevel@tonic-gate if (err == 0) { 13947c478bd9Sstevel@tonic-gate struct termios termios; 13957c478bd9Sstevel@tonic-gate int rval; 13967c478bd9Sstevel@tonic-gate int stdin_muxid; 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate consconfig_prepare_dev(new_lh, 13997c478bd9Sstevel@tonic-gate "kb", TR_CANNOT, sp->cons_input_type, CONS_KBD); 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate /* Re-set baud rate */ 14027c478bd9Sstevel@tonic-gate (void) ldi_ioctl(new_lh, TCGETS, (intptr_t)&termios, 14037c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate /* Set baud rate */ 14067c478bd9Sstevel@tonic-gate if (consconfig_setmodes(stdindev, &termios) == 0) { 14077c478bd9Sstevel@tonic-gate err = ldi_ioctl(new_lh, 14087c478bd9Sstevel@tonic-gate TCSETSF, (intptr_t)&termios, 14097c478bd9Sstevel@tonic-gate FKIOCTL, kcred, &rval); 14107c478bd9Sstevel@tonic-gate if (err) { 14117c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 14127c478bd9Sstevel@tonic-gate "consconfig_init_input: " 14137c478bd9Sstevel@tonic-gate "TCSETSF failed, error %d", err); 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate } 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate /* 14187c478bd9Sstevel@tonic-gate * Now link the serial keyboard direcly under wc 14197c478bd9Sstevel@tonic-gate * we don't save the returned muxid because we 14207c478bd9Sstevel@tonic-gate * don't support changing/hotplugging the console 14217c478bd9Sstevel@tonic-gate * keyboard when it is a serial keyboard. 14227c478bd9Sstevel@tonic-gate */ 14237c478bd9Sstevel@tonic-gate (void) consconfig_relink_wc(sp, new_lh, &stdin_muxid); 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate (void) ldi_close(new_lh, FREAD|FWRITE, kcred); 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate cons_final_dev = sp->cons_wc_vp->v_rdev; 14297c478bd9Sstevel@tonic-gate break; 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate default: 14327c478bd9Sstevel@tonic-gate panic("consconfig_init_input: " 14337c478bd9Sstevel@tonic-gate "unsupported console input/output combination"); 14347c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate /* 14387c478bd9Sstevel@tonic-gate * Use the redirection device/workstation console pair as the "real" 14397c478bd9Sstevel@tonic-gate * console if the latter hasn't already been set. 14407c478bd9Sstevel@tonic-gate * The workstation console driver needs to see rwsconsvp, but 14417c478bd9Sstevel@tonic-gate * all other access should be through the redirecting driver. 14427c478bd9Sstevel@tonic-gate */ 14437c478bd9Sstevel@tonic-gate if (rconsvp == NULL) { 14447c478bd9Sstevel@tonic-gate consconfig_dprintf(DPRINT_L0, "setup redirection driver\n"); 14457c478bd9Sstevel@tonic-gate rconsvp = wsconsvp; 14467c478bd9Sstevel@tonic-gate rconsdev = wsconsvp->v_rdev; 14477c478bd9Sstevel@tonic-gate } 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate ASSERT(cons_final_dev != NODEV); 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate err = ldi_open_by_dev(&cons_final_dev, OTYP_CHR, FREAD|FWRITE|FNOCTTY, 14527c478bd9Sstevel@tonic-gate kcred, &new_lh, sp->cons_li); 14537c478bd9Sstevel@tonic-gate if (err) { 14547c478bd9Sstevel@tonic-gate panic("consconfig_init_input: " 14557c478bd9Sstevel@tonic-gate "unable to open console device"); 14567c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate /* Enable abort on the console */ 14607c478bd9Sstevel@tonic-gate (void) consconfig_kbd_abort_enable(new_lh); 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* Now we must close it to make console logins happy */ 14637c478bd9Sstevel@tonic-gate (void) ldi_close(new_lh, FREAD|FWRITE, kcred); 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate /* Set up polled input if it is supported by the console device */ 14667c478bd9Sstevel@tonic-gate if (plat_use_polled_debug()) { 14677c478bd9Sstevel@tonic-gate /* 14687c478bd9Sstevel@tonic-gate * In the debug case, register the keyboard polled entry 14697c478bd9Sstevel@tonic-gate * points, but don't throw the switch in the debugger. This 14707c478bd9Sstevel@tonic-gate * allows the polled entry points to be checked by hand 14717c478bd9Sstevel@tonic-gate */ 14727c478bd9Sstevel@tonic-gate consconfig_setup_polledio(sp, sp->cons_wc_vp->v_rdev); 14737c478bd9Sstevel@tonic-gate } else { 14747c478bd9Sstevel@tonic-gate consconfig_setup_polledio(sp, cons_final_dev); 14757c478bd9Sstevel@tonic-gate } 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate kadb_uses_kernel(); 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate /* 14817c478bd9Sstevel@tonic-gate * This function kicks off the console configuration. 14827c478bd9Sstevel@tonic-gate * Configure keyboard and mouse. Main entry here. 14837c478bd9Sstevel@tonic-gate */ 14847c478bd9Sstevel@tonic-gate void 14857c478bd9Sstevel@tonic-gate dynamic_console_config(void) 14867c478bd9Sstevel@tonic-gate { 14877c478bd9Sstevel@tonic-gate /* initialize space.c globals */ 14887c478bd9Sstevel@tonic-gate stdindev = NODEV; 14897c478bd9Sstevel@tonic-gate mousedev = NODEV; 14907c478bd9Sstevel@tonic-gate kbddev = NODEV; 14917c478bd9Sstevel@tonic-gate fbdev = NODEV; 14927c478bd9Sstevel@tonic-gate fbvp = NULL; 14937c478bd9Sstevel@tonic-gate fbdip = NULL; 14947c478bd9Sstevel@tonic-gate wsconsvp = NULL; 14957c478bd9Sstevel@tonic-gate rwsconsvp = NULL; 14967c478bd9Sstevel@tonic-gate rwsconsdev = NODEV; 14977c478bd9Sstevel@tonic-gate rconsvp = NULL; 14987c478bd9Sstevel@tonic-gate rconsdev = NODEV; 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate /* Initialize cons_state_t structure and console device paths */ 1501ae115bc7Smrj consconfig_sp = consconfig_state_init(); 1502ae115bc7Smrj ASSERT(consconfig_sp); 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate /* Build upper layer of console stream */ 1505ae115bc7Smrj cons_build_upper_layer(consconfig_sp); 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate /* 15087c478bd9Sstevel@tonic-gate * Load keyboard/mouse drivers. The dacf routines will 15097c478bd9Sstevel@tonic-gate * plumb the devices into the console stream 15107c478bd9Sstevel@tonic-gate * 15117c478bd9Sstevel@tonic-gate * At the conclusion of the ddi_pathname_to_dev_t calls, the keyboard 15127c478bd9Sstevel@tonic-gate * and mouse drivers are linked into their respective console 15137c478bd9Sstevel@tonic-gate * streams if the pathnames are valid. 15147c478bd9Sstevel@tonic-gate */ 1515ae115bc7Smrj consconfig_load_drivers(consconfig_sp); 15161b83305cSjm22469 consconfig_sp->cons_input_type = cons_get_input_type(consconfig_sp); 15177c478bd9Sstevel@tonic-gate 15187c478bd9Sstevel@tonic-gate /* 15197c478bd9Sstevel@tonic-gate * This is legacy special case code for the "cool" virtual console 15207c478bd9Sstevel@tonic-gate * for the Starfire project. Starfire has a dummy "ssp-serial" 15217c478bd9Sstevel@tonic-gate * node in the OBP device tree and cvc is a pseudo driver. 15227c478bd9Sstevel@tonic-gate */ 1523ae115bc7Smrj if (consconfig_sp->cons_stdout_path != NULL && stdindev == NODEV && 1524ae115bc7Smrj strstr(consconfig_sp->cons_stdout_path, "ssp-serial")) { 15257c478bd9Sstevel@tonic-gate /* 15267c478bd9Sstevel@tonic-gate * Setup the virtual console driver for Starfire 15277c478bd9Sstevel@tonic-gate * Note that console I/O will still go through prom for now 15287c478bd9Sstevel@tonic-gate * (notice we don't open the driver here). The cvc driver 15297c478bd9Sstevel@tonic-gate * will be activated when /dev/console is opened by init. 15307c478bd9Sstevel@tonic-gate * During that time, a cvcd daemon will be started that 15317c478bd9Sstevel@tonic-gate * will open the cvcredirection driver to facilitate 15327c478bd9Sstevel@tonic-gate * the redirection of console I/O from cvc to cvcd. 15337c478bd9Sstevel@tonic-gate */ 15347c478bd9Sstevel@tonic-gate rconsvp = i_consconfig_createvp(CVC_PATH); 15357c478bd9Sstevel@tonic-gate if (rconsvp == NULL) 153640482326SVincent Wang goto done; 15377c478bd9Sstevel@tonic-gate rconsdev = rconsvp->v_rdev; 153840482326SVincent Wang goto done; 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate 1541ae115bc7Smrj rwsconsvp = consconfig_sp->cons_wc_vp; 1542ae115bc7Smrj rwsconsdev = consconfig_sp->cons_wc_vp->v_rdev; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate /* initialize framebuffer, console input, and redirection device */ 1546ae115bc7Smrj consconfig_init_framebuffer(consconfig_sp); 1547ae115bc7Smrj consconfig_init_input(consconfig_sp); 15487c478bd9Sstevel@tonic-gate 1549361ed64aSJames Anderson #if !defined(__x86) 1550361ed64aSJames Anderson /* initialize virtual console vp for logging if needed */ 1551361ed64aSJames Anderson consconfig_virtual_console_vp(consconfig_sp); 1552361ed64aSJames Anderson #endif 1553361ed64aSJames Anderson 15547c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, 15557c478bd9Sstevel@tonic-gate "mousedev %lx, kbddev %lx, fbdev %lx, rconsdev %lx\n", 15567c478bd9Sstevel@tonic-gate mousedev, kbddev, fbdev, rconsdev); 155728cdc3d7Sszhou 155848633f18SJan Setje-Eilers flush_deferred_console_buf(); 155940482326SVincent Wang done: 156040482326SVincent Wang consconfig_sp->cons_initialized = B_TRUE; 15617c478bd9Sstevel@tonic-gate } 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate /* 15657c478bd9Sstevel@tonic-gate * Start of DACF interfaces 15667c478bd9Sstevel@tonic-gate */ 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate /* 15697c478bd9Sstevel@tonic-gate * Do the real job for keyboard/mouse auto-configuration. 15707c478bd9Sstevel@tonic-gate */ 15717c478bd9Sstevel@tonic-gate static int 15727c478bd9Sstevel@tonic-gate do_config(cons_state_t *sp, cons_prop_t *prop) 15737c478bd9Sstevel@tonic-gate { 15747c478bd9Sstevel@tonic-gate ldi_handle_t lh; 15757c478bd9Sstevel@tonic-gate dev_t dev; 15767c478bd9Sstevel@tonic-gate int error; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate ASSERT((prop->cp_type == CONS_KBD) || (prop->cp_type == CONS_MS)); 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate dev = prop->cp_dev; 15817c478bd9Sstevel@tonic-gate error = ldi_open_by_dev(&dev, OTYP_CHR, 15827c478bd9Sstevel@tonic-gate FREAD|FWRITE|FNOCTTY, kcred, &lh, sp->cons_li); 15837c478bd9Sstevel@tonic-gate if (error) { 15847c478bd9Sstevel@tonic-gate return (DACF_FAILURE); 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate ASSERT(dev == prop->cp_dev); /* clone not supported */ 15877c478bd9Sstevel@tonic-gate 15887c478bd9Sstevel@tonic-gate /* 15897c478bd9Sstevel@tonic-gate * Prepare the new keyboard/mouse driver 15907c478bd9Sstevel@tonic-gate * to be linked under conskbd/consms. 15917c478bd9Sstevel@tonic-gate */ 15927c478bd9Sstevel@tonic-gate consconfig_prepare_dev(lh, prop->cp_pushmod, TR_CAN, 15937c478bd9Sstevel@tonic-gate sp->cons_input_type, prop->cp_type); 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate if (prop->cp_type == CONS_KBD) { 15967c478bd9Sstevel@tonic-gate /* 15977c478bd9Sstevel@tonic-gate * Tell the physical keyboard driver to send 15987c478bd9Sstevel@tonic-gate * the abort sequences up to the virtual keyboard 15997c478bd9Sstevel@tonic-gate * driver so that STOP and A (or F1 and A) 16007c478bd9Sstevel@tonic-gate * can be applied to different keyboards. 16017c478bd9Sstevel@tonic-gate */ 16027c478bd9Sstevel@tonic-gate (void) consconfig_kbd_abort_disable(lh); 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate /* Link the stream underneath conskbd */ 16057c478bd9Sstevel@tonic-gate error = consconfig_relink_conskbd(sp, lh, &prop->cp_muxid); 16067c478bd9Sstevel@tonic-gate } else { 16077c478bd9Sstevel@tonic-gate /* Link the stream underneath consms */ 16087c478bd9Sstevel@tonic-gate error = consconfig_relink_consms(sp, lh, &prop->cp_muxid); 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate /* 16127c478bd9Sstevel@tonic-gate * At this point, the stream is: 16137c478bd9Sstevel@tonic-gate * for keyboard: wc->conskbd->["pushmod"->"kbd_vp driver"] 16147c478bd9Sstevel@tonic-gate * for mouse: consms->["module_name"->]"mouse_avp driver" 16157c478bd9Sstevel@tonic-gate */ 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate /* Close the driver stream, it will stay linked under conskbd */ 16187c478bd9Sstevel@tonic-gate (void) ldi_close(lh, FREAD|FWRITE, kcred); 16197c478bd9Sstevel@tonic-gate 16207c478bd9Sstevel@tonic-gate if (error) { 16217c478bd9Sstevel@tonic-gate return (DACF_FAILURE); 16227c478bd9Sstevel@tonic-gate } 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate return (DACF_SUCCESS); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate static int 16287c478bd9Sstevel@tonic-gate do_unconfig(cons_state_t *sp, cons_prop_t *prop) 16297c478bd9Sstevel@tonic-gate { 16307c478bd9Sstevel@tonic-gate ASSERT((prop->cp_type == CONS_KBD) || (prop->cp_type == CONS_MS)); 16317c478bd9Sstevel@tonic-gate 16327c478bd9Sstevel@tonic-gate if (prop->cp_type == CONS_KBD) 16337c478bd9Sstevel@tonic-gate return (consconfig_relink_conskbd(sp, NULL, &prop->cp_muxid)); 16347c478bd9Sstevel@tonic-gate else 16357c478bd9Sstevel@tonic-gate return (consconfig_relink_consms(sp, NULL, &prop->cp_muxid)); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate static int 16397c478bd9Sstevel@tonic-gate kb_ms_config(dacf_infohdl_t minor_hdl, dacf_arghdl_t arg_hdl, int type) 16407c478bd9Sstevel@tonic-gate { 16417c478bd9Sstevel@tonic-gate major_t major; 16427c478bd9Sstevel@tonic-gate minor_t minor; 16437c478bd9Sstevel@tonic-gate dev_t dev; 16447c478bd9Sstevel@tonic-gate dev_info_t *dip; 16457c478bd9Sstevel@tonic-gate cons_state_t *sp; 16467c478bd9Sstevel@tonic-gate cons_prop_t *prop; 16477c478bd9Sstevel@tonic-gate const char *pushmod; 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate /* 16507c478bd9Sstevel@tonic-gate * Retrieve the state information 16517c478bd9Sstevel@tonic-gate * Some platforms may use the old-style "consconfig" to configure 16527c478bd9Sstevel@tonic-gate * console stream modules but may also support devices that happen 16537c478bd9Sstevel@tonic-gate * to match a rule in /etc/dacf.conf. This will cause a problem 16547c478bd9Sstevel@tonic-gate * since the console state structure will not be initialized. 16557c478bd9Sstevel@tonic-gate * In that case, these entry points should silently fail and 16567c478bd9Sstevel@tonic-gate * permit console to be plumbed later in boot. 16577c478bd9Sstevel@tonic-gate */ 16587c478bd9Sstevel@tonic-gate if ((sp = (cons_state_t *)space_fetch("consconfig")) == NULL) 16597c478bd9Sstevel@tonic-gate return (DACF_FAILURE); 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate dip = dacf_devinfo_node(minor_hdl); 16627c478bd9Sstevel@tonic-gate major = ddi_driver_major(dip); 1663a204de77Scth ASSERT(major != DDI_MAJOR_T_NONE); 16647c478bd9Sstevel@tonic-gate minor = dacf_minor_number(minor_hdl); 16657c478bd9Sstevel@tonic-gate dev = makedevice(major, minor); 16667c478bd9Sstevel@tonic-gate ASSERT(dev != NODEV); 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate DPRINTF(DPRINT_L0, "driver name = \"%s\", dev = 0x%lx, major = 0x%x\n", 16697c478bd9Sstevel@tonic-gate (char *)dacf_driver_name(minor_hdl), dev, major); 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate /* Access to the global variables is synchronized */ 16727c478bd9Sstevel@tonic-gate mutex_enter(&sp->cons_lock); 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate /* 16757c478bd9Sstevel@tonic-gate * Check if the keyboard/mouse has already configured. 16767c478bd9Sstevel@tonic-gate */ 16777c478bd9Sstevel@tonic-gate if (consconfig_find_dev(sp, dev) != NULL) { 16787c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 16797c478bd9Sstevel@tonic-gate return (DACF_SUCCESS); 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate prop = kmem_zalloc(sizeof (cons_prop_t), KM_SLEEP); 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate /* Config the new keyboard/mouse device */ 16857c478bd9Sstevel@tonic-gate prop->cp_dev = dev; 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate pushmod = dacf_get_arg(arg_hdl, "pushmod"); 16887c478bd9Sstevel@tonic-gate prop->cp_pushmod = i_ddi_strdup((char *)pushmod, KM_SLEEP); 16897c478bd9Sstevel@tonic-gate 16907c478bd9Sstevel@tonic-gate prop->cp_type = type; 16917c478bd9Sstevel@tonic-gate if (do_config(sp, prop) != DACF_SUCCESS) { 16927c478bd9Sstevel@tonic-gate /* 16937c478bd9Sstevel@tonic-gate * The keyboard/mouse node failed to open. 16947c478bd9Sstevel@tonic-gate * Set the major and minor numbers to 0 so 16957c478bd9Sstevel@tonic-gate * kb_unconfig/ms_unconfig won't unconfigure 16967c478bd9Sstevel@tonic-gate * this node if it is detached. 16977c478bd9Sstevel@tonic-gate */ 16987c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 16997c478bd9Sstevel@tonic-gate consconfig_free_prop(prop); 17007c478bd9Sstevel@tonic-gate return (DACF_FAILURE); 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate consconfig_add_dev(sp, prop); 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate /* 17067c478bd9Sstevel@tonic-gate * See if there was a problem with the console keyboard during boot. 17077c478bd9Sstevel@tonic-gate * If so, try to register polled input for this keyboard. 17087c478bd9Sstevel@tonic-gate */ 17097c478bd9Sstevel@tonic-gate if ((type == CONS_KBD) && (sp->cons_keyboard_problem)) { 17107c478bd9Sstevel@tonic-gate consconfig_setup_polledio(sp, sp->cons_wc_vp->v_rdev); 17117c478bd9Sstevel@tonic-gate sp->cons_keyboard_problem = B_FALSE; 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate /* Prevent autodetach due to memory pressure */ 17157c478bd9Sstevel@tonic-gate (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1); 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate return (DACF_SUCCESS); 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate static int 17237c478bd9Sstevel@tonic-gate kb_ms_unconfig(dacf_infohdl_t minor_hdl, dacf_arghdl_t arg_hdl) 17247c478bd9Sstevel@tonic-gate { 17257c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(arg_hdl)) 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate major_t major; 17287c478bd9Sstevel@tonic-gate minor_t minor; 17297c478bd9Sstevel@tonic-gate dev_t dev; 17307c478bd9Sstevel@tonic-gate dev_info_t *dip; 17317c478bd9Sstevel@tonic-gate cons_state_t *sp; 17327c478bd9Sstevel@tonic-gate cons_prop_t *prop; 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate /* 17357c478bd9Sstevel@tonic-gate * Retrieve the state information 17367c478bd9Sstevel@tonic-gate * So if there isn't a state available, then this entry point just 17377c478bd9Sstevel@tonic-gate * returns. See note in kb_config(). 17387c478bd9Sstevel@tonic-gate */ 17397c478bd9Sstevel@tonic-gate if ((sp = (cons_state_t *)space_fetch("consconfig")) == NULL) 17407c478bd9Sstevel@tonic-gate return (DACF_SUCCESS); 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate dip = dacf_devinfo_node(minor_hdl); 17437c478bd9Sstevel@tonic-gate major = ddi_driver_major(dip); 1744a204de77Scth ASSERT(major != DDI_MAJOR_T_NONE); 17457c478bd9Sstevel@tonic-gate minor = dacf_minor_number(minor_hdl); 17467c478bd9Sstevel@tonic-gate dev = makedevice(major, minor); 17477c478bd9Sstevel@tonic-gate ASSERT(dev != NODEV); 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate /* 17507c478bd9Sstevel@tonic-gate * Check if the keyboard/mouse that is being detached 17517c478bd9Sstevel@tonic-gate * is the console keyboard/mouse or not. 17527c478bd9Sstevel@tonic-gate */ 17537c478bd9Sstevel@tonic-gate mutex_enter(&sp->cons_lock); 17547c478bd9Sstevel@tonic-gate if ((prop = consconfig_find_dev(sp, dev)) == NULL) { 17557c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 17567c478bd9Sstevel@tonic-gate return (DACF_SUCCESS); 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate /* 17607c478bd9Sstevel@tonic-gate * This dev may be opened physically and then hotplugged out. 17617c478bd9Sstevel@tonic-gate */ 17627c478bd9Sstevel@tonic-gate if (prop->cp_muxid != -1) { 17637c478bd9Sstevel@tonic-gate (void) do_unconfig(sp, prop); 17647c478bd9Sstevel@tonic-gate consconfig_rem_dev(sp, dev); 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate return (DACF_SUCCESS); 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate /* 17737c478bd9Sstevel@tonic-gate * This is the post-attach / pre-detach action function for the keyboard 17747c478bd9Sstevel@tonic-gate * and mouse. This function is associated with a node type in /etc/dacf.conf. 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate static int 17777c478bd9Sstevel@tonic-gate kb_config(dacf_infohdl_t minor_hdl, dacf_arghdl_t arg_hdl, int flags) 17787c478bd9Sstevel@tonic-gate { 17797c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(flags)) 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate return (kb_ms_config(minor_hdl, arg_hdl, CONS_KBD)); 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate static int 17857c478bd9Sstevel@tonic-gate ms_config(dacf_infohdl_t minor_hdl, dacf_arghdl_t arg_hdl, int flags) 17867c478bd9Sstevel@tonic-gate { 17877c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(flags)) 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate return (kb_ms_config(minor_hdl, arg_hdl, CONS_MS)); 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate static int 17937c478bd9Sstevel@tonic-gate kb_unconfig(dacf_infohdl_t minor_hdl, dacf_arghdl_t arg_hdl, int flags) 17947c478bd9Sstevel@tonic-gate { 17957c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(flags)) 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate return (kb_ms_unconfig(minor_hdl, arg_hdl)); 17987c478bd9Sstevel@tonic-gate } 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate static int 18017c478bd9Sstevel@tonic-gate ms_unconfig(dacf_infohdl_t minor_hdl, dacf_arghdl_t arg_hdl, int flags) 18027c478bd9Sstevel@tonic-gate { 18037c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(flags)) 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate return (kb_ms_unconfig(minor_hdl, arg_hdl)); 18067c478bd9Sstevel@tonic-gate } 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate /* 18097c478bd9Sstevel@tonic-gate * consconfig_link and consconfig_unlink are provided to support 18107c478bd9Sstevel@tonic-gate * direct access to physical keyboard/mouse underlying conskbd/ 18117c478bd9Sstevel@tonic-gate * consms. 18127c478bd9Sstevel@tonic-gate * When the keyboard/mouse is opened physically via its device 18137c478bd9Sstevel@tonic-gate * file, it will be unlinked from the virtual one, and when it 18147c478bd9Sstevel@tonic-gate * is closed physically, it will be linked back under the virtual 18157c478bd9Sstevel@tonic-gate * one. 18167c478bd9Sstevel@tonic-gate */ 18177c478bd9Sstevel@tonic-gate void 18187c478bd9Sstevel@tonic-gate consconfig_link(major_t major, minor_t minor) 18197c478bd9Sstevel@tonic-gate { 18207c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 18217c478bd9Sstevel@tonic-gate dev_t dev; 18227c478bd9Sstevel@tonic-gate cons_state_t *sp; 18237c478bd9Sstevel@tonic-gate cons_prop_t *prop; 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate if ((sp = (cons_state_t *)space_fetch("consconfig")) == NULL) 18267c478bd9Sstevel@tonic-gate return; 18277c478bd9Sstevel@tonic-gate 18287c478bd9Sstevel@tonic-gate dev = makedevice(major, minor); 18297c478bd9Sstevel@tonic-gate ASSERT(dev != NODEV); 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate mutex_enter(&sp->cons_lock); 18327c478bd9Sstevel@tonic-gate if ((prop = consconfig_find_dev(sp, dev)) == NULL) { 18337c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 18347c478bd9Sstevel@tonic-gate return; 18357c478bd9Sstevel@tonic-gate } 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate if (do_config(sp, prop) != DACF_SUCCESS) { 18387c478bd9Sstevel@tonic-gate (void) ddi_dev_pathname(dev, 0, buf); 18397c478bd9Sstevel@tonic-gate if (prop->cp_type == CONS_KBD) 18407c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Failed to relink the keyboard " 18417c478bd9Sstevel@tonic-gate "(%s) underneath virtual keyboard", buf); 18427c478bd9Sstevel@tonic-gate else 18437c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "Failed to relink the mouse " 18447c478bd9Sstevel@tonic-gate "(%s) underneath virtual mouse", buf); 18457c478bd9Sstevel@tonic-gate consconfig_rem_dev(sp, dev); 18467c478bd9Sstevel@tonic-gate } 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate int 18537c478bd9Sstevel@tonic-gate consconfig_unlink(major_t major, minor_t minor) 18547c478bd9Sstevel@tonic-gate { 18557c478bd9Sstevel@tonic-gate dev_t dev; 18567c478bd9Sstevel@tonic-gate cons_state_t *sp; 18577c478bd9Sstevel@tonic-gate cons_prop_t *prop; 18587c478bd9Sstevel@tonic-gate int error; 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate if ((sp = (cons_state_t *)space_fetch("consconfig")) == NULL) 18617c478bd9Sstevel@tonic-gate return (DACF_SUCCESS); 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate dev = makedevice(major, minor); 18647c478bd9Sstevel@tonic-gate ASSERT(dev != NODEV); 18657c478bd9Sstevel@tonic-gate 18667c478bd9Sstevel@tonic-gate mutex_enter(&sp->cons_lock); 18677c478bd9Sstevel@tonic-gate if ((prop = consconfig_find_dev(sp, dev)) == NULL) { 18687c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 18697c478bd9Sstevel@tonic-gate return (DACF_FAILURE); 18707c478bd9Sstevel@tonic-gate } 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate error = do_unconfig(sp, prop); 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate /* 18757c478bd9Sstevel@tonic-gate * Keep this dev on the list, for this dev is still online. 18767c478bd9Sstevel@tonic-gate */ 18777c478bd9Sstevel@tonic-gate mutex_exit(&sp->cons_lock); 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate return (error); 18807c478bd9Sstevel@tonic-gate } 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate /* 18837c478bd9Sstevel@tonic-gate * Routine to set baud rate, bits-per-char, parity and stop bits 18847c478bd9Sstevel@tonic-gate * on the console line when necessary. 18857c478bd9Sstevel@tonic-gate */ 18867c478bd9Sstevel@tonic-gate static int 18877c478bd9Sstevel@tonic-gate consconfig_setmodes(dev_t dev, struct termios *termiosp) 18887c478bd9Sstevel@tonic-gate { 18897c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 18907c478bd9Sstevel@tonic-gate int len = MAXPATHLEN; 18917c478bd9Sstevel@tonic-gate char name[16]; 1892d0495a01Sedp int ppos, i; 18937c478bd9Sstevel@tonic-gate char *path; 18947c478bd9Sstevel@tonic-gate dev_t tdev; 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate /* 18977c478bd9Sstevel@tonic-gate * First, search for a devalias which matches this dev_t. 18987c478bd9Sstevel@tonic-gate * Try all of ttya through ttyz until no such alias 18997c478bd9Sstevel@tonic-gate */ 19007c478bd9Sstevel@tonic-gate (void) strcpy(name, "ttya"); 19017c478bd9Sstevel@tonic-gate for (i = 0; i < ('z'-'a'); i++) { 19027c478bd9Sstevel@tonic-gate name[3] = 'a' + i; /* increment device name */ 19037c478bd9Sstevel@tonic-gate path = get_alias(name, buf); 19047c478bd9Sstevel@tonic-gate if (path == NULL) 19057c478bd9Sstevel@tonic-gate return (1); 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate tdev = ddi_pathname_to_dev_t(path); 19087c478bd9Sstevel@tonic-gate if (tdev == dev) 19097c478bd9Sstevel@tonic-gate break; /* Exit loop if found */ 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate if (i >= ('z'-'a')) 19137c478bd9Sstevel@tonic-gate return (1); /* If we didn't find it, return */ 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gate /* 19167c478bd9Sstevel@tonic-gate * Now that we know which "tty" this corresponds to, retrieve 19177c478bd9Sstevel@tonic-gate * the "ttya-mode" options property, which tells us how to configure 19187c478bd9Sstevel@tonic-gate * the line. 19197c478bd9Sstevel@tonic-gate */ 19207c478bd9Sstevel@tonic-gate (void) strcpy(name, "ttya-mode"); /* name of option we want */ 19217c478bd9Sstevel@tonic-gate name[3] = 'a' + i; /* Adjust to correct line */ 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_root_node(), 0, name, 19247c478bd9Sstevel@tonic-gate buf, &len) != DDI_PROP_SUCCESS) 19257c478bd9Sstevel@tonic-gate return (1); /* if no such option, just return */ 19267c478bd9Sstevel@tonic-gate 1927d0495a01Sedp /* 1928d0495a01Sedp * The IEEE 1275 standard specifies that /aliases string property 1929c1d90a7fSGeorge Shepherd * values should be null-terminated. Unfortunately the reality 1930d0495a01Sedp * is that most aren't and the OBP can't easily be modified to 1931d0495a01Sedp * add null termination to these strings. So we'll add the 1932d0495a01Sedp * null termination here. If the string already contains a 1933d0495a01Sedp * null termination character then that's ok too because we'll 1934d0495a01Sedp * just be adding a second one. 1935d0495a01Sedp */ 1936d0495a01Sedp buf[len] = '\0'; 1937d0495a01Sedp 19387c478bd9Sstevel@tonic-gate /* Clear out options we will be setting */ 19397c478bd9Sstevel@tonic-gate termiosp->c_cflag &= 19407c478bd9Sstevel@tonic-gate ~(CSIZE | CBAUD | CBAUDEXT | PARODD | PARENB | CSTOPB); 19417c478bd9Sstevel@tonic-gate 1942c1d90a7fSGeorge Shepherd /* Clear options which potentially conflict with new settings */ 1943c1d90a7fSGeorge Shepherd termiosp->c_cflag &= ~(CIBAUD | CIBAUDEXT); 1944c1d90a7fSGeorge Shepherd 19457c478bd9Sstevel@tonic-gate /* 19467c478bd9Sstevel@tonic-gate * Now, parse the string. Wish I could use sscanf(). 19477c478bd9Sstevel@tonic-gate * Format 9600,8,n,1,- 19487c478bd9Sstevel@tonic-gate * baud rate, bits-per-char, parity, stop-bits, ignored 19497c478bd9Sstevel@tonic-gate */ 19507c478bd9Sstevel@tonic-gate for (ppos = 0; ppos < (MAXPATHLEN-8); ppos++) { /* Find first comma */ 19517c478bd9Sstevel@tonic-gate if ((buf[ppos] == 0) || (buf[ppos] == ',')) 19527c478bd9Sstevel@tonic-gate break; 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate if (buf[ppos] != ',') { 19567c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_setmodes: " 19577c478bd9Sstevel@tonic-gate "invalid mode string %s", buf); 19587c478bd9Sstevel@tonic-gate return (1); 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_SPEEDS; i++) { 19627c478bd9Sstevel@tonic-gate if (strncmp(buf, speedtab[i].name, ppos) == 0) 19637c478bd9Sstevel@tonic-gate break; 19647c478bd9Sstevel@tonic-gate } 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate if (i >= MAX_SPEEDS) { 19677c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 19687c478bd9Sstevel@tonic-gate "consconfig_setmodes: unrecognized speed in %s", buf); 19697c478bd9Sstevel@tonic-gate return (1); 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate 19727c478bd9Sstevel@tonic-gate /* Found the baud rate, set it */ 19737c478bd9Sstevel@tonic-gate termiosp->c_cflag |= speedtab[i].code & CBAUD; 19747c478bd9Sstevel@tonic-gate if (speedtab[i].code > 16) /* cfsetospeed! */ 19757c478bd9Sstevel@tonic-gate termiosp->c_cflag |= CBAUDEXT; 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate /* Set bits per character */ 19787c478bd9Sstevel@tonic-gate switch (buf[ppos+1]) { 19797c478bd9Sstevel@tonic-gate case '8': 19807c478bd9Sstevel@tonic-gate termiosp->c_cflag |= CS8; 19817c478bd9Sstevel@tonic-gate break; 19827c478bd9Sstevel@tonic-gate case '7': 19837c478bd9Sstevel@tonic-gate termiosp->c_cflag |= CS7; 19847c478bd9Sstevel@tonic-gate break; 19857c478bd9Sstevel@tonic-gate default: 19867c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 19877c478bd9Sstevel@tonic-gate "consconfig_setmodes: illegal bits-per-char %s", buf); 19887c478bd9Sstevel@tonic-gate return (1); 19897c478bd9Sstevel@tonic-gate } 19907c478bd9Sstevel@tonic-gate 19917c478bd9Sstevel@tonic-gate /* Set parity */ 19927c478bd9Sstevel@tonic-gate switch (buf[ppos+3]) { 19937c478bd9Sstevel@tonic-gate case 'o': 19947c478bd9Sstevel@tonic-gate termiosp->c_cflag |= PARENB | PARODD; 19957c478bd9Sstevel@tonic-gate break; 19967c478bd9Sstevel@tonic-gate case 'e': 19977c478bd9Sstevel@tonic-gate termiosp->c_cflag |= PARENB; /* enabled, not odd */ 19987c478bd9Sstevel@tonic-gate break; 19997c478bd9Sstevel@tonic-gate case 'n': 20007c478bd9Sstevel@tonic-gate break; /* not enabled. */ 20017c478bd9Sstevel@tonic-gate default: 20027c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_setmodes: illegal parity %s", buf); 20037c478bd9Sstevel@tonic-gate return (1); 20047c478bd9Sstevel@tonic-gate } 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate /* Set stop bits */ 20077c478bd9Sstevel@tonic-gate switch (buf[ppos+5]) { 20087c478bd9Sstevel@tonic-gate case '1': 20097c478bd9Sstevel@tonic-gate break; /* No extra stop bit */ 20107c478bd9Sstevel@tonic-gate case '2': 20117c478bd9Sstevel@tonic-gate termiosp->c_cflag |= CSTOPB; /* 1 extra stop bit */ 20127c478bd9Sstevel@tonic-gate break; 20137c478bd9Sstevel@tonic-gate default: 20147c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "consconfig_setmodes: " 20157c478bd9Sstevel@tonic-gate "illegal stop bits %s", buf); 20167c478bd9Sstevel@tonic-gate return (1); 20177c478bd9Sstevel@tonic-gate } 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate return (0); 20207c478bd9Sstevel@tonic-gate } 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate /* 20237c478bd9Sstevel@tonic-gate * Check to see if underlying keyboard devices are still online, 20247c478bd9Sstevel@tonic-gate * if any one is offline now, unlink it. 20257c478bd9Sstevel@tonic-gate */ 20267c478bd9Sstevel@tonic-gate static void 20277c478bd9Sstevel@tonic-gate consconfig_check_phys_kbd(cons_state_t *sp) 20287c478bd9Sstevel@tonic-gate { 20297c478bd9Sstevel@tonic-gate ldi_handle_t kb_lh; 20307c478bd9Sstevel@tonic-gate cons_prop_t *prop; 20317c478bd9Sstevel@tonic-gate int error; 20327c478bd9Sstevel@tonic-gate int rval; 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate for (prop = sp->cons_km_prop; prop; prop = prop->cp_next) { 20357c478bd9Sstevel@tonic-gate if ((prop->cp_type != CONS_KBD) || (prop->cp_muxid == -1)) 20367c478bd9Sstevel@tonic-gate continue; 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate error = ldi_open_by_dev(&prop->cp_dev, OTYP_CHR, 20397c478bd9Sstevel@tonic-gate FREAD|FWRITE|FNOCTTY, kcred, &kb_lh, sp->cons_li); 20407c478bd9Sstevel@tonic-gate 20417c478bd9Sstevel@tonic-gate if (error) { 20427c478bd9Sstevel@tonic-gate (void) ldi_ioctl(sp->conskbd_lh, I_PUNLINK, 20437c478bd9Sstevel@tonic-gate prop->cp_muxid, FKIOCTL, kcred, &rval); 20447c478bd9Sstevel@tonic-gate prop->cp_dev = NODEV; 20457c478bd9Sstevel@tonic-gate } else { 20467c478bd9Sstevel@tonic-gate (void) ldi_close(kb_lh, FREAD|FWRITE, kcred); 20477c478bd9Sstevel@tonic-gate } 20487c478bd9Sstevel@tonic-gate } 20497c478bd9Sstevel@tonic-gate 20507c478bd9Sstevel@tonic-gate /* 20517c478bd9Sstevel@tonic-gate * Remove all disconnected keyboards, 20527c478bd9Sstevel@tonic-gate * whose dev is turned into NODEV above. 20537c478bd9Sstevel@tonic-gate */ 20547c478bd9Sstevel@tonic-gate consconfig_rem_dev(sp, NODEV); 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate /* 20587c478bd9Sstevel@tonic-gate * Remove devices according to dev, which may be NODEV 20597c478bd9Sstevel@tonic-gate */ 20607c478bd9Sstevel@tonic-gate static void 20617c478bd9Sstevel@tonic-gate consconfig_rem_dev(cons_state_t *sp, dev_t dev) 20627c478bd9Sstevel@tonic-gate { 20637c478bd9Sstevel@tonic-gate cons_prop_t *prop; 20647c478bd9Sstevel@tonic-gate cons_prop_t *prev_prop; 20657c478bd9Sstevel@tonic-gate cons_prop_t *tmp_prop; 20667c478bd9Sstevel@tonic-gate cons_prop_t *head_prop; 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate head_prop = NULL; 20697c478bd9Sstevel@tonic-gate prev_prop = NULL; 20707c478bd9Sstevel@tonic-gate for (prop = sp->cons_km_prop; prop != NULL; ) { 20717c478bd9Sstevel@tonic-gate if (prop->cp_dev == dev) { 20727c478bd9Sstevel@tonic-gate tmp_prop = prop->cp_next; 20737c478bd9Sstevel@tonic-gate consconfig_free_prop(prop); 20747c478bd9Sstevel@tonic-gate prop = tmp_prop; 20757c478bd9Sstevel@tonic-gate if (prev_prop) 20767c478bd9Sstevel@tonic-gate prev_prop->cp_next = prop; 20777c478bd9Sstevel@tonic-gate } else { 20787c478bd9Sstevel@tonic-gate if (head_prop == NULL) 20797c478bd9Sstevel@tonic-gate head_prop = prop; 20807c478bd9Sstevel@tonic-gate prev_prop = prop; 20817c478bd9Sstevel@tonic-gate prop = prop->cp_next; 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate } 20847c478bd9Sstevel@tonic-gate sp->cons_km_prop = head_prop; 20857c478bd9Sstevel@tonic-gate } 20867c478bd9Sstevel@tonic-gate 20877c478bd9Sstevel@tonic-gate /* 20887c478bd9Sstevel@tonic-gate * Add a dev according to prop 20897c478bd9Sstevel@tonic-gate */ 20907c478bd9Sstevel@tonic-gate static void 20917c478bd9Sstevel@tonic-gate consconfig_add_dev(cons_state_t *sp, cons_prop_t *prop) 20927c478bd9Sstevel@tonic-gate { 20937c478bd9Sstevel@tonic-gate prop->cp_next = sp->cons_km_prop; 20947c478bd9Sstevel@tonic-gate sp->cons_km_prop = prop; 20957c478bd9Sstevel@tonic-gate } 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate /* 20987c478bd9Sstevel@tonic-gate * Find a device from our list according to dev 20997c478bd9Sstevel@tonic-gate */ 21007c478bd9Sstevel@tonic-gate static cons_prop_t * 21017c478bd9Sstevel@tonic-gate consconfig_find_dev(cons_state_t *sp, dev_t dev) 21027c478bd9Sstevel@tonic-gate { 21037c478bd9Sstevel@tonic-gate cons_prop_t *prop; 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate for (prop = sp->cons_km_prop; prop; prop = prop->cp_next) { 21067c478bd9Sstevel@tonic-gate if (prop->cp_dev == dev) 21077c478bd9Sstevel@tonic-gate break; 21087c478bd9Sstevel@tonic-gate } 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate return (prop); 21117c478bd9Sstevel@tonic-gate } 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate /* 21147c478bd9Sstevel@tonic-gate * Free a cons prop associated with a keyboard or mouse 21157c478bd9Sstevel@tonic-gate */ 21167c478bd9Sstevel@tonic-gate static void 21177c478bd9Sstevel@tonic-gate consconfig_free_prop(cons_prop_t *prop) 21187c478bd9Sstevel@tonic-gate { 21197c478bd9Sstevel@tonic-gate if (prop->cp_pushmod) 21207c478bd9Sstevel@tonic-gate kmem_free(prop->cp_pushmod, strlen(prop->cp_pushmod) + 1); 21217c478bd9Sstevel@tonic-gate kmem_free(prop, sizeof (cons_prop_t)); 21227c478bd9Sstevel@tonic-gate } 212328cdc3d7Sszhou 212428cdc3d7Sszhou /* 212548633f18SJan Setje-Eilers * The early boot code can't print to a usb serial device or the 212648633f18SJan Setje-Eilers * graphical boot screen. 212748633f18SJan Setje-Eilers * 212848633f18SJan Setje-Eilers * The early boot messages are saved in a buffer at the address indicated 212948633f18SJan Setje-Eilers * by "deferred-console-buf" This function flushes the message to the 213048633f18SJan Setje-Eilers * current console now that it is set up. 213128cdc3d7Sszhou */ 213228cdc3d7Sszhou static void 213348633f18SJan Setje-Eilers flush_deferred_console_buf(void) 213428cdc3d7Sszhou { 213528cdc3d7Sszhou int rval; 213628cdc3d7Sszhou vnode_t *vp; 213748633f18SJan Setje-Eilers uint_t defcons_buf; 213848633f18SJan Setje-Eilers char *kc, *bc, *defcons_kern_buf; 213928cdc3d7Sszhou 214048633f18SJan Setje-Eilers /* defcons_buf is in low memory, so an int works here */ 214148633f18SJan Setje-Eilers defcons_buf = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), 214248633f18SJan Setje-Eilers DDI_PROP_DONTPASS, "deferred-console-buf", 0); 214328cdc3d7Sszhou 214448633f18SJan Setje-Eilers if (defcons_buf == 0) 214528cdc3d7Sszhou return; 214628cdc3d7Sszhou 214728cdc3d7Sszhou /* 214828cdc3d7Sszhou * After consconfig() and before userland opens /dev/sysmsg, 214928cdc3d7Sszhou * console I/O is goes to polled I/O entry points. 215028cdc3d7Sszhou * 215128cdc3d7Sszhou * If usb-serial doesn't implement polled I/O, we need 215228cdc3d7Sszhou * to open /dev/console now to get kernel console I/O to work. 215328cdc3d7Sszhou * We also push ttcompat and ldterm explicitly to get the 215428cdc3d7Sszhou * correct output format (autopush isn't set up yet). We 215528cdc3d7Sszhou * ignore push errors because they are non-fatal. 215628cdc3d7Sszhou * Note that opening /dev/console causes rconsvp to be 215728cdc3d7Sszhou * opened as well. 215828cdc3d7Sszhou */ 215928cdc3d7Sszhou if (cons_polledio == NULL) { 216028cdc3d7Sszhou if (vn_open("/dev/console", UIO_SYSSPACE, FWRITE | FNOCTTY, 216128cdc3d7Sszhou 0, &vp, 0, 0) != 0) 216228cdc3d7Sszhou return; 216328cdc3d7Sszhou 216428cdc3d7Sszhou if (rconsvp) { 216528cdc3d7Sszhou (void) strioctl(rconsvp, __I_PUSH_NOCTTY, 216628cdc3d7Sszhou (intptr_t)"ldterm", FKIOCTL, K_TO_K, kcred, &rval); 216728cdc3d7Sszhou (void) strioctl(rconsvp, __I_PUSH_NOCTTY, 216828cdc3d7Sszhou (intptr_t)"ttcompat", FKIOCTL, K_TO_K, 216928cdc3d7Sszhou kcred, &rval); 217028cdc3d7Sszhou } 217128cdc3d7Sszhou } 217228cdc3d7Sszhou 217328cdc3d7Sszhou /* 217428cdc3d7Sszhou * Copy message to a kernel buffer. Various kernel routines 217528cdc3d7Sszhou * expect buffer to be above kernelbase 217628cdc3d7Sszhou */ 2177de81e71eSTim Marsland kc = defcons_kern_buf = kmem_zalloc(MMU_PAGESIZE, KM_SLEEP); 217848633f18SJan Setje-Eilers bc = (char *)(uintptr_t)defcons_buf; 217928cdc3d7Sszhou while (*kc++ = *bc++) 218028cdc3d7Sszhou ; 218148633f18SJan Setje-Eilers console_printf("%s", defcons_kern_buf); 218228cdc3d7Sszhou 218348633f18SJan Setje-Eilers kmem_free(defcons_kern_buf, MMU_PAGESIZE); 218428cdc3d7Sszhou } 2185aecfc01dSrui zang - Sun Microsystems - Beijing China 2186aecfc01dSrui zang - Sun Microsystems - Beijing China boolean_t 2187aecfc01dSrui zang - Sun Microsystems - Beijing China consconfig_console_is_tipline(void) 2188aecfc01dSrui zang - Sun Microsystems - Beijing China { 2189aecfc01dSrui zang - Sun Microsystems - Beijing China cons_state_t *sp; 2190aecfc01dSrui zang - Sun Microsystems - Beijing China 2191aecfc01dSrui zang - Sun Microsystems - Beijing China if ((sp = (cons_state_t *)space_fetch("consconfig")) == NULL) 2192aecfc01dSrui zang - Sun Microsystems - Beijing China return (B_FALSE); 2193aecfc01dSrui zang - Sun Microsystems - Beijing China 2194aecfc01dSrui zang - Sun Microsystems - Beijing China if (sp->cons_input_type == CONSOLE_TIP) 2195aecfc01dSrui zang - Sun Microsystems - Beijing China return (B_TRUE); 2196aecfc01dSrui zang - Sun Microsystems - Beijing China 2197aecfc01dSrui zang - Sun Microsystems - Beijing China return (B_FALSE); 2198aecfc01dSrui zang - Sun Microsystems - Beijing China } 219940482326SVincent Wang 220040482326SVincent Wang boolean_t 220140482326SVincent Wang consconfig_dacf_initialized(void) 220240482326SVincent Wang { 220340482326SVincent Wang cons_state_t *sp; 220440482326SVincent Wang 220540482326SVincent Wang if ((sp = (cons_state_t *)space_fetch("consconfig")) == NULL) 220640482326SVincent Wang return (B_FALSE); 220740482326SVincent Wang 220840482326SVincent Wang return (sp->cons_initialized); 220940482326SVincent Wang } 2210