25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER START
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The contents of this file are subject to the terms of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Common Development and Distribution License (the "License").
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You may not use this file except in compliance with the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * See the License for the specific language governing permissions
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * and limitations under the License.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * When distributing Covered Code, include this CDDL HEADER in each
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If applicable, add the following below this CDDL HEADER, with the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * fields enclosed by brackets "[]" replaced with your own identifying
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information: Portions Copyright [yyyy] [name of copyright owner]
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * CDDL HEADER END
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
193974072f41a843678abf5f61979c748687e66bSherry Moore * Use is subject to license terms.
25cf1a301a396c38e8adf52c15f537b80d2483f7jlextern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl 0, /* devo_refcnt */
193974072f41a843678abf5f61979c748687e66bSherry Moore "OPL serial mux driver",
25cf1a301a396c38e8adf52c15f537b80d2483f7jluinst_t oplmsu_uinst_local; /* upper_instance_table structure */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlint oplmsu_debug_mode = 0; /* Enable/disable debug mode */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlmsu_trc_t *oplmsu_ltrc_tail; /* Tail of trace data area */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlmsu_trc_t *oplmsu_ltrc_cur; /* Current pointer of trace data area */
25cf1a301a396c38e8adf52c15f537b80d2483f7jlkmutex_t oplmsu_ltrc_lock; /* Lock table for trace mode */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* oplmsu_conf_st */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Locking hierarcy of oplmsu driver. This driver have 5 locks in uinst_t.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Each mutex guards as follows.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * uinst_t->lock: This mutex is read/write mutex.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * read lock : acquired if the member of uinst_t is refered only.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * write lock: acquired if the member of uinst_t is changed.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * uinst_t->u_lock: This mutex is normal mutex.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This mutex is acquired at reading/changing the member of all upath_t.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * uinst_t->l_lock: This mutex is normal mutex.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This mutex is acquired at reading/changing the member of all lpath_t.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * uinst_t->c_lock: This mutex is normal mutex.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This mutex is acquired at reading/changing the member of the ctrl_t.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * oplmsu_bthrd_excl: This mutex is normal mutex.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This mutex is used only to start/stop the configuring thread of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * multiplexed STREAMS.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This mutex is exclusively acquired with the above-mentioned 4 mutexes.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * To guard of the deadlock by cross locking, the base locking hierarcy
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is as follows:
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * uisnt->lock ==> uinst->u_lock ==> uinst->l_lock ==> uinst->c_lock
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Initialize R/W lock for uinst_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rw_init(&oplmsu_uinst->lock, "uinst rwlock", RW_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Initialize mutex for upath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&oplmsu_uinst->u_lock, "upath lock", MUTEX_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Initialize mutex for lpath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&oplmsu_uinst->l_lock, "lpath lock", MUTEX_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Initialize mutex for ctrl_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&oplmsu_uinst->c_lock, "ctrl lock", MUTEX_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Initialize mutex for protecting background thread */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&oplmsu_bthrd_excl, NULL, MUTEX_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Initialize condition variable */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jloplmsu_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl switch (cmd) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (instance != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Create minor number for meta control node */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Create minor number for user access node */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Create minor node for user access */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = ddi_create_minor_node(dip, USER_NAME, S_IFCHR, user_minor,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Create minor node for meta control */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = ddi_create_internal_pathname(dip, META_NAME, S_IFCHR,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "ddi_create_internal_pathname failed. errno = %d", rval);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get each properties */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DDI_PROP_DONTPASS|DDI_PROP_NOTPROM), "check-superuser", 1);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize members of uinst_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jl oplmsu_ltrc_size = (uint_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (DDI_PROP_DONTPASS|DDI_PROP_NOTPROM), "trace-bufsize", 128);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Initialize mutex for msu_trc_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mutex_init(&oplmsu_ltrc_lock, "trc lock", MUTEX_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Delete all upath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Delete all lpath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jloplmsu_open(queue_t *urq, dev_t *dev, int oflag, int sflag, cred_t *cred_p)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get minor device number */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get node type */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((node_flag != MSU_NODE_USER) && (node_flag != MSU_NODE_META)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (oplmsu_conf_st != MSU_CONFIGURED)) { /* User access & First open */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Start up background thread */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Wait with cv_wait_sig() until background thread is
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * completed.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (cv_rval == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If the node which will open is meta-control-node or
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * user-access-node, and q_ptr, this is queue_t queue
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * table member, is not NULL, then oplmsu returns
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * SUCCESS immidiately.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * This process is used to protect dual open.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If the node which will open is User-Access-Node, and instance
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * status of oplmsu is no ONLINE, then oplmsu_open process fails
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * with return value 'EIO'.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl *dev = makedevice(majdev, mindev); /* Make device number */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Allocate kernel memory for ctrl_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize members of ctrl_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (struct buf_tbl *)kmem_zalloc(sizeof (struct buf_tbl), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cv_init(&ctrl->cvp, "oplmsu ctrl_tbl condvar", CV_DRIVER, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl } else { /* Meta control node */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* ARGSUSED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "close has already been completed"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: close: ctrl->minor = 0x%x", qmindev));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Check that queue which is waiting for response from lower stream
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * exist. If queue exists, oplmsu sets CV_SLEEP to sleep_flag.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* If sleep_flag is not CV_SLEEP, oplmsu calls cv_wait. */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "oplmsu: close: node_flag = 0x%lx", node_flag);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (wbuf_id != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (wtout_id != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Free kernel memory for ctrl_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Upper write put procedure
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Link high priority message to local queue */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Upper write service procedure
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Handle high priority message */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (oplmsu_wcmn_through_hndl(uwq, mp, MSU_HIGH, RW_READER) ==
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Handle normal priority message */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Lower write service procedure
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Lower read put procedure
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Link high priority message to local queue */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Lower read service procedure
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Handle normal priority message */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * When 1st byte of the received M_DATA is XON or,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * 1st byte is XOFF and 2nd byte is XON.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Path switching by XOFF/XON */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* FALLTHRU */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Upper read service procedure
25cf1a301a396c38e8adf52c15f537b80d2483f7jloplmsu_open_msu(dev_info_t *dip, ldi_ident_t *lip, ldi_handle_t *lhp)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Allocate LDI identifier */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Open oplmsu(meta ctrl node) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl devt = makedevice(ddi_driver_major(dip), META_NODE_MASK);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl ldi_open_by_dev(&devt, OTYP_CHR, (FREAD|FWRITE), kcred, lhp, *lip);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jloplmsu_plink_serial(dev_info_t *dip, ldi_handle_t msu_lh, int *id)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Create physical path-name for serial */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(pathname, "/devices%s:%c", wrkbuf,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Allocate LDI identifier */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "%s ldi_ident_from_dip failed. errno = %d", pathname, rval);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Open serial */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = ldi_open_by_name(pathname, (FREAD|FWRITE|FEXCL), kcred, &lh, li);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Try to remove the top module from the stream */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl while ((ldi_ioctl(lh, I_POP, (intptr_t)0, FKIOCTL, kcred, ¶m))
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Issue ioctl(I_PLINK) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = ldi_ioctl(msu_lh, I_PLINK, (intptr_t)lh, FKIOCTL, kcred, ¶m);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get instance for serial */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get current number of paths */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check specified upath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Open oplmsu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = oplmsu_open_msu(oplmsu_uinst->msu_dip, &msu_li, &msu_lh);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Connect two streams */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Issue ioctl(I_PUNLINK) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ldi_ioctl(msu_lh, I_PUNLINK, (intptr_t)lnk_id, FKIOCTL,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Add the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Issue ioctl(I_PUNLINK) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ldi_ioctl(msu_lh, I_PUNLINK, (intptr_t)lnk_id, FKIOCTL,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Start to use the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (struct msu_path) + sizeof (struct msu_dev);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mpath = (struct msu_path *)kmem_zalloc((size_t)len, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Delete the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Issue ioctl(I_PUNLINK) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Close oplmsu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get instance for serial */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Get current number of paths */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check specified upath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Save status of specified path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check status of specified path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((status == MSU_PSTAT_ACTIVE) || (status == MSU_PSTAT_STANDBY)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Stop to use the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Prepare to unlink the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "oplmsu: detach(dr): Can not find link ID");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Open oplmsu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = oplmsu_open_msu(oplmsu_uinst->msu_dip, &msu_li, &msu_lh);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Issue ioctl(I_PUNLINK) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = ldi_ioctl(msu_lh, I_PUNLINK, (intptr_t)lpath->link_id, FKIOCTL,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Close oplmsu(meta node) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl len = sizeof (struct msu_path) + sizeof (struct msu_dev);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mpath = (struct msu_path *)kmem_zalloc((size_t)len, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Delete the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * The ebus and the serial device path under a given CMU_CH chip
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * is expected to be always at the same address. So, it is safe
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * to hard-code the pathnames as below.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Given the CMU_CH dip, find the serial device dip.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Find all console related serial devices.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl namep = ddi_binding_name(cmuch_dip); /* Get binding name */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: find-serial: name => %s", namep));
5b20806ae198c3fcc384c453bb02089b8ab80074raghuram * Online the cmuch_dip so that its in the right state
5b20806ae198c3fcc384c453bb02089b8ab80074raghuram * to get the complete path, that is both name and address.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Call ddi_pathname_to_dev_t to forceload and attach
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the required drivers.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: find-serial: serial device "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Configure STREAM */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "oplmsu: conf-stream: stream configuration start!"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Find serial devices */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Open oplmsu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = oplmsu_open_msu(msu_uinst->msu_dip, &msu_li, &msu_lh);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl size = (sizeof (struct msu_path) + (sizeof (struct msu_dev) * devcnt));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl mpath = (struct msu_path *)kmem_zalloc((size_t)size, KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl plink_id = (int *)kmem_zalloc((sizeof (int) * devcnt), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < devcnt; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Connect two streams */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl rval = oplmsu_plink_serial(ser_dl->dip, msu_lh, &plink_id[i]);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Issue ioctl(I_PUNLINK) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (connected == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Setup all structure */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Start to use all paths */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval != 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Delete the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: conf-stream: stream configuration end!"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jloplmsu_unlinks(ldi_handle_t msu_lh, int *plink_id, int devcnt)
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < devcnt; i++) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (plink_id[i] == 0) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Issue ioctl(I_PUNLINK) */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl (void) ldi_ioctl(msu_lh, I_PUNLINK, (intptr_t)plink_id[i],
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: setup: Background thread start!"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cv_broadcast(&oplmsu_conf_cv); /* Wake up from cv_wait_sig() */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: setup: Background thread end!"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl lsb = ddi_prop_get_int(DDI_DEV_T_ANY, cmuch_dip, 0, MSU_BOARD_PROP,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl upath = (upath_t *)kmem_zalloc(sizeof (upath_t), KM_SLEEP);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Initialize members of upath_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jl oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_STOP, MSU_PSTAT_EMPTY,
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Setup new upper instance structure */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: conf-new: config_new() called"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (rval == BUSY) { /* Check whether Lower path is usable */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Other processing is using this device");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Because the OPLMSU instance already exists when the upper path
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * table exists, the configure_new processing cannot be done.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cmn_err(CE_WARN, "oplmsu: conf-new: upath_t already exist");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Because the config_new processing has already been done
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * if oplmsu_uinst->path_num isn't -1, this processing cannot be
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * continued.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "conf-new processing has already been completed");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Only the number of specified paths makes the upper path
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information tables.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Associate upper path information table with lower path
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information table.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * If the upper path information table and the lower path
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * information table cannot be associated, the link list of
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * the upper path information table is released.
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Setup members of uinst_t
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Add path information */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: conf-add: config_add() called"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "conf-new processing has not been completed yet");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper upath_t doesn't find");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Delete each path information */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl DBG_PRINT((CE_NOTE, "oplmsu: conf-del: config_del() called"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl upath = oplmsu_search_upath_info(ddi_get_instance(mdev->dip));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper upath_t doesn't find");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Other processing is using this device");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Status of path is improper");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Other processing is using lower path");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Status of path isn't 'Offline:stop/fail'");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Stop to use the path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "All path can't be transferred to the status of "
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "'Offline:stop'");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl upath = oplmsu_search_upath_info(pathnum); /* Search upath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper upath_t doesn't find");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper lpath_t doesn't exist");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check status of lpath_t */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Other processing is using lower path");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if (altn_upath == NULL) { /* Alternate path doesn't exist */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Alternate upper path doesn't find"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl use_flag = oplmsu_set_ioctl_path(altn_lpath, NULL, NULL);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Other processing is using alternate lower path");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* termios is not held. Change alternate path to MSU_ACTIVE */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Make M_FLUSH and send to alternate path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Change status of alternate path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Notify of the active path changing */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Send XON to notify active path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Send XOFF to notify all standby paths */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Switch active path of oplmsu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Restart queuing of user access node */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Stop previous active path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Send termios information to alternate path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Wait for the completion of path switching */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* NOTREACHED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Status of path is improper");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* NOTREACHED */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Start to use path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "oplmsu: conf-start: config_start(%d) called", pathnum));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl if ((pathnum != MSU_PATH_ALL) && (upath->path_no != pathnum)) {
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper lpath_t doesn't exist");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * with PATH_ALL
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper lpath_t doesn't exist"));
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Notify of the active path changing */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) prom_opl_switch_console(upath->ser_devcb.lsb);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Send XON to notify active path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Notify of the active path changing */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Send XON to notify active path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper alternate lpath_t doesn't exist");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper alternate upath_t doesn't exist");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Send XOFF to notify all standby paths */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Change active path of oplmsu */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl/* Prepare of unlink path */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper upath_t doesn't find");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Status of path is improper");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Proper lpath_t doesn't exist");
25cf1a301a396c38e8adf52c15f537b80d2483f7jl /* Check lower path status */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl "Other processing is using lower path");