Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * This module performs two functions.  First, it kicks off the driver loading
     29  * of the console devices during boot in dynamic_console_config().
     30  * The loading of the drivers for the console devices triggers the
     31  * additional device autoconfiguration to link the drivers into the keyboard
     32  * and mouse console streams.
     33  *
     34  * The second function of this module is to provide the dacf functions
     35  * to be called after a driver has attached and before it detaches.  For
     36  * example, a driver associated with the keyboard will have kb_config called
     37  * after the driver attaches and kb_unconfig before it detaches.  Similar
     38  * configuration actions are performed on behalf of minor nodes representing
     39  * mice.  The configuration functions for the attach case take a module
     40  * name as a parameter.  The module is pushed on top of the driver during
     41  * the configuration.
     42  *
     43  * Although the dacf framework is used to configure all keyboards and mice,
     44  * its primary function is to allow keyboard and mouse hotplugging.
     45  *
     46  * This module supports multiple keyboards and mice at the same time.
     47  *
     48  * From the kernel perspective, there are roughly three different possible
     49  * console configurations.  Across these three configurations, the following
     50  * elements are constant:
     51  * 	wsconsvp = IWSCN_PATH
     52  * 	rwsconsvp = WC_PATH
     53  * 	consms -> msdev
     54  *
     55  * The "->" syntax indicates that the streams device on the right is
     56  * linked under the streams device on the left.
     57  *
     58  * The following lists how the system is configured for different setups:
     59  *
     60  * stdin is a local keyboard.  use stdin and stdout as the console.
     61  * 	sp->cons_input_type = CONSOLE_LOCAL
     62  *	rconsvp = IWSCN_PATH
     63  *	wc -> conskbd -> kbddev
     64  *
     65  * stdin is not a keyboard and stdin is the same as stdout.
     66  * assume we running on a tip line and use stdin/stdout as the console.
     67  * 	sp->cons_input_type = CONSOLE_TIP
     68  *	rconsvp = (stdindev/stdoutdev)
     69  *	wc -> conskbd -> kbddev
     70  *
     71  * stdin is not a keyboard device and it's not the same as stdout.
     72  * assume we have a serial keyboard hooked up and use it along with
     73  * stdout as the console.
     74  * 	sp->cons_input_type = CONSOLE_SERIAL_KEYBOARD
     75  *	rconsvp = IWSCN_PATH
     76  *	wc -> stdindev
     77  *	conskbd -> kbddev
     78  *
     79  * CAVEAT:
     80  * 	The above is all true except for one possible Intel configuration.
     81  * 	If stdin is set to a local keyboard but stdout is set to something
     82  * 	other than the local display (a tip port for example) stdout will
     83  * 	still go to the local display.  This is an artifact of the console
     84  * 	implementation on intel.
     85  */
     86 
     87 #include <sys/types.h>
     88 #include <sys/param.h>
     89 #include <sys/cmn_err.h>
     90 #include <sys/user.h>
     91 #include <sys/vfs.h>
     92 #include <sys/vnode.h>
     93 #include <sys/pathname.h>
     94 #include <sys/systm.h>
     95 #include <sys/file.h>
     96 #include <sys/stropts.h>
     97 #include <sys/stream.h>
     98 #include <sys/strsubr.h>
     99 
    100 #include <sys/consdev.h>
    101 #include <sys/console.h>
    102 #include <sys/wscons.h>
    103 #include <sys/kbio.h>
    104 #include <sys/debug.h>
    105 #include <sys/reboot.h>
    106 #include <sys/termios.h>
    107 
    108 #include <sys/ddi.h>
    109 #include <sys/sunddi.h>
    110 #include <sys/sunldi.h>
    111 #include <sys/sunndi.h>
    112 #include <sys/ndi_impldefs.h>
    113 #include <sys/modctl.h>
    114 #include <sys/ddi_impldefs.h>
    115 #include <sys/ddi_implfuncs.h>
    116 #include <sys/promif.h>
    117 #include <sys/fs/snode.h>
    118 
    119 #include <sys/errno.h>
    120 #include <sys/devops.h>
    121 #include <sys/note.h>
    122 
    123 #include <sys/tem_impl.h>
    124 #include <sys/polled_io.h>
    125 #include <sys/kmem.h>
    126 #include <sys/dacf.h>
    127 #include <sys/consconfig_dacf.h>
    128 #include <sys/consplat.h>
    129 #include <sys/log.h>
    130 #include <sys/disp.h>
    131 
    132 /*
    133  * External global variables
    134  */
    135 extern vnode_t		*rconsvp;
    136 extern dev_t		rwsconsdev;
    137 
    138 /*
    139  * External functions
    140  */
    141 extern uintptr_t	space_fetch(char *key);
    142 extern int		space_store(char *key, uintptr_t ptr);
    143 
    144 /*
    145  * Tasks
    146  */
    147 static int	kb_config(dacf_infohdl_t, dacf_arghdl_t, int);
    148 static int	kb_unconfig(dacf_infohdl_t, dacf_arghdl_t, int);
    149 static int	ms_config(dacf_infohdl_t, dacf_arghdl_t, int);
    150 static int	ms_unconfig(dacf_infohdl_t, dacf_arghdl_t, int);
    151 
    152 /*
    153  * Internal functions
    154  */
    155 static int	consconfig_setmodes(dev_t dev, struct termios *termiosp);
    156 static void	consconfig_check_phys_kbd(cons_state_t *);
    157 static void	consconfig_rem_dev(cons_state_t *, dev_t);
    158 static void	consconfig_add_dev(cons_state_t *, cons_prop_t *);
    159 static cons_prop_t *consconfig_find_dev(cons_state_t *, dev_t);
    160 static void	consconfig_free_prop(cons_prop_t *prop);
    161 static void	flush_usb_serial_buf(void);
    162 
    163 
    164 /*
    165  * On supported configurations, the firmware defines the keyboard and mouse
    166  * paths.  However, during USB development, it is useful to be able to use
    167  * the USB keyboard and mouse on machines without full USB firmware support.
    168  * These variables may be set in /etc/system according to a machine's
    169  * USB configuration.  This module will override the firmware's values
    170  * with these.
    171  *
    172  * NOTE:
    173  * The master copies of these variables in the misc/consconfig module.
    174  * The reason for this is historic.  In versions of solaris up to and
    175  * including solaris 9 the conscole configuration code was split into a
    176  * seperate sparc and intel version.  These variables were defined
    177  * in misc/consconfig on sparc and dacf/consconfig_dacf on intel.
    178  *
    179  * Unfortunatly the sparc variables were well documented.
    180  * So to aviod breaking either sparc or intel we'll declare the variables
    181  * in both modules.  This will allow any /etc/system entries that
    182  * users may have to continue working.
    183  *
    184  * The variables in misc/consconfig will take precedence over the variables
    185  * found in this file.  Since we eventually want to remove the variables
    186  * local to this this file, if the user set them we'll emmit an error
    187  * message telling them they need to set the variables in misc/consconfig
    188  * instead.
    189  */
    190 static char *usb_kb_path = NULL;
    191 static char *usb_ms_path = NULL;
    192 
    193 /*
    194  * Access functions in the misc/consconfig module used to retrieve the
    195  * values of it local usb_kb_path and usb_ms_path variables
    196  */
    197 extern char *consconfig_get_usb_kb_path();
    198 extern char *consconfig_get_usb_ms_path();
    199 
    200 /*
    201  * Local variables used to store the value of the usb_kb_path and
    202  * usb_ms_path variables found in misc/consconfig
    203  */
    204 static char *consconfig_usb_kb_path = NULL;
    205 static char *consconfig_usb_ms_path = NULL;
    206 
    207 /*
    208  * Internal variables
    209  */
    210 static dev_t		stdoutdev;
    211 static cons_state_t	*consconfig_sp;
    212 
    213 /*
    214  * consconfig_errlevel:  debug verbosity; smaller numbers are more
    215  * verbose.
    216  */
    217 int consconfig_errlevel = DPRINT_L3;
    218 
    219 /*
    220  * Baud rate table
    221  */
    222 #define	MAX_SPEEDS 24
    223 static struct speed {
    224 	char *name;
    225 	int code;
    226 } speedtab[MAX_SPEEDS] = {
    227 	{"0", B0},		{"50", B50},		{"75", B75},
    228 	{"110", B110},		{"134", B134},		{"150", B150},
    229 	{"200", B200},		{"300", B300},		{"600", B600},
    230 	{"1200", B1200},	{"1800", B1800},	{"2400", B2400},
    231 	{"4800", B4800},	{"9600", B9600},	{"19200", B19200},
    232 	{"38400", B38400},	{"57600", B57600},	{"76800", B76800},
    233 	{"115200", B115200},	{"153600", B153600},	{"230400", B230400},
    234 	{"307200", B307200},	{"460800", B460800},	{"", 0}
    235 };
    236 
    237 static dacf_op_t kbconfig_op[] = {
    238 	{ DACF_OPID_POSTATTACH,	kb_config },
    239 	{ DACF_OPID_PREDETACH,	kb_unconfig },
    240 	{ DACF_OPID_END,	NULL },
    241 };
    242 
    243 static dacf_op_t msconfig_op[] = {
    244 	{ DACF_OPID_POSTATTACH,	ms_config },
    245 	{ DACF_OPID_PREDETACH,	ms_unconfig },
    246 	{ DACF_OPID_END,	NULL },
    247 };
    248 
    249 static dacf_opset_t opsets[] = {
    250 	{ "kb_config",	kbconfig_op },
    251 	{ "ms_config",	msconfig_op },
    252 	{ NULL,		NULL }
    253 };
    254 
    255 struct dacfsw dacfsw = {
    256 	DACF_MODREV_1,
    257 	opsets,
    258 };
    259 
    260 static struct modldacf modldacf = {
    261 	&mod_dacfops,   /* Type of module */
    262 	"Consconfig DACF",
    263 	&dacfsw
    264 };
    265 
    266 static struct modlinkage modlinkage = {
    267 	MODREV_1, (void *)&modldacf, NULL
    268 };
    269 
    270 int
    271 _init(void) {
    272 	return (mod_install(&modlinkage));
    273 }
    274 
    275 int
    276 _fini(void)
    277 {
    278 	/*
    279 	 * This modules state is held in the kernel by space.c
    280 	 * allowing this module to be unloaded.
    281 	 */
    282 	return (mod_remove(&modlinkage));
    283 }
    284 
    285 int
    286 _info(struct modinfo *modinfop)
    287 {
    288 	return (mod_info(&modlinkage, modinfop));
    289 }
    290 
    291 /*PRINTFLIKE2*/
    292 static void consconfig_dprintf(int, const char *, ...)
    293     __KPRINTFLIKE(2);
    294 
    295 static void
    296 consconfig_dprintf(int l, const char *fmt, ...)
    297 {
    298 	va_list ap;
    299 
    300 #ifndef DEBUG
    301 	if (!l) {
    302 		return;
    303 	}
    304 #endif /* DEBUG */
    305 	if (l < consconfig_errlevel) {
    306 		return;
    307 	}
    308 
    309 	va_start(ap, fmt);
    310 	(void) vprintf(fmt, ap);
    311 	va_end(ap);
    312 }
    313 
    314 /*
    315  * Return a property value for the specified alias in /aliases.
    316  */
    317 char *
    318 get_alias(char *alias, char *buf)
    319 {
    320 	pnode_t node;
    321 	int len;
    322 
    323 	/* The /aliases node only exists in OBP >= 2.4. */
    324 	if ((node = prom_alias_node()) == OBP_BADNODE)
    325 		return (NULL);
    326 
    327 	if ((len = prom_getproplen(node, (caddr_t)alias)) <= 0)
    328 		return (NULL);
    329 
    330 	(void) prom_getprop(node, (caddr_t)alias, (caddr_t)buf);
    331 
    332 	/*
    333 	 * The IEEE 1275 standard specifies that /aliases string property
    334 	 * values should be null-terminated.  Unfortunatly the reality
    335 	 * is that most aren't and the OBP can't easily be modified to
    336 	 * add null termination to these strings.  So we'll add the
    337 	 * null termination here.  If the string already contains a
    338 	 * null termination character then that's ok too because we'll
    339 	 * just be adding a second one.
    340 	 */
    341 	buf[len] = '\0';
    342 
    343 	prom_pathname(buf);
    344 	return (buf);
    345 }
    346 
    347 /*
    348  * i_consconfig_createvp:
    349  *	This routine is a convenience routine that is passed a path and returns
    350  *	a vnode.
    351  */
    352 static vnode_t *
    353 i_consconfig_createvp(char *path)
    354 {
    355 	int error;
    356 	vnode_t *vp;
    357 	char *buf = NULL, *fullpath;
    358 
    359 	DPRINTF(DPRINT_L0, "i_consconfig_createvp: %s\n", path);
    360 	fullpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
    361 
    362 	if (strchr(path, ':') == NULL) {
    363 		/* convert an OBP path to a /devices path */
    364 		buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
    365 		if (i_ddi_prompath_to_devfspath(path, buf) != DDI_SUCCESS) {
    366 			kmem_free(buf, MAXPATHLEN);
    367 			kmem_free(fullpath, MAXPATHLEN);
    368 			return (NULL);
    369 		}
    370 		(void) snprintf(fullpath, MAXPATHLEN, "/devices%s", buf);
    371 		kmem_free(buf, MAXPATHLEN);
    372 	} else {
    373 		/* convert a devfs path to a /devices path */
    374 		(void) snprintf(fullpath, MAXPATHLEN, "/devices%s", path);
    375 	}
    376 
    377 	DPRINTF(DPRINT_L0, "lookupname(%s)\n", fullpath);
    378 	error = lookupname(fullpath, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp);
    379 	kmem_free(fullpath, MAXPATHLEN);
    380 	if (error)
    381 		return (NULL);
    382 
    383 	DPRINTF(DPRINT_L0, "create vnode = 0x%p - dev 0x%lx\n", vp, vp->v_rdev);
    384 	ASSERT(vn_matchops(vp, spec_getvnodeops()));
    385 
    386 	return (vp);
    387 }
    388 
    389 /*
    390  * consconfig_print_paths:
    391  *	Function to print out the various paths
    392  */
    393 static void
    394 consconfig_print_paths(void)
    395 {
    396 	char    *path;
    397 
    398 	if (usb_kb_path != NULL)
    399 		cmn_err(CE_WARN,
    400 		    "consconfig_dacf:usb_kb_path has been deprecated, "
    401 		    "use consconfig:usb_kb_path instead");
    402 
    403 	if (usb_ms_path != NULL)
    404 		cmn_err(CE_WARN,
    405 		    "consconfig_dacf:usb_ms_path has been deprecated, "
    406 		    "use consconfig:usb_ms_path instead");
    407 
    408 	if (consconfig_errlevel > DPRINT_L0)
    409 		return;
    410 
    411 	path = NULL;
    412 	if (consconfig_usb_kb_path != NULL)
    413 		path = consconfig_usb_kb_path;
    414 	else if (usb_kb_path != NULL)
    415 		path = usb_kb_path;
    416 	if (path != NULL)
    417 		DPRINTF(DPRINT_L0, "usb keyboard path = %s\n", path);
    418 
    419 	path = plat_kbdpath();
    420 	if (path != NULL)
    421 		DPRINTF(DPRINT_L0, "keyboard path = %s\n", path);
    422 
    423 	path = NULL;
    424 	if (consconfig_usb_ms_path != NULL)
    425 		path = consconfig_usb_ms_path;
    426 	else if (usb_ms_path != NULL)
    427 		path = usb_ms_path;
    428 	if (path != NULL)
    429 		DPRINTF(DPRINT_L0, "usb mouse path = %s\n", path);
    430 
    431 	path = plat_mousepath();
    432 	if (path != NULL)
    433 		DPRINTF(DPRINT_L0, "mouse path = %s\n", path);
    434 
    435 	path = plat_stdinpath();
    436 	if (path != NULL)
    437 		DPRINTF(DPRINT_L0, "stdin path = %s\n", path);
    438 
    439 	path = plat_stdoutpath();
    440 	if (path != NULL)
    441 		DPRINTF(DPRINT_L0, "stdout path = %s\n", path);
    442 
    443 	path = plat_fbpath();
    444 	if (path != NULL)
    445 		DPRINTF(DPRINT_L0, "fb path = %s\n", path);
    446 }
    447 
    448 /*
    449  * consconfig_kbd_abort_enable:
    450  * 	Send the CONSSETABORTENABLE ioctl to the lower layers.  This ioctl
    451  * 	will only be sent to the device if it is the console device.
    452  * 	This ioctl tells the device to pay attention to abort sequences.
    453  * 	In the case of kbtrans, this would tell the driver to pay attention
    454  * 	to the two key abort sequences like STOP-A.  In the case of the
    455  * 	serial keyboard, it would be an abort sequence like a break.
    456  */
    457 static int
    458 consconfig_kbd_abort_enable(ldi_handle_t lh)
    459 {
    460 	int	err, rval;
    461 
    462 	DPRINTF(DPRINT_L0, "consconfig_kbd_abort_enable\n");
    463 
    464 	err = ldi_ioctl(lh, CONSSETABORTENABLE, (uintptr_t)B_TRUE,
    465 	    FKIOCTL, kcred, &rval);
    466 	return (err);
    467 }
    468 
    469 /*
    470  * consconfig_kbd_abort_disable:
    471  * 	Send CONSSETABORTENABLE ioctl to lower layers.  This ioctl
    472  * 	will only be sent to the device if it is the console device.
    473  * 	This ioctl tells the physical device to ignore abort sequences,
    474  * 	and send the sequences up to virtual keyboard(conskbd) so that
    475  * 	STOP and A (or F1 and A) can be combined.
    476  */
    477 static int
    478 consconfig_kbd_abort_disable(ldi_handle_t lh)
    479 {
    480 	int	err, rval;
    481 
    482 	DPRINTF(DPRINT_L0, "consconfig_kbd_abort_disable\n");
    483 
    484 	err = ldi_ioctl(lh, CONSSETABORTENABLE, (uintptr_t)B_FALSE,
    485 	    FKIOCTL, kcred, &rval);
    486 	return (err);
    487 }
    488 
    489 #ifdef _HAVE_TEM_FIRMWARE
    490 static int
    491 consconfig_tem_supported(cons_state_t *sp)
    492 {
    493 	dev_t			dev;
    494 	dev_info_t		*dip;
    495 	int			*int_array;
    496 	uint_t			nint;
    497 	int			rv = 0;
    498 
    499 	if (sp->cons_fb_path == NULL)
    500 		return (0);
    501 
    502 	if ((dev = ddi_pathname_to_dev_t(sp->cons_fb_path)) == NODEV)
    503 		return (0); /* warning printed later by common code */
    504 
    505 	/*
    506 	 * Here we hold the driver and check "tem-support" property.
    507 	 * We're doing this with e_ddi_hold_devi_by_dev and
    508 	 * ddi_prop_lookup_int_array without opening the driver since
    509 	 * some video cards that don't support the kernel terminal
    510 	 * emulator could hang or crash if opened too early during
    511 	 * boot.
    512 	 */
    513 	if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) {
    514 		cmn_err(CE_WARN, "consconfig: cannot hold fb dev %s",
    515 		    sp->cons_fb_path);
    516 		return (0);
    517 	}
    518 
    519 	/*
    520 	 * Check that the tem-support property exists AND that
    521 	 * it is equal to 1.
    522 	 */
    523 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
    524 	    DDI_PROP_DONTPASS, "tem-support", &int_array, &nint) ==
    525 	    DDI_SUCCESS) {
    526 		if (nint > 0)
    527 			rv = int_array[0] == 1;
    528 		ddi_prop_free(int_array);
    529 	}
    530 
    531 	ddi_release_devi(dip);
    532 
    533 	return (rv);
    534 }
    535 #endif /* _HAVE_TEM_FIRMWARE */
    536 
    537 /*
    538  * consconfig_get_polledio:
    539  * 	Query the console with the CONSPOLLEDIO ioctl.
    540  * 	The polled I/O routines are used by debuggers to perform I/O while
    541  * 	interrupts and normal kernel services are disabled.
    542  */
    543 static cons_polledio_t *
    544 consconfig_get_polledio(ldi_handle_t lh)
    545 {
    546 	int		err, rval;
    547 	struct strioctl	strioc;
    548 	cons_polledio_t	*polled_io;
    549 
    550 	/*
    551 	 * Setup the ioctl to be sent down to the lower driver.
    552 	 */
    553 	strioc.ic_cmd = CONSOPENPOLLEDIO;
    554 	strioc.ic_timout = INFTIM;
    555 	strioc.ic_len = sizeof (polled_io);
    556 	strioc.ic_dp = (char *)&polled_io;
    557 
    558 	/*
    559 	 * Send the ioctl to the driver.  The ioctl will wait for
    560 	 * the response to come back from wc.  wc has already issued
    561 	 * the CONSOPENPOLLEDIO to the lower layer driver.
    562 	 */
    563 	err = ldi_ioctl(lh, I_STR, (intptr_t)&strioc, FKIOCTL, kcred, &rval);
    564 
    565 	if (err != 0) {
    566 		/*
    567 		 * If the lower driver does not support polled I/O, then
    568 		 * return NULL.  This will be the case if the driver does
    569 		 * not handle polled I/O, or OBP is going to handle polled
    570 		 * I/O for the device.
    571 		 */
    572 
    573 		return (NULL);
    574 	}
    575 
    576 	/*
    577 	 * Return the polled I/O structure.
    578 	 */
    579 	return (polled_io);
    580 }
    581 
    582 /*
    583  * consconfig_setup_polledio:
    584  * 	This routine does the setup work for polled I/O.  First we get
    585  * 	the polled_io structure from the lower layers
    586  * 	and then we register the polled I/O
    587  * 	callbacks with the debugger that will be using them.
    588  */
    589 static void
    590 consconfig_setup_polledio(cons_state_t *sp, dev_t dev)
    591 {
    592 	cons_polledio_t		*polled_io;
    593 	ldi_handle_t		lh;
    594 
    595 	DPRINTF(DPRINT_L0, "consconfig_setup_polledio: start\n");
    596 
    597 
    598 	if (ldi_open_by_dev(&dev, OTYP_CHR,
    599 	    FREAD|FWRITE|FNOCTTY, kcred, &lh, sp->cons_li) != 0)
    600 		return;
    601 
    602 
    603 	/*
    604 	 * Get the polled io routines so that we can use this
    605 	 * device with the debuggers.
    606 	 */
    607 	polled_io = consconfig_get_polledio(lh);
    608 
    609 	/*
    610 	 * If the get polledio failed, then we do not want to throw
    611 	 * the polled I/O switch.
    612 	 */
    613 	if (polled_io == NULL) {
    614 		DPRINTF(DPRINT_L0,
    615 		    "consconfig_setup_polledio: get_polledio failed\n");
    616 		(void) ldi_close(lh, FREAD|FWRITE, kcred);
    617 		return;
    618 	}
    619 
    620 	/* Initialize the polled input */
    621 	polled_io_init();
    622 
    623 	/* Register the callbacks */
    624 	DPRINTF(DPRINT_L0,
    625 	    "consconfig_setup_polledio: registering callbacks\n");
    626 	(void) polled_io_register_callbacks(polled_io, 0);
    627 
    628 	(void) ldi_close(lh, FREAD|FWRITE, kcred);
    629 
    630 	DPRINTF(DPRINT_L0, "consconfig_setup_polledio: end\n");
    631 }
    632 
    633 static cons_state_t *
    634 consconfig_state_init(void)
    635 {
    636 	cons_state_t	*sp;
    637 	int		rval;
    638 
    639 	/* Initialize console information */
    640 	sp = kmem_zalloc(sizeof (cons_state_t), KM_SLEEP);
    641 	sp->cons_keyboard_problem = B_FALSE;
    642 
    643 	mutex_init(&sp->cons_lock, NULL, MUTEX_DRIVER, NULL);
    644 
    645 	/* check if consconfig:usb_kb_path is set in /etc/system */
    646 	consconfig_usb_kb_path = consconfig_get_usb_kb_path();
    647 
    648 	/* check if consconfig:usb_ms_path is set in /etc/system */
    649 	consconfig_usb_ms_path = consconfig_get_usb_ms_path();
    650 
    651 	consconfig_print_paths();
    652 
    653 	/* init external globals */
    654 	stdoutdev = NODEV;
    655 
    656 	/*
    657 	 * Find keyboard, mouse, stdin and stdout devices, if they
    658 	 * exist on this platform.
    659 	 */
    660 
    661 	if (consconfig_usb_kb_path != NULL) {
    662 		sp->cons_keyboard_path = consconfig_usb_kb_path;
    663 	} else if (usb_kb_path != NULL) {
    664 		sp->cons_keyboard_path = usb_kb_path;
    665 	} else {
    666 		sp->cons_keyboard_path = plat_kbdpath();
    667 	}
    668 
    669 	if (consconfig_usb_ms_path != NULL) {
    670 		sp->cons_mouse_path = consconfig_usb_ms_path;
    671 	} else if (usb_ms_path != NULL) {
    672 		sp->cons_mouse_path = usb_ms_path;
    673 	} else {
    674 		sp->cons_mouse_path = plat_mousepath();
    675 	}
    676 
    677 	/* Identify the stdout driver */
    678 	sp->cons_stdout_path = plat_stdoutpath();
    679 	sp->cons_stdout_is_fb = plat_stdout_is_framebuffer();
    680 
    681 	sp->cons_stdin_is_kbd = plat_stdin_is_keyboard();
    682 
    683 	if (sp->cons_stdin_is_kbd &&
    684 	    (usb_kb_path != NULL || consconfig_usb_kb_path != NULL))  {
    685 		sp->cons_stdin_path = sp->cons_keyboard_path;
    686 	} else {
    687 		/*
    688 		 * The standard in device may or may not be the same as
    689 		 * the keyboard. Even if the keyboard is not the
    690 		 * standard input, the keyboard console stream will
    691 		 * still be built if the keyboard alias provided by the
    692 		 * firmware exists and is valid.
    693 		 */
    694 		sp->cons_stdin_path = plat_stdinpath();
    695 	}
    696 
    697 	if (sp->cons_stdout_is_fb) {
    698 		sp->cons_fb_path = sp->cons_stdout_path;
    699 
    700 #ifdef _HAVE_TEM_FIRMWARE
    701 		sp->cons_tem_supported = consconfig_tem_supported(sp);
    702 
    703 		/*
    704 		 * Systems which offer a virtual console must use that
    705 		 * as a fallback whenever the fb doesn't support tem.
    706 		 * Such systems cannot render characters to the screen
    707 		 * using OBP.
    708 		 */
    709 		if (!sp->cons_tem_supported) {
    710 			char *path;
    711 
    712 			if (plat_virtual_console_path(&path) >= 0) {
    713 				sp->cons_stdin_is_kbd = 0;
    714 				sp->cons_stdout_is_fb = 0;
    715 				sp->cons_stdin_path = path;
    716 				sp->cons_stdout_path = path;
    717 				sp->cons_fb_path = plat_fbpath();
    718 
    719 				cmn_err(CE_WARN,
    720 				    "%s doesn't support terminal emulation "
    721 				    "mode; switching to virtual console.",
    722 				    sp->cons_fb_path);
    723 			}
    724 		}
    725 #endif /* _HAVE_TEM_FIRMWARE */
    726 	} else {
    727 		sp->cons_fb_path = plat_fbpath();
    728 #ifdef _HAVE_TEM_FIRMWARE
    729 		sp->cons_tem_supported = consconfig_tem_supported(sp);
    730 #endif /* _HAVE_TEM_FIRMWARE */
    731 	}
    732 
    733 	sp->cons_li = ldi_ident_from_anon();
    734 
    735 	/* Save the pointer for retrieval by the dacf functions */
    736 	rval = space_store("consconfig", (uintptr_t)sp);
    737 	ASSERT(rval == 0);
    738 
    739 	return (sp);
    740 }
    741 
    742 static int
    743 consconfig_relink_wc(cons_state_t *sp, ldi_handle_t new_lh, int *muxid)
    744 {
    745 	int		err, rval;
    746 	ldi_handle_t	wc_lh;
    747 	dev_t		wc_dev;
    748 
    749 	ASSERT(muxid != NULL);
    750 
    751 	/*
    752 	 * NOTE: we could be in a dacf callback context right now. normally
    753 	 * it's not legal to call any ldi_open_*() function from this context
    754 	 * because we're currently holding device tree locks and if the
    755 	 * ldi_open_*() call could try to acquire other device tree locks
    756 	 * (to attach the device we're trying to open.)  if this happens then
    757 	 * we could deadlock.  To avoid this situation, during initialization
    758 	 * we made sure to grab a hold on the dip of the device we plan to
    759 	 * open so that it can never be detached.  Then we use
    760 	 * ldi_open_by_dev() to actually open the device since it will see
    761 	 * that the device is already attached and held and instead of
    762 	 * acquire any locks it will only increase the reference count
    763 	 * on the device.
    764 	 */
    765 	wc_dev = sp->cons_wc_vp->v_rdev;
    766 	err = ldi_open_by_dev(&wc_dev, OTYP_CHR, FREAD|FWRITE|FNOCTTY,
    767 	    kcred, &wc_lh, sp->cons_li);
    768 	ASSERT(wc_dev == sp->cons_wc_vp->v_rdev);
    769 	if (err) {
    770 		cmn_err(CE_WARN, "consconfig_relink_wc: "
    771 		    "unable to open wc device");
    772 		return (err);
    773 	}
    774 
    775 	if (new_lh != NULL) {
    776 		DPRINTF(DPRINT_L0, "linking stream under wc\n");
    777 
    778 		err = ldi_ioctl(wc_lh, I_PLINK, (uintptr_t)new_lh,
    779 		    FKIOCTL, kcred, muxid);
    780 		if (err != 0) {
    781 			cmn_err(CE_WARN, "consconfig_relink_wc: "
    782 			    "wc link failed, error %d", err);
    783 		}
    784 	} else {
    785 		DPRINTF(DPRINT_L0, "unlinking stream from under wc\n");
    786 
    787 		err = ldi_ioctl(wc_lh, I_PUNLINK, *muxid,
    788 		    FKIOCTL, kcred, &rval);
    789 		if (err != 0) {
    790 			cmn_err(CE_WARN, "consconfig_relink_wc: "
    791 			    "wc unlink failed, error %d", err);
    792 		} else {
    793 			*muxid = -1;
    794 		}
    795 	}
    796 
    797 	(void) ldi_close(wc_lh, FREAD|FWRITE, kcred);
    798 	return (err);
    799 }
    800 
    801 static void
    802 cons_build_upper_layer(cons_state_t *sp)
    803 {
    804 	ldi_handle_t		wc_lh;
    805 	struct strioctl		strioc;
    806 	int			rval;
    807 	dev_t			dev;
    808 	dev_t			wc_dev;
    809 
    810 	/*
    811 	 * Build the wc->conskbd portion of the keyboard console stream.
    812 	 * Even if no keyboard is attached to the system, the upper
    813 	 * layer of the stream will be built. If the user attaches
    814 	 * a keyboard after the system is booted, the keyboard driver
    815 	 * and module will be linked under conskbd.
    816 	 *
    817 	 * Errors are generally ignored here because conskbd and wc
    818 	 * are pseudo drivers and should be present on the system.
    819 	 */
    820 
    821 	/* open the console keyboard device.  will never be closed */
    822 	if (ldi_open_by_name(CONSKBD_PATH, FREAD|FWRITE|FNOCTTY,
    823 	    kcred, &sp->conskbd_lh, sp->cons_li) != 0) {
    824 		panic("consconfig: unable to open conskbd device");
    825 		/*NOTREACHED*/
    826 	}
    827 
    828 	DPRINTF(DPRINT_L0, "conskbd_lh = %p\n", sp->conskbd_lh);
    829 
    830 	/* open the console mouse device.  will never be closed */
    831 	if (ldi_open_by_name(CONSMS_PATH, FREAD|FWRITE|FNOCTTY,
    832 	    kcred, &sp->consms_lh, sp->cons_li) != 0) {
    833 		panic("consconfig: unable to open consms device");
    834 		/*NOTREACHED*/
    835 	}
    836 
    837 	DPRINTF(DPRINT_L0, "consms_lh = %p\n", sp->consms_lh);
    838 
    839 	/*
    840 	 * Get a vnode for the wc device and then grab a hold on the
    841 	 * device dip so it can never detach.  We need to do this now
    842 	 * because later we'll have to open the wc device in a context
    843 	 * were it isn't safe to acquire any device tree locks (ie, during
    844 	 * a dacf callback.)
    845 	 */
    846 	sp->cons_wc_vp = i_consconfig_createvp(WC_PATH);
    847 	if (sp->cons_wc_vp == NULL)
    848 		panic("consconfig: unable to find wc device");
    849 
    850 	if (e_ddi_hold_devi_by_dev(sp->cons_wc_vp->v_rdev, 0) == NULL)
    851 		panic("consconfig: unable to hold wc device");
    852 
    853 	/*
    854 	 * Build the wc->conskbd portion of the keyboard console stream.
    855 	 * Even if no keyboard is attached to the system, the upper
    856 	 * layer of the stream will be built. If the user attaches
    857 	 * a keyboard after the system is booted, the keyboard driver
    858 	 * and module will be linked under conskbd.
    859 	 *
    860 	 * The act of linking conskbd under wc will cause wc to
    861 	 * query the lower layers about their polled I/O routines
    862 	 * using CONSOPENPOLLEDIO.  This will fail on this link because
    863 	 * there is not a physical keyboard linked under conskbd.
    864 	 *
    865 	 * Since conskbd and wc are pseudo drivers, errors are
    866 	 * generally ignored when linking and unlinking them.
    867 	 */
    868 	(void) consconfig_relink_wc(sp, sp->conskbd_lh, &sp->conskbd_muxid);
    869 
    870 	/*
    871 	 * Get a vnode for the redirection device.  (It has the
    872 	 * connection to the workstation console device wired into it,
    873 	 * so that it's not necessary to establish the connection
    874 	 * here.  If the redirection device is ever generalized to
    875 	 * handle multiple client devices, it won't be able to
    876 	 * establish the connection itself, and we'll have to do it
    877 	 * here.)
    878 	 */
    879 	wsconsvp = i_consconfig_createvp(IWSCN_PATH);
    880 	if (wsconsvp == NULL) {
    881 		panic("consconfig: unable to find iwscn device");
    882 		/*NOTREACHED*/
    883 	}
    884 
    885 	if (cons_tem_disable)
    886 		return;
    887 
    888 	if (sp->cons_fb_path == NULL) {
    889 #if defined(__x86)
    890 		if (sp->cons_stdout_is_fb)
    891 			cmn_err(CE_WARN, "consconfig: no screen found");
    892 #endif
    893 		return;
    894 	}
    895 
    896 	/* make sure the frame buffer device exists */
    897 	dev = ddi_pathname_to_dev_t(sp->cons_fb_path);
    898 	if (dev == NODEV) {
    899 		cmn_err(CE_WARN, "consconfig: "
    900 		    "cannot find driver for screen device %s",
    901 		    sp->cons_fb_path);
    902 		return;
    903 	}
    904 
    905 #ifdef _HAVE_TEM_FIRMWARE
    906 	/*
    907 	 * If the underlying fb device doesn't support terminal emulation,
    908 	 * we don't want to open the wc device (below) because it depends
    909 	 * on features which aren't available (polled mode io).
    910 	 */
    911 	if (!sp->cons_tem_supported)
    912 		return;
    913 #endif /* _HAVE_TEM_FIRMWARE */
    914 
    915 	/* tell wc to open the frame buffer device */
    916 	wc_dev = sp->cons_wc_vp->v_rdev;
    917 	if (ldi_open_by_dev(&wc_dev, OTYP_CHR, FREAD|FWRITE|FNOCTTY, kcred,
    918 	    &wc_lh, sp->cons_li)) {
    919 		cmn_err(CE_PANIC, "cons_build_upper_layer: "
    920 		    "unable to open wc device");
    921 		return;
    922 	}
    923 	ASSERT(wc_dev == sp->cons_wc_vp->v_rdev);
    924 
    925 	strioc.ic_cmd = WC_OPEN_FB;
    926 	strioc.ic_timout = INFTIM;
    927 	strioc.ic_len = strlen(sp->cons_fb_path) + 1;
    928 	strioc.ic_dp = sp->cons_fb_path;
    929 
    930 	if (ldi_ioctl(wc_lh, I_STR, (intptr_t)&strioc,
    931 	    FKIOCTL, kcred, &rval) == 0)
    932 		consmode = CONS_KFB;
    933 	else
    934 		cmn_err(CE_WARN,
    935 		    "consconfig: terminal emulator failed to initialize");
    936 	(void) ldi_close(wc_lh, FREAD|FWRITE, kcred);
    937 }
    938 
    939 static void
    940 consconfig_load_drivers(cons_state_t *sp)
    941 {
    942 	/*
    943 	 * Calling ddi_pathname_to_dev_t causes the drivers to be loaded.
    944 	 * The attaching of the drivers will cause the creation of the
    945 	 * keyboard and mouse minor nodes, which will in turn trigger the
    946 	 * dacf framework to call the keyboard and mouse configuration
    947 	 * tasks.  See PSARC/1998/212 for more details about the dacf
    948 	 * framework.
    949 	 *
    950 	 * on sparc, when the console is ttya, zs0 is stdin/stdout, and zs1
    951 	 * is kb/mouse.  zs0 must be attached before zs1. The zs driver
    952 	 * is written this way and the hardware may depend on this, too.
    953 	 * It would be better to enforce this by attaching zs in sibling
    954 	 * order with a driver property, such as ddi-attachall.
    955 	 */
    956 	if (sp->cons_stdin_path != NULL)
    957 		stdindev = ddi_pathname_to_dev_t(sp->cons_stdin_path);
    958 	if (stdindev == NODEV) {
    959 		DPRINTF(DPRINT_L0,
    960 		    "!fail to attach stdin: %s\n", sp->cons_stdin_path);
    961 	}
    962 	if (sp->cons_stdout_path != NULL)
    963 		stdoutdev = ddi_pathname_to_dev_t(sp->cons_stdout_path);
    964 	if (sp->cons_keyboard_path != NULL)
    965 		kbddev = ddi_pathname_to_dev_t(sp->cons_keyboard_path);
    966 	if (sp->cons_mouse_path != NULL)
    967 		mousedev =  ddi_pathname_to_dev_t(sp->cons_mouse_path);
    968 
    969 	/*
    970 	 * On x86, make sure the fb driver is loaded even if we don't use it
    971 	 * for the console. This will ensure that we create a /dev/fb link
    972 	 * which is required to start Xorg.
    973 	 */
    974 #if defined(__x86)
    975 	if (sp->cons_fb_path != NULL)
    976 		fbdev = ddi_pathname_to_dev_t(sp->cons_fb_path);
    977 #endif
    978 
    979 	DPRINTF(DPRINT_L0, "stdindev %lx, stdoutdev %lx, kbddev %lx, "
    980 	    "mousedev %lx\n", stdindev, stdoutdev, kbddev, mousedev);
    981 }
    982 
    983 static void
    984 consconfig_init_framebuffer(cons_state_t *sp)
    985 {
    986 	if (!sp->cons_stdout_is_fb)
    987 		return;
    988 
    989 	DPRINTF(DPRINT_L0, "stdout is framebuffer\n");
    990 	ASSERT(strcmp(sp->cons_fb_path, sp->cons_stdout_path) == 0);
    991 
    992 	/*
    993 	 * Console output is a framebuffer.
    994 	 * Find the framebuffer driver if we can, and make
    995 	 * ourselves a shadow vnode to track it with.
    996 	 */
    997 	fbdev = stdoutdev;
    998 	if (fbdev == NODEV) {
    999 		DPRINTF(DPRINT_L3,
   1000 		    "Can't find driver for console framebuffer\n");
   1001 	} else {
   1002 		/* stdoutdev is valid, of fbvp should exist */
   1003 		fbvp = i_consconfig_createvp(sp->cons_stdout_path);
   1004 		if (fbvp == NULL) {
   1005 			panic("consconfig_load_drivers: "
   1006 			    "unable to find frame buffer device");
   1007 			/*NOTREACHED*/
   1008 		}
   1009 		ASSERT(fbvp->v_rdev == fbdev);
   1010 
   1011 		/* console device is never released */
   1012 		fbdip = e_ddi_hold_devi_by_dev(fbdev, 0);
   1013 	}
   1014 	pm_cfb_setup(sp->cons_stdout_path);
   1015 }
   1016 
   1017 /*
   1018  * consconfig_prepare_dev:
   1019  * 	Flush the stream, push "pushmod" onto the stream.
   1020  * 	for keyboard, issue the KIOCTRANSABLE ioctl, and
   1021  *	possible enable abort.
   1022  */
   1023 static void
   1024 consconfig_prepare_dev(
   1025     ldi_handle_t	new_lh,
   1026     const char		*pushmod,
   1027     int			kbdtranslatable,
   1028     int			input_type,
   1029     int			dev_type)
   1030 {
   1031 	int err, rval;
   1032 
   1033 	/* send a flush down the stream to the keyboard driver */
   1034 	(void) ldi_ioctl(new_lh, I_FLUSH, (intptr_t)FLUSHRW,
   1035 	    FKIOCTL, kcred, &rval);
   1036 
   1037 	if (pushmod) {
   1038 		err = ldi_ioctl(new_lh, I_PUSH, (intptr_t)pushmod,
   1039 		    FKIOCTL, kcred, &rval);
   1040 		if (err) {
   1041 			cmn_err(CE_WARN, "consconfig_prepare_dev: "
   1042 			    "can't push streams module \"%s\", error %d",
   1043 			    pushmod, err);
   1044 		}
   1045 	}
   1046 
   1047 	if (dev_type == CONS_MS)
   1048 		return;
   1049 
   1050 	ASSERT(dev_type == CONS_KBD);
   1051 
   1052 	err = ldi_ioctl(new_lh, KIOCTRANSABLE,
   1053 	    (intptr_t)&kbdtranslatable, FKIOCTL, kcred, &rval);
   1054 	if (err) {
   1055 		cmn_err(CE_WARN, "consconfig_prepare_dev: "
   1056 		    "KIOCTRANSABLE failed, error: %d", err);
   1057 	}
   1058 
   1059 	/*
   1060 	 * During boot, dynamic_console_config() will call the
   1061 	 * function to enable abort on the console.  If the
   1062 	 * keyboard is hotplugged after boot, check to see if
   1063 	 * the keyboard is the console input.  If it is
   1064 	 * enable abort on it.
   1065 	 */
   1066 	if (input_type == CONSOLE_LOCAL)
   1067 		(void) consconfig_kbd_abort_enable(new_lh);
   1068 }
   1069 
   1070 /*
   1071  * consconfig_relink_conskbd:
   1072  * 	If new_lh is not NULL it should represent a driver with a
   1073  * 	keyboard module pushed on top of it. The driver is then linked
   1074  * 	underneath conskbd.  the resulting stream will be
   1075  *	wc->conskbd->"new_lh driver".
   1076  *
   1077  * 	If new_lh is NULL, then an unlink operation is done on conskbd
   1078  * 	that attempts to unlink the stream specified by *muxid.
   1079  *	the resulting stream will be wc->conskbd.
   1080  */
   1081 static int
   1082 consconfig_relink_conskbd(cons_state_t *sp, ldi_handle_t new_lh, int *muxid)
   1083 {
   1084 	int		err, rval;
   1085 	int		conskbd_relink = 0;
   1086 
   1087 	ASSERT(muxid != NULL);
   1088 
   1089 	DPRINTF(DPRINT_L0, "consconfig_relink_conskbd: "
   1090 	    "conskbd_lh = %p, new_lh = %p,  muxid = %x\n",
   1091 	    sp->conskbd_lh, new_lh, *muxid);
   1092 
   1093 	/*
   1094 	 * If conskbd is linked under wc then temporarily unlink it
   1095 	 * from under wc so that the new_lh stream may be linked under
   1096 	 * conskbd.  This has to be done because streams are built bottom
   1097 	 * up and linking a stream under conskbd isn't allowed when
   1098 	 * conskbd is linked under wc.
   1099 	 */
   1100 	if (sp->conskbd_muxid != -1) {
   1101 		DPRINTF(DPRINT_L0, "unlinking conskbd from under wc\n");
   1102 		conskbd_relink = 1;
   1103 		err = consconfig_relink_wc(sp, NULL, &sp->conskbd_muxid);
   1104 		if (err) {
   1105 			cmn_err(CE_WARN, "consconfig_relink_conskbd: "
   1106 			    "wc unlink failed, error %d", err);
   1107 			return (err);
   1108 		}
   1109 	}
   1110 
   1111 	if (new_lh != NULL) {
   1112 		DPRINTF(DPRINT_L0, "linking keyboard under conskbd\n");
   1113 
   1114 		/* Link the stream represented by new_lh under conskbd */
   1115 		err = ldi_ioctl(sp->conskbd_lh, I_PLINK, (uintptr_t)new_lh,
   1116 		    FKIOCTL, kcred, muxid);
   1117 		if (err != 0) {
   1118 			cmn_err(CE_WARN, "consconfig_relink_conskbd: "
   1119 			    "conskbd link failed, error %d", err);
   1120 			goto relink_failed;
   1121 		}
   1122 	} else {
   1123 		DPRINTF(DPRINT_L0, "unlinking keyboard from under conskbd\n");
   1124 
   1125 		/*
   1126 		 * This will cause the keyboard driver to be closed,
   1127 		 * all modules to be popped, and the keyboard vnode released.
   1128 		 */
   1129 		err = ldi_ioctl(sp->conskbd_lh, I_PUNLINK, *muxid,
   1130 		    FKIOCTL, kcred, &rval);
   1131 		if (err != 0) {
   1132 			cmn_err(CE_WARN, "consconfig_relink_conskbd: "
   1133 			    "conskbd unlink failed, error %d", err);
   1134 			goto relink_failed;
   1135 		} else {
   1136 			*muxid = -1;
   1137 		}
   1138 
   1139 		consconfig_check_phys_kbd(sp);
   1140 	}
   1141 
   1142 	if (!conskbd_relink)
   1143 		return (err);
   1144 
   1145 	/*
   1146 	 * Link consbkd back under wc.
   1147 	 *
   1148 	 * The act of linking conskbd back under wc will cause wc
   1149 	 * to query the lower lower layers about their polled I/O
   1150 	 * routines.  This time the request will succeed because there
   1151 	 * is a physical keyboard linked under conskbd.
   1152 	 */
   1153 	DPRINTF(DPRINT_L0, "re-linking conskbd under wc\n");
   1154 	err = consconfig_relink_wc(sp, sp->conskbd_lh, &sp->conskbd_muxid);
   1155 	if (err) {
   1156 		cmn_err(CE_WARN, "consconfig_relink_conskbd: "
   1157 		    "wc link failed, error %d", err);
   1158 	}
   1159 	return (err);
   1160 
   1161 relink_failed:
   1162 	if (!conskbd_relink)