125cf1a3jl/*
225cf1a3jl * CDDL HEADER START
325cf1a3jl *
425cf1a3jl * The contents of this file are subject to the terms of the
525cf1a3jl * Common Development and Distribution License (the "License").
625cf1a3jl * You may not use this file except in compliance with the License.
725cf1a3jl *
825cf1a3jl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925cf1a3jl * or http://www.opensolaris.org/os/licensing.
1025cf1a3jl * See the License for the specific language governing permissions
1125cf1a3jl * and limitations under the License.
1225cf1a3jl *
1325cf1a3jl * When distributing Covered Code, include this CDDL HEADER in each
1425cf1a3jl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525cf1a3jl * If applicable, add the following below this CDDL HEADER, with the
1625cf1a3jl * fields enclosed by brackets "[]" replaced with your own identifying
1725cf1a3jl * information: Portions Copyright [yyyy] [name of copyright owner]
1825cf1a3jl *
1925cf1a3jl * CDDL HEADER END
2025cf1a3jl */
2125cf1a3jl/*
2225cf1a3jl * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
2325cf1a3jl */
2425cf1a3jl
2525cf1a3jl#include <sys/errno.h>
2625cf1a3jl#include <sys/modctl.h>
2725cf1a3jl#include <sys/stat.h>
2825cf1a3jl#include <sys/kmem.h>
2925cf1a3jl#include <sys/ksynch.h>
3025cf1a3jl#include <sys/stream.h>
3125cf1a3jl#include <sys/stropts.h>
3225cf1a3jl#include <sys/termio.h>
3325cf1a3jl#include <sys/ddi.h>
3425cf1a3jl#include <sys/file.h>
3525cf1a3jl#include <sys/disp.h>
3625cf1a3jl#include <sys/sunddi.h>
3725cf1a3jl#include <sys/sunldi.h>
3825cf1a3jl#include <sys/sunndi.h>
3925cf1a3jl#include <sys/strsun.h>
4025cf1a3jl#include <sys/oplmsu/oplmsu.h>
4125cf1a3jl#include <sys/oplmsu/oplmsu_proto.h>
4225cf1a3jl
4325cf1a3jl/*
4425cf1a3jl * Link upper_path_table structure
4525cf1a3jl *
4625cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
4725cf1a3jl *  -. uinst_t->lock   : M [RW_WRITER]
4825cf1a3jl *  -. uinst_t->u_lock : M
4925cf1a3jl *  -. uinst_t->l_lock : A
5025cf1a3jl *  -. uinst_t->c_lock : A
5125cf1a3jl */
5225cf1a3jlvoid
5325cf1a3jloplmsu_link_upath(upath_t *add_upath)
5425cf1a3jl{
5525cf1a3jl
5625cf1a3jl	ASSERT(add_upath != NULL);
5725cf1a3jl	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
5825cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
5925cf1a3jl
6025cf1a3jl	if (oplmsu_uinst->first_upath == NULL) {
6125cf1a3jl		oplmsu_uinst->first_upath = add_upath;
6225cf1a3jl		add_upath->u_prev = NULL;
6325cf1a3jl	} else {
6425cf1a3jl		upath_t	*last_upath;
6525cf1a3jl
6625cf1a3jl		last_upath = oplmsu_uinst->last_upath;
6725cf1a3jl		last_upath->u_next = add_upath;
6825cf1a3jl		add_upath->u_prev = last_upath;
6925cf1a3jl	}
7025cf1a3jl
7125cf1a3jl	oplmsu_uinst->last_upath = add_upath;
7225cf1a3jl	add_upath->u_next = NULL;
7325cf1a3jl}
7425cf1a3jl
7525cf1a3jl/*
7625cf1a3jl * Unlink upper_path_table structure
7725cf1a3jl *
7825cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
7925cf1a3jl *  -. uinst_t->lock   : M [RW_WRITER]
8025cf1a3jl *  -. uinst_t->u_lock : P
8125cf1a3jl *  -. uinst_t->l_lock : P
8225cf1a3jl *  -. uinst_t->c_lock : P
8325cf1a3jl */
8425cf1a3jlvoid
8525cf1a3jloplmsu_unlink_upath(upath_t *del_upath)
8625cf1a3jl{
8725cf1a3jl	upath_t **first, **last;
8825cf1a3jl
8925cf1a3jl	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
9025cf1a3jl
9125cf1a3jl	first = &oplmsu_uinst->first_upath;
9225cf1a3jl	last = &oplmsu_uinst->last_upath;
9325cf1a3jl
9425cf1a3jl	if ((*first != del_upath) && (*last != del_upath)) {
9525cf1a3jl		del_upath->u_prev->u_next = del_upath->u_next;
9625cf1a3jl		del_upath->u_next->u_prev = del_upath->u_prev;
9725cf1a3jl	} else {
9825cf1a3jl		if (*first == del_upath) {
9925cf1a3jl			*first = (*first)->u_next;
10025cf1a3jl			if (*first) {
10125cf1a3jl				(*first)->u_prev = NULL;
10225cf1a3jl			}
10325cf1a3jl		}
10425cf1a3jl
10525cf1a3jl		if (*last == del_upath) {
10625cf1a3jl			*last = (*last)->u_prev;
10725cf1a3jl			if (*last) {
10825cf1a3jl				(*last)->u_next = NULL;
10925cf1a3jl			}
11025cf1a3jl		}
11125cf1a3jl	}
11225cf1a3jl
11325cf1a3jl	del_upath->u_next = NULL;
11425cf1a3jl	del_upath->u_prev = NULL;
11525cf1a3jl}
11625cf1a3jl
11725cf1a3jl/*
11825cf1a3jl * Link lower_path_table structure
11925cf1a3jl *
12025cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
12125cf1a3jl *  -. uinst_t->lock   : M [RW_WRITER]
12225cf1a3jl *  -. uinst_t->u_lock : A
12325cf1a3jl *  -. uinst_t->l_lock : M
12425cf1a3jl *  -. uinst_t->c_lock : A
12525cf1a3jl */
12625cf1a3jlvoid
12725cf1a3jloplmsu_link_lpath(lpath_t *add_lpath)
12825cf1a3jl{
12925cf1a3jl
13025cf1a3jl	ASSERT(add_lpath != NULL);
13125cf1a3jl	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
13225cf1a3jl
13325cf1a3jl	if (oplmsu_uinst->first_lpath == NULL) {
13425cf1a3jl		oplmsu_uinst->first_lpath = add_lpath;
13525cf1a3jl		add_lpath->l_prev = NULL;
13625cf1a3jl	} else {
13725cf1a3jl		lpath_t	*last_lpath;
13825cf1a3jl
13925cf1a3jl		last_lpath = oplmsu_uinst->last_lpath;
14025cf1a3jl		last_lpath->l_next = add_lpath;
14125cf1a3jl		add_lpath->l_prev = last_lpath;
14225cf1a3jl	}
14325cf1a3jl
14425cf1a3jl	oplmsu_uinst->last_lpath = add_lpath;
14525cf1a3jl	add_lpath->l_next = NULL;
14625cf1a3jl}
14725cf1a3jl
14825cf1a3jl/*
14925cf1a3jl * Unlink lower_path_table structure
15025cf1a3jl *
15125cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
15225cf1a3jl *  -. uinst_t->lock   : M [RW_WRITER]
15325cf1a3jl *  -. uinst_t->u_lock : P
15425cf1a3jl *  -. uinst_t->l_lock : P
15525cf1a3jl *  -. uinst_t->c_lock : P
15625cf1a3jl */
15725cf1a3jlvoid
15825cf1a3jloplmsu_unlink_lpath(lpath_t *del_lpath)
15925cf1a3jl{
16025cf1a3jl	lpath_t **first, **last;
16125cf1a3jl
16225cf1a3jl	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
16325cf1a3jl
16425cf1a3jl	first = &oplmsu_uinst->first_lpath;
16525cf1a3jl	last = &oplmsu_uinst->last_lpath;
16625cf1a3jl
16725cf1a3jl	if ((*first != del_lpath) && (*last != del_lpath)) {
16825cf1a3jl		del_lpath->l_prev->l_next = del_lpath->l_next;
16925cf1a3jl		del_lpath->l_next->l_prev = del_lpath->l_prev;
17025cf1a3jl	} else {
17125cf1a3jl		if (*first == del_lpath) {
17225cf1a3jl			*first = (*first)->l_next;
17325cf1a3jl			if (*first) {
17425cf1a3jl				(*first)->l_prev = NULL;
17525cf1a3jl			}
17625cf1a3jl		}
17725cf1a3jl
17825cf1a3jl		if (*last == del_lpath) {
17925cf1a3jl			*last = (*last)->l_prev;
18025cf1a3jl			if (*last) {
18125cf1a3jl				(*last)->l_next = NULL;
18225cf1a3jl			}
18325cf1a3jl		}
18425cf1a3jl	}
18525cf1a3jl
18625cf1a3jl	del_lpath->l_next = NULL;
18725cf1a3jl	del_lpath->l_prev = NULL;
18825cf1a3jl}
18925cf1a3jl
19025cf1a3jl/*
19125cf1a3jl * Link msgb structure of high priority
19225cf1a3jl *
19325cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
19425cf1a3jl *  -. uinst_t->lock   : M [RW_READER]
19525cf1a3jl *  -. uinst_t->u_lock : A
19625cf1a3jl *  -. uinst_t->l_lock : A [It depends on caller]
19725cf1a3jl *  -. uinst_t->c_lock : A [It depends on caller]
19825cf1a3jl */
19925cf1a3jlvoid
20025cf1a3jloplmsu_link_high_primsg(mblk_t **first, mblk_t **last, mblk_t *add_msg)
20125cf1a3jl{
20225cf1a3jl
20325cf1a3jl	ASSERT(add_msg != NULL);
20425cf1a3jl	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
20525cf1a3jl
20625cf1a3jl	if (*first == NULL) {
20725cf1a3jl		*first = add_msg;
20825cf1a3jl		add_msg->b_prev = NULL;
20925cf1a3jl	} else {
21025cf1a3jl		(*last)->b_next = add_msg;
21125cf1a3jl		add_msg->b_prev = *last;
21225cf1a3jl	}
21325cf1a3jl
21425cf1a3jl	*last = add_msg;
21525cf1a3jl	add_msg->b_next = NULL;
21625cf1a3jl}
21725cf1a3jl
21825cf1a3jl/*
21925cf1a3jl * Check whether lower path is usable by lower path info table address
22025cf1a3jl *
22125cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
22225cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
22325cf1a3jl *  -. uinst_t->u_lock : A
22425cf1a3jl *  -. uinst_t->l_lock : M
22525cf1a3jl *  -. uinst_t->c_lock : P
22625cf1a3jl */
22725cf1a3jlint
22825cf1a3jloplmsu_check_lpath_usable(void)
22925cf1a3jl{
23025cf1a3jl	lpath_t	*lpath;
23125cf1a3jl	int	rval = SUCCESS;
23225cf1a3jl
23325cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
23425cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
23525cf1a3jl
23625cf1a3jl	lpath = oplmsu_uinst->first_lpath;
23725cf1a3jl	while (lpath) {
23825cf1a3jl		if ((lpath->hndl_uqueue != NULL) || (lpath->hndl_mp != NULL)) {
23925cf1a3jl			rval = BUSY;
24025cf1a3jl			break;
24125cf1a3jl		}
24225cf1a3jl		lpath = lpath->l_next;
24325cf1a3jl	}
24425cf1a3jl	return (rval);
24525cf1a3jl}
24625cf1a3jl
24725cf1a3jl/*
24825cf1a3jl * Search upath_t by path number
24925cf1a3jl *
25025cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
25125cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
25225cf1a3jl *  -. uinst_t->u_lock : M
25325cf1a3jl *  -. uinst_t->l_lock : A
25425cf1a3jl *  -. uinst_t->c_lock : P
25525cf1a3jl */
25625cf1a3jlupath_t	*
25725cf1a3jloplmsu_search_upath_info(int path_no)
25825cf1a3jl{
25925cf1a3jl	upath_t	*upath;
26025cf1a3jl
26125cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
26225cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
26325cf1a3jl
26425cf1a3jl	upath = oplmsu_uinst->first_upath;
26525cf1a3jl	while (upath) {
26625cf1a3jl		if (upath->path_no == path_no) {
26725cf1a3jl			break;
26825cf1a3jl		}
26925cf1a3jl		upath = upath->u_next;
27025cf1a3jl	}
27125cf1a3jl	return (upath);
27225cf1a3jl}
27325cf1a3jl
27425cf1a3jl/*
27525cf1a3jl * Send M_IOCACK(or M_IOCNAK) message to stream
27625cf1a3jl *
27725cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
27825cf1a3jl *  -. uinst_t->lock   : P
27925cf1a3jl *  -. uinst_t->u_lock : P
28025cf1a3jl *  -. uinst_t->l_lock : P
28125cf1a3jl *  -. uinst_t->c_lock : P
28225cf1a3jl */
28325cf1a3jlvoid
28425cf1a3jloplmsu_iocack(queue_t *q, mblk_t *mp, int errno)
28525cf1a3jl{
28625cf1a3jl	struct iocblk	*iocp = NULL;
28725cf1a3jl
28825cf1a3jl	ASSERT(mp != NULL);
28925cf1a3jl
29025cf1a3jl	iocp = (struct iocblk *)mp->b_rptr;
29125cf1a3jl	iocp->ioc_error = errno;
29225cf1a3jl
29325cf1a3jl	if (errno) {	/* Error */
29425cf1a3jl		mp->b_datap->db_type = M_IOCNAK;
29525cf1a3jl		iocp->ioc_rval = FAILURE;
29625cf1a3jl
29725cf1a3jl		OPLMSU_TRACE(q, mp, MSU_TRC_UO);
29825cf1a3jl		qreply(q, mp);
29925cf1a3jl	} else {	/* Good */
30025cf1a3jl		mp->b_datap->db_type = M_IOCACK;
30125cf1a3jl		iocp->ioc_rval = SUCCESS;
30225cf1a3jl
30325cf1a3jl		OPLMSU_TRACE(q, mp, MSU_TRC_UO);
30425cf1a3jl		qreply(q, mp);
30525cf1a3jl	}
30625cf1a3jl}
30725cf1a3jl
30825cf1a3jl/*
30925cf1a3jl * Delete all upath_t
31025cf1a3jl *
31125cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
31225cf1a3jl *  -. uinst_t->lock   : M [RW_WRITER]
31325cf1a3jl *  -. uinst_t->u_lock : M
31425cf1a3jl *  -. uinst_t->l_lock : A
31525cf1a3jl *  -. uinst_t->c_lock : A
31625cf1a3jl */
31725cf1a3jlvoid
31825cf1a3jloplmsu_delete_upath_info(void)
31925cf1a3jl{
32025cf1a3jl	upath_t	*upath, *next_upath;
32125cf1a3jl
32225cf1a3jl	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
32325cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
32425cf1a3jl
32525cf1a3jl	upath = oplmsu_uinst->first_upath;
32625cf1a3jl	oplmsu_uinst->first_upath = NULL;
32725cf1a3jl	oplmsu_uinst->last_upath = NULL;
32825cf1a3jl
32925cf1a3jl	while (upath) {
33025cf1a3jl		next_upath = upath->u_next;
33125cf1a3jl		kmem_free(upath, sizeof (upath_t));
33225cf1a3jl		upath = next_upath;
33325cf1a3jl	}
33425cf1a3jl}
33525cf1a3jl
33625cf1a3jl/*
33725cf1a3jl * Set queue and ioctl to lpath_t
33825cf1a3jl *
33925cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
34025cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
34125cf1a3jl *  -. uinst_t->u_lock : A
34225cf1a3jl *  -. uinst_t->l_lock : M
34325cf1a3jl *  -. uinst_t->c_lock : P
34425cf1a3jl */
34525cf1a3jlint
34625cf1a3jloplmsu_set_ioctl_path(lpath_t *lpath, queue_t *hndl_queue, mblk_t *mp)
34725cf1a3jl{
34825cf1a3jl	int	rval = SUCCESS;
34925cf1a3jl
35025cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
35125cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
35225cf1a3jl
35325cf1a3jl	if ((lpath->hndl_uqueue == NULL) && (lpath->hndl_mp == NULL) &&
35425cf1a3jl	    (lpath->sw_flag == 0)) {
35525cf1a3jl		if ((lpath->status == MSU_EXT_NOTUSED) ||
35625cf1a3jl		    (lpath->status == MSU_EXT_ACTIVE_CANDIDATE) ||
35725cf1a3jl		    (lpath->status == MSU_SETID_NU)) {
35825cf1a3jl			if (hndl_queue == NULL) {
35925cf1a3jl				lpath->hndl_uqueue = hndl_queue;
36025cf1a3jl			} else {
36125cf1a3jl				lpath->hndl_uqueue = WR(hndl_queue);
36225cf1a3jl			}
36325cf1a3jl			lpath->hndl_mp = mp;
36425cf1a3jl		} else {
36525cf1a3jl			rval = BUSY;
36625cf1a3jl		}
36725cf1a3jl	} else {
36825cf1a3jl		rval = BUSY;
36925cf1a3jl	}
37025cf1a3jl	return (rval);
37125cf1a3jl}
37225cf1a3jl
37325cf1a3jl/*
37425cf1a3jl * Clear queue and ioctl to lpath_t
37525cf1a3jl *
37625cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
37725cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
37825cf1a3jl *  -. uinst_t->u_lock : A
37925cf1a3jl *  -. uinst_t->l_lock : M
38025cf1a3jl *  -. uinst_t->c_lock : P
38125cf1a3jl */
38225cf1a3jlvoid
38325cf1a3jloplmsu_clear_ioctl_path(lpath_t *lpath)
38425cf1a3jl{
38525cf1a3jl
38625cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
38725cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
38825cf1a3jl
38925cf1a3jl	lpath->hndl_uqueue = NULL;
39025cf1a3jl	lpath->hndl_mp = NULL;
39125cf1a3jl}
39225cf1a3jl
39325cf1a3jl/*
39425cf1a3jl * Get instanse status from status of upath_t
39525cf1a3jl *
39625cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
39725cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
39825cf1a3jl *  -. uinst_t->u_lock : M
39925cf1a3jl *  -. uinst_t->l_lock : A
40025cf1a3jl *  -. uinst_t->c_lock : P
40125cf1a3jl */
40225cf1a3jlint
40325cf1a3jloplmsu_get_inst_status(void)
40425cf1a3jl{
40525cf1a3jl	upath_t	*upath;
40625cf1a3jl	int	sts, pre_sts = INST_STAT_UNCONFIGURED;
40725cf1a3jl
40825cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
40925cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
41025cf1a3jl
41125cf1a3jl	upath = oplmsu_uinst->first_upath;
41225cf1a3jl	while (upath) {
41325cf1a3jl		if (((upath->status == MSU_PSTAT_ACTIVE) &&
41425cf1a3jl		    (upath->traditional_status == MSU_ACTIVE)) ||
41525cf1a3jl		    ((upath->status == MSU_PSTAT_STANDBY) &&
41625cf1a3jl		    (upath->traditional_status == MSU_STANDBY))) {
41725cf1a3jl			sts = INST_STAT_ONLINE;
41825cf1a3jl		} else if (((upath->status == MSU_PSTAT_STOP) &&
41925cf1a3jl		    (upath->traditional_status == MSU_STOP)) ||
42025cf1a3jl		    ((upath->status == MSU_PSTAT_FAIL) &&
42125cf1a3jl		    (upath->traditional_status == MSU_FAIL))) {
42225cf1a3jl			sts = INST_STAT_OFFLINE;
42325cf1a3jl		} else if (((upath->status == MSU_PSTAT_DISCON) &&
42425cf1a3jl		    (upath->traditional_status == MSU_DISCON)) ||
42525cf1a3jl		    ((upath->status == MSU_PSTAT_EMPTY) &&
42625cf1a3jl		    (upath->traditional_status == MSU_EMPTY))) {
42725cf1a3jl			sts = INST_STAT_UNCONFIGURED;
42825cf1a3jl		} else {
42925cf1a3jl			sts = INST_STAT_BUSY;
43025cf1a3jl		}
43125cf1a3jl
43225cf1a3jl		if (pre_sts > sts) {
43325cf1a3jl			pre_sts = sts;
43425cf1a3jl		}
43525cf1a3jl		upath = upath->u_next;
43625cf1a3jl	}
43725cf1a3jl	return (pre_sts);
43825cf1a3jl}
43925cf1a3jl
44025cf1a3jl/*
44125cf1a3jl * Search path of "online:standby" status
44225cf1a3jl *
44325cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
44425cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
44525cf1a3jl *  -. uinst_t->u_lock : M
44625cf1a3jl *  -. uinst_t->l_lock : A
44725cf1a3jl *  -. uinst_t->c_lock : P
44825cf1a3jl */
44925cf1a3jlupath_t	*
45025cf1a3jloplmsu_search_standby(void)
45125cf1a3jl{
45225cf1a3jl	upath_t	*upath, *altn_upath = NULL;
45325cf1a3jl	int	max_pathnum = UNDEFINED;
45425cf1a3jl
45525cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
45625cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
45725cf1a3jl
45825cf1a3jl	upath = oplmsu_uinst->first_upath;
45925cf1a3jl	while (upath) {
46025cf1a3jl		if ((upath->status == MSU_PSTAT_STANDBY) &&
46125cf1a3jl		    (upath->traditional_status == MSU_STANDBY) &&
46225cf1a3jl		    (upath->lpath != NULL)) {
46325cf1a3jl			if ((max_pathnum == UNDEFINED) ||
46425cf1a3jl			    (max_pathnum > upath->path_no)) {
46525cf1a3jl				max_pathnum = upath->path_no;
46625cf1a3jl				altn_upath = upath;
46725cf1a3jl			}
46825cf1a3jl		}
46925cf1a3jl		upath = upath->u_next;
47025cf1a3jl	}
47125cf1a3jl	return (altn_upath);
47225cf1a3jl}
47325cf1a3jl
47425cf1a3jl/*
47525cf1a3jl * Search path of "offline:stop" status, and minimum path number
47625cf1a3jl *
47725cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
47825cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
47925cf1a3jl *  -. uinst_t->u_lock : M
48025cf1a3jl *  -. uinst_t->l_lock : P
48125cf1a3jl *  -. uinst_t->c_lock : P
48225cf1a3jl */
48325cf1a3jlvoid
48425cf1a3jloplmsu_search_min_stop_path(void)
48525cf1a3jl{
48625cf1a3jl	upath_t	*upath, *min_upath;
48725cf1a3jl	lpath_t	*lpath;
48825cf1a3jl	int	min_no = UNDEFINED;
48925cf1a3jl	int	active_flag = 0;
49025cf1a3jl
49125cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
49225cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
49325cf1a3jl
49425cf1a3jl	upath = oplmsu_uinst->first_upath;
49525cf1a3jl	while (upath) {
49625cf1a3jl		if ((upath->status == MSU_PSTAT_ACTIVE) &&
49725cf1a3jl		    (upath->traditional_status == MSU_ACTIVE)) {
49825cf1a3jl			active_flag = 1;
49925cf1a3jl			break;
50025cf1a3jl		} else if ((upath->status == MSU_PSTAT_STOP) &&
50125cf1a3jl		    (upath->traditional_status == MSU_STOP)) {
50225cf1a3jl			if (upath->lpath != NULL) {
50325cf1a3jl				if ((min_no == UNDEFINED) ||
50425cf1a3jl				    (upath->path_no < min_no)) {
50525cf1a3jl					lpath = upath->lpath;
50625cf1a3jl					mutex_enter(&oplmsu_uinst->l_lock);
50725cf1a3jl					if (lpath->status == MSU_EXT_NOTUSED) {
50825cf1a3jl						min_upath = upath;
50925cf1a3jl						min_no = upath->path_no;
51025cf1a3jl					}
51125cf1a3jl					mutex_exit(&oplmsu_uinst->l_lock);
51225cf1a3jl				}
51325cf1a3jl			}
51425cf1a3jl		}
51525cf1a3jl		upath = upath->u_next;
51625cf1a3jl	}
51725cf1a3jl
51825cf1a3jl	if (active_flag == 0) {
51925cf1a3jl		lpath = min_upath->lpath;
52025cf1a3jl		mutex_enter(&oplmsu_uinst->l_lock);
52125cf1a3jl		lpath->src_upath = NULL;
52225cf1a3jl		lpath->status = MSU_EXT_ACTIVE_CANDIDATE;
52325cf1a3jl		mutex_exit(&oplmsu_uinst->l_lock);
52425cf1a3jl	}
52525cf1a3jl}
52625cf1a3jl
52725cf1a3jl/*
52825cf1a3jl * Get the total number of serial paths
52925cf1a3jl *
53025cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
53125cf1a3jl *  -. uinst_t->lock   : M [RW_WRITER]
53225cf1a3jl *  -. uinst_t->u_lock : M
53325cf1a3jl *  -. uinst_t->l_lock : A
53425cf1a3jl *  -. uinst_t->c_lock : A
53525cf1a3jl */
53625cf1a3jlint
53725cf1a3jloplmsu_get_pathnum(void)
53825cf1a3jl{
53925cf1a3jl	upath_t	*upath;
54025cf1a3jl	int	total_num = 0;
54125cf1a3jl
54225cf1a3jl	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
54325cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
54425cf1a3jl
54525cf1a3jl	if (oplmsu_uinst->first_upath != NULL) {
54625cf1a3jl		upath = oplmsu_uinst->first_upath;
54725cf1a3jl		while (upath) {
54825cf1a3jl			total_num++;
54925cf1a3jl			upath = upath->u_next;
55025cf1a3jl		}
55125cf1a3jl	}
55225cf1a3jl	return (total_num);
55325cf1a3jl}
55425cf1a3jl
55525cf1a3jl/*
55625cf1a3jl * Put XOFF/ XON message on write queue
55725cf1a3jl *
55825cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
55925cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
56025cf1a3jl *  -. uinst_t->u_lock : A
56125cf1a3jl *  -. uinst_t->l_lock : A
56225cf1a3jl *  -. uinst_t->c_lock : A
56325cf1a3jl */
56425cf1a3jlint
56525cf1a3jloplmsu_cmn_put_xoffxon(queue_t *queue, int data)
56625cf1a3jl{
56725cf1a3jl	mblk_t	*mp;
56825cf1a3jl	int	rval = SUCCESS;
56925cf1a3jl
57025cf1a3jl	/* Send M_START */
57125cf1a3jl	if ((mp = allocb(0, BPRI_LO)) != NULL) {
57225cf1a3jl		mp->b_datap->db_type = M_START;
57307d06daSurya Prakki		(void) putq(queue, mp);
57425cf1a3jl
57525cf1a3jl		/* Send M_DATA(XOFF, XON) */
57625cf1a3jl		if ((mp = allocb(sizeof (int), BPRI_LO)) != NULL) {
57725cf1a3jl			*(uint_t *)mp->b_rptr = data;
57825cf1a3jl			mp->b_wptr = mp->b_rptr + sizeof (int);
57907d06daSurya Prakki			(void) putq(queue, mp);
58025cf1a3jl		} else {
58125cf1a3jl			rval = FAILURE;
58225cf1a3jl		}
58325cf1a3jl	} else {
58425cf1a3jl		rval = FAILURE;
58525cf1a3jl	}
58625cf1a3jl	return (rval);
58725cf1a3jl}
58825cf1a3jl
58925cf1a3jl/*
59025cf1a3jl * Put XOFF message on write queue for all standby paths
59125cf1a3jl *
59225cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
59325cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
59425cf1a3jl *  -. uinst_t->u_lock : M
59525cf1a3jl *  -. uinst_t->l_lock : M
59625cf1a3jl *  -. uinst_t->c_lock : P
59725cf1a3jl */
59825cf1a3jlvoid
59925cf1a3jloplmsu_cmn_putxoff_standby(void)
60025cf1a3jl{
60125cf1a3jl	upath_t	*upath;
60225cf1a3jl	lpath_t	*lpath;
60325cf1a3jl
60425cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
60525cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
60625cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
60725cf1a3jl
60825cf1a3jl	upath = oplmsu_uinst->first_upath;
60925cf1a3jl	while (upath) {
61025cf1a3jl		lpath = upath->lpath;
61125cf1a3jl		if ((upath->status != MSU_PSTAT_STANDBY) ||
61225cf1a3jl		    (lpath == NULL)) {
61325cf1a3jl			upath = upath->u_next;
61425cf1a3jl			continue;
61525cf1a3jl		}
61625cf1a3jl
61725cf1a3jl		(void) oplmsu_cmn_put_xoffxon(
61825cf1a3jl		    WR(lpath->lower_queue), MSU_XOFF_4);
61925cf1a3jl		upath = upath->u_next;
62025cf1a3jl	}
62125cf1a3jl}
62225cf1a3jl
62325cf1a3jl/*
62425cf1a3jl * Set M_FLUSH message
62525cf1a3jl *
62625cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
62725cf1a3jl *  -. uinst_t->lock   : A [RW_READER or RW_WRITER]
62825cf1a3jl *  -. uinst_t->u_lock : A
62925cf1a3jl *  -. uinst_t->l_lock : A
63025cf1a3jl *  -. uinst_t->c_lock : A
63125cf1a3jl */
63225cf1a3jlvoid
63325cf1a3jloplmsu_cmn_set_mflush(mblk_t *mp)
63425cf1a3jl{
63525cf1a3jl
63625cf1a3jl	mp->b_datap->db_type = M_FLUSH;
63725cf1a3jl	*mp->b_rptr = FLUSHW;
63825cf1a3jl	mp->b_wptr = mp->b_rptr + sizeof (char);
63925cf1a3jl}
64025cf1a3jl
64125cf1a3jl/*
64225cf1a3jl * Set status informations of upath_t
64325cf1a3jl *
64425cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
64525cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
64625cf1a3jl *  -. uinst_t->u_lock : M
64725cf1a3jl *  -. uinst_t->l_lock : A
64825cf1a3jl *  -. uinst_t->c_lock : A
64925cf1a3jl */
65025cf1a3jlvoid
65125cf1a3jloplmsu_cmn_set_upath_sts(upath_t *upath, int sts, int prev_sts,
65225cf1a3jl    ulong_t trad_sts)
65325cf1a3jl{
65425cf1a3jl
65525cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
65625cf1a3jl	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
65725cf1a3jl
65825cf1a3jl	upath->status = sts;
65925cf1a3jl	upath->prev_status = prev_sts;
66025cf1a3jl	upath->traditional_status = trad_sts;
66125cf1a3jl}
66225cf1a3jl
66325cf1a3jl/*
66425cf1a3jl * Allocate a message block
66525cf1a3jl *
66625cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
66725cf1a3jl *  -. uinst_t->lock   : M [RW_READER]
66825cf1a3jl *  -. uinst_t->u_lock : A
66925cf1a3jl *  -. uinst_t->l_lock : P
67025cf1a3jl *  -. uinst_t->c_lock : P
67125cf1a3jl */
67225cf1a3jlint
67325cf1a3jloplmsu_cmn_allocmb(queue_t *q, mblk_t *mp, mblk_t **nmp, size_t size,
67425cf1a3jl    int rw_flag)
67525cf1a3jl{
67625cf1a3jl	int	rval = SUCCESS;
67725cf1a3jl
67825cf1a3jl	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
67925cf1a3jl
68025cf1a3jl	if ((*nmp = (mblk_t *)allocb(size, BPRI_LO)) == NULL) {
68125cf1a3jl		oplmsu_cmn_bufcall(q, mp, size, rw_flag);
68225cf1a3jl		rval = FAILURE;
68325cf1a3jl	} else {
68425cf1a3jl		(*nmp)->b_wptr = (*nmp)->b_rptr + size;
68525cf1a3jl	}
68625cf1a3jl	return (rval);
68725cf1a3jl}
68825cf1a3jl
68925cf1a3jl/*
69025cf1a3jl * Copy a message
69125cf1a3jl *
69225cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
69325cf1a3jl *  -. uinst_t->lock   : M [RW_READER]
69425cf1a3jl *  -. uinst_t->u_lock : A
69525cf1a3jl *  -. uinst_t->l_lock : P
69625cf1a3jl *  -. uinst_t->c_lock : P
69725cf1a3jl */
69825cf1a3jlint
69925cf1a3jloplmsu_cmn_copymb(queue_t *q, mblk_t *mp, mblk_t **nmp, mblk_t *cmp,
70025cf1a3jl    int rw_flag)
70125cf1a3jl{
70225cf1a3jl	int	rval = SUCCESS;
70325cf1a3jl
70425cf1a3jl	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
70525cf1a3jl
70625cf1a3jl	if ((*nmp = copymsg(cmp)) == NULL) {
70725cf1a3jl		oplmsu_cmn_bufcall(q, mp, msgsize(cmp), rw_flag);
70825cf1a3jl		rval = FAILURE;
70925cf1a3jl	}
71025cf1a3jl	return (rval);
71125cf1a3jl}
71225cf1a3jl
71325cf1a3jl/*
71425cf1a3jl * bufcall request
71525cf1a3jl *
71625cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
71725cf1a3jl *  -. uinst_t->lock   : M [RW_READER]
71825cf1a3jl *  -. uinst_t->u_lock : A
71925cf1a3jl *  -. uinst_t->l_lock : P
72025cf1a3jl *  -. uinst_t->c_lock : P
72125cf1a3jl */
72225cf1a3jlvoid
72325cf1a3jloplmsu_cmn_bufcall(queue_t *q, mblk_t *mp, size_t size, int rw_flag)
72425cf1a3jl{
72525cf1a3jl
72625cf1a3jl	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
72725cf1a3jl
72825cf1a3jl	if (rw_flag == MSU_WRITE_SIDE) {
72925cf1a3jl		ctrl_t	*ctrl;
73025cf1a3jl
73107d06daSurya Prakki		(void) putbq(q, mp);
73225cf1a3jl
73325cf1a3jl		mutex_enter(&oplmsu_uinst->c_lock);
73425cf1a3jl		ctrl = (ctrl_t *)q->q_ptr;
73525cf1a3jl		if (ctrl->wbuf_id != 0) {
73625cf1a3jl			mutex_exit(&oplmsu_uinst->c_lock);
73725cf1a3jl			return;
73825cf1a3jl		}
73925cf1a3jl
74025cf1a3jl		ctrl->wbuftbl->q = q;
74125cf1a3jl		ctrl->wbuftbl->rw_flag = rw_flag;
74225cf1a3jl		ctrl->wbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb,
74325cf1a3jl		    (void *)ctrl->wbuftbl);
74425cf1a3jl
74525cf1a3jl		if (ctrl->wbuf_id == 0) {
74625cf1a3jl			if (ctrl->wtout_id != 0) {
74725cf1a3jl				mutex_exit(&oplmsu_uinst->c_lock);
74825cf1a3jl				return;
74925cf1a3jl			}
75025cf1a3jl
75125cf1a3jl			ctrl->wtout_id = timeout(oplmsu_cmn_bufcb,
75225cf1a3jl			    (void *)ctrl->wbuftbl, drv_usectohz(MSU_TM_500MS));
75325cf1a3jl		}
75425cf1a3jl		mutex_exit(&oplmsu_uinst->c_lock);
75525cf1a3jl	} else if (rw_flag == MSU_READ_SIDE) {
75625cf1a3jl		lpath_t	*lpath;
75725cf1a3jl		mblk_t	*wrk_msg;
75825cf1a3jl
75925cf1a3jl		mutex_enter(&oplmsu_uinst->l_lock);
76025cf1a3jl		lpath = (lpath_t *)q->q_ptr;
76125cf1a3jl		if (mp->b_datap->db_type >= QPCTL) {
76225cf1a3jl			if (lpath->first_lpri_hi == NULL) {
76325cf1a3jl				lpath->last_lpri_hi = mp;
76425cf1a3jl				mp->b_next = NULL;
76525cf1a3jl			} else {
76625cf1a3jl				wrk_msg = lpath->first_lpri_hi;
76725cf1a3jl				wrk_msg->b_prev = mp;
76825cf1a3jl				mp->b_next = wrk_msg;
76925cf1a3jl			}
77025cf1a3jl			mp->b_prev = NULL;
77125cf1a3jl			lpath->first_lpri_hi = mp;
77225cf1a3jl		} else {
77307d06daSurya Prakki			(void) putbq(q, mp);
77425cf1a3jl		}
77525cf1a3jl
77625cf1a3jl		if (lpath->rbuf_id != 0) {
77725cf1a3jl			mutex_exit(&oplmsu_uinst->l_lock);
77825cf1a3jl			return;
77925cf1a3jl		}
78025cf1a3jl
78125cf1a3jl		lpath->rbuftbl->q = q;
78225cf1a3jl		lpath->rbuftbl->rw_flag = rw_flag;
78325cf1a3jl		lpath->rbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb,
78425cf1a3jl		    (void *)lpath->rbuftbl);
78525cf1a3jl
78625cf1a3jl		if (lpath->rbuf_id == 0) {
78725cf1a3jl			if (lpath->rtout_id != 0) {
78825cf1a3jl				mutex_exit(&oplmsu_uinst->l_lock);
78925cf1a3jl				return;
79025cf1a3jl			}
79125cf1a3jl
79225cf1a3jl			lpath->rtout_id = timeout(oplmsu_cmn_bufcb,
79325cf1a3jl			    (void *)lpath->rbuftbl, drv_usectohz(MSU_TM_500MS));
79425cf1a3jl		}
79525cf1a3jl		mutex_exit(&oplmsu_uinst->l_lock);
79625cf1a3jl	}
79725cf1a3jl}
79825cf1a3jl
79925cf1a3jl/*
80025cf1a3jl * Previous sequence for active path change
80125cf1a3jl *
80225cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
80325cf1a3jl *  -. uinst_t->lock   : M [RW_READER]
80425cf1a3jl *  -. uinst_t->u_lock : A
80525cf1a3jl *  -. uinst_t->l_lock : P
80625cf1a3jl *  -. uinst_t->c_lock : P
80725cf1a3jl */
80825cf1a3jlint
80925cf1a3jloplmsu_cmn_prechg(queue_t *q, mblk_t *mp, int rw_flag, mblk_t **term_mp,
81025cf1a3jl    int *term_ioctl, int *term_stat)
81125cf1a3jl{
81225cf1a3jl
81325cf1a3jl	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
81425cf1a3jl
81525cf1a3jl	if (oplmsu_uinst->tcsets_p != NULL) {
81625cf1a3jl		struct iocblk	*iocp;
81725cf1a3jl
81825cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tcsets_p,
81925cf1a3jl		    rw_flag) == -1) {
82025cf1a3jl			return (FAILURE);
82125cf1a3jl		}
82225cf1a3jl
82325cf1a3jl		iocp = (struct iocblk *)(*term_mp)->b_rptr;
82425cf1a3jl		*term_ioctl = iocp->ioc_cmd;
82525cf1a3jl		*term_stat = MSU_WTCS_ACK;
82625cf1a3jl	} else if (oplmsu_uinst->tiocmset_p != NULL) {
82725cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p,
82825cf1a3jl		    rw_flag) == -1) {
82925cf1a3jl			return (FAILURE);
83025cf1a3jl		}
83125cf1a3jl
83225cf1a3jl		*term_ioctl = TIOCMSET;
83325cf1a3jl		*term_stat = MSU_WTMS_ACK;
83425cf1a3jl	} else if (oplmsu_uinst->tiocspps_p != NULL) {
83525cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p,
83625cf1a3jl		    rw_flag) == -1) {
83725cf1a3jl			return (FAILURE);
83825cf1a3jl		}
83925cf1a3jl
84025cf1a3jl		*term_ioctl = TIOCSPPS;
84125cf1a3jl		*term_stat = MSU_WPPS_ACK;
84225cf1a3jl	} else if (oplmsu_uinst->tiocswinsz_p != NULL) {
84325cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp,
84425cf1a3jl		    oplmsu_uinst->tiocswinsz_p, rw_flag) == -1) {
84525cf1a3jl			return (FAILURE);
84625cf1a3jl		}
84725cf1a3jl
84825cf1a3jl		*term_ioctl = TIOCSWINSZ;
84925cf1a3jl		*term_stat = MSU_WWSZ_ACK;
85025cf1a3jl	} else if (oplmsu_uinst->tiocssoftcar_p != NULL) {
85125cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp,
85225cf1a3jl		    oplmsu_uinst->tiocssoftcar_p, rw_flag) == -1) {
85325cf1a3jl			return (FAILURE);
85425cf1a3jl		}
85525cf1a3jl
85625cf1a3jl		*term_ioctl = TIOCSSOFTCAR;
85725cf1a3jl		*term_stat = MSU_WCAR_ACK;
85825cf1a3jl	} else {
85925cf1a3jl		*term_stat = MSU_WPTH_CHG;
86025cf1a3jl		*term_mp = NULL;
86125cf1a3jl	}
86225cf1a3jl	return (SUCCESS);
86325cf1a3jl}
86425cf1a3jl
86525cf1a3jl/*
86625cf1a3jl * Pick up termios to re-set
86725cf1a3jl *
86825cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
86925cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
87025cf1a3jl *  -. uinst_t->u_lock : A
87125cf1a3jl *  -. uinst_t->l_lock : A
87225cf1a3jl *  -. uinst_t->c_lock : A
87325cf1a3jl */
87425cf1a3jlint
87525cf1a3jloplmsu_stop_prechg(mblk_t **term_mp, int *term_ioctl, int *term_stat)
87625cf1a3jl{
87725cf1a3jl
87825cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
87925cf1a3jl
88025cf1a3jl	if (oplmsu_uinst->tcsets_p != NULL) {
88125cf1a3jl		struct iocblk	*iocp;
88225cf1a3jl
88325cf1a3jl		if ((*term_mp = copymsg(oplmsu_uinst->tcsets_p)) == NULL) {
88425cf1a3jl			return (FAILURE);
88525cf1a3jl		}
88625cf1a3jl
88725cf1a3jl		iocp = (struct iocblk *)(*term_mp)->b_rptr;
88825cf1a3jl		*term_ioctl = iocp->ioc_cmd;
88925cf1a3jl		*term_stat = MSU_WTCS_ACK;
89025cf1a3jl	} else if (oplmsu_uinst->tiocmset_p != NULL) {
89125cf1a3jl		if ((*term_mp = copymsg(oplmsu_uinst->tiocmset_p)) == NULL) {
89225cf1a3jl			return (FAILURE);
89325cf1a3jl		}
89425cf1a3jl
89525cf1a3jl		*term_ioctl = TIOCMSET;
89625cf1a3jl		*term_stat = MSU_WTMS_ACK;
89725cf1a3jl	} else if (oplmsu_uinst->tiocspps_p != NULL) {
89825cf1a3jl		if ((*term_mp = copymsg(oplmsu_uinst->tiocspps_p)) == NULL) {
89925cf1a3jl			return (FAILURE);
90025cf1a3jl		}
90125cf1a3jl
90225cf1a3jl		*term_ioctl = TIOCSPPS;
90325cf1a3jl		*term_stat = MSU_WPPS_ACK;
90425cf1a3jl	} else if (oplmsu_uinst->tiocswinsz_p != NULL) {
90525cf1a3jl		if ((*term_mp = copymsg(oplmsu_uinst->tiocswinsz_p)) == NULL) {
90625cf1a3jl			return (FAILURE);
90725cf1a3jl		}
90825cf1a3jl
90925cf1a3jl		*term_ioctl = TIOCSWINSZ;
91025cf1a3jl		*term_stat = MSU_WWSZ_ACK;
91125cf1a3jl	} else if (oplmsu_uinst->tiocssoftcar_p != NULL) {
91225cf1a3jl		if ((*term_mp = copymsg(oplmsu_uinst->tiocssoftcar_p))
91325cf1a3jl		    == NULL) {
91425cf1a3jl			return (FAILURE);
91525cf1a3jl		}
91625cf1a3jl
91725cf1a3jl		*term_ioctl = TIOCSSOFTCAR;
91825cf1a3jl		*term_stat = MSU_WCAR_ACK;
91925cf1a3jl	} else {
92025cf1a3jl		*term_stat = MSU_WPTH_CHG;
92125cf1a3jl		*term_mp = NULL;
92225cf1a3jl	}
92325cf1a3jl	return (SUCCESS);
92425cf1a3jl}
92525cf1a3jl
92625cf1a3jl/*
92725cf1a3jl * Previous sequence for active path change termio
92825cf1a3jl *
92925cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
93025cf1a3jl *  -. uinst_t->lock   : M [RW_READER]
93125cf1a3jl *  -. uinst_t->u_lock : A
93225cf1a3jl *  -. uinst_t->l_lock : P
93325cf1a3jl *  -. uinst_t->c_lock : P
93425cf1a3jl */
93525cf1a3jlint
93625cf1a3jloplmsu_cmn_prechg_termio(queue_t *q, mblk_t *mp, int rw_flag, int prev_flag,
93725cf1a3jl    mblk_t **term_mp, int *term_stat)
93825cf1a3jl{
93925cf1a3jl
94025cf1a3jl	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
94125cf1a3jl
94225cf1a3jl	if ((prev_flag == MSU_TIOS_TCSETS) &&
94325cf1a3jl	    (oplmsu_uinst->tiocmset_p != NULL)) {
94425cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p,
94525cf1a3jl		    rw_flag) == FAILURE) {
94625cf1a3jl			return (FAILURE);
94725cf1a3jl		}
94825cf1a3jl
94925cf1a3jl		*term_stat = MSU_WTMS_ACK;
95025cf1a3jl	} else if ((prev_flag <= MSU_TIOS_MSET) &&
95125cf1a3jl	    (oplmsu_uinst->tiocspps_p != NULL)) {
95225cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p,
95325cf1a3jl		    rw_flag) == FAILURE) {
95425cf1a3jl			return (FAILURE);
95525cf1a3jl		}
95625cf1a3jl
95725cf1a3jl		*term_stat = MSU_WPPS_ACK;
95825cf1a3jl	} else if ((prev_flag <= MSU_TIOS_PPS) &&
95925cf1a3jl	    (oplmsu_uinst->tiocswinsz_p != NULL)) {
96025cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp,
96125cf1a3jl		    oplmsu_uinst->tiocswinsz_p, rw_flag) == FAILURE) {
96225cf1a3jl			return (FAILURE);
96325cf1a3jl		}
96425cf1a3jl
96525cf1a3jl		*term_stat = MSU_WWSZ_ACK;
96625cf1a3jl	} else if ((prev_flag <= MSU_TIOS_WINSZP) &&
96725cf1a3jl	    (oplmsu_uinst->tiocssoftcar_p != NULL)) {
96825cf1a3jl		if (oplmsu_cmn_copymb(q, mp, term_mp,
96925cf1a3jl		    oplmsu_uinst->tiocssoftcar_p, rw_flag) == FAILURE) {
97025cf1a3jl			return (FAILURE);
97125cf1a3jl		}
97225cf1a3jl
97325cf1a3jl		*term_stat = MSU_WCAR_ACK;
97425cf1a3jl	} else if (prev_flag <= MSU_TIOS_SOFTCAR) {
97525cf1a3jl		*term_mp = NULL;
97625cf1a3jl		*term_stat = MSU_WPTH_CHG;
97725cf1a3jl	}
97825cf1a3jl	return (SUCCESS);
97925cf1a3jl}
98025cf1a3jl
98125cf1a3jl/*
98225cf1a3jl * Pull up messages
98325cf1a3jl *
98425cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
98525cf1a3jl *  -. uinst_t->lock   : P
98625cf1a3jl *  -. uinst_t->u_lock : P
98725cf1a3jl *  -. uinst_t->l_lock : P
98825cf1a3jl *  -. uinst_t->c_lock : P
98925cf1a3jl */
99025cf1a3jlint
99125cf1a3jloplmsu_cmn_pullup_msg(queue_t *q, mblk_t *mp)
99225cf1a3jl{
99325cf1a3jl	mblk_t	*nmp = NULL;
99425cf1a3jl
99525cf1a3jl	if ((mp != NULL) && (mp->b_cont != NULL) &&
99625cf1a3jl	    (mp->b_cont->b_cont != NULL)) {
99725cf1a3jl		if ((nmp = msgpullup(mp->b_cont, -1)) == NULL) {
99825cf1a3jl			oplmsu_iocack(q, mp, ENOSR);
99925cf1a3jl			return (FAILURE);
100025cf1a3jl		} else {
100125cf1a3jl			freemsg(mp->b_cont);
100225cf1a3jl			mp->b_cont = nmp;
100325cf1a3jl		}
100425cf1a3jl	}
100525cf1a3jl	return (SUCCESS);
100625cf1a3jl}
100725cf1a3jl
100825cf1a3jl/*
100925cf1a3jl * Wake up flow control
101025cf1a3jl *
101125cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
101225cf1a3jl *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
101325cf1a3jl *  -. uinst_t->u_lock : P
101425cf1a3jl *  -. uinst_t->l_lock : P
101525cf1a3jl *  -. uinst_t->c_lock : P
101625cf1a3jl */
101725cf1a3jlvoid
101825cf1a3jloplmsu_cmn_wakeup(queue_t *q)
101925cf1a3jl{
102025cf1a3jl	ctrl_t	*ctrl;
102125cf1a3jl
102225cf1a3jl	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
102325cf1a3jl
102425cf1a3jl	mutex_enter(&oplmsu_uinst->c_lock);
102525cf1a3jl	ctrl = (ctrl_t *)q->q_ptr;
102625cf1a3jl	if (ctrl->sleep_flag == CV_SLEEP) {
102725cf1a3jl		ctrl->sleep_flag = CV_WAKEUP;
102825cf1a3jl		cv_signal(&ctrl->cvp);
102925cf1a3jl	}
103025cf1a3jl	mutex_exit(&oplmsu_uinst->c_lock);
103125cf1a3jl}
103225cf1a3jl
103325cf1a3jl/*
103425cf1a3jl * bufcall() and timeout() callback entry for read/write stream
103525cf1a3jl *
103625cf1a3jl * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
103725cf1a3jl *  -. uinst_t->lock   : P
103825cf1a3jl *  -. uinst_t->u_lock : P
103925cf1a3jl *  -. uinst_t->l_lock : P
104025cf1a3jl *  -. uinst_t->c_lock : P
104125cf1a3jl */
104225cf1a3jlvoid
104325cf1a3jloplmsu_cmn_bufcb(void *arg)
104425cf1a3jl{
104525cf1a3jl	struct buf_tbl	*buftbl = arg;
104625cf1a3jl	lpath_t		*lpath;
104725cf1a3jl	ctrl_t		*ctrl;
104825cf1a3jl	queue_t		*q;
104925cf1a3jl	int		lq_flag = 0;
105025cf1a3jl
105125cf1a3jl	rw_enter(&oplmsu_uinst->lock, RW_WRITER);
105225cf1a3jl	mutex_enter(&oplmsu_uinst->l_lock);
105325cf1a3jl
105425cf1a3jl	lpath = oplmsu_uinst->first_lpath;
105525cf1a3jl	while (lpath) {
105625cf1a3jl		if ((buftbl == lpath->rbuftbl) &&
105725cf1a3jl		    (buftbl->rw_flag == MSU_READ_SIDE)) {
105825cf1a3jl			if ((lpath->rbuf_id == 0) && (lpath->rtout_id == 0)) {
105925cf1a3jl				mutex_exit(&oplmsu_uinst->l_lock);
106025cf1a3jl				rw_exit(&oplmsu_uinst->lock);
106125cf1a3jl			} else {
106225cf1a3jl				q = lpath->rbuftbl->q;
106325cf1a3jl				lpath->rbuftbl->q = NULL;
106425cf1a3jl				lpath->rbuftbl->rw_flag = UNDEFINED;
106525cf1a3jl
106625cf1a3jl				if (lpath->rbuf_id) {
106725cf1a3jl					lpath->rbuf_id = 0;
106825cf1a3jl				} else {
106925cf1a3jl					lpath->rtout_id = 0;
107025cf1a3jl				}
107125cf1a3jl				mutex_exit(&oplmsu_uinst->l_lock);
107225cf1a3jl
107325cf1a3jl				if (oplmsu_queue_flag == 1) {
107425cf1a3jl					lq_flag = 1;
107525cf1a3jl					oplmsu_queue_flag = 0;
107625cf1a3jl				}
107725cf1a3jl
107825cf1a3jl				rw_exit(&oplmsu_uinst->lock);
107925cf1a3jl				oplmsu_rcmn_high_qenable(q);
108025cf1a3jl
108125cf1a3jl				if (lq_flag == 1) {
108225cf1a3jl					rw_enter(&oplmsu_uinst->lock,
108325cf1a3jl					    RW_WRITER);
108425cf1a3jl					oplmsu_queue_flag = 1;
108525cf1a3jl					rw_exit(&oplmsu_uinst->lock);
108625cf1a3jl				}
108725cf1a3jl			}
108825cf1a3jl			return;
108925cf1a3jl		}
109025cf1a3jl		lpath = lpath->l_next;
109125cf1a3jl	}
109225cf1a3jl	mutex_exit(&oplmsu_uinst->l_lock);
109325cf1a3jl
109425cf1a3jl	mutex_enter(&oplmsu_uinst->c_lock);
109525cf1a3jl	if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) {
109625cf1a3jl		if ((buftbl == ctrl->wbuftbl) &&
1097