xref: /onnv-gate/usr/src/uts/sun4u/opl/io/oplmsu/oplmsu_cmn_func.c (revision 11311:639e7bc0b42f)
11772Sjl139090 /*
21772Sjl139090  * CDDL HEADER START
31772Sjl139090  *
41772Sjl139090  * The contents of this file are subject to the terms of the
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * You may not use this file except in compliance with the License.
71772Sjl139090  *
81772Sjl139090  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91772Sjl139090  * or http://www.opensolaris.org/os/licensing.
101772Sjl139090  * See the License for the specific language governing permissions
111772Sjl139090  * and limitations under the License.
121772Sjl139090  *
131772Sjl139090  * When distributing Covered Code, include this CDDL HEADER in each
141772Sjl139090  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151772Sjl139090  * If applicable, add the following below this CDDL HEADER, with the
161772Sjl139090  * fields enclosed by brackets "[]" replaced with your own identifying
171772Sjl139090  * information: Portions Copyright [yyyy] [name of copyright owner]
181772Sjl139090  *
191772Sjl139090  * CDDL HEADER END
201772Sjl139090  */
211772Sjl139090 /*
221772Sjl139090  * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
231772Sjl139090  */
241772Sjl139090 
251772Sjl139090 #include <sys/errno.h>
261772Sjl139090 #include <sys/modctl.h>
271772Sjl139090 #include <sys/stat.h>
281772Sjl139090 #include <sys/kmem.h>
291772Sjl139090 #include <sys/ksynch.h>
301772Sjl139090 #include <sys/stream.h>
311772Sjl139090 #include <sys/stropts.h>
321772Sjl139090 #include <sys/termio.h>
331772Sjl139090 #include <sys/ddi.h>
341772Sjl139090 #include <sys/file.h>
351772Sjl139090 #include <sys/disp.h>
361772Sjl139090 #include <sys/sunddi.h>
371772Sjl139090 #include <sys/sunldi.h>
381772Sjl139090 #include <sys/sunndi.h>
391772Sjl139090 #include <sys/strsun.h>
401772Sjl139090 #include <sys/oplmsu/oplmsu.h>
411772Sjl139090 #include <sys/oplmsu/oplmsu_proto.h>
421772Sjl139090 
431772Sjl139090 /*
441772Sjl139090  * Link upper_path_table structure
451772Sjl139090  *
461772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
471772Sjl139090  *  -. uinst_t->lock   : M [RW_WRITER]
481772Sjl139090  *  -. uinst_t->u_lock : M
491772Sjl139090  *  -. uinst_t->l_lock : A
501772Sjl139090  *  -. uinst_t->c_lock : A
511772Sjl139090  */
521772Sjl139090 void
oplmsu_link_upath(upath_t * add_upath)531772Sjl139090 oplmsu_link_upath(upath_t *add_upath)
541772Sjl139090 {
551772Sjl139090 
561772Sjl139090 	ASSERT(add_upath != NULL);
571772Sjl139090 	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
581772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
591772Sjl139090 
601772Sjl139090 	if (oplmsu_uinst->first_upath == NULL) {
611772Sjl139090 		oplmsu_uinst->first_upath = add_upath;
621772Sjl139090 		add_upath->u_prev = NULL;
631772Sjl139090 	} else {
641772Sjl139090 		upath_t	*last_upath;
651772Sjl139090 
661772Sjl139090 		last_upath = oplmsu_uinst->last_upath;
671772Sjl139090 		last_upath->u_next = add_upath;
681772Sjl139090 		add_upath->u_prev = last_upath;
691772Sjl139090 	}
701772Sjl139090 
711772Sjl139090 	oplmsu_uinst->last_upath = add_upath;
721772Sjl139090 	add_upath->u_next = NULL;
731772Sjl139090 }
741772Sjl139090 
751772Sjl139090 /*
761772Sjl139090  * Unlink upper_path_table structure
771772Sjl139090  *
781772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
791772Sjl139090  *  -. uinst_t->lock   : M [RW_WRITER]
801772Sjl139090  *  -. uinst_t->u_lock : P
811772Sjl139090  *  -. uinst_t->l_lock : P
821772Sjl139090  *  -. uinst_t->c_lock : P
831772Sjl139090  */
841772Sjl139090 void
oplmsu_unlink_upath(upath_t * del_upath)851772Sjl139090 oplmsu_unlink_upath(upath_t *del_upath)
861772Sjl139090 {
871772Sjl139090 	upath_t **first, **last;
881772Sjl139090 
891772Sjl139090 	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
901772Sjl139090 
911772Sjl139090 	first = &oplmsu_uinst->first_upath;
921772Sjl139090 	last = &oplmsu_uinst->last_upath;
931772Sjl139090 
941772Sjl139090 	if ((*first != del_upath) && (*last != del_upath)) {
951772Sjl139090 		del_upath->u_prev->u_next = del_upath->u_next;
961772Sjl139090 		del_upath->u_next->u_prev = del_upath->u_prev;
971772Sjl139090 	} else {
981772Sjl139090 		if (*first == del_upath) {
991772Sjl139090 			*first = (*first)->u_next;
1001772Sjl139090 			if (*first) {
1011772Sjl139090 				(*first)->u_prev = NULL;
1021772Sjl139090 			}
1031772Sjl139090 		}
1041772Sjl139090 
1051772Sjl139090 		if (*last == del_upath) {
1061772Sjl139090 			*last = (*last)->u_prev;
1071772Sjl139090 			if (*last) {
1081772Sjl139090 				(*last)->u_next = NULL;
1091772Sjl139090 			}
1101772Sjl139090 		}
1111772Sjl139090 	}
1121772Sjl139090 
1131772Sjl139090 	del_upath->u_next = NULL;
1141772Sjl139090 	del_upath->u_prev = NULL;
1151772Sjl139090 }
1161772Sjl139090 
1171772Sjl139090 /*
1181772Sjl139090  * Link lower_path_table structure
1191772Sjl139090  *
1201772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
1211772Sjl139090  *  -. uinst_t->lock   : M [RW_WRITER]
1221772Sjl139090  *  -. uinst_t->u_lock : A
1231772Sjl139090  *  -. uinst_t->l_lock : M
1241772Sjl139090  *  -. uinst_t->c_lock : A
1251772Sjl139090  */
1261772Sjl139090 void
oplmsu_link_lpath(lpath_t * add_lpath)1271772Sjl139090 oplmsu_link_lpath(lpath_t *add_lpath)
1281772Sjl139090 {
1291772Sjl139090 
1301772Sjl139090 	ASSERT(add_lpath != NULL);
1311772Sjl139090 	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
1321772Sjl139090 
1331772Sjl139090 	if (oplmsu_uinst->first_lpath == NULL) {
1341772Sjl139090 		oplmsu_uinst->first_lpath = add_lpath;
1351772Sjl139090 		add_lpath->l_prev = NULL;
1361772Sjl139090 	} else {
1371772Sjl139090 		lpath_t	*last_lpath;
1381772Sjl139090 
1391772Sjl139090 		last_lpath = oplmsu_uinst->last_lpath;
1401772Sjl139090 		last_lpath->l_next = add_lpath;
1411772Sjl139090 		add_lpath->l_prev = last_lpath;
1421772Sjl139090 	}
1431772Sjl139090 
1441772Sjl139090 	oplmsu_uinst->last_lpath = add_lpath;
1451772Sjl139090 	add_lpath->l_next = NULL;
1461772Sjl139090 }
1471772Sjl139090 
1481772Sjl139090 /*
1491772Sjl139090  * Unlink lower_path_table structure
1501772Sjl139090  *
1511772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
1521772Sjl139090  *  -. uinst_t->lock   : M [RW_WRITER]
1531772Sjl139090  *  -. uinst_t->u_lock : P
1541772Sjl139090  *  -. uinst_t->l_lock : P
1551772Sjl139090  *  -. uinst_t->c_lock : P
1561772Sjl139090  */
1571772Sjl139090 void
oplmsu_unlink_lpath(lpath_t * del_lpath)1581772Sjl139090 oplmsu_unlink_lpath(lpath_t *del_lpath)
1591772Sjl139090 {
1601772Sjl139090 	lpath_t **first, **last;
1611772Sjl139090 
1621772Sjl139090 	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
1631772Sjl139090 
1641772Sjl139090 	first = &oplmsu_uinst->first_lpath;
1651772Sjl139090 	last = &oplmsu_uinst->last_lpath;
1661772Sjl139090 
1671772Sjl139090 	if ((*first != del_lpath) && (*last != del_lpath)) {
1681772Sjl139090 		del_lpath->l_prev->l_next = del_lpath->l_next;
1691772Sjl139090 		del_lpath->l_next->l_prev = del_lpath->l_prev;
1701772Sjl139090 	} else {
1711772Sjl139090 		if (*first == del_lpath) {
1721772Sjl139090 			*first = (*first)->l_next;
1731772Sjl139090 			if (*first) {
1741772Sjl139090 				(*first)->l_prev = NULL;
1751772Sjl139090 			}
1761772Sjl139090 		}
1771772Sjl139090 
1781772Sjl139090 		if (*last == del_lpath) {
1791772Sjl139090 			*last = (*last)->l_prev;
1801772Sjl139090 			if (*last) {
1811772Sjl139090 				(*last)->l_next = NULL;
1821772Sjl139090 			}
1831772Sjl139090 		}
1841772Sjl139090 	}
1851772Sjl139090 
1861772Sjl139090 	del_lpath->l_next = NULL;
1871772Sjl139090 	del_lpath->l_prev = NULL;
1881772Sjl139090 }
1891772Sjl139090 
1901772Sjl139090 /*
1911772Sjl139090  * Link msgb structure of high priority
1921772Sjl139090  *
1931772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
1941772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
1951772Sjl139090  *  -. uinst_t->u_lock : A
1961772Sjl139090  *  -. uinst_t->l_lock : A [It depends on caller]
1971772Sjl139090  *  -. uinst_t->c_lock : A [It depends on caller]
1981772Sjl139090  */
1991772Sjl139090 void
oplmsu_link_high_primsg(mblk_t ** first,mblk_t ** last,mblk_t * add_msg)2001772Sjl139090 oplmsu_link_high_primsg(mblk_t **first, mblk_t **last, mblk_t *add_msg)
2011772Sjl139090 {
2021772Sjl139090 
2031772Sjl139090 	ASSERT(add_msg != NULL);
2041772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
2051772Sjl139090 
2061772Sjl139090 	if (*first == NULL) {
2071772Sjl139090 		*first = add_msg;
2081772Sjl139090 		add_msg->b_prev = NULL;
2091772Sjl139090 	} else {
2101772Sjl139090 		(*last)->b_next = add_msg;
2111772Sjl139090 		add_msg->b_prev = *last;
2121772Sjl139090 	}
2131772Sjl139090 
2141772Sjl139090 	*last = add_msg;
2151772Sjl139090 	add_msg->b_next = NULL;
2161772Sjl139090 }
2171772Sjl139090 
2181772Sjl139090 /*
2191772Sjl139090  * Check whether lower path is usable by lower path info table address
2201772Sjl139090  *
2211772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
2221772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
2231772Sjl139090  *  -. uinst_t->u_lock : A
2241772Sjl139090  *  -. uinst_t->l_lock : M
2251772Sjl139090  *  -. uinst_t->c_lock : P
2261772Sjl139090  */
2271772Sjl139090 int
oplmsu_check_lpath_usable(void)2281772Sjl139090 oplmsu_check_lpath_usable(void)
2291772Sjl139090 {
2301772Sjl139090 	lpath_t	*lpath;
2311772Sjl139090 	int	rval = SUCCESS;
2321772Sjl139090 
2331772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
2341772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
2351772Sjl139090 
2361772Sjl139090 	lpath = oplmsu_uinst->first_lpath;
2371772Sjl139090 	while (lpath) {
2381772Sjl139090 		if ((lpath->hndl_uqueue != NULL) || (lpath->hndl_mp != NULL)) {
2391772Sjl139090 			rval = BUSY;
2401772Sjl139090 			break;
2411772Sjl139090 		}
2421772Sjl139090 		lpath = lpath->l_next;
2431772Sjl139090 	}
2441772Sjl139090 	return (rval);
2451772Sjl139090 }
2461772Sjl139090 
2471772Sjl139090 /*
2481772Sjl139090  * Search upath_t by path number
2491772Sjl139090  *
2501772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
2511772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
2521772Sjl139090  *  -. uinst_t->u_lock : M
2531772Sjl139090  *  -. uinst_t->l_lock : A
2541772Sjl139090  *  -. uinst_t->c_lock : P
2551772Sjl139090  */
2561772Sjl139090 upath_t	*
oplmsu_search_upath_info(int path_no)2571772Sjl139090 oplmsu_search_upath_info(int path_no)
2581772Sjl139090 {
2591772Sjl139090 	upath_t	*upath;
2601772Sjl139090 
2611772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
2621772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
2631772Sjl139090 
2641772Sjl139090 	upath = oplmsu_uinst->first_upath;
2651772Sjl139090 	while (upath) {
2661772Sjl139090 		if (upath->path_no == path_no) {
2671772Sjl139090 			break;
2681772Sjl139090 		}
2691772Sjl139090 		upath = upath->u_next;
2701772Sjl139090 	}
2711772Sjl139090 	return (upath);
2721772Sjl139090 }
2731772Sjl139090 
2741772Sjl139090 /*
2751772Sjl139090  * Send M_IOCACK(or M_IOCNAK) message to stream
2761772Sjl139090  *
2771772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
2781772Sjl139090  *  -. uinst_t->lock   : P
2791772Sjl139090  *  -. uinst_t->u_lock : P
2801772Sjl139090  *  -. uinst_t->l_lock : P
2811772Sjl139090  *  -. uinst_t->c_lock : P
2821772Sjl139090  */
2831772Sjl139090 void
oplmsu_iocack(queue_t * q,mblk_t * mp,int errno)2841772Sjl139090 oplmsu_iocack(queue_t *q, mblk_t *mp, int errno)
2851772Sjl139090 {
2861772Sjl139090 	struct iocblk	*iocp = NULL;
2871772Sjl139090 
2881772Sjl139090 	ASSERT(mp != NULL);
2891772Sjl139090 
2901772Sjl139090 	iocp = (struct iocblk *)mp->b_rptr;
2911772Sjl139090 	iocp->ioc_error = errno;
2921772Sjl139090 
2931772Sjl139090 	if (errno) {	/* Error */
2941772Sjl139090 		mp->b_datap->db_type = M_IOCNAK;
2951772Sjl139090 		iocp->ioc_rval = FAILURE;
2961772Sjl139090 
2971772Sjl139090 		OPLMSU_TRACE(q, mp, MSU_TRC_UO);
2981772Sjl139090 		qreply(q, mp);
2991772Sjl139090 	} else {	/* Good */
3001772Sjl139090 		mp->b_datap->db_type = M_IOCACK;
3011772Sjl139090 		iocp->ioc_rval = SUCCESS;
3021772Sjl139090 
3031772Sjl139090 		OPLMSU_TRACE(q, mp, MSU_TRC_UO);
3041772Sjl139090 		qreply(q, mp);
3051772Sjl139090 	}
3061772Sjl139090 }
3071772Sjl139090 
3081772Sjl139090 /*
3091772Sjl139090  * Delete all upath_t
3101772Sjl139090  *
3111772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
3121772Sjl139090  *  -. uinst_t->lock   : M [RW_WRITER]
3131772Sjl139090  *  -. uinst_t->u_lock : M
3141772Sjl139090  *  -. uinst_t->l_lock : A
3151772Sjl139090  *  -. uinst_t->c_lock : A
3161772Sjl139090  */
3171772Sjl139090 void
oplmsu_delete_upath_info(void)3181772Sjl139090 oplmsu_delete_upath_info(void)
3191772Sjl139090 {
3201772Sjl139090 	upath_t	*upath, *next_upath;
3211772Sjl139090 
3221772Sjl139090 	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
3231772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
3241772Sjl139090 
3251772Sjl139090 	upath = oplmsu_uinst->first_upath;
3261772Sjl139090 	oplmsu_uinst->first_upath = NULL;
3271772Sjl139090 	oplmsu_uinst->last_upath = NULL;
3281772Sjl139090 
3291772Sjl139090 	while (upath) {
3301772Sjl139090 		next_upath = upath->u_next;
3311772Sjl139090 		kmem_free(upath, sizeof (upath_t));
3321772Sjl139090 		upath = next_upath;
3331772Sjl139090 	}
3341772Sjl139090 }
3351772Sjl139090 
3361772Sjl139090 /*
3371772Sjl139090  * Set queue and ioctl to lpath_t
3381772Sjl139090  *
3391772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
3401772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
3411772Sjl139090  *  -. uinst_t->u_lock : A
3421772Sjl139090  *  -. uinst_t->l_lock : M
3431772Sjl139090  *  -. uinst_t->c_lock : P
3441772Sjl139090  */
3451772Sjl139090 int
oplmsu_set_ioctl_path(lpath_t * lpath,queue_t * hndl_queue,mblk_t * mp)3461772Sjl139090 oplmsu_set_ioctl_path(lpath_t *lpath, queue_t *hndl_queue, mblk_t *mp)
3471772Sjl139090 {
3481772Sjl139090 	int	rval = SUCCESS;
3491772Sjl139090 
3501772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
3511772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
3521772Sjl139090 
3531772Sjl139090 	if ((lpath->hndl_uqueue == NULL) && (lpath->hndl_mp == NULL) &&
3541772Sjl139090 	    (lpath->sw_flag == 0)) {
3551772Sjl139090 		if ((lpath->status == MSU_EXT_NOTUSED) ||
3561772Sjl139090 		    (lpath->status == MSU_EXT_ACTIVE_CANDIDATE) ||
3571772Sjl139090 		    (lpath->status == MSU_SETID_NU)) {
3581772Sjl139090 			if (hndl_queue == NULL) {
3591772Sjl139090 				lpath->hndl_uqueue = hndl_queue;
3601772Sjl139090 			} else {
3611772Sjl139090 				lpath->hndl_uqueue = WR(hndl_queue);
3621772Sjl139090 			}
3631772Sjl139090 			lpath->hndl_mp = mp;
3641772Sjl139090 		} else {
3651772Sjl139090 			rval = BUSY;
3661772Sjl139090 		}
3671772Sjl139090 	} else {
3681772Sjl139090 		rval = BUSY;
3691772Sjl139090 	}
3701772Sjl139090 	return (rval);
3711772Sjl139090 }
3721772Sjl139090 
3731772Sjl139090 /*
3741772Sjl139090  * Clear queue and ioctl to lpath_t
3751772Sjl139090  *
3761772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
3771772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
3781772Sjl139090  *  -. uinst_t->u_lock : A
3791772Sjl139090  *  -. uinst_t->l_lock : M
3801772Sjl139090  *  -. uinst_t->c_lock : P
3811772Sjl139090  */
3821772Sjl139090 void
oplmsu_clear_ioctl_path(lpath_t * lpath)3831772Sjl139090 oplmsu_clear_ioctl_path(lpath_t *lpath)
3841772Sjl139090 {
3851772Sjl139090 
3861772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
3871772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
3881772Sjl139090 
3891772Sjl139090 	lpath->hndl_uqueue = NULL;
3901772Sjl139090 	lpath->hndl_mp = NULL;
3911772Sjl139090 }
3921772Sjl139090 
3931772Sjl139090 /*
3941772Sjl139090  * Get instanse status from status of upath_t
3951772Sjl139090  *
3961772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
3971772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
3981772Sjl139090  *  -. uinst_t->u_lock : M
3991772Sjl139090  *  -. uinst_t->l_lock : A
4001772Sjl139090  *  -. uinst_t->c_lock : P
4011772Sjl139090  */
4021772Sjl139090 int
oplmsu_get_inst_status(void)4031772Sjl139090 oplmsu_get_inst_status(void)
4041772Sjl139090 {
4051772Sjl139090 	upath_t	*upath;
4061772Sjl139090 	int	sts, pre_sts = INST_STAT_UNCONFIGURED;
4071772Sjl139090 
4081772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
4091772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
4101772Sjl139090 
4111772Sjl139090 	upath = oplmsu_uinst->first_upath;
4121772Sjl139090 	while (upath) {
4131772Sjl139090 		if (((upath->status == MSU_PSTAT_ACTIVE) &&
4141772Sjl139090 		    (upath->traditional_status == MSU_ACTIVE)) ||
4151772Sjl139090 		    ((upath->status == MSU_PSTAT_STANDBY) &&
4161772Sjl139090 		    (upath->traditional_status == MSU_STANDBY))) {
4171772Sjl139090 			sts = INST_STAT_ONLINE;
4181772Sjl139090 		} else if (((upath->status == MSU_PSTAT_STOP) &&
4191772Sjl139090 		    (upath->traditional_status == MSU_STOP)) ||
4201772Sjl139090 		    ((upath->status == MSU_PSTAT_FAIL) &&
4211772Sjl139090 		    (upath->traditional_status == MSU_FAIL))) {
4221772Sjl139090 			sts = INST_STAT_OFFLINE;
4231772Sjl139090 		} else if (((upath->status == MSU_PSTAT_DISCON) &&
4241772Sjl139090 		    (upath->traditional_status == MSU_DISCON)) ||
4251772Sjl139090 		    ((upath->status == MSU_PSTAT_EMPTY) &&
4261772Sjl139090 		    (upath->traditional_status == MSU_EMPTY))) {
4271772Sjl139090 			sts = INST_STAT_UNCONFIGURED;
4281772Sjl139090 		} else {
4291772Sjl139090 			sts = INST_STAT_BUSY;
4301772Sjl139090 		}
4311772Sjl139090 
4321772Sjl139090 		if (pre_sts > sts) {
4331772Sjl139090 			pre_sts = sts;
4341772Sjl139090 		}
4351772Sjl139090 		upath = upath->u_next;
4361772Sjl139090 	}
4371772Sjl139090 	return (pre_sts);
4381772Sjl139090 }
4391772Sjl139090 
4401772Sjl139090 /*
4411772Sjl139090  * Search path of "online:standby" status
4421772Sjl139090  *
4431772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
4441772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
4451772Sjl139090  *  -. uinst_t->u_lock : M
4461772Sjl139090  *  -. uinst_t->l_lock : A
4471772Sjl139090  *  -. uinst_t->c_lock : P
4481772Sjl139090  */
4491772Sjl139090 upath_t	*
oplmsu_search_standby(void)4501772Sjl139090 oplmsu_search_standby(void)
4511772Sjl139090 {
4521772Sjl139090 	upath_t	*upath, *altn_upath = NULL;
4531772Sjl139090 	int	max_pathnum = UNDEFINED;
4541772Sjl139090 
4551772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
4561772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
4571772Sjl139090 
4581772Sjl139090 	upath = oplmsu_uinst->first_upath;
4591772Sjl139090 	while (upath) {
4601772Sjl139090 		if ((upath->status == MSU_PSTAT_STANDBY) &&
4611772Sjl139090 		    (upath->traditional_status == MSU_STANDBY) &&
4621772Sjl139090 		    (upath->lpath != NULL)) {
4631772Sjl139090 			if ((max_pathnum == UNDEFINED) ||
4641772Sjl139090 			    (max_pathnum > upath->path_no)) {
4651772Sjl139090 				max_pathnum = upath->path_no;
4661772Sjl139090 				altn_upath = upath;
4671772Sjl139090 			}
4681772Sjl139090 		}
4691772Sjl139090 		upath = upath->u_next;
4701772Sjl139090 	}
4711772Sjl139090 	return (altn_upath);
4721772Sjl139090 }
4731772Sjl139090 
4741772Sjl139090 /*
4751772Sjl139090  * Search path of "offline:stop" status, and minimum path number
4761772Sjl139090  *
4771772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
4781772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
4791772Sjl139090  *  -. uinst_t->u_lock : M
4801772Sjl139090  *  -. uinst_t->l_lock : P
4811772Sjl139090  *  -. uinst_t->c_lock : P
4821772Sjl139090  */
4831772Sjl139090 void
oplmsu_search_min_stop_path(void)4841772Sjl139090 oplmsu_search_min_stop_path(void)
4851772Sjl139090 {
4861772Sjl139090 	upath_t	*upath, *min_upath;
4871772Sjl139090 	lpath_t	*lpath;
4881772Sjl139090 	int	min_no = UNDEFINED;
4891772Sjl139090 	int	active_flag = 0;
4901772Sjl139090 
4911772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
4921772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
4931772Sjl139090 
4941772Sjl139090 	upath = oplmsu_uinst->first_upath;
4951772Sjl139090 	while (upath) {
4961772Sjl139090 		if ((upath->status == MSU_PSTAT_ACTIVE) &&
4971772Sjl139090 		    (upath->traditional_status == MSU_ACTIVE)) {
4981772Sjl139090 			active_flag = 1;
4991772Sjl139090 			break;
5001772Sjl139090 		} else if ((upath->status == MSU_PSTAT_STOP) &&
5011772Sjl139090 		    (upath->traditional_status == MSU_STOP)) {
5021772Sjl139090 			if (upath->lpath != NULL) {
5031772Sjl139090 				if ((min_no == UNDEFINED) ||
5041772Sjl139090 				    (upath->path_no < min_no)) {
5051772Sjl139090 					lpath = upath->lpath;
5061772Sjl139090 					mutex_enter(&oplmsu_uinst->l_lock);
5071772Sjl139090 					if (lpath->status == MSU_EXT_NOTUSED) {
5081772Sjl139090 						min_upath = upath;
5091772Sjl139090 						min_no = upath->path_no;
5101772Sjl139090 					}
5111772Sjl139090 					mutex_exit(&oplmsu_uinst->l_lock);
5121772Sjl139090 				}
5131772Sjl139090 			}
5141772Sjl139090 		}
5151772Sjl139090 		upath = upath->u_next;
5161772Sjl139090 	}
5171772Sjl139090 
5181772Sjl139090 	if (active_flag == 0) {
5191772Sjl139090 		lpath = min_upath->lpath;
5201772Sjl139090 		mutex_enter(&oplmsu_uinst->l_lock);
5211772Sjl139090 		lpath->src_upath = NULL;
5221772Sjl139090 		lpath->status = MSU_EXT_ACTIVE_CANDIDATE;
5231772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
5241772Sjl139090 	}
5251772Sjl139090 }
5261772Sjl139090 
5271772Sjl139090 /*
5281772Sjl139090  * Get the total number of serial paths
5291772Sjl139090  *
5301772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
5311772Sjl139090  *  -. uinst_t->lock   : M [RW_WRITER]
5321772Sjl139090  *  -. uinst_t->u_lock : M
5331772Sjl139090  *  -. uinst_t->l_lock : A
5341772Sjl139090  *  -. uinst_t->c_lock : A
5351772Sjl139090  */
5361772Sjl139090 int
oplmsu_get_pathnum(void)5371772Sjl139090 oplmsu_get_pathnum(void)
5381772Sjl139090 {
5391772Sjl139090 	upath_t	*upath;
5401772Sjl139090 	int	total_num = 0;
5411772Sjl139090 
5421772Sjl139090 	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
5431772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
5441772Sjl139090 
5451772Sjl139090 	if (oplmsu_uinst->first_upath != NULL) {
5461772Sjl139090 		upath = oplmsu_uinst->first_upath;
5471772Sjl139090 		while (upath) {
5481772Sjl139090 			total_num++;
5491772Sjl139090 			upath = upath->u_next;
5501772Sjl139090 		}
5511772Sjl139090 	}
5521772Sjl139090 	return (total_num);
5531772Sjl139090 }
5541772Sjl139090 
5551772Sjl139090 /*
5561772Sjl139090  * Put XOFF/ XON message on write queue
5571772Sjl139090  *
5581772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
5591772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
5601772Sjl139090  *  -. uinst_t->u_lock : A
5611772Sjl139090  *  -. uinst_t->l_lock : A
5621772Sjl139090  *  -. uinst_t->c_lock : A
5631772Sjl139090  */
5641772Sjl139090 int
oplmsu_cmn_put_xoffxon(queue_t * queue,int data)5651772Sjl139090 oplmsu_cmn_put_xoffxon(queue_t *queue, int data)
5661772Sjl139090 {
5671772Sjl139090 	mblk_t	*mp;
5681772Sjl139090 	int	rval = SUCCESS;
5691772Sjl139090 
5701772Sjl139090 	/* Send M_START */
5711772Sjl139090 	if ((mp = allocb(0, BPRI_LO)) != NULL) {
5721772Sjl139090 		mp->b_datap->db_type = M_START;
573*11311SSurya.Prakki@Sun.COM 		(void) putq(queue, mp);
5741772Sjl139090 
5751772Sjl139090 		/* Send M_DATA(XOFF, XON) */
5761772Sjl139090 		if ((mp = allocb(sizeof (int), BPRI_LO)) != NULL) {
5771772Sjl139090 			*(uint_t *)mp->b_rptr = data;
5781772Sjl139090 			mp->b_wptr = mp->b_rptr + sizeof (int);
579*11311SSurya.Prakki@Sun.COM 			(void) putq(queue, mp);
5801772Sjl139090 		} else {
5811772Sjl139090 			rval = FAILURE;
5821772Sjl139090 		}
5831772Sjl139090 	} else {
5841772Sjl139090 		rval = FAILURE;
5851772Sjl139090 	}
5861772Sjl139090 	return (rval);
5871772Sjl139090 }
5881772Sjl139090 
5891772Sjl139090 /*
5901772Sjl139090  * Put XOFF message on write queue for all standby paths
5911772Sjl139090  *
5921772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
5931772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
5941772Sjl139090  *  -. uinst_t->u_lock : M
5951772Sjl139090  *  -. uinst_t->l_lock : M
5961772Sjl139090  *  -. uinst_t->c_lock : P
5971772Sjl139090  */
5981772Sjl139090 void
oplmsu_cmn_putxoff_standby(void)5991772Sjl139090 oplmsu_cmn_putxoff_standby(void)
6001772Sjl139090 {
6011772Sjl139090 	upath_t	*upath;
6021772Sjl139090 	lpath_t	*lpath;
6031772Sjl139090 
6041772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
6051772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
6061772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->l_lock));
6071772Sjl139090 
6081772Sjl139090 	upath = oplmsu_uinst->first_upath;
6091772Sjl139090 	while (upath) {
6101772Sjl139090 		lpath = upath->lpath;
6111772Sjl139090 		if ((upath->status != MSU_PSTAT_STANDBY) ||
6121772Sjl139090 		    (lpath == NULL)) {
6131772Sjl139090 			upath = upath->u_next;
6141772Sjl139090 			continue;
6151772Sjl139090 		}
6161772Sjl139090 
6171772Sjl139090 		(void) oplmsu_cmn_put_xoffxon(
6181772Sjl139090 		    WR(lpath->lower_queue), MSU_XOFF_4);
6191772Sjl139090 		upath = upath->u_next;
6201772Sjl139090 	}
6211772Sjl139090 }
6221772Sjl139090 
6231772Sjl139090 /*
6241772Sjl139090  * Set M_FLUSH message
6251772Sjl139090  *
6261772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
6271772Sjl139090  *  -. uinst_t->lock   : A [RW_READER or RW_WRITER]
6281772Sjl139090  *  -. uinst_t->u_lock : A
6291772Sjl139090  *  -. uinst_t->l_lock : A
6301772Sjl139090  *  -. uinst_t->c_lock : A
6311772Sjl139090  */
6321772Sjl139090 void
oplmsu_cmn_set_mflush(mblk_t * mp)6331772Sjl139090 oplmsu_cmn_set_mflush(mblk_t *mp)
6341772Sjl139090 {
6351772Sjl139090 
6361772Sjl139090 	mp->b_datap->db_type = M_FLUSH;
6371772Sjl139090 	*mp->b_rptr = FLUSHW;
6381772Sjl139090 	mp->b_wptr = mp->b_rptr + sizeof (char);
6391772Sjl139090 }
6401772Sjl139090 
6411772Sjl139090 /*
6421772Sjl139090  * Set status informations of upath_t
6431772Sjl139090  *
6441772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
6451772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
6461772Sjl139090  *  -. uinst_t->u_lock : M
6471772Sjl139090  *  -. uinst_t->l_lock : A
6481772Sjl139090  *  -. uinst_t->c_lock : A
6491772Sjl139090  */
6501772Sjl139090 void
oplmsu_cmn_set_upath_sts(upath_t * upath,int sts,int prev_sts,ulong_t trad_sts)6511772Sjl139090 oplmsu_cmn_set_upath_sts(upath_t *upath, int sts, int prev_sts,
6521772Sjl139090     ulong_t trad_sts)
6531772Sjl139090 {
6541772Sjl139090 
6551772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
6561772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->u_lock));
6571772Sjl139090 
6581772Sjl139090 	upath->status = sts;
6591772Sjl139090 	upath->prev_status = prev_sts;
6601772Sjl139090 	upath->traditional_status = trad_sts;
6611772Sjl139090 }
6621772Sjl139090 
6631772Sjl139090 /*
6641772Sjl139090  * Allocate a message block
6651772Sjl139090  *
6661772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
6671772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
6681772Sjl139090  *  -. uinst_t->u_lock : A
6691772Sjl139090  *  -. uinst_t->l_lock : P
6701772Sjl139090  *  -. uinst_t->c_lock : P
6711772Sjl139090  */
6721772Sjl139090 int
oplmsu_cmn_allocmb(queue_t * q,mblk_t * mp,mblk_t ** nmp,size_t size,int rw_flag)6731772Sjl139090 oplmsu_cmn_allocmb(queue_t *q, mblk_t *mp, mblk_t **nmp, size_t size,
6741772Sjl139090     int rw_flag)
6751772Sjl139090 {
6761772Sjl139090 	int	rval = SUCCESS;
6771772Sjl139090 
6781772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
6791772Sjl139090 
6801772Sjl139090 	if ((*nmp = (mblk_t *)allocb(size, BPRI_LO)) == NULL) {
6811772Sjl139090 		oplmsu_cmn_bufcall(q, mp, size, rw_flag);
6821772Sjl139090 		rval = FAILURE;
6831772Sjl139090 	} else {
6841772Sjl139090 		(*nmp)->b_wptr = (*nmp)->b_rptr + size;
6851772Sjl139090 	}
6861772Sjl139090 	return (rval);
6871772Sjl139090 }
6881772Sjl139090 
6891772Sjl139090 /*
6901772Sjl139090  * Copy a message
6911772Sjl139090  *
6921772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
6931772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
6941772Sjl139090  *  -. uinst_t->u_lock : A
6951772Sjl139090  *  -. uinst_t->l_lock : P
6961772Sjl139090  *  -. uinst_t->c_lock : P
6971772Sjl139090  */
6981772Sjl139090 int
oplmsu_cmn_copymb(queue_t * q,mblk_t * mp,mblk_t ** nmp,mblk_t * cmp,int rw_flag)6991772Sjl139090 oplmsu_cmn_copymb(queue_t *q, mblk_t *mp, mblk_t **nmp, mblk_t *cmp,
7001772Sjl139090     int rw_flag)
7011772Sjl139090 {
7021772Sjl139090 	int	rval = SUCCESS;
7031772Sjl139090 
7041772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
7051772Sjl139090 
7061772Sjl139090 	if ((*nmp = copymsg(cmp)) == NULL) {
7071772Sjl139090 		oplmsu_cmn_bufcall(q, mp, msgsize(cmp), rw_flag);
7081772Sjl139090 		rval = FAILURE;
7091772Sjl139090 	}
7101772Sjl139090 	return (rval);
7111772Sjl139090 }
7121772Sjl139090 
7131772Sjl139090 /*
7141772Sjl139090  * bufcall request
7151772Sjl139090  *
7161772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
7171772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
7181772Sjl139090  *  -. uinst_t->u_lock : A
7191772Sjl139090  *  -. uinst_t->l_lock : P
7201772Sjl139090  *  -. uinst_t->c_lock : P
7211772Sjl139090  */
7221772Sjl139090 void
oplmsu_cmn_bufcall(queue_t * q,mblk_t * mp,size_t size,int rw_flag)7231772Sjl139090 oplmsu_cmn_bufcall(queue_t *q, mblk_t *mp, size_t size, int rw_flag)
7241772Sjl139090 {
7251772Sjl139090 
7261772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
7271772Sjl139090 
7281772Sjl139090 	if (rw_flag == MSU_WRITE_SIDE) {
7291772Sjl139090 		ctrl_t	*ctrl;
7301772Sjl139090 
731*11311SSurya.Prakki@Sun.COM 		(void) putbq(q, mp);
7321772Sjl139090 
7331772Sjl139090 		mutex_enter(&oplmsu_uinst->c_lock);
7341772Sjl139090 		ctrl = (ctrl_t *)q->q_ptr;
7351772Sjl139090 		if (ctrl->wbuf_id != 0) {
7361772Sjl139090 			mutex_exit(&oplmsu_uinst->c_lock);
7371772Sjl139090 			return;
7381772Sjl139090 		}
7391772Sjl139090 
7401772Sjl139090 		ctrl->wbuftbl->q = q;
7411772Sjl139090 		ctrl->wbuftbl->rw_flag = rw_flag;
7421772Sjl139090 		ctrl->wbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb,
7431772Sjl139090 		    (void *)ctrl->wbuftbl);
7441772Sjl139090 
7451772Sjl139090 		if (ctrl->wbuf_id == 0) {
7461772Sjl139090 			if (ctrl->wtout_id != 0) {
7471772Sjl139090 				mutex_exit(&oplmsu_uinst->c_lock);
7481772Sjl139090 				return;
7491772Sjl139090 			}
7501772Sjl139090 
7511772Sjl139090 			ctrl->wtout_id = timeout(oplmsu_cmn_bufcb,
7521772Sjl139090 			    (void *)ctrl->wbuftbl, drv_usectohz(MSU_TM_500MS));
7531772Sjl139090 		}
7541772Sjl139090 		mutex_exit(&oplmsu_uinst->c_lock);
7551772Sjl139090 	} else if (rw_flag == MSU_READ_SIDE) {
7561772Sjl139090 		lpath_t	*lpath;
7571772Sjl139090 		mblk_t	*wrk_msg;
7581772Sjl139090 
7591772Sjl139090 		mutex_enter(&oplmsu_uinst->l_lock);
7601772Sjl139090 		lpath = (lpath_t *)q->q_ptr;
7611772Sjl139090 		if (mp->b_datap->db_type >= QPCTL) {
7621772Sjl139090 			if (lpath->first_lpri_hi == NULL) {
7631772Sjl139090 				lpath->last_lpri_hi = mp;
7641772Sjl139090 				mp->b_next = NULL;
7651772Sjl139090 			} else {
7661772Sjl139090 				wrk_msg = lpath->first_lpri_hi;
7671772Sjl139090 				wrk_msg->b_prev = mp;
7681772Sjl139090 				mp->b_next = wrk_msg;
7691772Sjl139090 			}
7701772Sjl139090 			mp->b_prev = NULL;
7711772Sjl139090 			lpath->first_lpri_hi = mp;
7721772Sjl139090 		} else {
773*11311SSurya.Prakki@Sun.COM 			(void) putbq(q, mp);
7741772Sjl139090 		}
7751772Sjl139090 
7761772Sjl139090 		if (lpath->rbuf_id != 0) {
7771772Sjl139090 			mutex_exit(&oplmsu_uinst->l_lock);
7781772Sjl139090 			return;
7791772Sjl139090 		}
7801772Sjl139090 
7811772Sjl139090 		lpath->rbuftbl->q = q;
7821772Sjl139090 		lpath->rbuftbl->rw_flag = rw_flag;
7831772Sjl139090 		lpath->rbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb,
7841772Sjl139090 		    (void *)lpath->rbuftbl);
7851772Sjl139090 
7861772Sjl139090 		if (lpath->rbuf_id == 0) {
7871772Sjl139090 			if (lpath->rtout_id != 0) {
7881772Sjl139090 				mutex_exit(&oplmsu_uinst->l_lock);
7891772Sjl139090 				return;
7901772Sjl139090 			}
7911772Sjl139090 
7921772Sjl139090 			lpath->rtout_id = timeout(oplmsu_cmn_bufcb,
7931772Sjl139090 			    (void *)lpath->rbuftbl, drv_usectohz(MSU_TM_500MS));
7941772Sjl139090 		}
7951772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
7961772Sjl139090 	}
7971772Sjl139090 }
7981772Sjl139090 
7991772Sjl139090 /*
8001772Sjl139090  * Previous sequence for active path change
8011772Sjl139090  *
8021772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
8031772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
8041772Sjl139090  *  -. uinst_t->u_lock : A
8051772Sjl139090  *  -. uinst_t->l_lock : P
8061772Sjl139090  *  -. uinst_t->c_lock : P
8071772Sjl139090  */
8081772Sjl139090 int
oplmsu_cmn_prechg(queue_t * q,mblk_t * mp,int rw_flag,mblk_t ** term_mp,int * term_ioctl,int * term_stat)8091772Sjl139090 oplmsu_cmn_prechg(queue_t *q, mblk_t *mp, int rw_flag, mblk_t **term_mp,
8101772Sjl139090     int *term_ioctl, int *term_stat)
8111772Sjl139090 {
8121772Sjl139090 
8131772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
8141772Sjl139090 
8151772Sjl139090 	if (oplmsu_uinst->tcsets_p != NULL) {
8161772Sjl139090 		struct iocblk	*iocp;
8171772Sjl139090 
8181772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tcsets_p,
8191772Sjl139090 		    rw_flag) == -1) {
8201772Sjl139090 			return (FAILURE);
8211772Sjl139090 		}
8221772Sjl139090 
8231772Sjl139090 		iocp = (struct iocblk *)(*term_mp)->b_rptr;
8241772Sjl139090 		*term_ioctl = iocp->ioc_cmd;
8251772Sjl139090 		*term_stat = MSU_WTCS_ACK;
8261772Sjl139090 	} else if (oplmsu_uinst->tiocmset_p != NULL) {
8271772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p,
8281772Sjl139090 		    rw_flag) == -1) {
8291772Sjl139090 			return (FAILURE);
8301772Sjl139090 		}
8311772Sjl139090 
8321772Sjl139090 		*term_ioctl = TIOCMSET;
8331772Sjl139090 		*term_stat = MSU_WTMS_ACK;
8341772Sjl139090 	} else if (oplmsu_uinst->tiocspps_p != NULL) {
8351772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p,
8361772Sjl139090 		    rw_flag) == -1) {
8371772Sjl139090 			return (FAILURE);
8381772Sjl139090 		}
8391772Sjl139090 
8401772Sjl139090 		*term_ioctl = TIOCSPPS;
8411772Sjl139090 		*term_stat = MSU_WPPS_ACK;
8421772Sjl139090 	} else if (oplmsu_uinst->tiocswinsz_p != NULL) {
8431772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp,
8441772Sjl139090 		    oplmsu_uinst->tiocswinsz_p, rw_flag) == -1) {
8451772Sjl139090 			return (FAILURE);
8461772Sjl139090 		}
8471772Sjl139090 
8481772Sjl139090 		*term_ioctl = TIOCSWINSZ;
8491772Sjl139090 		*term_stat = MSU_WWSZ_ACK;
8501772Sjl139090 	} else if (oplmsu_uinst->tiocssoftcar_p != NULL) {
8511772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp,
8521772Sjl139090 		    oplmsu_uinst->tiocssoftcar_p, rw_flag) == -1) {
8531772Sjl139090 			return (FAILURE);
8541772Sjl139090 		}
8551772Sjl139090 
8561772Sjl139090 		*term_ioctl = TIOCSSOFTCAR;
8571772Sjl139090 		*term_stat = MSU_WCAR_ACK;
8581772Sjl139090 	} else {
8591772Sjl139090 		*term_stat = MSU_WPTH_CHG;
8601772Sjl139090 		*term_mp = NULL;
8611772Sjl139090 	}
8621772Sjl139090 	return (SUCCESS);
8631772Sjl139090 }
8641772Sjl139090 
8651772Sjl139090 /*
8661772Sjl139090  * Pick up termios to re-set
8671772Sjl139090  *
8681772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
8691772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
8701772Sjl139090  *  -. uinst_t->u_lock : A
8711772Sjl139090  *  -. uinst_t->l_lock : A
8721772Sjl139090  *  -. uinst_t->c_lock : A
8731772Sjl139090  */
8741772Sjl139090 int
oplmsu_stop_prechg(mblk_t ** term_mp,int * term_ioctl,int * term_stat)8751772Sjl139090 oplmsu_stop_prechg(mblk_t **term_mp, int *term_ioctl, int *term_stat)
8761772Sjl139090 {
8771772Sjl139090 
8781772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
8791772Sjl139090 
8801772Sjl139090 	if (oplmsu_uinst->tcsets_p != NULL) {
8811772Sjl139090 		struct iocblk	*iocp;
8821772Sjl139090 
8831772Sjl139090 		if ((*term_mp = copymsg(oplmsu_uinst->tcsets_p)) == NULL) {
8841772Sjl139090 			return (FAILURE);
8851772Sjl139090 		}
8861772Sjl139090 
8871772Sjl139090 		iocp = (struct iocblk *)(*term_mp)->b_rptr;
8881772Sjl139090 		*term_ioctl = iocp->ioc_cmd;
8891772Sjl139090 		*term_stat = MSU_WTCS_ACK;
8901772Sjl139090 	} else if (oplmsu_uinst->tiocmset_p != NULL) {
8911772Sjl139090 		if ((*term_mp = copymsg(oplmsu_uinst->tiocmset_p)) == NULL) {
8921772Sjl139090 			return (FAILURE);
8931772Sjl139090 		}
8941772Sjl139090 
8951772Sjl139090 		*term_ioctl = TIOCMSET;
8961772Sjl139090 		*term_stat = MSU_WTMS_ACK;
8971772Sjl139090 	} else if (oplmsu_uinst->tiocspps_p != NULL) {
8981772Sjl139090 		if ((*term_mp = copymsg(oplmsu_uinst->tiocspps_p)) == NULL) {
8991772Sjl139090 			return (FAILURE);
9001772Sjl139090 		}
9011772Sjl139090 
9021772Sjl139090 		*term_ioctl = TIOCSPPS;
9031772Sjl139090 		*term_stat = MSU_WPPS_ACK;
9041772Sjl139090 	} else if (oplmsu_uinst->tiocswinsz_p != NULL) {
9051772Sjl139090 		if ((*term_mp = copymsg(oplmsu_uinst->tiocswinsz_p)) == NULL) {
9061772Sjl139090 			return (FAILURE);
9071772Sjl139090 		}
9081772Sjl139090 
9091772Sjl139090 		*term_ioctl = TIOCSWINSZ;
9101772Sjl139090 		*term_stat = MSU_WWSZ_ACK;
9111772Sjl139090 	} else if (oplmsu_uinst->tiocssoftcar_p != NULL) {
9121772Sjl139090 		if ((*term_mp = copymsg(oplmsu_uinst->tiocssoftcar_p))
9131772Sjl139090 		    == NULL) {
9141772Sjl139090 			return (FAILURE);
9151772Sjl139090 		}
9161772Sjl139090 
9171772Sjl139090 		*term_ioctl = TIOCSSOFTCAR;
9181772Sjl139090 		*term_stat = MSU_WCAR_ACK;
9191772Sjl139090 	} else {
9201772Sjl139090 		*term_stat = MSU_WPTH_CHG;
9211772Sjl139090 		*term_mp = NULL;
9221772Sjl139090 	}
9231772Sjl139090 	return (SUCCESS);
9241772Sjl139090 }
9251772Sjl139090 
9261772Sjl139090 /*
9271772Sjl139090  * Previous sequence for active path change termio
9281772Sjl139090  *
9291772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
9301772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
9311772Sjl139090  *  -. uinst_t->u_lock : A
9321772Sjl139090  *  -. uinst_t->l_lock : P
9331772Sjl139090  *  -. uinst_t->c_lock : P
9341772Sjl139090  */
9351772Sjl139090 int
oplmsu_cmn_prechg_termio(queue_t * q,mblk_t * mp,int rw_flag,int prev_flag,mblk_t ** term_mp,int * term_stat)9361772Sjl139090 oplmsu_cmn_prechg_termio(queue_t *q, mblk_t *mp, int rw_flag, int prev_flag,
9371772Sjl139090     mblk_t **term_mp, int *term_stat)
9381772Sjl139090 {
9391772Sjl139090 
9401772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
9411772Sjl139090 
9421772Sjl139090 	if ((prev_flag == MSU_TIOS_TCSETS) &&
9431772Sjl139090 	    (oplmsu_uinst->tiocmset_p != NULL)) {
9441772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocmset_p,
9451772Sjl139090 		    rw_flag) == FAILURE) {
9461772Sjl139090 			return (FAILURE);
9471772Sjl139090 		}
9481772Sjl139090 
9491772Sjl139090 		*term_stat = MSU_WTMS_ACK;
9501772Sjl139090 	} else if ((prev_flag <= MSU_TIOS_MSET) &&
9511772Sjl139090 	    (oplmsu_uinst->tiocspps_p != NULL)) {
9521772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp, oplmsu_uinst->tiocspps_p,
9531772Sjl139090 		    rw_flag) == FAILURE) {
9541772Sjl139090 			return (FAILURE);
9551772Sjl139090 		}
9561772Sjl139090 
9571772Sjl139090 		*term_stat = MSU_WPPS_ACK;
9581772Sjl139090 	} else if ((prev_flag <= MSU_TIOS_PPS) &&
9591772Sjl139090 	    (oplmsu_uinst->tiocswinsz_p != NULL)) {
9601772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp,
9611772Sjl139090 		    oplmsu_uinst->tiocswinsz_p, rw_flag) == FAILURE) {
9621772Sjl139090 			return (FAILURE);
9631772Sjl139090 		}
9641772Sjl139090 
9651772Sjl139090 		*term_stat = MSU_WWSZ_ACK;
9661772Sjl139090 	} else if ((prev_flag <= MSU_TIOS_WINSZP) &&
9671772Sjl139090 	    (oplmsu_uinst->tiocssoftcar_p != NULL)) {
9681772Sjl139090 		if (oplmsu_cmn_copymb(q, mp, term_mp,
9691772Sjl139090 		    oplmsu_uinst->tiocssoftcar_p, rw_flag) == FAILURE) {
9701772Sjl139090 			return (FAILURE);
9711772Sjl139090 		}
9721772Sjl139090 
9731772Sjl139090 		*term_stat = MSU_WCAR_ACK;
9741772Sjl139090 	} else if (prev_flag <= MSU_TIOS_SOFTCAR) {
9751772Sjl139090 		*term_mp = NULL;
9761772Sjl139090 		*term_stat = MSU_WPTH_CHG;
9771772Sjl139090 	}
9781772Sjl139090 	return (SUCCESS);
9791772Sjl139090 }
9801772Sjl139090 
9811772Sjl139090 /*
9821772Sjl139090  * Pull up messages
9831772Sjl139090  *
9841772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
9851772Sjl139090  *  -. uinst_t->lock   : P
9861772Sjl139090  *  -. uinst_t->u_lock : P
9871772Sjl139090  *  -. uinst_t->l_lock : P
9881772Sjl139090  *  -. uinst_t->c_lock : P
9891772Sjl139090  */
9901772Sjl139090 int
oplmsu_cmn_pullup_msg(queue_t * q,mblk_t * mp)9911772Sjl139090 oplmsu_cmn_pullup_msg(queue_t *q, mblk_t *mp)
9921772Sjl139090 {
9931772Sjl139090 	mblk_t	*nmp = NULL;
9941772Sjl139090 
9951772Sjl139090 	if ((mp != NULL) && (mp->b_cont != NULL) &&
9961772Sjl139090 	    (mp->b_cont->b_cont != NULL)) {
9971772Sjl139090 		if ((nmp = msgpullup(mp->b_cont, -1)) == NULL) {
9981772Sjl139090 			oplmsu_iocack(q, mp, ENOSR);
9991772Sjl139090 			return (FAILURE);
10001772Sjl139090 		} else {
10011772Sjl139090 			freemsg(mp->b_cont);
10021772Sjl139090 			mp->b_cont = nmp;
10031772Sjl139090 		}
10041772Sjl139090 	}
10051772Sjl139090 	return (SUCCESS);
10061772Sjl139090 }
10071772Sjl139090 
10081772Sjl139090 /*
10091772Sjl139090  * Wake up flow control
10101772Sjl139090  *
10111772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
10121772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
10131772Sjl139090  *  -. uinst_t->u_lock : P
10141772Sjl139090  *  -. uinst_t->l_lock : P
10151772Sjl139090  *  -. uinst_t->c_lock : P
10161772Sjl139090  */
10171772Sjl139090 void
oplmsu_cmn_wakeup(queue_t * q)10181772Sjl139090 oplmsu_cmn_wakeup(queue_t *q)
10191772Sjl139090 {
10201772Sjl139090 	ctrl_t	*ctrl;
10211772Sjl139090 
10221772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
10231772Sjl139090 
10241772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
10251772Sjl139090 	ctrl = (ctrl_t *)q->q_ptr;
10261772Sjl139090 	if (ctrl->sleep_flag == CV_SLEEP) {
10271772Sjl139090 		ctrl->sleep_flag = CV_WAKEUP;
10281772Sjl139090 		cv_signal(&ctrl->cvp);
10291772Sjl139090 	}
10301772Sjl139090 	mutex_exit(&oplmsu_uinst->c_lock);
10311772Sjl139090 }
10321772Sjl139090 
10331772Sjl139090 /*
10341772Sjl139090  * bufcall() and timeout() callback entry for read/write stream
10351772Sjl139090  *
10361772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
10371772Sjl139090  *  -. uinst_t->lock   : P
10381772Sjl139090  *  -. uinst_t->u_lock : P
10391772Sjl139090  *  -. uinst_t->l_lock : P
10401772Sjl139090  *  -. uinst_t->c_lock : P
10411772Sjl139090  */
10421772Sjl139090 void
oplmsu_cmn_bufcb(void * arg)10431772Sjl139090 oplmsu_cmn_bufcb(void *arg)
10441772Sjl139090 {
10451772Sjl139090 	struct buf_tbl	*buftbl = arg;
10461772Sjl139090 	lpath_t		*lpath;
10471772Sjl139090 	ctrl_t		*ctrl;
10481772Sjl139090 	queue_t		*q;
10491772Sjl139090 	int		lq_flag = 0;
10501772Sjl139090 
10511772Sjl139090 	rw_enter(&oplmsu_uinst->lock, RW_WRITER);
10521772Sjl139090 	mutex_enter(&oplmsu_uinst->l_lock);
10531772Sjl139090 
10541772Sjl139090 	lpath = oplmsu_uinst->first_lpath;
10551772Sjl139090 	while (lpath) {
10561772Sjl139090 		if ((buftbl == lpath->rbuftbl) &&
10571772Sjl139090 		    (buftbl->rw_flag == MSU_READ_SIDE)) {
10581772Sjl139090 			if ((lpath->rbuf_id == 0) && (lpath->rtout_id == 0)) {
10591772Sjl139090 				mutex_exit(&oplmsu_uinst->l_lock);
10601772Sjl139090 				rw_exit(&oplmsu_uinst->lock);
10611772Sjl139090 			} else {
10621772Sjl139090 				q = lpath->rbuftbl->q;
10631772Sjl139090 				lpath->rbuftbl->q = NULL;
10641772Sjl139090 				lpath->rbuftbl->rw_flag = UNDEFINED;
10651772Sjl139090 
10661772Sjl139090 				if (lpath->rbuf_id) {
10671772Sjl139090 					lpath->rbuf_id = 0;
10681772Sjl139090 				} else {
10691772Sjl139090 					lpath->rtout_id = 0;
10701772Sjl139090 				}
10711772Sjl139090 				mutex_exit(&oplmsu_uinst->l_lock);
10721772Sjl139090 
10731772Sjl139090 				if (oplmsu_queue_flag == 1) {
10741772Sjl139090 					lq_flag = 1;
10751772Sjl139090 					oplmsu_queue_flag = 0;
10761772Sjl139090 				}
10771772Sjl139090 
10781772Sjl139090 				rw_exit(&oplmsu_uinst->lock);
10791772Sjl139090 				oplmsu_rcmn_high_qenable(q);
10801772Sjl139090 
10811772Sjl139090 				if (lq_flag == 1) {
10821772Sjl139090 					rw_enter(&oplmsu_uinst->lock,
10831772Sjl139090 					    RW_WRITER);
10841772Sjl139090 					oplmsu_queue_flag = 1;
10851772Sjl139090 					rw_exit(&oplmsu_uinst->lock);
10861772Sjl139090 				}
10871772Sjl139090 			}
10881772Sjl139090 			return;
10891772Sjl139090 		}
10901772Sjl139090 		lpath = lpath->l_next;
10911772Sjl139090 	}
10921772Sjl139090 	mutex_exit(&oplmsu_uinst->l_lock);
10931772Sjl139090 
10941772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
10951772Sjl139090 	if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) {
10961772Sjl139090 		if ((buftbl == ctrl->wbuftbl) &&
10971772Sjl139090 		    (buftbl->rw_flag == MSU_WRITE_SIDE)) {
10981772Sjl139090 			oplmsu_wbufcb_posthndl(ctrl);
10991772Sjl139090 			mutex_exit(&oplmsu_uinst->c_lock);
11001772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
11011772Sjl139090 			return;
11021772Sjl139090 		}
11031772Sjl139090 	}
11041772Sjl139090 
11051772Sjl139090 	if ((ctrl = oplmsu_uinst->meta_ctrl) != NULL) {
11061772Sjl139090 		if ((buftbl == ctrl->wbuftbl) &&
11071772Sjl139090 		    (buftbl->rw_flag == MSU_WRITE_SIDE)) {
11081772Sjl139090 			oplmsu_wbufcb_posthndl(ctrl);
11091772Sjl139090 			mutex_exit(&oplmsu_uinst->c_lock);
11101772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
11111772Sjl139090 			return;
11121772Sjl139090 		}
11131772Sjl139090 	}
11141772Sjl139090 	mutex_exit(&oplmsu_uinst->c_lock);
11151772Sjl139090 	rw_exit(&oplmsu_uinst->lock);
11161772Sjl139090 }
11171772Sjl139090 
11181772Sjl139090 /*
11191772Sjl139090  * bufcall() or timeout() callback post handling for write stream
11201772Sjl139090  *
11211772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
11221772Sjl139090  *  -. uinst_t->lock   : M [RW_WRITER]
11231772Sjl139090  *  -. uinst_t->u_lock : P
11241772Sjl139090  *  -. uinst_t->l_lock : P
11251772Sjl139090  *  -. uinst_t->c_lock : M
11261772Sjl139090  */
11271772Sjl139090 void
oplmsu_wbufcb_posthndl(ctrl_t * ctrl)11281772Sjl139090 oplmsu_wbufcb_posthndl(ctrl_t *ctrl)
11291772Sjl139090 {
11301772Sjl139090 	queue_t	*q;
11311772Sjl139090 	int	lq_flag = 0;
11321772Sjl139090 
11331772Sjl139090 	ASSERT(RW_WRITE_HELD(&oplmsu_uinst->lock));
11341772Sjl139090 	ASSERT(MUTEX_HELD(&oplmsu_uinst->c_lock));
11351772Sjl139090 
11361772Sjl139090 	if ((ctrl->wbuf_id == 0) && (ctrl->wtout_id == 0)) {
11371772Sjl139090 		return;
11381772Sjl139090 	}
11391772Sjl139090 
11401772Sjl139090 	q = ctrl->wbuftbl->q;
11411772Sjl139090 	ctrl->wbuftbl->q = NULL;
11421772Sjl139090 	ctrl->wbuftbl->rw_flag = UNDEFINED;
11431772Sjl139090 	if (ctrl->wbuf_id) {
11441772Sjl139090 		ctrl->wbuf_id = 0;
11451772Sjl139090 	} else {
11461772Sjl139090 		ctrl->wtout_id = 0;
11471772Sjl139090 	}
11481772Sjl139090 
11491772Sjl139090 	if (oplmsu_queue_flag == 1) {
11501772Sjl139090 		lq_flag = 1;
11511772Sjl139090 		oplmsu_queue_flag = 0;
11521772Sjl139090 	}
11531772Sjl139090 
11541772Sjl139090 	mutex_exit(&oplmsu_uinst->c_lock);
11551772Sjl139090 	oplmsu_wcmn_high_qenable(q, RW_WRITER);
11561772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
11571772Sjl139090 
11581772Sjl139090 	if (lq_flag == 1) {
11591772Sjl139090 		oplmsu_queue_flag = 1;
11601772Sjl139090 	}
11611772Sjl139090 }
11621772Sjl139090 
11631772Sjl139090 /*
11641772Sjl139090  *	COMMON FUNCTIONS FOR WRITE STREAM
11651772Sjl139090  */
11661772Sjl139090 
11671772Sjl139090 /*
11681772Sjl139090  * Check control node and driver privilege
11691772Sjl139090  *
11701772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
11711772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
11721772Sjl139090  *  -. uinst_t->u_lock : A
11731772Sjl139090  *  -. uinst_t->l_lock : A
11741772Sjl139090  *  -. uinst_t->c_lock : P
11751772Sjl139090  */
11761772Sjl139090 int
oplmsu_wcmn_chknode(queue_t * q,int node,mblk_t * mp)11771772Sjl139090 oplmsu_wcmn_chknode(queue_t *q, int node, mblk_t *mp)
11781772Sjl139090 {
11791772Sjl139090 	struct iocblk	*iocp;
11801772Sjl139090 
11811772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
11821772Sjl139090 
11831772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
11841772Sjl139090 	if (((ctrl_t *)q->q_ptr)->node_type != node) {
11851772Sjl139090 		mutex_exit(&oplmsu_uinst->c_lock);
11861772Sjl139090 		cmn_err(CE_WARN, "oplmsu: chk-node: ctrl node type = %d", node);
11871772Sjl139090 		return (EINVAL);
11881772Sjl139090 	}
11891772Sjl139090 	mutex_exit(&oplmsu_uinst->c_lock);
11901772Sjl139090 
11911772Sjl139090 	/* Check super-user by oplmsu.conf */
11921772Sjl139090 	if (oplmsu_check_su != 0) {
11931772Sjl139090 		iocp = (struct iocblk *)mp->b_rptr;
11941772Sjl139090 		if (drv_priv(iocp->ioc_cr) != 0) {
11951772Sjl139090 			cmn_err(CE_WARN, "oplmsu: chk-node: Permission denied");
11961772Sjl139090 			return (EPERM);
11971772Sjl139090 		}
11981772Sjl139090 	}
11991772Sjl139090 	return (SUCCESS);
12001772Sjl139090 }
12011772Sjl139090 
12021772Sjl139090 /*
12031772Sjl139090  * Flush handle for write side stream
12041772Sjl139090  *
12051772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
12061772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
12071772Sjl139090  *  -. uinst_t->u_lock : P
12081772Sjl139090  *  -. uinst_t->l_lock : P
12091772Sjl139090  *  -. uinst_t->c_lock : P
12101772Sjl139090  */
12111772Sjl139090 void
oplmsu_wcmn_flush_hndl(queue_t * q,mblk_t * mp,krw_t rw)12121772Sjl139090 oplmsu_wcmn_flush_hndl(queue_t *q, mblk_t *mp, krw_t rw)
12131772Sjl139090 {
12141772Sjl139090 	queue_t	*dst_queue = NULL;
12151772Sjl139090 
12161772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
12171772Sjl139090 
12181772Sjl139090 	if (*mp->b_rptr & FLUSHW) {	/* Write side */
12191772Sjl139090 		flushq(q, FLUSHDATA);
12201772Sjl139090 	}
12211772Sjl139090 
12221772Sjl139090 	dst_queue = oplmsu_uinst->lower_queue;
12231772Sjl139090 	if (dst_queue == NULL) {
12241772Sjl139090 		if (*mp->b_rptr & FLUSHR) {
12251772Sjl139090 			flushq(RD(q), FLUSHDATA);
12261772Sjl139090 			*mp->b_rptr &= ~FLUSHW;
12271772Sjl139090 
12281772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
12291772Sjl139090 			OPLMSU_TRACE(q, mp, MSU_TRC_UO);
12301772Sjl139090 			qreply(q, mp);
12311772Sjl139090 			rw_enter(&oplmsu_uinst->lock, rw);
12321772Sjl139090 		} else {
12331772Sjl139090 			freemsg(mp);
12341772Sjl139090 		}
12351772Sjl139090 	} else {
1236*11311SSurya.Prakki@Sun.COM 		(void) putq(WR(dst_queue), mp);
12371772Sjl139090 	}
12381772Sjl139090 }
12391772Sjl139090 
12401772Sjl139090 /*
12411772Sjl139090  * Through message handle for write side stream
12421772Sjl139090  *
12431772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
12441772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
12451772Sjl139090  *  -. uinst_t->u_lock : P
12461772Sjl139090  *  -. uinst_t->l_lock : P
12471772Sjl139090  *  -. uinst_t->c_lock : P
12481772Sjl139090  */
12491772Sjl139090 int
oplmsu_wcmn_through_hndl(queue_t * q,mblk_t * mp,int pri_flag,krw_t rw)12501772Sjl139090 oplmsu_wcmn_through_hndl(queue_t *q, mblk_t *mp, int pri_flag, krw_t rw)
12511772Sjl139090 {
12521772Sjl139090 	queue_t	*usr_queue = NULL, *dst_queue = NULL;
12531772Sjl139090 	ctrl_t	*ctrl;
12541772Sjl139090 
12551772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
12561772Sjl139090 
12571772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
12581772Sjl139090 	if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) {
12591772Sjl139090 		usr_queue = ctrl->queue;
12601772Sjl139090 		mutex_exit(&oplmsu_uinst->c_lock);
12611772Sjl139090 	} else {
12621772Sjl139090 		mutex_exit(&oplmsu_uinst->c_lock);
12631772Sjl139090 		if (mp->b_datap->db_type == M_IOCTL) {
12641772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
12651772Sjl139090 			oplmsu_iocack(q, mp, ENODEV);
12661772Sjl139090 			rw_enter(&oplmsu_uinst->lock, rw);
12671772Sjl139090 		} else {
12681772Sjl139090 			freemsg(mp);
12691772Sjl139090 		}
12701772Sjl139090 		return (SUCCESS);
12711772Sjl139090 	}
12721772Sjl139090 
12731772Sjl139090 	if (oplmsu_uinst->lower_queue != NULL) {
12741772Sjl139090 		dst_queue = WR(oplmsu_uinst->lower_queue);
12751772Sjl139090 	} else {
12761772Sjl139090 		cmn_err(CE_WARN, "!oplmsu: through-lwq: "
12771772Sjl139090 		    "Active path doesn't exist");
12781772Sjl139090 
12791772Sjl139090 		if (mp->b_datap->db_type == M_IOCTL) {
12801772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
12811772Sjl139090 			oplmsu_iocack(q, mp, ENODEV);
12821772Sjl139090 			rw_enter(&oplmsu_uinst->lock, rw);
12831772Sjl139090 		} else {
12841772Sjl139090 			freemsg(mp);
12851772Sjl139090 		}
12861772Sjl139090 		return (SUCCESS);
12871772Sjl139090 	}
12881772Sjl139090 
12891772Sjl139090 	if ((usr_queue == WR(q)) || (usr_queue == RD(q))) {
12901772Sjl139090 		if (pri_flag == MSU_HIGH) {
1291*11311SSurya.Prakki@Sun.COM 			(void) putq(dst_queue, mp);
12921772Sjl139090 		} else {
12931772Sjl139090 			if (canput(dst_queue)) {
1294*11311SSurya.Prakki@Sun.COM 				(void) putq(dst_queue, mp);
12951772Sjl139090 			} else {
12961772Sjl139090 				oplmsu_wcmn_norm_putbq(WR(q), mp, dst_queue);
12971772Sjl139090 				return (FAILURE);
12981772Sjl139090 			}
12991772Sjl139090 		}
13001772Sjl139090 	} else {
13011772Sjl139090 		cmn_err(CE_WARN, "oplmsu: through-lwq: "
13021772Sjl139090 		    "Inappropriate message for this node");
13031772Sjl139090 
13041772Sjl139090 		if (mp->b_datap->db_type == M_IOCTL) {
13051772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
13061772Sjl139090 			oplmsu_iocack(q, mp, ENODEV);
13071772Sjl139090 			rw_enter(&oplmsu_uinst->lock, rw);
13081772Sjl139090 		} else {
13091772Sjl139090 			freemsg(mp);
13101772Sjl139090 		}
13111772Sjl139090 	}
13121772Sjl139090 	return (SUCCESS);
13131772Sjl139090 }
13141772Sjl139090 
13151772Sjl139090 /*
13161772Sjl139090  * Get high priority message from buffer for upper write stream
13171772Sjl139090  *
13181772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
13191772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
13201772Sjl139090  *  -. uinst_t->u_lock : A
13211772Sjl139090  *  -. uinst_t->l_lock : A
13221772Sjl139090  *  -. uinst_t->c_lock : P
13231772Sjl139090  */
13241772Sjl139090 mblk_t *
oplmsu_wcmn_high_getq(queue_t * uwq)13251772Sjl139090 oplmsu_wcmn_high_getq(queue_t *uwq)
13261772Sjl139090 {
13271772Sjl139090 	mblk_t	*mp;
13281772Sjl139090 	ctrl_t	*ctrl;
13291772Sjl139090 
13301772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
13311772Sjl139090 
13321772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
13331772Sjl139090 	ctrl = (ctrl_t *)uwq->q_ptr;
13341772Sjl139090 	mp = ctrl->first_upri_hi;
13351772Sjl139090 	if (mp != NULL) {
13361772Sjl139090 		if (mp->b_next == NULL) {
13371772Sjl139090 			ctrl->first_upri_hi = NULL;
13381772Sjl139090 			ctrl->last_upri_hi = NULL;
13391772Sjl139090 		} else {
13401772Sjl139090 			ctrl->first_upri_hi = mp->b_next;
13411772Sjl139090 			mp->b_next->b_prev = NULL;
13421772Sjl139090 			mp->b_next = NULL;
13431772Sjl139090 		}
13441772Sjl139090 		mp->b_prev = NULL;
13451772Sjl139090 	}
13461772Sjl139090 	mutex_exit(&oplmsu_uinst->c_lock);
13471772Sjl139090 	return (mp);
13481772Sjl139090 }
13491772Sjl139090 
13501772Sjl139090 /*
13511772Sjl139090  * putbq() function for normal priority message of write stream
13521772Sjl139090  *
13531772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
13541772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
13551772Sjl139090  *  -. uinst_t->u_lock : A
13561772Sjl139090  *  -. uinst_t->l_lock : P
13571772Sjl139090  *  -. uinst_t->c_lock : P
13581772Sjl139090  */
13591772Sjl139090 void
oplmsu_wcmn_norm_putbq(queue_t * uwq,mblk_t * mp,queue_t * dq)13601772Sjl139090 oplmsu_wcmn_norm_putbq(queue_t *uwq, mblk_t *mp, queue_t *dq)
13611772Sjl139090 {
13621772Sjl139090 	lpath_t	*lpath;
13631772Sjl139090 
13641772Sjl139090 	ASSERT(mp != NULL);
13651772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
13661772Sjl139090 
13671772Sjl139090 	mutex_enter(&oplmsu_uinst->l_lock);
13681772Sjl139090 	lpath = (lpath_t *)dq->q_ptr;
13691772Sjl139090 	lpath->uwq_flag = 1;
13701772Sjl139090 	lpath->uwq_queue = uwq;
13711772Sjl139090 	mutex_exit(&oplmsu_uinst->l_lock);
1372*11311SSurya.Prakki@Sun.COM 	(void) putbq(uwq, mp);
13731772Sjl139090 }
13741772Sjl139090 
13751772Sjl139090 /*
13761772Sjl139090  * Restart queuing for high priority message of write stream when flow control
13771772Sjl139090  * failed
13781772Sjl139090  *
13791772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
13801772Sjl139090  *  -. uinst_t->lock   : M [RW_READER or RW_WRITER]
13811772Sjl139090  *  -. uinst_t->u_lock : P
13821772Sjl139090  *  -. uinst_t->l_lock : P
13831772Sjl139090  *  -. uinst_t->c_lock : P
13841772Sjl139090  */
13851772Sjl139090 void
oplmsu_wcmn_high_qenable(queue_t * q,krw_t rw)13861772Sjl139090 oplmsu_wcmn_high_qenable(queue_t *q, krw_t rw)
13871772Sjl139090 {
13881772Sjl139090 	mblk_t	*mp;
13891772Sjl139090 
13901772Sjl139090 	ASSERT(RW_LOCK_HELD(&oplmsu_uinst->lock));
13911772Sjl139090 
13921772Sjl139090 	if (oplmsu_queue_flag == 1) {
13931772Sjl139090 		return;
13941772Sjl139090 	}
13951772Sjl139090 
13961772Sjl139090 	/* Handle high priority message */
13971772Sjl139090 	while (mp = oplmsu_wcmn_high_getq(WR(q))) {
13981772Sjl139090 		if (mp->b_datap->db_type & M_FLUSH) {
13991772Sjl139090 			oplmsu_wcmn_flush_hndl(q, mp, rw);
14001772Sjl139090 			continue;
14011772Sjl139090 		}
14021772Sjl139090 
14031772Sjl139090 		if (oplmsu_wcmn_through_hndl(q, mp, MSU_HIGH, rw) == FAILURE) {
14041772Sjl139090 			return;
14051772Sjl139090 		}
14061772Sjl139090 	}
14071772Sjl139090 	qenable(WR(q));	/* enable upper write queue */
14081772Sjl139090 }
14091772Sjl139090 
14101772Sjl139090 /*
14111772Sjl139090  *	COMMON FUNCTIONS FOR READ STREAM
14121772Sjl139090  */
14131772Sjl139090 
14141772Sjl139090 /*
14151772Sjl139090  * Flush handle for read side stream
14161772Sjl139090  *
14171772Sjl139090  * Requires lock ( M: mandatory  P: prohibited  A: allowed
14181772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
14191772Sjl139090  *  -. uinst_t->u_lock : P
14201772Sjl139090  *  -. uinst_t->l_lock : P
14211772Sjl139090  *  -. uinst_t->c_lock : P
14221772Sjl139090  */
14231772Sjl139090 void
oplmsu_rcmn_flush_hndl(queue_t * q,mblk_t * mp)14241772Sjl139090 oplmsu_rcmn_flush_hndl(queue_t *q, mblk_t *mp)
14251772Sjl139090 {
14261772Sjl139090 	queue_t	*dst_queue = NULL;
14271772Sjl139090 	ctrl_t	*ctrl;
14281772Sjl139090 
14291772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
14301772Sjl139090 
14311772Sjl139090 	if (*mp->b_rptr & FLUSHR) {
14321772Sjl139090 		/* Remove only data messages from read queue */
14331772Sjl139090 		flushq(q, FLUSHDATA);
14341772Sjl139090 	}
14351772Sjl139090 
14361772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
14371772Sjl139090 	if ((ctrl = oplmsu_uinst->user_ctrl) != NULL) {
14381772Sjl139090 		dst_queue = RD(ctrl->queue);
14391772Sjl139090 		mutex_exit(&oplmsu_uinst->c_lock);
14401772Sjl139090 
14411772Sjl139090 		if (dst_queue != NULL) {
1442*11311SSurya.Prakki@Sun.COM 			(void) putq(dst_queue, mp);
14431772Sjl139090 		} else {
14441772Sjl139090 			if (*mp->b_rptr & FLUSHW) {
14451772Sjl139090 				flushq(WR(q), FLUSHDATA);
14461772Sjl139090 				*mp->b_rptr &= ~FLUSHR;
14471772Sjl139090 
14481772Sjl139090 				rw_exit(&oplmsu_uinst->lock);
14491772Sjl139090 				OPLMSU_TRACE(q, mp, MSU_TRC_LO);
14501772Sjl139090 				qreply(q, mp);
14511772Sjl139090 				rw_enter(&oplmsu_uinst->lock, RW_READER);
14521772Sjl139090 			} else {
14531772Sjl139090 				freemsg(mp);
14541772Sjl139090 			}
14551772Sjl139090 		}
14561772Sjl139090 	} else {
14571772Sjl139090 		mutex_exit(&oplmsu_uinst->c_lock);
14581772Sjl139090 		if (*mp->b_rptr & FLUSHW) {
14591772Sjl139090 			flushq(WR(q), FLUSHDATA);
14601772Sjl139090 			*mp->b_rptr &= ~FLUSHR;
14611772Sjl139090 
14621772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
14631772Sjl139090 			OPLMSU_TRACE(q, mp, MSU_TRC_LO);
14641772Sjl139090 			qreply(q, mp);
14651772Sjl139090 			rw_enter(&oplmsu_uinst->lock, RW_READER);
14661772Sjl139090 		} else {
14671772Sjl139090 			freemsg(mp);
14681772Sjl139090 		}
14691772Sjl139090 	}
14701772Sjl139090 }
14711772Sjl139090 
14721772Sjl139090 /*
14731772Sjl139090  * Through message handle for read side stream
14741772Sjl139090  *
14751772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
14761772Sjl139090  *  -. uinst_t->lock   : M [RW_READER]
14771772Sjl139090  *  -. uinst_t->u_lock : A
14781772Sjl139090  *  -. uinst_t->l_lock : P
14791772Sjl139090  *  -. uinst_t->c_lock : P
14801772Sjl139090  */
14811772Sjl139090 int
oplmsu_rcmn_through_hndl(queue_t * q,mblk_t * mp,int pri_flag)14821772Sjl139090 oplmsu_rcmn_through_hndl(queue_t *q, mblk_t *mp, int pri_flag)
14831772Sjl139090 {
14841772Sjl139090 	lpath_t	*lpath;
14851772Sjl139090 	ctrl_t	*ctrl;
14861772Sjl139090 	queue_t	*dst_queue = NULL;
14871772Sjl139090 	int	act_flag;
14881772Sjl139090 
14891772Sjl139090 	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));
14901772Sjl139090 
14911772Sjl139090 	mutex_enter(&oplmsu_uinst->l_lock);
14921772Sjl139090 	lpath = (lpath_t *)q->q_ptr;
14931772Sjl139090 	if (lpath->uinst != NULL) {
14941772Sjl139090 		act_flag = ACTIVE_RES;
14951772Sjl139090 	} else {
14961772Sjl139090 		act_flag = NOT_ACTIVE_RES;
14971772Sjl139090 	}
14981772Sjl139090 	mutex_exit(&oplmsu_uinst->l_lock);
14991772Sjl139090 
15001772Sjl139090 	mutex_enter(&oplmsu_uinst->c_lock);
15011772Sjl139090 	if (((ctrl = oplmsu_uinst->user_ctrl) != NULL) &&
15021772Sjl139090 	    (((mp->b_datap->db_type == M_IOCACK) ||
15031772Sjl139090 	    (mp->b_datap->db_type == M_IOCNAK)) || (act_flag == ACTIVE_RES))) {
15041772Sjl139090 		dst_queue = RD(ctrl->queue);
15051772Sjl139090 	} else {
15061772Sjl139090 		mutex_exit(&oplmsu_uinst->c_lock);
15071772Sjl139090 		freemsg(mp);
15081772Sjl139090 		return (SUCCESS);
15091772Sjl139090 	}
15101772Sjl139090 
15111772Sjl139090 	if (pri_flag == MSU_HIGH) {
1512*11311SSurya.Prakki@Sun.COM 		(void) putq(dst_queue, mp);
15131772Sjl139090 	} else {
15141772Sjl139090 		if (canput(dst_queue)) {
1515*11311SSurya.Prakki@Sun.COM 			(void) putq(dst_queue, mp);
15161772Sjl139090 		} else {
15171772Sjl139090 			/*
15181772Sjl139090 			 * Place a normal priority message at the head of
15191772Sjl139090 			 * read queue
15201772Sjl139090 			 */
15211772Sjl139090 
15221772Sjl139090 			ctrl = (ctrl_t *)dst_queue->q_ptr;
15231772Sjl139090 			ctrl->lrq_flag = 1;
15241772Sjl139090 			ctrl->lrq_queue = q;
15251772Sjl139090 			mutex_exit(&oplmsu_uinst->c_lock);
1526*11311SSurya.Prakki@Sun.COM 			(void) putbq(q, mp);
15271772Sjl139090 			return (FAILURE);
15281772Sjl139090 		}
15291772Sjl139090 	}
15301772Sjl139090 	mutex_exit(&oplmsu_uinst->c_lock);
15311772Sjl139090 	return (SUCCESS);
15321772Sjl139090 }
15331772Sjl139090 
15341772Sjl139090 /*
15351772Sjl139090  * Restart queuing for high priority message of read stream
15361772Sjl139090  * when flow control failed
15371772Sjl139090  *
15381772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
15391772Sjl139090  *  -. uinst_t->lock   : P
15401772Sjl139090  *  -. uinst_t->u_lock : P
15411772Sjl139090  *  -. uinst_t->l_lock : P
15421772Sjl139090  *  -. uinst_t->c_lock : P
15431772Sjl139090  */
15441772Sjl139090 void
oplmsu_rcmn_high_qenable(queue_t * q)15451772Sjl139090 oplmsu_rcmn_high_qenable(queue_t *q)
15461772Sjl139090 {
15471772Sjl139090 	mblk_t		*mp;
15481772Sjl139090 	struct iocblk	*iocp = NULL;
15491772Sjl139090 	lpath_t		*lpath;
15501772Sjl139090 	int		rval;
15511772Sjl139090 
15521772Sjl139090 	rw_enter(&oplmsu_uinst->lock, RW_READER);
15531772Sjl139090 
15541772Sjl139090 	for (;;) {	/* Handle high priority message */
15551772Sjl139090 		mutex_enter(&oplmsu_uinst->l_lock);
15561772Sjl139090 		lpath = (lpath_t *)q->q_ptr;
15571772Sjl139090 		if ((mp = lpath->first_lpri_hi) == NULL) {
15581772Sjl139090 			mutex_exit(&oplmsu_uinst->l_lock);
15591772Sjl139090 			break;
15601772Sjl139090 		}
15611772Sjl139090 
15621772Sjl139090 		if (mp->b_next == NULL) {
15631772Sjl139090 			lpath->first_lpri_hi = NULL;
15641772Sjl139090 			lpath->last_lpri_hi = NULL;
15651772Sjl139090 		} else {
15661772Sjl139090 			lpath->first_lpri_hi = mp->b_next;
15671772Sjl139090 			mp->b_next->b_prev = NULL;
15681772Sjl139090 			mp->b_next = NULL;
15691772Sjl139090 		}
15701772Sjl139090 		mp->b_prev = NULL;
15711772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
15721772Sjl139090 
15731772Sjl139090 		rval = SUCCESS;
15741772Sjl139090 		switch (mp->b_datap->db_type) {
15751772Sjl139090 		case M_IOCACK :		/* FALLTHRU */
15761772Sjl139090 		case M_IOCNAK :
15771772Sjl139090 			iocp = (struct iocblk *)mp->b_rptr;
15781772Sjl139090 			switch (iocp->ioc_cmd) {
15791772Sjl139090 			case TCSETS :		/* FALLTHRU */
15801772Sjl139090 			case TCSETSW :		/* FALLTHRU */
15811772Sjl139090 			case TCSETSF :		/* FALLTHRU */
15821772Sjl139090 			case TIOCMSET :		/* FALLTHRU */
15831772Sjl139090 			case TIOCSPPS :		/* FALLTHRU */
15841772Sjl139090 			case TIOCSWINSZ :	/* FALLTHRU */
15851772Sjl139090 			case TIOCSSOFTCAR :
15861772Sjl139090 				rw_exit(&oplmsu_uinst->lock);
15871772Sjl139090 				rval = oplmsu_lrioctl_termios(q, mp);
15881772Sjl139090 				rw_enter(&oplmsu_uinst->lock, RW_WRITER);
15891772Sjl139090 				break;
15901772Sjl139090 
15911772Sjl139090 			default :
15921772Sjl139090 				rval = oplmsu_rcmn_through_hndl(
15931772Sjl139090 				    q, mp, MSU_HIGH);
15941772Sjl139090 				if (rval == FAILURE) {
15951772Sjl139090 					rw_exit(&oplmsu_uinst->lock);
15961772Sjl139090 					return;
15971772Sjl139090 				}
15981772Sjl139090 			}
15991772Sjl139090 			break;
16001772Sjl139090 
16011772Sjl139090 		case M_ERROR :
16021772Sjl139090 			rw_exit(&oplmsu_uinst->lock);
16031772Sjl139090 			rval = oplmsu_lrmsg_error(q, mp);
16041772Sjl139090 			rw_enter(&oplmsu_uinst->lock, RW_WRITER);
16051772Sjl139090 			break;
16061772Sjl139090 
16071772Sjl139090 		case M_FLUSH :
16081772Sjl139090 			oplmsu_rcmn_flush_hndl(q, mp);
16091772Sjl139090 			break;
16101772Sjl139090 
16111772Sjl139090 		default :
16121772Sjl139090 			rval = oplmsu_rcmn_through_hndl(q, mp, MSU_HIGH);
16131772Sjl139090 			if (rval == FAILURE) {
16141772Sjl139090 				rw_exit(&oplmsu_uinst->lock);
16151772Sjl139090 				return;
16161772Sjl139090 			}
16171772Sjl139090 		}
16181772Sjl139090 
16191772Sjl139090 		if (rval == FAILURE) {
16201772Sjl139090 			break;
16211772Sjl139090 		}
16221772Sjl139090 	}
16231772Sjl139090 
16241772Sjl139090 	rw_exit(&oplmsu_uinst->lock);
16251772Sjl139090 	qenable(q);	/* Enable lower read queue */
16261772Sjl139090 }
16271772Sjl139090 
16281772Sjl139090 #ifdef DEBUG
16291772Sjl139090 /*
16301772Sjl139090  * Online trace
16311772Sjl139090  *
16321772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
16331772Sjl139090  *  -. uinst_t->lock   : P
16341772Sjl139090  *  -. uinst_t->u_lock : P
16351772Sjl139090  *  -. uinst_t->l_lock : P
16361772Sjl139090  *  -. uinst_t->c_lock : P
16371772Sjl139090  */
16381772Sjl139090 void
oplmsu_cmn_trace(queue_t * q,mblk_t * mp,int op)16391772Sjl139090 oplmsu_cmn_trace(queue_t *q, mblk_t *mp, int op)
16401772Sjl139090 {
16411772Sjl139090 	struct iocblk	*iocp;
16421772Sjl139090 
16431772Sjl139090 	if ((op < MSU_TRC_UI) || (op > MSU_TRC_CLS)) {
16441772Sjl139090 		return;
16451772Sjl139090 	}
16461772Sjl139090 
16471772Sjl139090 	mutex_enter(&oplmsu_ltrc_lock);
16481772Sjl139090 
16491772Sjl139090 	if (oplmsu_debug_mode & MSU_DPRINT_ON) {
16501772Sjl139090 		oplmsu_cmn_msglog(mp, op);
16511772Sjl139090 	}
16521772Sjl139090 
16531772Sjl139090 	/* Trace current counter */
1654*11311SSurya.Prakki@Sun.COM 	(void) drv_getparm(LBOLT, (void *)&oplmsu_ltrc_ccnt);
16551772Sjl139090 
16561772Sjl139090 	if (oplmsu_ltrc_cur == oplmsu_ltrc_tail) {
16571772Sjl139090 		oplmsu_ltrc_cur = oplmsu_ltrc_top;
16581772Sjl139090 	} else {
16591772Sjl139090 		oplmsu_ltrc_cur++;
16601772Sjl139090 	}
16611772Sjl139090 	oplmsu_ltrc_cur->q = q;
16621772Sjl139090 	oplmsu_ltrc_cur->mp = mp;
16631772Sjl139090 
16641772Sjl139090 	switch (op) {
16651772Sjl139090 	case MSU_TRC_UI :
16661772Sjl139090 		oplmsu_ltrc_cur->op[0] = 'u';
16671772Sjl139090 		oplmsu_ltrc_cur->op[1] = 'i';
16681772Sjl139090 		break;
16691772Sjl139090 
16701772Sjl139090 	case MSU_TRC_UO :
16711772Sjl139090 		oplmsu_ltrc_cur->op[0] = 'u';
16721772Sjl139090 		oplmsu_ltrc_cur->op[1] = 'o';
16731772Sjl139090 		break;
16741772Sjl139090 
16751772Sjl139090 	case MSU_TRC_LI :
16761772Sjl139090 		oplmsu_ltrc_cur->op[0] = 'l';
16771772Sjl139090 		oplmsu_ltrc_cur->op[1] = 'i';
16781772Sjl139090 		break;
16791772Sjl139090 
16801772Sjl139090 	case MSU_TRC_LO :
16811772Sjl139090 		oplmsu_ltrc_cur->op[0] = 'l';
16821772Sjl139090 		oplmsu_ltrc_cur->op[1] = 'o';
16831772Sjl139090 		break;
16841772Sjl139090 
16851772Sjl139090 	case MSU_TRC_OPN :
16861772Sjl139090 		oplmsu_ltrc_cur->op[0] = 'o';
16871772Sjl139090 		oplmsu_ltrc_cur->op[1] = 'p';
16881772Sjl139090 		break;
16891772Sjl139090 
16901772Sjl139090 	case MSU_TRC_CLS :
16911772Sjl139090 		oplmsu_ltrc_cur->op[0] = 'c';
16921772Sjl139090 		oplmsu_ltrc_cur->op[1] = 'l';
16931772Sjl139090 		break;
16941772Sjl139090 	}
16951772Sjl139090 
16961772Sjl139090 	if ((op == MSU_TRC_LI) || (op == MSU_TRC_LO)) {
16971772Sjl139090 		mutex_enter(&oplmsu_uinst->l_lock);
16981772Sjl139090 		oplmsu_ltrc_cur->pathno = ((lpath_t *)q->q_ptr)->path_no;
16991772Sjl139090 		mutex_exit(&oplmsu_uinst->l_lock);
17001772Sjl139090 	} else {
17011772Sjl139090 		oplmsu_ltrc_cur->pathno = 0;
17021772Sjl139090 	}
17031772Sjl139090 
17041772Sjl139090 	if ((op == MSU_TRC_OPN) || (op == MSU_TRC_CLS)) {
17051772Sjl139090 		oplmsu_ltrc_cur->msg_type = 0;
17061772Sjl139090 		oplmsu_ltrc_cur->msg_cmd = 0;
17071772Sjl139090 		oplmsu_ltrc_cur->data = 0;
17081772Sjl139090 
17091772Sjl139090 		switch ((ulong_t)mp) {
17101772Sjl139090 		case MSU_NODE_USER :
17111772Sjl139090 			oplmsu_ltrc_cur->data = MSU_TRC_USER;
17121772Sjl139090 			break;
17131772Sjl139090 
17141772Sjl139090 		case MSU_NODE_META :
17151772Sjl139090 			oplmsu_ltrc_cur->data = MSU_TRC_META;
17161772Sjl139090 			break;
17171772Sjl139090 		}
17181772Sjl139090 		oplmsu_ltrc_cur->mp = NULL;
17191772Sjl139090 	} else {
17201772Sjl139090 		oplmsu_ltrc_cur->msg_type = mp->b_datap->db_type;
17211772Sjl139090 		iocp = (struct iocblk *)mp->b_rptr;
17221772Sjl139090 		oplmsu_ltrc_cur->msg_cmd = iocp->ioc_cmd;
17231772Sjl139090 
17241772Sjl139090 		if ((mp->b_datap->db_type == M_IOCTL) ||
17251772Sjl139090 		    (mp->b_datap->db_type == M_IOCACK) ||
17261772Sjl139090 		    (mp->b_datap->db_type == M_IOCNAK)) {
17271772Sjl139090 			oplmsu_ltrc_cur->msg_cmd = iocp->ioc_cmd;
17281772Sjl139090 
17291772Sjl139090 			if (mp->b_cont != NULL) {
17301772Sjl139090 				oplmsu_ltrc_cur->data =
17311772Sjl139090 				    (ulong_t)mp->b_cont->b_rptr;
17321772Sjl139090 			} else {
17331772Sjl139090 				oplmsu_ltrc_cur->data = 0;
17341772Sjl139090 			}
17351772Sjl139090 		} else {
17361772Sjl139090 			oplmsu_ltrc_cur->msg_cmd = 0;
17371772Sjl139090 
17381772Sjl139090 			if (mp->b_rptr == NULL) {
17391772Sjl139090 				oplmsu_ltrc_cur->data = 0;
17401772Sjl139090 			} else {
17411772Sjl139090 				oplmsu_ltrc_cur->data = *(ulong_t *)mp->b_rptr;
17421772Sjl139090 			}
17431772Sjl139090 		}
17441772Sjl139090 	}
17451772Sjl139090 	mutex_exit(&oplmsu_ltrc_lock);
17461772Sjl139090 }
17471772Sjl139090 
17481772Sjl139090 /*
17491772Sjl139090  * Display message log to console
17501772Sjl139090  *
17511772Sjl139090  * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
17521772Sjl139090  *  -. uinst_t->lock   : P
17531772Sjl139090  *  -. uinst_t->u_lock : P
17541772Sjl139090  *  -. uinst_t->l_lock : P
17551772Sjl139090  *  -. uinst_t->c_lock : P
17561772Sjl139090  */
17571772Sjl139090 void
oplmsu_cmn_msglog(mblk_t * mp,int direction)17581772Sjl139090 oplmsu_cmn_msglog(mblk_t *mp, int direction)
17591772Sjl139090 {
17601772Sjl139090 	uchar_t	*cur = NULL;
17611772Sjl139090 	mblk_t	*tmp_mp = NULL;
17621772Sjl139090 	ulong_t	len;
17631772Sjl139090 	ulong_t	line;
17641772Sjl139090 	ulong_t	col;
17651772Sjl139090 	ulong_t	row;
17661772Sjl139090 	ulong_t	count;
17671772Sjl139090 	char	buffer[70];
17681772Sjl139090 	char	*bufp;
17691772Sjl139090 
17701772Sjl139090 	if (mp == NULL) {
17711772Sjl139090 		return;
17721772Sjl139090 	}
17731772Sjl139090 
17741772Sjl139090 	switch (direction) {
17751772Sjl139090 	case 0:
17761772Sjl139090 		cmn_err(CE_NOTE, "!---------- Upper in --------");
17771772Sjl139090 		break;
17781772Sjl139090 
17791772Sjl139090 	case 1:
17801772Sjl139090 		cmn_err(CE_NOTE, "!---------- Upper out -------");
17811772Sjl139090 		break;
17821772Sjl139090 
17831772Sjl139090 	case 2:
17841772Sjl139090 		cmn_err(CE_NOTE, "!---------- Lower in --------");
17851772Sjl139090 		break;
17861772Sjl139090 
17871772Sjl139090 	case 3:
17881772Sjl139090 		cmn_err(CE_NOTE, "!---------- Lower out -------");
17891772Sjl139090 		break;
17901772Sjl139090 
17911772Sjl139090 	default:
17921772Sjl139090 		return;
17931772Sjl139090 	}
17941772Sjl139090 
17951772Sjl139090 	for (tmp_mp = mp; tmp_mp; tmp_mp = tmp_mp->b_cont) {
17961772Sjl139090 		cmn_err(CE_NOTE, "!db_type = 0x%02x", tmp_mp->b_datap->db_type);
17971772Sjl139090 
17981772Sjl139090 		len = tmp_mp->b_wptr - tmp_mp->b_rptr;
17991772Sjl139090 		line = (len + 31) / 32;
18001772Sjl139090 		cur = (uchar_t *)tmp_mp->b_rptr;
18011772Sjl139090 		count = 0;
18021772Sjl139090 
18031772Sjl139090 		for (col = 0; col < line; col++) {
18041772Sjl139090 			bufp = buffer;
18051772Sjl139090 
18061772Sjl139090 			for (row = 0; row < 32; row++) {
18071772Sjl139090 				if (row != 0 && (row % 8) == 0) {
18081772Sjl139090 					*bufp = ' ';
18091772Sjl139090 					bufp++;
18101772Sjl139090 				}
1811*11311SSurya.Prakki@Sun.COM 				(void) sprintf(bufp, "%02x", *cur);
18121772Sjl139090 				bufp += 2;
18131772Sjl139090 				cur++;
18141772Sjl139090 				count++;
18151772Sjl139090 
18161772Sjl139090 				if (count >= len) {
18171772Sjl139090 					break;
18181772Sjl139090 				}
18191772Sjl139090 			}
18201772Sjl139090 			*bufp = '\0';
18211772Sjl139090 			cmn_err(CE_NOTE, "!%s", buffer);
18221772Sjl139090 
18231772Sjl139090 			if (count >= len) {
18241772Sjl139090 				break;
18251772Sjl139090 			}
18261772Sjl139090 		}
18271772Sjl139090 	}
18281772Sjl139090 }
18291772Sjl139090 
18301772Sjl139090 void
oplmsu_cmn_prt_pathname(dev_info_t * dip)18311772Sjl139090 oplmsu_cmn_prt_pathname(dev_info_t *dip)
18321772Sjl139090 {
18331772Sjl139090 	char	pathname[128];
18341772Sjl139090 	char	wrkbuf[128];
18351772Sjl139090 
1836*11311SSurya.Prakki@Sun.COM 	(void) ddi_pathname(dip, wrkbuf);
18371772Sjl139090 	*(wrkbuf + strlen(wrkbuf)) = '\0';
1838*11311SSurya.Prakki@Sun.COM 	(void) sprintf(pathname, "/devices%s:%c", wrkbuf,
1839*11311SSurya.Prakki@Sun.COM 	    'a'+ ddi_get_instance(dip));
18401772Sjl139090 
18411772Sjl139090 	DBG_PRINT((CE_NOTE, "oplmsu: debug-info: "
18421772Sjl139090 	    "Active path change to path => %s", pathname));
18431772Sjl139090 }
18441772Sjl139090 #endif
1845