consconfig_dacf.c revision 361ed64a5abddd9ed26f47e25824bbce82557ab4
0N/A * The contents of this file are subject to the terms of the 0N/A * Common Development and Distribution License (the "License"). 0N/A * You may not use this file except in compliance with the License. 0N/A * See the License for the specific language governing permissions 0N/A * and limitations under the License. 0N/A * When distributing Covered Code, include this CDDL HEADER in each 0N/A * If applicable, add the following below this CDDL HEADER, with the 0N/A * fields enclosed by brackets "[]" replaced with your own identifying 0N/A * information: Portions Copyright [yyyy] [name of copyright owner] 0N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 0N/A * Use is subject to license terms. 0N/A * This module performs two functions. First, it kicks off the driver loading 0N/A * of the console devices during boot in dynamic_console_config(). 0N/A * The loading of the drivers for the console devices triggers the 0N/A * additional device autoconfiguration to link the drivers into the keyboard 0N/A * and mouse console streams. 0N/A * The second function of this module is to provide the dacf functions 0N/A * to be called after a driver has attached and before it detaches. For 0N/A * example, a driver associated with the keyboard will have kb_config called 0N/A * after the driver attaches and kb_unconfig before it detaches. Similar 0N/A * configuration actions are performed on behalf of minor nodes representing 0N/A * mice. The configuration functions for the attach case take a module 0N/A * name as a parameter. The module is pushed on top of the driver during 0N/A * the configuration. 0N/A * Although the dacf framework is used to configure all keyboards and mice, 0N/A * its primary function is to allow keyboard and mouse hotplugging. 0N/A * This module supports multiple keyboards and mice at the same time. 0N/A * From the kernel perspective, there are roughly three different possible 0N/A * console configurations. Across these three configurations, the following 0N/A * elements are constant: 0N/A * wsconsvp = IWSCN_PATH 0N/A * rwsconsvp = WC_PATH 0N/A * The "->" syntax indicates that the streams device on the right is 0N/A * linked under the streams device on the left. 0N/A * The following lists how the system is configured for different setups: 0N/A * stdin is a local keyboard. use stdin and stdout as the console. 0N/A * sp->cons_input_type = CONSOLE_LOCAL 0N/A * rconsvp = IWSCN_PATH 0N/A * wc -> conskbd -> kbddev 0N/A * stdin is not a keyboard and stdin is the same as stdout. 0N/A * assume we running on a tip line and use stdin/stdout as the console. 0N/A * sp->cons_input_type = CONSOLE_TIP 0N/A * wc -> conskbd -> kbddev 0N/A * stdin is not a keyboard device and it's not the same as stdout. 0N/A * assume we have a serial keyboard hooked up and use it along with 0N/A * stdout as the console. 0N/A * sp->cons_input_type = CONSOLE_SERIAL_KEYBOARD 0N/A * rconsvp = IWSCN_PATH 0N/A * The above is all true except for one possible Intel configuration. 0N/A * If stdin is set to a local keyboard but stdout is set to something 0N/A * other than the local display (a tip port for example) stdout will 0N/A * still go to the local display. This is an artifact of the console 0N/A * implementation on intel. 0N/A * External global variables 0N/A * External functions 0N/A * Internal functions 0N/A * On supported configurations, the firmware defines the keyboard and mouse 0N/A * paths. However, during USB development, it is useful to be able to use 0N/A * the USB keyboard and mouse on machines without full USB firmware support. 0N/A * These variables may be set in /etc/system according to a machine's 0N/A * USB configuration. This module will override the firmware's values 0N/A * The reason for this is historic. In versions of solaris up to and 0N/A * including solaris 9 the conscole configuration code was split into a 0N/A * seperate sparc and intel version. These variables were defined 0N/A * Unfortunatly the sparc variables were well documented. 0N/A * So to aviod breaking either sparc or intel we'll declare the variables 0N/A * in both modules. This will allow any /etc/system entries that 0N/A * users may have to continue working. 0N/A * found in this file. Since we eventually want to remove the variables 0N/A * local to this this file, if the user set them we'll emmit an error 0N/A * values of it local usb_kb_path and usb_ms_path variables 0N/A * Local variables used to store the value of the usb_kb_path and 0N/A * Internal variables 0N/A * consconfig_errlevel: debug verbosity; smaller numbers are more 0N/A * This modules state is held in the kernel by space.c 0N/A * allowing this module to be unloaded. 0N/A * Return a property value for the specified alias in /aliases. 0N/A /* The /aliases node only exists in OBP >= 2.4. */ 0N/A * The IEEE 1275 standard specifies that /aliases string property 0N/A * values should be null-terminated. Unfortunatly the reality 0N/A * is that most aren't and the OBP can't easily be modified to 0N/A * add null termination to these strings. So we'll add the 0N/A * null termination here. If the string already contains a 0N/A * null termination character then that's ok too because we'll 0N/A * just be adding a second one. 0N/A * i_consconfig_createvp: 0N/A * This routine is a convenience routine that is passed a path and returns 0N/A /* convert an OBP path to a /devices path */ 0N/A /* convert a devfs path to a /devices path */ 0N/A * consconfig_print_paths: 0N/A * Function to print out the various paths 0N/A "consconfig_dacf:usb_kb_path has been deprecated, " 0N/A "use consconfig:usb_kb_path instead");
0N/A "consconfig_dacf:usb_ms_path has been deprecated, " 0N/A "use consconfig:usb_ms_path instead");
0N/A * consconfig_kbd_abort_enable: 0N/A * Send the CONSSETABORTENABLE ioctl to the lower layers. This ioctl 0N/A * will only be sent to the device if it is the console device. 0N/A * This ioctl tells the device to pay attention to abort sequences. 0N/A * In the case of kbtrans, this would tell the driver to pay attention 0N/A * to the two key abort sequences like STOP-A. In the case of the 0N/A * serial keyboard, it would be an abort sequence like a break. 0N/A * consconfig_kbd_abort_disable: 0N/A * Send CONSSETABORTENABLE ioctl to lower layers. This ioctl 0N/A * will only be sent to the device if it is the console device. 0N/A * This ioctl tells the physical device to ignore abort sequences, 0N/A * and send the sequences up to virtual keyboard(conskbd) so that 0N/A * STOP and A (or F1 and A) can be combined. 0N/A return (0);
/* warning printed later by common code */ 0N/A * Here we hold the driver and check "tem-support" property. 0N/A * We're doing this with e_ddi_hold_devi_by_dev and 0N/A * ddi_prop_lookup_int_array without opening the driver since 0N/A * some video cards that don't support the kernel terminal 0N/A * emulator could hang or crash if opened too early during 0N/A * Check that the tem-support property exists AND that 0N/A#
endif /* _HAVE_TEM_FIRMWARE */ 0N/A * consconfig_get_polledio: 0N/A * Query the console with the CONSPOLLEDIO ioctl. 0N/A * The polled I/O routines are used by debuggers to perform I/O while 0N/A * interrupts and normal kernel services are disabled. 0N/A * Setup the ioctl to be sent down to the lower driver. 0N/A * Send the ioctl to the driver. The ioctl will wait for 0N/A * the response to come back from wc. wc has already issued 0N/A * the CONSOPENPOLLEDIO to the lower layer driver. 0N/A * If the lower driver does not support polled I/O, then 0N/A * return NULL. This will be the case if the driver does 0N/A * not handle polled I/O, or OBP is going to handle polled 0N/A * I/O for the device. 0N/A * Return the polled I/O structure. 0N/A * consconfig_setup_polledio: 0N/A * This routine does the setup work for polled I/O. First we get 0N/A * the polled_io structure from the lower layers 0N/A * and then we register the polled I/O 0N/A * callbacks with the debugger that will be using them. 0N/A * Get the polled io routines so that we can use this 0N/A * device with the debuggers. 0N/A * If the get polledio failed, then we do not want to throw 0N/A * the polled I/O switch. 0N/A "consconfig_setup_polledio: get_polledio failed\n");
0N/A /* Initialize the polled input */ 0N/A /* Register the callbacks */ 0N/A "consconfig_setup_polledio: registering callbacks\n");
0N/A /* Initialize console information */ 0N/A /* init external globals */ 0N/A * Find keyboard, mouse, stdin and stdout devices, if they 0N/A * exist on this platform. 0N/A /* Identify the stdout driver */ 0N/A * The standard in device may or may not be the same as 0N/A * the keyboard. Even if the keyboard is not the 0N/A * standard input, the keyboard console stream will 0N/A * still be built if the keyboard alias provided by the 0N/A * firmware exists and is valid. 0N/A * Systems which offer a virtual console must use that 0N/A * as a fallback whenever the fb doesn't support tem. 0N/A * Such systems cannot render characters to the screen 0N/A "%s doesn't support terminal emulation " 0N/A "mode; switching to virtual console.",
0N/A#
endif /* _HAVE_TEM_FIRMWARE */ 0N/A#
endif /* _HAVE_TEM_FIRMWARE */ 0N/A /* Save the pointer for retrieval by the dacf functions */ 0N/A * NOTE: we could be in a dacf callback context right now. normally 0N/A * it's not legal to call any ldi_open_*() function from this context 0N/A * because we're currently holding device tree locks and if the 0N/A * ldi_open_*() call could try to acquire other device tree locks 0N/A * (to attach the device we're trying to open.) if this happens then 0N/A * we could deadlock. To avoid this situation, during initialization 0N/A * we made sure to grab a hold on the dip of the device we plan to 0N/A * open so that it can never be detached. Then we use 0N/A * ldi_open_by_dev() to actually open the device since it will see 0N/A * that the device is already attached and held and instead of 0N/A * acquire any locks it will only increase the reference count 0N/A "unable to open wc device");
0N/A "wc link failed, error %d",
err);
0N/A "wc unlink failed, error %d",
err);
0N/A * Build the wc->conskbd portion of the keyboard console stream. 0N/A * Even if no keyboard is attached to the system, the upper 0N/A * layer of the stream will be built. If the user attaches 0N/A * a keyboard after the system is booted, the keyboard driver 0N/A * and module will be linked under conskbd. 0N/A * Errors are generally ignored here because conskbd and wc 0N/A * are pseudo drivers and should be present on the system. 0N/A /* open the console keyboard device. will never be closed */ 0N/A panic(
"consconfig: unable to open conskbd device");
0N/A /* open the console mouse device. will never be closed */ 0N/A panic(
"consconfig: unable to open consms device");
0N/A * Get a vnode for the wc device and then grab a hold on the 0N/A * device dip so it can never detach. We need to do this now 0N/A * because later we'll have to open the wc device in a context 0N/A * were it isn't safe to acquire any device tree locks (ie, during 0N/A panic(
"consconfig: unable to find wc device");
0N/A panic(
"consconfig: unable to hold wc device");
0N/A * Build the wc->conskbd portion of the keyboard console stream. 0N/A * Even if no keyboard is attached to the system, the upper 0N/A * layer of the stream will be built. If the user attaches 0N/A * a keyboard after the system is booted, the keyboard driver 0N/A * and module will be linked under conskbd. 0N/A * The act of linking conskbd under wc will cause wc to 0N/A * query the lower layers about their polled I/O routines 0N/A * using CONSOPENPOLLEDIO. This will fail on this link because 0N/A * there is not a physical keyboard linked under conskbd. 0N/A * Since conskbd and wc are pseudo drivers, errors are 0N/A * generally ignored when linking and unlinking them. 0N/A * Get a vnode for the redirection device. (It has the 0N/A * connection to the workstation console device wired into it, 0N/A * so that it's not necessary to establish the connection 0N/A * here. If the redirection device is ever generalized to 0N/A * handle multiple client devices, it won't be able to 0N/A * establish the connection itself, and we'll have to do it 0N/A panic(
"consconfig: unable to find iwscn device");
0N/A /* make sure the frame buffer device exists */ 0N/A "cannot find driver for screen device %s",
0N/A * If the underlying fb device doesn't support terminal emulation, 0N/A * we don't want to open the wc device (below) because it depends 0N/A * on features which aren't available (polled mode io). 0N/A#
endif /* _HAVE_TEM_FIRMWARE */ 0N/A /* tell wc to open the frame buffer device */ 0N/A "unable to open wc device");
0N/A "consconfig: terminal emulator failed to initialize");
0N/A * Calling ddi_pathname_to_dev_t causes the drivers to be loaded. 0N/A * The attaching of the drivers will cause the creation of the 0N/A * keyboard and mouse minor nodes, which will in turn trigger the 0N/A * dacf framework to call the keyboard and mouse configuration 0N/A * tasks. See PSARC/1998/212 for more details about the dacf 0N/A * is kb/mouse. zs0 must be attached before zs1. The zs driver 0N/A * is written this way and the hardware may depend on this, too. 0N/A * It would be better to enforce this by attaching zs in sibling 0N/A * order with a driver property, such as ddi-attachall. 0N/A * On x86, make sure the fb driver is loaded even if we don't use it 0N/A * for the console. This will ensure that we create a /dev/fb link 0N/A * which is required to start Xorg. 0N/A /* virtual console already in use */ 0N/A "unable to find serial virtual console device %s",
0N/A * Console output is a framebuffer. 0N/A * Find the framebuffer driver if we can, and make 0N/A * ourselves a shadow vnode to track it with. 0N/A "Can't find driver for console framebuffer\n");
0N/A /* stdoutdev is valid, of fbvp should exist */ 0N/A "unable to find frame buffer device");
0N/A /* console device is never released */ 0N/A * consconfig_prepare_dev: 0N/A * Flush the stream, push "pushmod" onto the stream. 0N/A * for keyboard, issue the KIOCTRANSABLE ioctl, and 0N/A * possible enable abort. 0N/A /* send a flush down the stream to the keyboard driver */ 0N/A "can't push streams module \"%s\", error %d",
0N/A "KIOCTRANSABLE failed, error: %d",
err);
0N/A * During boot, dynamic_console_config() will call the 0N/A * function to enable abort on the console. If the 0N/A * keyboard is hotplugged after boot, check to see if 0N/A * the keyboard is the console input. If it is 0N/A * enable abort on it. 0N/A * consconfig_relink_conskbd: 0N/A * If new_lh is not NULL it should represent a driver with a 0N/A * keyboard module pushed on top of it. The driver is then linked 0N/A * underneath conskbd. the resulting stream will be 0N/A * wc->conskbd->"new_lh driver". 0N/A * If new_lh is NULL, then an unlink operation is done on conskbd 0N/A * that attempts to unlink the stream specified by *muxid. 0N/A * the resulting stream will be wc->conskbd. 0N/A "conskbd_lh = %p, new_lh = %p, muxid = %x\n",
0N/A * If conskbd is linked under wc then temporarily unlink it 0N/A * from under wc so that the new_lh stream may be linked under 0N/A * conskbd. This has to be done because streams are built bottom 0N/A * up and linking a stream under conskbd isn't allowed when 0N/A * conskbd is linked under wc. 0N/A "wc unlink failed, error %d",
err);
0N/A /* Link the stream represented by new_lh under conskbd */ 0N/A "conskbd link failed, error %d",
err);
0N/A * This will cause the keyboard driver to be closed, 0N/A * all modules to be popped, and the keyboard vnode released. 0N/A "conskbd unlink failed, error %d",
err);
0N/A * Link consbkd back under wc. 0N/A * The act of linking conskbd back under wc will cause wc 0N/A * to query the lower lower layers about their polled I/O 0N/A * routines. This time the request will succeed because there 0N/A * is a physical keyboard linked under conskbd. 0N/A "wc link failed, error %d",
err);
0N/A /* something went wrong, try to reconnect conskbd back under wc */ 0N/A * consconfig_relink_consms: 0N/A * If new_lh is not NULL it should represent a driver with a 0N/A * mouse module pushed on top of it. The driver is then linked 0N/A * underneath consms. the resulting stream will be 0N/A * consms->"new_lh driver". 0N/A * If new_lh is NULL, then an unlink operation is done on consms 0N/A * that attempts to unlink the stream specified by *muxid. 0N/A "consms_lh = %p, new_lh = %p, muxid = %x\n",
0N/A /* Link ms/usbms stream underneath consms multiplexor. */ 0N/A "mouse link failed, error %d",
err);
0N/A /* Tear down the mouse stream */ 0N/A "mouse unlink failed, error %d",
err);
0N/A * Now that we know what all the devices are, we can figure out 0N/A * what kind of console we have. 0N/A /* Stdin is from the system keyboard */ 0N/A * A reliable indicator that we are doing a remote console 0N/A * is that stdin and stdout are the same. 0N/A * This is probably a tip line. 0N/A * The machine is allowed to boot without a keyboard. 0N/A * If a user attaches a keyboard later, the keyboard 0N/A * will be hooked into the console stream with the dacf 0N/A * The only drivers that look at kbbdev are the 0N/A * serial drivers, which looks at kbdev to see if 0N/A * they should allow abort on a break. In the absence 0N/A * of keyboard, the serial drivers won't be attached 0N/A * for any keyboard instance. 0N/A * If there is a problem with the keyboard 0N/A * during the driver loading, then the polled 0N/A * input won't get setup properly if polled 0N/A * input is needed. This means that if the 0N/A * keyboard is hotplugged, the keyboard would 0N/A * work normally, but going down to the 0N/A * debugger would not work if polled input is 0N/A * required. This field is set here. The next 0N/A * time a keyboard is plugged in, the field is 0N/A * checked in order to give the next keyboard a 0N/A * chance at being registered for console 0N/A * Although this code will rarely be needed, 0N/A * USB keyboards can be flaky, so this code 0N/A * will be useful on the occasion that the 0N/A * keyboard doesn't enumerate when the drivers 0N/A * Console device drivers must be able to output 0N/A * after being closed. 0N/A "unable to find stdin device (%s)",
0N/A * Non-keyboard input device, but not rconsdev. 0N/A * This is known as the "serial keyboard" case - the 0N/A * most likely use is someone has a keyboard attached 0N/A * to a serial port (tip) and still has output on a 0N/A * In this case, the serial driver must be linked 0N/A * directly beneath wc. Since conskbd was linked 0N/A * underneath wc above, first we unlink conskbd. 0N/A * Open the serial keyboard, configure it, 0N/A * and link it underneath wc. 0N/A /* Re-set baud rate */ 0N/A "consconfig_init_input: " 0N/A "TCSETSF failed, error %d",
err);
0N/A * Now link the serial keyboard direcly under wc 0N/A * we don't save the returned muxid because we 0N/A * keyboard when it is a serial keyboard. 0N/A * console if the latter hasn't already been set. 0N/A * The workstation console driver needs to see rwsconsvp, but 0N/A * all other access should be through the redirecting driver. 0N/A "unable to open console device");
0N/A /* Enable abort on the console */ 0N/A /* Now we must close it to make console logins happy */ 0N/A /* Set up polled input if it is supported by the console device */ 0N/A * In the debug case, register the keyboard polled entry 0N/A * points, but don't throw the switch in the debugger. This 0N/A * allows the polled entry points to be checked by hand 0N/A * This function kicks off the console configuration. 0N/A * Configure keyboard and mouse. Main entry here. 0N/A /* Initialize cons_state_t structure and console device paths */ 0N/A /* Build upper layer of console stream */ 0N/A * plumb the devices into the console stream 0N/A * At the conclusion of the ddi_pathname_to_dev_t calls, the keyboard 0N/A * and mouse drivers are linked into their respective console 0N/A * streams if the pathnames are valid. 0N/A * This is legacy special case code for the "cool" virtual console 0N/A * for the Starfire project. Starfire has a dummy "ssp-serial" 0N/A * node in the OBP device tree and cvc is a pseudo driver. 0N/A * Setup the virtual console driver for Starfire 0N/A * Note that console I/O will still go through prom for now 0N/A * (notice we don't open the driver here). The cvc driver 0N/A * During that time, a cvcd daemon will be started that 0N/A * will open the cvcredirection driver to facilitate 0N/A * the redirection of console I/O from cvc to cvcd. 0N/A /* initialize framebuffer, console input, and redirection device */ 0N/A /* initialize virtual console vp for logging if needed */ 0N/A "mousedev %lx, kbddev %lx, fbdev %lx, rconsdev %lx\n",
0N/A * Start of DACF interfaces 0N/A * Tell the physical keyboard driver to send 0N/A * the abort sequences up to the virtual keyboard 0N/A * driver so that STOP and A (or F1 and A) 0N/A * can be applied to different keyboards. 0N/A /* Link the stream underneath conskbd */ 0N/A /* Link the stream underneath consms */ 0N/A * At this point, the stream is: 0N/A * for keyboard: wc->conskbd->["pushmod"->"kbd_vp driver"] 0N/A * for mouse: consms->["module_name"->]"mouse_avp driver" 0N/A /* Close the driver stream, it will stay linked under conskbd */ 0N/A * Retrieve the state information 0N/A * Some platforms may use the old-style "consconfig" to configure 0N/A * console stream modules but may also support devices that happen 0N/A * since the console state structure will not be initialized. 0N/A * In that case, these entry points should silently fail and 0N/A * permit console to be plumbed later in boot. 0N/A /* Access to the global variables is synchronized */ 0N/A * Set the major and minor numbers to 0 so 0N/A * this node if it is detached. 0N/A * See if there was a problem with the console keyboard during boot. 0N/A * If so, try to register polled input for this keyboard. 0N/A /* Prevent autodetach due to memory pressure */ 0N/A * Retrieve the state information 0N/A * So if there isn't a state available, then this entry point just 0N/A * returns. See note in kb_config(). 0N/A * This dev may be opened physically and then hotplugged out. 0N/A * This is the post-attach / pre-detach action function for the keyboard 0N/A * and mouse. This function is associated with a node type in /etc/dacf.conf. 0N/A * consconfig_link and consconfig_unlink are provided to support 0N/A * file, it will be unlinked from the virtual one, and when it 0N/A * is closed physically, it will be linked back under the virtual 0N/A "(%s) underneath virtual keyboard",
buf);
0N/A "(%s) underneath virtual mouse",
buf);
0N/A * Keep this dev on the list, for this dev is still online. 0N/A * Routine to set baud rate, bits-per-char, parity and stop bits 0N/A * on the console line when necessary. 0N/A * First, search for a devalias which matches this dev_t. 0N/A * Try all of ttya through ttyz until no such alias 0N/A for (i = 0; i < (
'z'-
'a'); i++) {
0N/A name[
3] =
'a' + i;
/* increment device name */ 0N/A break;
/* Exit loop if found */ 0N/A return (
1);
/* If we didn't find it, return */ 0N/A * Now that we know which "tty" this corresponds to, retrieve 0N/A * the "ttya-mode" options property, which tells us how to configure 0N/A name[
3] =
'a' + i;
/* Adjust to correct line */ 0N/A return (
1);
/* if no such option, just return */ 0N/A * The IEEE 1275 standard specifies that /aliases string property 0N/A * values should be null-terminated. Unfortunately the reality 0N/A * is that most aren't and the OBP can't easily be modified to 0N/A * add null termination to these strings. So we'll add the 0N/A * null termination here. If the string already contains a 0N/A * null termination character then that's ok too because we'll 0N/A * just be adding a second one. 0N/A /* Clear out options we will be setting */ 0N/A /* Clear options which potentially conflict with new settings */ 0N/A * Now, parse the string. Wish I could use sscanf(). 0N/A * Format 9600,8,n,1,- 0N/A * baud rate, bits-per-char, parity, stop-bits, ignored 0N/A "invalid mode string %s",
buf);
0N/A "consconfig_setmodes: unrecognized speed in %s",
buf);
0N/A /* Found the baud rate, set it */ 0N/A /* Set bits per character */ 0N/A "consconfig_setmodes: illegal bits-per-char %s",
buf);
0N/A break;
/* not enabled. */ 0N/A break;
/* No extra stop bit */ 0N/A * Check to see if underlying keyboard devices are still online, 0N/A * if any one is offline now, unlink it. 0N/A * Remove all disconnected keyboards, 0N/A * whose dev is turned into NODEV above. 0N/A * Remove devices according to dev, which may be NODEV 0N/A * Add a dev according to prop 0N/A * Find a device from our list according to dev 0N/A * Free a cons prop associated with a keyboard or mouse 0N/A * The early boot code can't print to a usb serial device or the 0N/A * graphical boot screen. 0N/A * The early boot messages are saved in a buffer at the address indicated 0N/A * by "deferred-console-buf" This function flushes the message to the 0N/A * current console now that it is set up. 0N/A /* defcons_buf is in low memory, so an int works here */ 0N/A * console I/O is goes to polled I/O entry points. 0N/A * If usb-serial doesn't implement polled I/O, we need 0N/A * We also push ttcompat and ldterm explicitly to get the 0N/A * correct output format (autopush isn't set up yet). We 0N/A * ignore push errors because they are non-fatal. 0N/A * Copy message to a kernel buffer. Various kernel routines 0N/A * expect buffer to be above kernelbase