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 */
21*11311SSurya.Prakki@Sun.COM
221772Sjl139090 /*
231772Sjl139090 * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
241772Sjl139090 */
251772Sjl139090
261772Sjl139090 #include <sys/errno.h>
271772Sjl139090 #include <sys/modctl.h>
281772Sjl139090 #include <sys/stat.h>
291772Sjl139090 #include <sys/kmem.h>
301772Sjl139090 #include <sys/ksynch.h>
311772Sjl139090 #include <sys/stream.h>
321772Sjl139090 #include <sys/stropts.h>
331772Sjl139090 #include <sys/termio.h>
341772Sjl139090 #include <sys/ddi.h>
351772Sjl139090 #include <sys/file.h>
361772Sjl139090 #include <sys/disp.h>
371772Sjl139090 #include <sys/sunddi.h>
381772Sjl139090 #include <sys/sunldi.h>
391772Sjl139090 #include <sys/sunndi.h>
401772Sjl139090 #include <sys/prom_plat.h>
411772Sjl139090 #include <sys/oplmsu/oplmsu.h>
421772Sjl139090 #include <sys/oplmsu/oplmsu_proto.h>
431772Sjl139090
441772Sjl139090 /*
451772Sjl139090 * LOWER READ SERVICE PROCEDURE
461772Sjl139090 */
471772Sjl139090
481772Sjl139090 /* termios ioctl response received */
491772Sjl139090 int
oplmsu_lrioctl_termios(queue_t * lrq,mblk_t * mp)501772Sjl139090 oplmsu_lrioctl_termios(queue_t *lrq, mblk_t *mp)
511772Sjl139090 {
521772Sjl139090 upath_t *upath, *altn_upath = NULL, *stp_upath = NULL;
531772Sjl139090 lpath_t *lpath, *altn_lpath = NULL, *stp_lpath = NULL;
541772Sjl139090 struct iocblk *iocp, *temp_iocp = NULL;
551772Sjl139090 mblk_t *hndl_mp, *nmp = NULL, *fmp = NULL;
561772Sjl139090 queue_t *dst_queue;
571772Sjl139090 int term_ioctl, term_stat, sts;
581772Sjl139090 int ack_flag, termio_flag, chkflag;
591772Sjl139090 ulong_t trad_sts;
601772Sjl139090
611772Sjl139090 rw_enter(&oplmsu_uinst->lock, RW_READER);
621772Sjl139090 iocp = (struct iocblk *)mp->b_rptr;
631772Sjl139090
641772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
651772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
661772Sjl139090 lpath = (lpath_t *)lrq->q_ptr;
671772Sjl139090 hndl_mp = lpath->hndl_mp;
681772Sjl139090
691772Sjl139090 upath = oplmsu_search_upath_info(lpath->path_no);
701772Sjl139090 trad_sts = upath->traditional_status;
711772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
721772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
731772Sjl139090
741772Sjl139090 if (((iocp->ioc_cmd == TCSETS) && (trad_sts == MSU_WTCS_ACK)) ||
751772Sjl139090 ((iocp->ioc_cmd == TCSETSW) && (trad_sts == MSU_WTCS_ACK)) ||
761772Sjl139090 ((iocp->ioc_cmd == TCSETSF) && (trad_sts == MSU_WTCS_ACK)) ||
771772Sjl139090 ((iocp->ioc_cmd == TIOCMSET) && (trad_sts == MSU_WTMS_ACK)) ||
781772Sjl139090 ((iocp->ioc_cmd == TIOCSPPS) && (trad_sts == MSU_WPPS_ACK)) ||
791772Sjl139090 ((iocp->ioc_cmd == TIOCSWINSZ) && (trad_sts == MSU_WWSZ_ACK)) ||
801772Sjl139090 ((iocp->ioc_cmd == TIOCSSOFTCAR) && (trad_sts == MSU_WCAR_ACK))) {
811772Sjl139090 if (mp->b_datap->db_type == M_IOCACK) {
821772Sjl139090 ack_flag = ACK_RES;
831772Sjl139090 } else {
841772Sjl139090 ack_flag = NAK_RES;
851772Sjl139090 }
861772Sjl139090 } else {
871772Sjl139090 rw_exit(&oplmsu_uinst->lock);
881772Sjl139090 freemsg(mp);
891772Sjl139090 cmn_err(CE_WARN, "oplmsu: lr-termios: "
901772Sjl139090 "Status of path is improper");
911772Sjl139090 return (SUCCESS);
921772Sjl139090 }
931772Sjl139090
941772Sjl139090 switch (trad_sts) {
951772Sjl139090 case MSU_WTCS_ACK :
961772Sjl139090 termio_flag = MSU_TIOS_TCSETS;
971772Sjl139090 break;
981772Sjl139090
991772Sjl139090 case MSU_WTMS_ACK :
1001772Sjl139090 termio_flag = MSU_TIOS_MSET;
1011772Sjl139090 break;
1021772Sjl139090
1031772Sjl139090 case MSU_WPPS_ACK :
1041772Sjl139090 termio_flag = MSU_TIOS_PPS;
1051772Sjl139090 break;
1061772Sjl139090
1071772Sjl139090 case MSU_WWSZ_ACK :
1081772Sjl139090 termio_flag = MSU_TIOS_WINSZP;
1091772Sjl139090 break;
1101772Sjl139090
1111772Sjl139090 case MSU_WCAR_ACK :
1121772Sjl139090 termio_flag = MSU_TIOS_SOFTCAR;
1131772Sjl139090 break;
1141772Sjl139090
1151772Sjl139090 default :
1161772Sjl139090 termio_flag = MSU_TIOS_END;
1171772Sjl139090 break;
1181772Sjl139090 }
1191772Sjl139090
1201772Sjl139090 if (hndl_mp == NULL) {
1211772Sjl139090 switch (trad_sts) {
1221772Sjl139090 case MSU_WTCS_ACK : /* FALLTHRU */
1231772Sjl139090 case MSU_WTMS_ACK : /* FALLTHRU */
1241772Sjl139090 case MSU_WPPS_ACK : /* FALLTHRU */
1251772Sjl139090 case MSU_WWSZ_ACK : /* FALLTHRU */
1261772Sjl139090 case MSU_WCAR_ACK :
1271772Sjl139090 chkflag = MSU_CMD_STOP;
1281772Sjl139090 break;
1291772Sjl139090
1301772Sjl139090 default :
1311772Sjl139090 chkflag = FAILURE;
1321772Sjl139090 break;
1331772Sjl139090 }
1341772Sjl139090 } else {
1351772Sjl139090 /* xoff/xon received */
1361772Sjl139090 if (hndl_mp->b_datap->db_type == M_DATA) {
1371772Sjl139090 chkflag = MSU_CMD_ACTIVE;
1381772Sjl139090 } else { /* Normal termios */
1391772Sjl139090 temp_iocp = (struct iocblk *)hndl_mp->b_rptr;
1401772Sjl139090 chkflag = temp_iocp->ioc_cmd;
1411772Sjl139090 }
1421772Sjl139090 }
1431772Sjl139090
1441772Sjl139090 if ((chkflag == MSU_CMD_ACTIVE) || (chkflag == MSU_CMD_STOP)) {
1451772Sjl139090 if (ack_flag == ACK_RES) { /* M_IOCACK received */
1461772Sjl139090 ctrl_t *ctrl;
1471772Sjl139090
1481772Sjl139090 if (oplmsu_cmn_prechg_termio(lrq, mp, MSU_READ_SIDE,
1491772Sjl139090 termio_flag, &nmp, &term_stat) == FAILURE) {
1501772Sjl139090 rw_exit(&oplmsu_uinst->lock);
1511772Sjl139090 return (FAILURE);
1521772Sjl139090 }
1531772Sjl139090
1541772Sjl139090 OPLMSU_RWLOCK_UPGRADE();
1551772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
1561772Sjl139090 if (term_stat != MSU_WPTH_CHG) {
1571772Sjl139090 upath->traditional_status = term_stat;
1581772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
1591772Sjl139090 rw_exit(&oplmsu_uinst->lock);
1601772Sjl139090 freemsg(mp);
1611772Sjl139090
1621772Sjl139090 OPLMSU_TRACE(RD(lrq), nmp, MSU_TRC_LO);
1631772Sjl139090
1641772Sjl139090 /* Continue sending termios ioctls */
1651772Sjl139090 qreply(RD(lrq), nmp);
1661772Sjl139090 return (SUCCESS);
1671772Sjl139090 }
1681772Sjl139090 freemsg(mp);
1691772Sjl139090
1701772Sjl139090 /* Change status of new active path */
1711772Sjl139090 oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_ACTIVE,
1721772Sjl139090 upath->status, MSU_ACTIVE);
1731772Sjl139090
1741772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
1751772Sjl139090 lpath->uinst = oplmsu_uinst;
1761772Sjl139090 dst_queue = lpath->hndl_uqueue;
1771772Sjl139090
1781772Sjl139090 ctrl = oplmsu_uinst->user_ctrl;
1791772Sjl139090 if ((chkflag == MSU_CMD_ACTIVE) && (hndl_mp != NULL)) {
1801772Sjl139090 /* Put a message(M_DATA) on a queue */
1811772Sjl139090 if (ctrl != NULL) {
1821772Sjl139090 mutex_enter(&oplmsu_uinst->c_lock);
183*11311SSurya.Prakki@Sun.COM (void) putq(RD(ctrl->queue), hndl_mp);
1841772Sjl139090 mutex_exit(&oplmsu_uinst->c_lock);
1851772Sjl139090 }
1861772Sjl139090 }
1871772Sjl139090
1881772Sjl139090 oplmsu_clear_ioctl_path(lpath);
1891772Sjl139090 stp_upath = lpath->src_upath;
1901772Sjl139090 lpath->src_upath = NULL;
1911772Sjl139090 lpath->status = MSU_EXT_NOTUSED;
1921772Sjl139090
1931772Sjl139090 /* Notify of the active path changing */
194*11311SSurya.Prakki@Sun.COM (void) prom_opl_switch_console(upath->ser_devcb.lsb);
1951772Sjl139090
1961772Sjl139090 /* Send XON to notify active path */
1971772Sjl139090 (void) oplmsu_cmn_put_xoffxon(WR(lrq), MSU_XON_4);
1981772Sjl139090
1991772Sjl139090 stp_lpath = stp_upath->lpath;
2001772Sjl139090 stp_lpath->uinst = NULL;
2011772Sjl139090 oplmsu_clear_ioctl_path(stp_lpath);
2021772Sjl139090 stp_lpath->src_upath = NULL;
2031772Sjl139090 stp_lpath->status = MSU_EXT_NOTUSED;
2041772Sjl139090
2051772Sjl139090 /* Change status of stopped or old-active path */
2061772Sjl139090 if (chkflag == MSU_CMD_STOP) {
2071772Sjl139090 sts = MSU_PSTAT_STOP;
2081772Sjl139090 trad_sts = MSU_STOP;
2091772Sjl139090 } else { /* == MSU_CMD_ACTIVE */
2101772Sjl139090 sts = MSU_PSTAT_STANDBY;
2111772Sjl139090 trad_sts = MSU_STANDBY;
2121772Sjl139090 }
2131772Sjl139090 oplmsu_cmn_set_upath_sts(stp_upath, sts,
2141772Sjl139090 stp_upath->status, trad_sts);
2151772Sjl139090
2161772Sjl139090 /* Send XOFF to notify all standby paths */
2171772Sjl139090 oplmsu_cmn_putxoff_standby();
2181772Sjl139090 oplmsu_uinst->lower_queue = lrq;
2191772Sjl139090 oplmsu_uinst->inst_status = oplmsu_get_inst_status();
2201772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
2211772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
2221772Sjl139090
2231772Sjl139090 /* Change active path of user node */
2241772Sjl139090 if (ctrl != NULL) {
2251772Sjl139090 queue_t *temp_queue;
2261772Sjl139090
2271772Sjl139090 mutex_enter(&oplmsu_uinst->c_lock);
2281772Sjl139090 temp_queue = WR(ctrl->queue);
2291772Sjl139090 mutex_exit(&oplmsu_uinst->c_lock);
2301772Sjl139090
2311772Sjl139090 /* Reschedule a queue for service */
2321772Sjl139090 enableok(temp_queue);
2331772Sjl139090
2341772Sjl139090 oplmsu_queue_flag = 0;
2351772Sjl139090 oplmsu_wcmn_high_qenable(temp_queue, RW_WRITER);
2361772Sjl139090 }
2371772Sjl139090 rw_exit(&oplmsu_uinst->lock);
2381772Sjl139090
2391772Sjl139090 if (nmp != NULL) {
2401772Sjl139090 freemsg(nmp);
2411772Sjl139090 }
2421772Sjl139090
2431772Sjl139090 /* Wake up oplmsu_config_stop */
2441772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
2451772Sjl139090 if (stp_lpath->sw_flag) {
2461772Sjl139090 stp_lpath->sw_flag = 0;
2471772Sjl139090 cv_signal(&stp_lpath->sw_cv);
2481772Sjl139090 }
2491772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
2501772Sjl139090 return (SUCCESS);
2511772Sjl139090 } else { /* M_IOCNAK received */
2521772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
2531772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
2541772Sjl139090 if ((chkflag == MSU_CMD_ACTIVE) &&
2551772Sjl139090 (lpath->hndl_uqueue == NULL)) {
2561772Sjl139090 oplmsu_clear_ioctl_path(lpath);
2571772Sjl139090 stp_upath = lpath->src_upath;
2581772Sjl139090 lpath->src_upath = NULL;
2591772Sjl139090 lpath->status = MSU_EXT_NOTUSED;
2601772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
2611772Sjl139090
2621772Sjl139090 oplmsu_cmn_set_upath_sts(upath,
2631772Sjl139090 MSU_PSTAT_STANDBY, upath->status,
2641772Sjl139090 MSU_STANDBY);
2651772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
2661772Sjl139090
2671772Sjl139090 if (hndl_mp != NULL) {
2681772Sjl139090 freemsg(hndl_mp);
2691772Sjl139090 }
2701772Sjl139090
2711772Sjl139090 OPLMSU_RWLOCK_UPGRADE();
2721772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
2731772Sjl139090 oplmsu_uinst->inst_status =
2741772Sjl139090 oplmsu_get_inst_status();
2751772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
2761772Sjl139090 rw_exit(&oplmsu_uinst->lock);
2771772Sjl139090 return (SUCCESS);
2781772Sjl139090 } else if ((chkflag == MSU_CMD_STOP) &&
2791772Sjl139090 (lpath->src_upath != NULL) &&
2801772Sjl139090 (lpath->src_upath->lpath->sw_flag)) {
2811772Sjl139090 /* MSU_CMD_STOP for active path */
2821772Sjl139090
2831772Sjl139090 dst_queue = RD(lpath->hndl_uqueue);
2841772Sjl139090 stp_upath = lpath->src_upath;
2851772Sjl139090
2861772Sjl139090 /* Search alternate path from standby paths */
2871772Sjl139090 altn_upath = oplmsu_search_standby();
2881772Sjl139090 if (altn_upath == NULL) {
2891772Sjl139090 altn_upath = upath;
2901772Sjl139090 }
2911772Sjl139090
2921772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
2931772Sjl139090 if (oplmsu_cmn_allocmb(lrq, mp, &fmp,
2941772Sjl139090 sizeof (char), MSU_READ_SIDE) == FAILURE) {
2951772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
2961772Sjl139090 rw_exit(&oplmsu_uinst->lock);
2971772Sjl139090 return (FAILURE);
2981772Sjl139090 }
2991772Sjl139090
3001772Sjl139090 if (oplmsu_cmn_prechg(lrq, mp, MSU_READ_SIDE,
3011772Sjl139090 &nmp, &term_ioctl, &term_stat) == FAILURE) {
3021772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
3031772Sjl139090 rw_exit(&oplmsu_uinst->lock);
3041772Sjl139090 freeb(fmp);
3051772Sjl139090 return (FAILURE);
3061772Sjl139090 }
3071772Sjl139090
3081772Sjl139090 altn_upath->traditional_status = term_stat;
3091772Sjl139090 altn_lpath = altn_upath->lpath;
3101772Sjl139090
3111772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
3121772Sjl139090 altn_lpath->hndl_mp = hndl_mp;
3131772Sjl139090 altn_lpath->hndl_uqueue = dst_queue;
3141772Sjl139090 altn_lpath->src_upath = stp_upath;
3151772Sjl139090 altn_lpath->status = MSU_EXT_VOID;
3161772Sjl139090 dst_queue = RD(altn_lpath->lower_queue);
3171772Sjl139090
3181772Sjl139090 oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL,
3191772Sjl139090 upath->status, MSU_FAIL);
3201772Sjl139090
3211772Sjl139090 oplmsu_clear_ioctl_path(lpath);
3221772Sjl139090 lpath->src_upath = NULL;
3231772Sjl139090 lpath->status = MSU_EXT_NOTUSED;
3241772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
3251772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
3261772Sjl139090
3271772Sjl139090 OPLMSU_RWLOCK_UPGRADE();
3281772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
3291772Sjl139090 oplmsu_uinst->inst_status =
3301772Sjl139090 oplmsu_get_inst_status();
3311772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
3321772Sjl139090 rw_exit(&oplmsu_uinst->lock);
3331772Sjl139090 freemsg(mp);
3341772Sjl139090 oplmsu_cmn_set_mflush(fmp);
3351772Sjl139090
3361772Sjl139090 OPLMSU_TRACE(dst_queue, fmp, MSU_TRC_LO);
3371772Sjl139090 qreply(dst_queue, fmp);
3381772Sjl139090
3391772Sjl139090 OPLMSU_TRACE(dst_queue, nmp, MSU_TRC_LO);
3401772Sjl139090 qreply(dst_queue, nmp);
3411772Sjl139090 return (SUCCESS);
3421772Sjl139090 }
3431772Sjl139090 }
3441772Sjl139090 } else if ((chkflag == TCSETS) || (chkflag == TCSETSW) ||
3451772Sjl139090 (chkflag == TCSETSF) || (chkflag == TIOCMSET) ||
3461772Sjl139090 (chkflag == TIOCSPPS) || (chkflag == TIOCSWINSZ) ||
3471772Sjl139090 (chkflag == TIOCSSOFTCAR)) {
3481772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
3491772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
3501772Sjl139090
3511772Sjl139090 if ((ack_flag == ACK_RES) &&
3521772Sjl139090 (lpath->hndl_uqueue != NULL)) { /* M_IOCACK received */
3531772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
3541772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
3551772Sjl139090 if (oplmsu_cmn_copymb(lrq, mp, &nmp, hndl_mp,
3561772Sjl139090 MSU_READ_SIDE) == FAILURE) {
3571772Sjl139090 rw_exit(&oplmsu_uinst->lock);
3581772Sjl139090 return (FAILURE);
3591772Sjl139090 }
3601772Sjl139090
3611772Sjl139090 OPLMSU_RWLOCK_UPGRADE();
3621772Sjl139090 switch (chkflag) {
3631772Sjl139090 case TCSETS : /* FALLTHRU */
3641772Sjl139090 case TCSETSW : /* FALLTHRU */
3651772Sjl139090 case TCSETSF :
3661772Sjl139090 if (oplmsu_uinst->tcsets_p != NULL) {
3671772Sjl139090 freemsg(oplmsu_uinst->tcsets_p);
3681772Sjl139090 }
3691772Sjl139090 oplmsu_uinst->tcsets_p = nmp;
3701772Sjl139090 break;
3711772Sjl139090
3721772Sjl139090 case TIOCMSET :
3731772Sjl139090 if (oplmsu_uinst->tiocmset_p != NULL) {
3741772Sjl139090 freemsg(oplmsu_uinst->tiocmset_p);
3751772Sjl139090 }
3761772Sjl139090 oplmsu_uinst->tiocmset_p = nmp;
3771772Sjl139090 break;
3781772Sjl139090
3791772Sjl139090 case TIOCSPPS :
3801772Sjl139090 if (oplmsu_uinst->tiocspps_p != NULL) {
3811772Sjl139090 freemsg(oplmsu_uinst->tiocspps_p);
3821772Sjl139090 }
3831772Sjl139090 oplmsu_uinst->tiocspps_p = nmp;
3841772Sjl139090 break;
3851772Sjl139090
3861772Sjl139090 case TIOCSWINSZ :
3871772Sjl139090 if (oplmsu_uinst->tiocswinsz_p != NULL) {
3881772Sjl139090 freemsg(oplmsu_uinst->tiocswinsz_p);
3891772Sjl139090 }
3901772Sjl139090 oplmsu_uinst->tiocswinsz_p = nmp;
3911772Sjl139090 break;
3921772Sjl139090
3931772Sjl139090 case TIOCSSOFTCAR :
3941772Sjl139090 if (oplmsu_uinst->tiocssoftcar_p != NULL) {
3951772Sjl139090 freemsg(oplmsu_uinst->tiocssoftcar_p);
3961772Sjl139090 }
3971772Sjl139090 oplmsu_uinst->tiocssoftcar_p = nmp;
3981772Sjl139090 break;
3991772Sjl139090 }
4001772Sjl139090
4011772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
4021772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
4031772Sjl139090 upath->traditional_status = lpath->status;
4041772Sjl139090 nmp = lpath->hndl_mp;
4051772Sjl139090 nmp->b_datap->db_type = M_IOCACK;
4061772Sjl139090 dst_queue = RD(lpath->hndl_uqueue);
4071772Sjl139090 bcopy(mp->b_rptr, nmp->b_rptr, sizeof (struct iocblk));
4081772Sjl139090
4091772Sjl139090 oplmsu_clear_ioctl_path(lpath);
4101772Sjl139090 lpath->src_upath = NULL;
4111772Sjl139090 lpath->status = MSU_EXT_NOTUSED;
4121772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
4131772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
4141772Sjl139090 freemsg(mp);
415*11311SSurya.Prakki@Sun.COM (void) putq(dst_queue, nmp);
4161772Sjl139090
4171772Sjl139090 /* Check sleep flag and wake up thread */
4181772Sjl139090 oplmsu_cmn_wakeup(dst_queue);
4191772Sjl139090 rw_exit(&oplmsu_uinst->lock);
4201772Sjl139090 return (SUCCESS);
4211772Sjl139090 } else if ((ack_flag == NAK_RES) &&
4221772Sjl139090 (lpath->hndl_uqueue != NULL)) { /* M_IOCNAK received */
4231772Sjl139090 upath->traditional_status = lpath->status;
4241772Sjl139090
4251772Sjl139090 nmp = lpath->hndl_mp;
4261772Sjl139090 nmp->b_datap->db_type = M_IOCNAK;
4271772Sjl139090 dst_queue = RD(lpath->hndl_uqueue);
4281772Sjl139090
4291772Sjl139090 oplmsu_clear_ioctl_path(lpath);
4301772Sjl139090 lpath->src_upath = NULL;
4311772Sjl139090 lpath->status = MSU_EXT_NOTUSED;
4321772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
4331772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
4341772Sjl139090 freemsg(mp);
435*11311SSurya.Prakki@Sun.COM (void) putq(dst_queue, nmp);
4361772Sjl139090
4371772Sjl139090 /* Check sleep flag and wake up thread */
4381772Sjl139090 oplmsu_cmn_wakeup(dst_queue);
4391772Sjl139090 rw_exit(&oplmsu_uinst->lock);
4401772Sjl139090 return (SUCCESS);
4411772Sjl139090 }
4421772Sjl139090 }
4431772Sjl139090
4441772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
4451772Sjl139090 switch (upath->status) {
4461772Sjl139090 case MSU_PSTAT_FAIL :
4471772Sjl139090 upath->traditional_status = MSU_FAIL;
4481772Sjl139090 break;
4491772Sjl139090
4501772Sjl139090 case MSU_PSTAT_STOP :
4511772Sjl139090 upath->traditional_status = MSU_STOP;
4521772Sjl139090 break;
4531772Sjl139090
4541772Sjl139090 case MSU_PSTAT_STANDBY :
4551772Sjl139090 upath->traditional_status = MSU_STANDBY;
4561772Sjl139090 break;
4571772Sjl139090
4581772Sjl139090 case MSU_PSTAT_ACTIVE :
4591772Sjl139090 upath->traditional_status = MSU_ACTIVE;
4601772Sjl139090 break;
4611772Sjl139090 }
4621772Sjl139090
4631772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
4641772Sjl139090 oplmsu_clear_ioctl_path(lpath);
4651772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
4661772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
4671772Sjl139090 rw_exit(&oplmsu_uinst->lock);
4681772Sjl139090 freemsg(mp);
4691772Sjl139090 return (SUCCESS);
4701772Sjl139090 }
4711772Sjl139090
4721772Sjl139090 /* M_ERROR or M_HANGUP response received */
4731772Sjl139090 int
oplmsu_lrmsg_error(queue_t * lrq,mblk_t * mp)4741772Sjl139090 oplmsu_lrmsg_error(queue_t *lrq, mblk_t *mp)
4751772Sjl139090 {
4761772Sjl139090 upath_t *upath, *altn_upath = NULL;
4771772Sjl139090 lpath_t *lpath, *altn_lpath = NULL;
4781772Sjl139090 mblk_t *nmp = NULL, *fmp = NULL;
4791772Sjl139090 queue_t *dst_queue = NULL;
4801772Sjl139090 ctrl_t *ctrl;
4811772Sjl139090 int term_stat, term_ioctl;
4821772Sjl139090
4831772Sjl139090 rw_enter(&oplmsu_uinst->lock, RW_READER);
4841772Sjl139090 mutex_enter(&oplmsu_uinst->c_lock);
4851772Sjl139090 ctrl = oplmsu_uinst->user_ctrl;
4861772Sjl139090 if (ctrl != NULL) {
4871772Sjl139090 dst_queue = RD(ctrl->queue);
4881772Sjl139090 }
4891772Sjl139090 mutex_exit(&oplmsu_uinst->c_lock);
4901772Sjl139090
4911772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
4921772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
4931772Sjl139090 lpath = (lpath_t *)lrq->q_ptr;
4941772Sjl139090 upath = oplmsu_search_upath_info(lpath->path_no);
4951772Sjl139090
4961873Sraghuram if (upath == NULL) {
4971873Sraghuram mutex_exit(&oplmsu_uinst->l_lock);
4981873Sraghuram mutex_exit(&oplmsu_uinst->u_lock);
4991873Sraghuram rw_exit(&oplmsu_uinst->lock);
5001873Sraghuram freemsg(mp);
5011873Sraghuram return (SUCCESS);
5021873Sraghuram }
5031873Sraghuram
5041772Sjl139090 if ((lpath->status == MSU_LINK_NU) ||
5051772Sjl139090 (lpath->status == MSU_SETID_NU) ||
5061772Sjl139090 (upath->traditional_status == MSU_WSTR_ACK) ||
5071772Sjl139090 (upath->traditional_status == MSU_WTCS_ACK) ||
5081772Sjl139090 (upath->traditional_status == MSU_WTMS_ACK) ||
5091772Sjl139090 (upath->traditional_status == MSU_WPPS_ACK) ||
5101772Sjl139090 (upath->traditional_status == MSU_WWSZ_ACK) ||
5111772Sjl139090 (upath->traditional_status == MSU_WCAR_ACK) ||
5121772Sjl139090 (upath->traditional_status == MSU_WSTP_ACK) ||
5131772Sjl139090 (upath->traditional_status == MSU_WPTH_CHG)) {
5141772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
5151772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
5161772Sjl139090 rw_exit(&oplmsu_uinst->lock);
5171772Sjl139090 freemsg(mp);
5181772Sjl139090 } else if ((upath->traditional_status == MSU_MAKE_INST) ||
5191772Sjl139090 (upath->traditional_status == MSU_STOP) ||
5201772Sjl139090 (upath->traditional_status == MSU_STANDBY) ||
5211772Sjl139090 (upath->traditional_status == MSU_SETID) ||
5221772Sjl139090 (upath->traditional_status == MSU_LINK)) {
5231772Sjl139090 oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL, upath->status,
5241772Sjl139090 MSU_FAIL);
5251772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
5261772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
5271772Sjl139090 rw_exit(&oplmsu_uinst->lock);
5281772Sjl139090 freemsg(mp);
5291772Sjl139090 } else if (upath->traditional_status == MSU_FAIL) {
5301772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
5311772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
5321772Sjl139090 rw_exit(&oplmsu_uinst->lock);
5331772Sjl139090 freemsg(mp);
5341772Sjl139090 } else if (upath->traditional_status == MSU_ACTIVE) {
5351772Sjl139090 altn_upath = oplmsu_search_standby();
5361772Sjl139090 if (altn_upath == NULL) {
5371772Sjl139090 oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL,
5381772Sjl139090 upath->status, MSU_FAIL);
5391772Sjl139090
5401772Sjl139090 oplmsu_clear_ioctl_path(lpath);
5411772Sjl139090 lpath->src_upath = NULL;
5421772Sjl139090 lpath->status = MSU_EXT_NOTUSED;
5431772Sjl139090 lpath->uinst = NULL;
5441772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
5451772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
5461772Sjl139090
5471772Sjl139090 OPLMSU_RWLOCK_UPGRADE();
5481772Sjl139090 oplmsu_uinst->lower_queue = NULL;
5491772Sjl139090 rw_exit(&oplmsu_uinst->lock);
5501772Sjl139090 freemsg(mp);
5511772Sjl139090 return (SUCCESS);
5521772Sjl139090 }
5531772Sjl139090
5541772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
5551772Sjl139090 if (oplmsu_cmn_allocmb(lrq, mp, &fmp, sizeof (char),
5561772Sjl139090 MSU_READ_SIDE) == FAILURE) {
5571772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
5581772Sjl139090 rw_exit(&oplmsu_uinst->lock);
5591772Sjl139090 return (FAILURE);
5601772Sjl139090 }
5611772Sjl139090
5621772Sjl139090 if (oplmsu_cmn_prechg(lrq, mp, MSU_READ_SIDE, &nmp, &term_ioctl,
5631772Sjl139090 &term_stat) == FAILURE) {
5641772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
5651772Sjl139090 rw_exit(&oplmsu_uinst->lock);
5661772Sjl139090 freeb(fmp);
5671772Sjl139090 return (FAILURE);
5681772Sjl139090 }
5691772Sjl139090
5701772Sjl139090 oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_FAIL,
5711772Sjl139090 upath->status, MSU_FAIL);
5721772Sjl139090
5731772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
5741772Sjl139090 lpath->uinst = NULL;
5751772Sjl139090
5761772Sjl139090 altn_upath->traditional_status = term_stat;
5771772Sjl139090 altn_lpath = altn_upath->lpath;
5781772Sjl139090
5791772Sjl139090 altn_lpath->hndl_mp = NULL;
5801772Sjl139090 altn_lpath->hndl_uqueue = NULL;
5811772Sjl139090 altn_lpath->src_upath = upath;
5821772Sjl139090 altn_lpath->status = MSU_EXT_VOID;
5831772Sjl139090 dst_queue = RD(altn_lpath->lower_queue);
5841772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
5851772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
5861772Sjl139090
5871772Sjl139090 OPLMSU_RWLOCK_UPGRADE();
5881772Sjl139090 oplmsu_uinst->lower_queue = NULL;
5891772Sjl139090 oplmsu_cmn_set_mflush(fmp);
5901772Sjl139090
5911772Sjl139090 if (ctrl != NULL) {
5921772Sjl139090 mutex_enter(&oplmsu_uinst->c_lock);
5931772Sjl139090 noenable(WR(ctrl->queue));
5941772Sjl139090 mutex_exit(&oplmsu_uinst->c_lock);
5951772Sjl139090
5961772Sjl139090 oplmsu_queue_flag = 1;
5971772Sjl139090 }
5981772Sjl139090
5991772Sjl139090 rw_exit(&oplmsu_uinst->lock);
6001772Sjl139090 freemsg(mp);
6011772Sjl139090
6021772Sjl139090 OPLMSU_TRACE(dst_queue, fmp, MSU_TRC_LO);
6031772Sjl139090 qreply(dst_queue, fmp);
6041772Sjl139090 OPLMSU_TRACE(dst_queue, nmp, MSU_TRC_LO);
6051772Sjl139090 qreply(dst_queue, nmp);
6061772Sjl139090 }
6071772Sjl139090 return (SUCCESS);
6081772Sjl139090 }
6091772Sjl139090
6101772Sjl139090 /* M_DATA[xoff/xon] was received from serial port */
6111772Sjl139090 int
oplmsu_lrdata_xoffxon(queue_t * lrq,mblk_t * mp)6121772Sjl139090 oplmsu_lrdata_xoffxon(queue_t *lrq, mblk_t *mp)
6131772Sjl139090 {
6141772Sjl139090 upath_t *upath, *stp_upath = NULL;
6151772Sjl139090 lpath_t *lpath, *stp_lpath = NULL;
6161772Sjl139090 mblk_t *nmp = NULL, *fmp = NULL;
6171772Sjl139090 ctrl_t *ctrl;
6181772Sjl139090 int term_stat, term_ioctl;
6191772Sjl139090
6201772Sjl139090 rw_enter(&oplmsu_uinst->lock, RW_READER);
6211772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
6221772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
6231772Sjl139090
6241772Sjl139090 if (oplmsu_uinst->lower_queue != NULL) {
6251772Sjl139090 /* Get lower path of active status */
6261772Sjl139090 stp_lpath = (lpath_t *)oplmsu_uinst->lower_queue->q_ptr;
6271772Sjl139090 if (stp_lpath != NULL) {
6281772Sjl139090 stp_upath =
6291772Sjl139090 oplmsu_search_upath_info(stp_lpath->path_no);
6301772Sjl139090 }
6311772Sjl139090 }
6321772Sjl139090
6331772Sjl139090 lpath = (lpath_t *)lrq->q_ptr;
6341772Sjl139090 upath = oplmsu_search_upath_info(lpath->path_no);
6351772Sjl139090
6361873Sraghuram if (upath == NULL) {
6371873Sraghuram mutex_exit(&oplmsu_uinst->l_lock);
6381873Sraghuram mutex_exit(&oplmsu_uinst->u_lock);
6391873Sraghuram rw_exit(&oplmsu_uinst->lock);
6401873Sraghuram freemsg(mp);
6411873Sraghuram return (SUCCESS);
6421873Sraghuram }
6431873Sraghuram
6441772Sjl139090 if ((stp_upath != NULL) && (stp_upath != upath)) {
6451772Sjl139090 if ((stp_upath->status != MSU_PSTAT_ACTIVE) ||
6461772Sjl139090 (stp_upath->traditional_status != MSU_ACTIVE)) {
6471772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
6481772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
6491772Sjl139090 rw_exit(&oplmsu_uinst->lock);
650*11311SSurya.Prakki@Sun.COM (void) putbq(lrq, mp);
6511772Sjl139090 return (FAILURE);
6521772Sjl139090 }
6531772Sjl139090 }
6541772Sjl139090
6551772Sjl139090 if ((upath->status == MSU_PSTAT_ACTIVE) &&
6561772Sjl139090 ((upath->traditional_status == MSU_ACTIVE) ||
6571772Sjl139090 (upath->traditional_status == MSU_WTCS_ACK) ||
6581772Sjl139090 (upath->traditional_status == MSU_WTMS_ACK) ||
6591772Sjl139090 (upath->traditional_status == MSU_WPPS_ACK) ||
6601772Sjl139090 (upath->traditional_status == MSU_WWSZ_ACK) ||
6611772Sjl139090 (upath->traditional_status == MSU_WCAR_ACK))) {
6621772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
6631772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
664*11311SSurya.Prakki@Sun.COM (void) oplmsu_rcmn_through_hndl(lrq, mp, MSU_NORM);
6651772Sjl139090 rw_exit(&oplmsu_uinst->lock);
6661772Sjl139090 return (SUCCESS);
6671772Sjl139090 } else if ((upath->status != MSU_PSTAT_STANDBY) ||
6681772Sjl139090 (upath->traditional_status != MSU_STANDBY)) {
6691772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
6701772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
6711772Sjl139090 rw_exit(&oplmsu_uinst->lock);
6721772Sjl139090 freemsg(mp);
6731772Sjl139090 cmn_err(CE_WARN, "oplmsu: lr-xoffxon: "
6741772Sjl139090 "Can't change to specified path");
6751772Sjl139090 return (SUCCESS);
6761772Sjl139090 }
6771772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
6781772Sjl139090
6791772Sjl139090 if (oplmsu_cmn_allocmb(lrq, mp, &fmp, sizeof (char), MSU_READ_SIDE) ==
6801772Sjl139090 FAILURE) {
6811772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
6821772Sjl139090 rw_exit(&oplmsu_uinst->lock);
6831772Sjl139090 return (FAILURE);
6841772Sjl139090 }
6851772Sjl139090
6861772Sjl139090 if (oplmsu_cmn_prechg(lrq, mp, MSU_READ_SIDE, &nmp, &term_ioctl,
6871772Sjl139090 &term_stat) == FAILURE) {
6881772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
6891772Sjl139090 rw_exit(&oplmsu_uinst->lock);
6901772Sjl139090 freeb(fmp);
6911772Sjl139090 return (FAILURE);
6921772Sjl139090 }
6931772Sjl139090
6941772Sjl139090 oplmsu_cmn_set_mflush(fmp);
6951772Sjl139090 upath->traditional_status = term_stat;
6961772Sjl139090
6971772Sjl139090 mutex_enter(&oplmsu_uinst->l_lock);
6981772Sjl139090 lpath->hndl_mp = mp;
6991772Sjl139090 lpath->hndl_uqueue = NULL;
7001772Sjl139090 lpath->src_upath = stp_upath;
7011772Sjl139090 lpath->status = MSU_EXT_VOID;
7021772Sjl139090
7031772Sjl139090 mutex_enter(&oplmsu_uinst->c_lock);
7041772Sjl139090 ctrl = oplmsu_uinst->user_ctrl;
7051772Sjl139090 if (term_stat != MSU_WPTH_CHG) {
7061772Sjl139090 /*
7071772Sjl139090 * Send termios to new active path and wait response
7081772Sjl139090 */
7091772Sjl139090 if (ctrl != NULL) {
7101772Sjl139090 noenable(WR(ctrl->queue));
7111772Sjl139090 }
7121772Sjl139090 mutex_exit(&oplmsu_uinst->c_lock);
7131772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
7141772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
7151772Sjl139090 rw_exit(&oplmsu_uinst->lock);
7161772Sjl139090
7171772Sjl139090 OPLMSU_TRACE(RD(lrq), fmp, MSU_TRC_LO);
7181772Sjl139090 qreply(RD(lrq), fmp);
7191772Sjl139090 OPLMSU_TRACE(RD(lrq), nmp, MSU_TRC_LO);
7201772Sjl139090 qreply(RD(lrq), nmp);
7211772Sjl139090 } else {
7221772Sjl139090 /*
7231772Sjl139090 * No termios messages are received. Change active path.
7241772Sjl139090 */
7251772Sjl139090
7261772Sjl139090 oplmsu_cmn_set_upath_sts(upath, MSU_PSTAT_ACTIVE, upath->status,
7271772Sjl139090 MSU_ACTIVE);
7281772Sjl139090
7291772Sjl139090 lpath->uinst = oplmsu_uinst;
7301772Sjl139090 lpath->src_upath = NULL;
7311772Sjl139090 lpath->status = MSU_EXT_NOTUSED;
7321772Sjl139090
7331772Sjl139090 /* Notify of the active path changing */
734*11311SSurya.Prakki@Sun.COM (void) prom_opl_switch_console(upath->ser_devcb.lsb);
7351772Sjl139090
736*11311SSurya.Prakki@Sun.COM (void) putq(WR(lrq), fmp);
7371772Sjl139090
7381772Sjl139090 /* Send XON to notify active path */
7391772Sjl139090 (void) oplmsu_cmn_put_xoffxon(WR(lrq), MSU_XON_4);
7401772Sjl139090
7411772Sjl139090 if (lpath->hndl_mp != NULL) {
7421772Sjl139090 /* Put a message(M_DATA) on a queue */
7431772Sjl139090 if (ctrl != NULL) {
744*11311SSurya.Prakki@Sun.COM (void) putq(RD(ctrl->queue), lpath->hndl_mp);
7451772Sjl139090 }
7461772Sjl139090 }
7471772Sjl139090
7481772Sjl139090 oplmsu_clear_ioctl_path(lpath);
7491772Sjl139090
7501772Sjl139090 if (ctrl != NULL) {
7511772Sjl139090 noenable(WR(ctrl->queue));
7521772Sjl139090 }
7531772Sjl139090
7541772Sjl139090 if ((stp_upath != NULL) && (stp_lpath != NULL)) {
7551772Sjl139090 /* Change the status of stop path */
7561772Sjl139090 oplmsu_cmn_set_upath_sts(stp_upath, MSU_PSTAT_STANDBY,
7571772Sjl139090 stp_upath->status, MSU_STANDBY);
7581772Sjl139090
7591772Sjl139090 oplmsu_clear_ioctl_path(stp_lpath);
7601772Sjl139090 stp_lpath->uinst = NULL;
7611772Sjl139090 stp_lpath->src_upath = NULL;
7621772Sjl139090 stp_lpath->status = MSU_EXT_NOTUSED;
7631772Sjl139090 }
7641772Sjl139090 #ifdef DEBUG
7651772Sjl139090 oplmsu_cmn_prt_pathname(upath->ser_devcb.dip);
7661772Sjl139090 #endif
7671772Sjl139090 /* Send XOFF to notify all standby paths */
7681772Sjl139090 oplmsu_cmn_putxoff_standby();
7691772Sjl139090 mutex_exit(&oplmsu_uinst->c_lock);
7701772Sjl139090 mutex_exit(&oplmsu_uinst->l_lock);
7711772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
7721772Sjl139090
7731772Sjl139090 OPLMSU_RWLOCK_UPGRADE();
7741772Sjl139090 mutex_enter(&oplmsu_uinst->u_lock);
7751772Sjl139090 oplmsu_uinst->lower_queue = lrq;
7761772Sjl139090 oplmsu_uinst->inst_status = oplmsu_get_inst_status();
7771772Sjl139090 mutex_exit(&oplmsu_uinst->u_lock);
7781772Sjl139090
7791772Sjl139090 if (ctrl != NULL) {
7801772Sjl139090 queue_t *temp_queue;
7811772Sjl139090
7821772Sjl139090 mutex_enter(&oplmsu_uinst->c_lock);
7831772Sjl139090 temp_queue = WR(ctrl->queue);
7841772Sjl139090 mutex_exit(&oplmsu_uinst->c_lock);
7851772Sjl139090
7861772Sjl139090 /* Reschedule a queue for service */
7871772Sjl139090 enableok(temp_queue);
7881772Sjl139090
7891772Sjl139090 oplmsu_queue_flag = 0;
7901772Sjl139090 oplmsu_wcmn_high_qenable(temp_queue, RW_WRITER);
7911772Sjl139090 }
7921772Sjl139090 rw_exit(&oplmsu_uinst->lock);
7931772Sjl139090 }
7941772Sjl139090 return (SUCCESS);
7951772Sjl139090 }
796