xref: /onnv-gate/usr/src/uts/sun4u/opl/io/dm2s.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 /*
2211066Srafael.vanoni@sun.com  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
231772Sjl139090  * Use is subject to license terms.
241772Sjl139090  */
251772Sjl139090 
261772Sjl139090 
271772Sjl139090 /*
281772Sjl139090  * DM2S - Domain side Mailbox to synchronous serial device driver.
291772Sjl139090  *
301772Sjl139090  * Description:
311772Sjl139090  * -----------
321772Sjl139090  * It is a streams driver which simulates a sync serial device on
331772Sjl139090  * top of a mailbox type of communication. That is, it sends/receives
341772Sjl139090  * frames as mailbox messages. The mailbox communication is provided
351772Sjl139090  * by another driver, which exports the mailbox interfaces.
361772Sjl139090  *
371772Sjl139090  * Synchronization:
381772Sjl139090  * ---------------
391772Sjl139090  * This driver uses streams perimeters to simplify the synchronization.
401772Sjl139090  * An inner perimeter D_MTPERMOD which protects the entire module,
411772Sjl139090  * that is only one thread exists inside the perimeter, is used. As
421772Sjl139090  * this driver supports only one instance and is not a high-performance
431772Sjl139090  * driver, D_MTPERMOD is highly suitable.
441772Sjl139090  *
451772Sjl139090  * All transmission and reception of frames is done inside the service
461772Sjl139090  * procedures so that all streams related operations are protected
471772Sjl139090  * by the perimeters.
481772Sjl139090  *
491772Sjl139090  * The mailbox event handler is the only asynchronous callback which
501772Sjl139090  * needs to be protected outside of the streams perimeters. This is
511772Sjl139090  * done using the module private lock('ms_lock');
521772Sjl139090  *
531772Sjl139090  */
541772Sjl139090 
551772Sjl139090 #include <sys/types.h>
561772Sjl139090 #include <sys/param.h>
571772Sjl139090 #include <sys/stream.h>
581772Sjl139090 #include <sys/cred.h>
591772Sjl139090 #include <sys/systm.h>
601772Sjl139090 #include <sys/sunddi.h>
611772Sjl139090 #include <sys/ddi.h>
621772Sjl139090 #include <sys/conf.h>
631772Sjl139090 #include <sys/modctl.h>
641772Sjl139090 #include <sys/mkdev.h>
651772Sjl139090 #include <sys/errno.h>
661772Sjl139090 #include <sys/debug.h>
671772Sjl139090 #include <sys/kbio.h>
681772Sjl139090 #include <sys/kmem.h>
691772Sjl139090 #include <sys/consdev.h>
701772Sjl139090 #include <sys/file.h>
711772Sjl139090 #include <sys/stropts.h>
721772Sjl139090 #include <sys/strsun.h>
731772Sjl139090 #include <sys/dlpi.h>
741772Sjl139090 #include <sys/stat.h>
751772Sjl139090 #include <sys/ser_sync.h>
761772Sjl139090 #include <sys/sysmacros.h>
771772Sjl139090 #include <sys/note.h>
781772Sjl139090 #include <sys/sdt.h>
791772Sjl139090 
801772Sjl139090 #include <sys/scfd/scfdscpif.h>
811772Sjl139090 #include <sys/dm2s.h>
821772Sjl139090 
831772Sjl139090 
841772Sjl139090 #define	DM2S_MODNAME	"dm2s"			/* Module name */
851772Sjl139090 #define	DM2S_TARGET_ID	0			/* Target ID of the peer */
861772Sjl139090 #define	DM2S_ID_NUM	0x4D53			/* 'M''S' */
871772Sjl139090 #define	DM2S_DEF_MTU	1504			/* Def. MTU size + PPP bytes */
881772Sjl139090 #define	DM2S_MAXPSZ	DM2S_DEF_MTU		/* Set it to the default MTU */
891772Sjl139090 #define	DM2S_LOWAT	(4 * 1024)		/* Low water mark */
901772Sjl139090 #define	DM2S_HIWAT	(12 * 1024)		/* High water mark */
911772Sjl139090 #define	DM2S_SM_TOUT	5000			/* Small timeout (5msec) */
921772Sjl139090 #define	DM2S_LG_TOUT	50000			/* Large timeout (50msec) */
931772Sjl139090 #define	DM2S_MB_TOUT	10000000		/* Mailbox timeout (10sec) */
941772Sjl139090 
951772Sjl139090 /*
961772Sjl139090  * Global variables
971772Sjl139090  */
981772Sjl139090 void		*dm2s_softstate = NULL;			/* Softstate pointer */
991772Sjl139090 
1001772Sjl139090 
1011772Sjl139090 /*
1021772Sjl139090  * Prototypes for the module related functions.
1031772Sjl139090  */
1041772Sjl139090 int dm2s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
1051772Sjl139090 int dm2s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
1061772Sjl139090 int dm2s_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
1071772Sjl139090     void *arg, void **result);
1081772Sjl139090 
1091772Sjl139090 /*
1101772Sjl139090  * Prototypes for the streams related functions.
1111772Sjl139090  */
1121772Sjl139090 int dm2s_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr);
1131772Sjl139090 int dm2s_close(queue_t *rq, int flag, cred_t *cred);
1141772Sjl139090 int dm2s_wput(queue_t *wq, mblk_t *mp);
1151772Sjl139090 int dm2s_rsrv(queue_t *rq);
1161772Sjl139090 int dm2s_wsrv(queue_t *wq);
1171772Sjl139090 
1181772Sjl139090 /*
1191772Sjl139090  * Prototypes for the internal functions.
1201772Sjl139090  */
1211772Sjl139090 void dm2s_start(queue_t *wq, dm2s_t *dm2sp);
1221772Sjl139090 void dm2s_event_handler(scf_event_t event, void *arg);
1231772Sjl139090 int dm2s_transmit(queue_t *wq, mblk_t *mp, target_id_t target, mkey_t key);
1241772Sjl139090 void dm2s_receive(dm2s_t *dm2sp);
1251772Sjl139090 void dm2s_wq_timeout(void *arg);
1261772Sjl139090 void dm2s_rq_timeout(void *arg);
1271772Sjl139090 void dm2s_bufcall_rcv(void *arg);
1281772Sjl139090 static clock_t dm2s_timeout_val(int error);
1291772Sjl139090 static void dm2s_cleanup(dm2s_t *dm2sp);
1301772Sjl139090 static int dm2s_mbox_init(dm2s_t *dm2sp);
1311772Sjl139090 static void dm2s_mbox_fini(dm2s_t *dm2sp);
1321772Sjl139090 static int dm2s_prep_scatgath(mblk_t *mp, uint32_t *numsg,
1331772Sjl139090     mscat_gath_t *sgp, int maxsg);
1341772Sjl139090 
1351772Sjl139090 #ifdef DEBUG
1361772Sjl139090 uint32_t dm2s_debug = DBG_WARN;
1371772Sjl139090 #endif /* DEBUG */
1381772Sjl139090 
1391772Sjl139090 
1401772Sjl139090 /*
1411772Sjl139090  * Streams and module related structures.
1421772Sjl139090  */
1431772Sjl139090 struct module_info dm2s_module_info = {
1441772Sjl139090 	DM2S_ID_NUM,		/* module ID number */
1451772Sjl139090 	DM2S_MODNAME,		/* module name. */
1461772Sjl139090 	0,			/* Minimum packet size (none) */
1471772Sjl139090 	DM2S_MAXPSZ,		/* Maximum packet size (none) */
1481772Sjl139090 	DM2S_HIWAT,		/* queue high water mark */
1491772Sjl139090 	DM2S_LOWAT		/* queue low water mark */
1501772Sjl139090 };
1511772Sjl139090 
1521772Sjl139090 struct qinit dm2s_rinit = {
1531772Sjl139090 	putq,			/* qi_putp */
1541772Sjl139090 	dm2s_rsrv,		/* qi_srvp */
1551772Sjl139090 	dm2s_open,		/* qi_qopen */
1561772Sjl139090 	dm2s_close,		/* qi_qlcose */
1571772Sjl139090 	NULL,			/* qi_qadmin */
1581772Sjl139090 	&dm2s_module_info,	/* qi_minfo */
1591772Sjl139090 	NULL			/* qi_mstat */
1601772Sjl139090 };
1611772Sjl139090 
1621772Sjl139090 struct qinit dm2s_winit = {
1631772Sjl139090 	dm2s_wput,		/* qi_putp */
1641772Sjl139090 	dm2s_wsrv,		/* qi_srvp */
1651772Sjl139090 	NULL,			/* qi_qopen */
1661772Sjl139090 	NULL,			/* qi_qlcose */
1671772Sjl139090 	NULL,			/* qi_qadmin */
1681772Sjl139090 	&dm2s_module_info,	/* qi_minfo */
1691772Sjl139090 	NULL			/* qi_mstat */
1701772Sjl139090 };
1711772Sjl139090 
1721772Sjl139090 
1731772Sjl139090 struct streamtab dm2s_streamtab = {
1741772Sjl139090 	&dm2s_rinit,
1751772Sjl139090 	&dm2s_winit,
1761772Sjl139090 	NULL,
1771772Sjl139090 	NULL
1781772Sjl139090 };
1791772Sjl139090 
1801772Sjl139090 DDI_DEFINE_STREAM_OPS(dm2s_ops, nulldev, nulldev, dm2s_attach,		\
1811772Sjl139090 	dm2s_detach, nodev, dm2s_info, D_NEW | D_MP | D_MTPERMOD,	\
1827656SSherry.Moore@Sun.COM 	&dm2s_streamtab, ddi_quiesce_not_supported);
1831772Sjl139090 
1841772Sjl139090 
1851772Sjl139090 struct modldrv modldrv = {
1861772Sjl139090 	&mod_driverops,
1877656SSherry.Moore@Sun.COM 	"OPL Mbox to Serial Driver",
1881772Sjl139090 	&dm2s_ops
1891772Sjl139090 };
1901772Sjl139090 
1911772Sjl139090 struct modlinkage modlinkage = {
1921772Sjl139090 	MODREV_1,
1931772Sjl139090 	&modldrv,
1941772Sjl139090 	NULL
1951772Sjl139090 };
1961772Sjl139090 
1971772Sjl139090 
1981772Sjl139090 /*
1991772Sjl139090  * _init - Module's init routine.
2001772Sjl139090  */
2011772Sjl139090 int
_init(void)2021772Sjl139090 _init(void)
2031772Sjl139090 {
2041772Sjl139090 	int ret;
2051772Sjl139090 
2061772Sjl139090 	if (ddi_soft_state_init(&dm2s_softstate, sizeof (dm2s_t), 1) != 0) {
2071772Sjl139090 		cmn_err(CE_WARN, "softstate initialization failed\n");
2081772Sjl139090 		return (DDI_FAILURE);
2091772Sjl139090 	}
2101772Sjl139090 	if ((ret = mod_install(&modlinkage)) != 0) {
2111772Sjl139090 		cmn_err(CE_WARN, "mod_install failed, error = %d", ret);
2121772Sjl139090 		ddi_soft_state_fini(&dm2s_softstate);
2131772Sjl139090 	}
2141772Sjl139090 	return (ret);
2151772Sjl139090 }
2161772Sjl139090 
2171772Sjl139090 /*
2181772Sjl139090  * _fini - Module's fini routine.
2191772Sjl139090  */
2201772Sjl139090 int
_fini(void)2211772Sjl139090 _fini(void)
2221772Sjl139090 {
2231772Sjl139090 	int ret;
2241772Sjl139090 
2251772Sjl139090 	if ((ret = mod_remove(&modlinkage)) != 0) {
2261772Sjl139090 		return (ret);
2271772Sjl139090 	}
2281772Sjl139090 	ddi_soft_state_fini(&dm2s_softstate);
2291772Sjl139090 	return (ret);
2301772Sjl139090 }
2311772Sjl139090 
2321772Sjl139090 /*
2331772Sjl139090  * _info - Module's info routine.
2341772Sjl139090  */
2351772Sjl139090 int
_info(struct modinfo * modinfop)2361772Sjl139090 _info(struct modinfo *modinfop)
2371772Sjl139090 {
2381772Sjl139090 	return (mod_info(&modlinkage, modinfop));
2391772Sjl139090 }
2401772Sjl139090 
2411772Sjl139090 /*
2421772Sjl139090  * dm2s_attach - Module's attach routine.
2431772Sjl139090  */
2441772Sjl139090 int
dm2s_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2451772Sjl139090 dm2s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2461772Sjl139090 {
2471772Sjl139090 	int instance;
2481772Sjl139090 	dm2s_t *dm2sp;
2491772Sjl139090 	char name[20];
2501772Sjl139090 
2511772Sjl139090 
2521772Sjl139090 	instance = ddi_get_instance(dip);
2531772Sjl139090 
2541772Sjl139090 	/* Only one instance is supported. */
2551772Sjl139090 	if (instance != 0) {
2561772Sjl139090 		cmn_err(CE_WARN, "only one instance is supported");
2571772Sjl139090 		return (DDI_FAILURE);
2581772Sjl139090 	}
2591772Sjl139090 
2601772Sjl139090 	if (cmd != DDI_ATTACH) {
2611772Sjl139090 		return (DDI_FAILURE);
2621772Sjl139090 	}
2631772Sjl139090 	if (ddi_soft_state_zalloc(dm2s_softstate, instance) != DDI_SUCCESS) {
2641772Sjl139090 		cmn_err(CE_WARN, "softstate allocation failure");
2651772Sjl139090 		return (DDI_FAILURE);
2661772Sjl139090 	}
2671772Sjl139090 	dm2sp = (dm2s_t *)ddi_get_soft_state(dm2s_softstate, instance);
2681772Sjl139090 	if (dm2sp == NULL) {
2691772Sjl139090 		ddi_soft_state_free(dm2s_softstate, instance);
2701772Sjl139090 		cmn_err(CE_WARN, "softstate allocation failure.");
2711772Sjl139090 		return (DDI_FAILURE);
2721772Sjl139090 	}
2731772Sjl139090 	dm2sp->ms_dip = dip;
2748459SJerry.Gilliam@Sun.COM 	dm2sp->ms_major = ddi_driver_major(dip);
2751772Sjl139090 	dm2sp->ms_ppa = instance;
2761772Sjl139090 
2771772Sjl139090 	/*
2781772Sjl139090 	 * Get an interrupt block cookie corresponding to the
2791772Sjl139090 	 * interrupt priority of the event handler.
2801772Sjl139090 	 * Assert that the event priority is not re-defined to
2811772Sjl139090 	 * some higher priority.
2821772Sjl139090 	 */
2831772Sjl139090 	/* LINTED */
2841772Sjl139090 	ASSERT(SCF_EVENT_PRI == DDI_SOFTINT_LOW);
2851772Sjl139090 	if (ddi_get_soft_iblock_cookie(dip, SCF_EVENT_PRI,
2861772Sjl139090 	    &dm2sp->ms_ibcookie) != DDI_SUCCESS) {
2871772Sjl139090 		cmn_err(CE_WARN, "ddi_get_soft_iblock_cookie failed.");
2881772Sjl139090 		goto error;
2891772Sjl139090 	}
2901772Sjl139090 	mutex_init(&dm2sp->ms_lock, NULL, MUTEX_DRIVER,
2911772Sjl139090 	    (void *)dm2sp->ms_ibcookie);
2921772Sjl139090 
2931772Sjl139090 	dm2sp->ms_clean |= DM2S_CLEAN_LOCK;
2941772Sjl139090 	cv_init(&dm2sp->ms_wait, NULL, CV_DRIVER, NULL);
2951772Sjl139090 	dm2sp->ms_clean |= DM2S_CLEAN_CV;
2961772Sjl139090 
2971772Sjl139090 	(void) sprintf(name, "%s%d", DM2S_MODNAME, instance);
2981772Sjl139090 	if (ddi_create_minor_node(dip, name, S_IFCHR, instance,
2991772Sjl139090 	    DDI_PSEUDO, NULL) == DDI_FAILURE) {
3001772Sjl139090 		ddi_remove_minor_node(dip, NULL);
3011772Sjl139090 		cmn_err(CE_WARN, "Device node creation failed.");
3021772Sjl139090 		goto error;
3031772Sjl139090 	}
3041772Sjl139090 
3051772Sjl139090 	dm2sp->ms_clean |= DM2S_CLEAN_NODE;
3061772Sjl139090 	ddi_set_driver_private(dip, (caddr_t)dm2sp);
3071772Sjl139090 	ddi_report_dev(dip);
3081772Sjl139090 	return (DDI_SUCCESS);
3091772Sjl139090 error:
3101772Sjl139090 	dm2s_cleanup(dm2sp);
3111772Sjl139090 	return (DDI_FAILURE);
3121772Sjl139090 }
3131772Sjl139090 
3141772Sjl139090 /*
3151772Sjl139090  * dm2s_info - Module's info routine.
3161772Sjl139090  */
3171772Sjl139090 /*ARGSUSED*/
3181772Sjl139090 int
dm2s_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)3191772Sjl139090 dm2s_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
3201772Sjl139090 {
3211772Sjl139090 	dm2s_t	*dm2sp;
3221772Sjl139090 	minor_t	minor;
3231772Sjl139090 	int	ret = DDI_FAILURE;
3241772Sjl139090 
3251772Sjl139090 	switch (infocmd) {
3261772Sjl139090 	case DDI_INFO_DEVT2DEVINFO:
3271772Sjl139090 		minor = getminor((dev_t)arg);
3281772Sjl139090 		dm2sp = (dm2s_t *)ddi_get_soft_state(dm2s_softstate, minor);
3291772Sjl139090 		if (dm2sp == NULL) {
3301772Sjl139090 			*result = NULL;
3311772Sjl139090 		} else {
3321772Sjl139090 			*result = dm2sp->ms_dip;
3331772Sjl139090 			ret = DDI_SUCCESS;
3341772Sjl139090 		}
3351772Sjl139090 		break;
3361772Sjl139090 
3371772Sjl139090 	case DDI_INFO_DEVT2INSTANCE:
3381772Sjl139090 		minor = getminor((dev_t)arg);
3391772Sjl139090 		*result = (void *)(uintptr_t)minor;
3401772Sjl139090 		ret = DDI_SUCCESS;
3411772Sjl139090 		break;
3421772Sjl139090 
3431772Sjl139090 	default:
3441772Sjl139090 		break;
3451772Sjl139090 	}
3461772Sjl139090 	return (ret);
3471772Sjl139090 }
3481772Sjl139090 
3491772Sjl139090 /*
3501772Sjl139090  * dm2s_detach - Module's detach routine.
3511772Sjl139090  */
3521772Sjl139090 int
dm2s_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3531772Sjl139090 dm2s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3541772Sjl139090 {
3551772Sjl139090 	int instance;
3561772Sjl139090 	dm2s_t *dm2sp;
3571772Sjl139090 
3581772Sjl139090 	if (cmd != DDI_DETACH) {
3591772Sjl139090 		return (DDI_FAILURE);
3601772Sjl139090 	}
3611772Sjl139090 
3621772Sjl139090 	instance = ddi_get_instance(dip);
3631772Sjl139090 	dm2sp = (dm2s_t *)ddi_get_soft_state(dm2s_softstate, instance);
3641772Sjl139090 	if (dm2sp == NULL) {
3651772Sjl139090 		return (DDI_FAILURE);
3661772Sjl139090 	}
3671772Sjl139090 
3681772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
3691772Sjl139090 
3701772Sjl139090 	/* Check if the mailbox is still in use. */
3711772Sjl139090 	if (dm2sp->ms_state & DM2S_MB_INITED) {
3721772Sjl139090 		mutex_exit(&dm2sp->ms_lock);
3731772Sjl139090 		cmn_err(CE_WARN, "Mailbox in use: Detach failed");
3741772Sjl139090 		return (DDI_FAILURE);
3751772Sjl139090 	}
3761772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
3771772Sjl139090 	dm2s_cleanup(dm2sp);
3781772Sjl139090 	return (DDI_SUCCESS);
3791772Sjl139090 }
3801772Sjl139090 
3811772Sjl139090 /*
3821772Sjl139090  * dm2s_open - Device open routine.
3831772Sjl139090  *
3841772Sjl139090  * Only one open supported. Clone open is not supported.
3851772Sjl139090  */
3861772Sjl139090 /* ARGSUSED */
3871772Sjl139090 int
dm2s_open(queue_t * rq,dev_t * dev,int flag,int sflag,cred_t * cr)3881772Sjl139090 dm2s_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
3891772Sjl139090 {
3901772Sjl139090 	dm2s_t *dm2sp;
3911772Sjl139090 	int instance = getminor(*dev);
3921772Sjl139090 	int ret = 0;
3931772Sjl139090 
3941772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_open: called\n"));
3951772Sjl139090 	if (sflag == CLONEOPEN)	{
3961772Sjl139090 		/* Clone open not supported */
3971772Sjl139090 		DPRINTF(DBG_WARN, ("dm2s_open: clone open not supported\n"));
3981772Sjl139090 		return (ENOTSUP);
3991772Sjl139090 	}
4001772Sjl139090 
4011772Sjl139090 	if (rq->q_ptr != NULL) {
4021772Sjl139090 		DPRINTF(DBG_WARN, ("dm2s_open: already opened\n"));
4031772Sjl139090 		return (EBUSY);
4041772Sjl139090 	}
4051772Sjl139090 
4061772Sjl139090 	if ((dm2sp = ddi_get_soft_state(dm2s_softstate, instance)) == NULL) {
4071772Sjl139090 		DPRINTF(DBG_WARN, ("dm2s_open: instance not found\n"));
4081772Sjl139090 		return (ENODEV);
4091772Sjl139090 	}
4101772Sjl139090 
4111772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
4121772Sjl139090 	if (dm2sp->ms_state & DM2S_OPENED) {
4131772Sjl139090 		/* Only one open supported */
4141772Sjl139090 		mutex_exit(&dm2sp->ms_lock);
4151772Sjl139090 		DPRINTF(DBG_WARN, ("dm2s_open: already opened\n"));
4161772Sjl139090 		return (EBUSY);
4171772Sjl139090 	}
4181772Sjl139090 
4191772Sjl139090 	dm2sp->ms_state |= DM2S_OPENED;
4201772Sjl139090 	/* Initialize the mailbox. */
4211772Sjl139090 	if ((ret = dm2s_mbox_init(dm2sp)) != 0) {
4221772Sjl139090 		dm2sp->ms_state = 0;
4231772Sjl139090 		mutex_exit(&dm2sp->ms_lock);
4241772Sjl139090 		return (ret);
4251772Sjl139090 	}
4261772Sjl139090 	rq->q_ptr = WR(rq)->q_ptr = (void *)dm2sp;
4271772Sjl139090 	dm2sp->ms_rq = rq;
4281772Sjl139090 	dm2sp->ms_wq = WR(rq);
4291772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
4301772Sjl139090 
4311772Sjl139090 	if (ret == 0) {
4321772Sjl139090 		qprocson(rq);		/* now schedule our queue */
4331772Sjl139090 	}
4341772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_open: ret=%d\n", ret));
4351772Sjl139090 	return (ret);
4361772Sjl139090 }
4371772Sjl139090 
4381772Sjl139090 /*
4391772Sjl139090  * dm2s_close - Device close routine.
4401772Sjl139090  */
4411772Sjl139090 /* ARGSUSED */
4421772Sjl139090 int
dm2s_close(queue_t * rq,int flag,cred_t * cred)4431772Sjl139090 dm2s_close(queue_t *rq, int flag, cred_t *cred)
4441772Sjl139090 {
4451772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)rq->q_ptr;
4461772Sjl139090 
4471772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_close: called\n"));
4481772Sjl139090 	if (dm2sp == NULL) {
4491772Sjl139090 		/* Already closed once */
4501772Sjl139090 		return (ENODEV);
4511772Sjl139090 	}
4521772Sjl139090 
4531772Sjl139090 	/* Close the lower layer first */
4541772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
4551772Sjl139090 	(void) scf_mb_flush(dm2sp->ms_target, dm2sp->ms_key, MB_FLUSH_ALL);
4561772Sjl139090 	dm2s_mbox_fini(dm2sp);
4571772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
4581772Sjl139090 
4591772Sjl139090 	/*
4601772Sjl139090 	 * Now we can assume that no asynchronous callbacks exist.
4611772Sjl139090 	 * Poison the stream head so that we can't be pushed again.
4621772Sjl139090 	 */
4631772Sjl139090 	(void) putnextctl(rq, M_HANGUP);
4641772Sjl139090 	qprocsoff(rq);
4651772Sjl139090 	if (dm2sp->ms_rbufcid != 0) {
4661772Sjl139090 		qunbufcall(rq, dm2sp->ms_rbufcid);
4671772Sjl139090 		dm2sp->ms_rbufcid = 0;
4681772Sjl139090 	}
4691772Sjl139090 	if (dm2sp->ms_rq_timeoutid != 0) {
4701772Sjl139090 		DTRACE_PROBE1(dm2s_rqtimeout__cancel, dm2s_t, dm2sp);
4711772Sjl139090 		(void) quntimeout(dm2sp->ms_rq, dm2sp->ms_rq_timeoutid);
4721772Sjl139090 		dm2sp->ms_rq_timeoutid = 0;
4731772Sjl139090 	}
4741772Sjl139090 	if (dm2sp->ms_wq_timeoutid != 0) {
4751772Sjl139090 		DTRACE_PROBE1(dm2s_wqtimeout__cancel, dm2s_t, dm2sp);
4761772Sjl139090 		(void) quntimeout(dm2sp->ms_wq, dm2sp->ms_wq_timeoutid);
4771772Sjl139090 		dm2sp->ms_wq_timeoutid = 0;
4781772Sjl139090 	}
4791772Sjl139090 	/*
4801772Sjl139090 	 * Now we can really mark it closed.
4811772Sjl139090 	 */
4821772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
4831772Sjl139090 	dm2sp->ms_rq = dm2sp->ms_wq = NULL;
4841772Sjl139090 	dm2sp->ms_state &= ~DM2S_OPENED;
4851772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
4861772Sjl139090 
4871772Sjl139090 	rq->q_ptr = WR(rq)->q_ptr = NULL;
4881772Sjl139090 	(void) qassociate(rq, -1);
4891772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_close: successfully closed\n"));
4901772Sjl139090 	return (0);
4911772Sjl139090 }
4921772Sjl139090 
4931772Sjl139090 /*
4941772Sjl139090  * dm2s_rsrv - Streams read side service procedure.
4951772Sjl139090  *
4961772Sjl139090  * All messages are received in the service procedure
4971772Sjl139090  * only. This is done to simplify the streams synchronization.
4981772Sjl139090  */
4991772Sjl139090 int
dm2s_rsrv(queue_t * rq)5001772Sjl139090 dm2s_rsrv(queue_t *rq)
5011772Sjl139090 {
5021772Sjl139090 	mblk_t *mp;
5031772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)rq->q_ptr;
5041772Sjl139090 
5051772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_rsrv: called\n"));
5061772Sjl139090 	ASSERT(dm2sp != NULL);
5071772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
5081772Sjl139090 
5091772Sjl139090 	/* Receive if there are any messages waiting in the mailbox. */
5101772Sjl139090 	dm2s_receive(dm2sp);
5111772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
5121772Sjl139090 
5131772Sjl139090 	/* Send the received messages up the stream. */
5141772Sjl139090 	while ((mp = getq(rq)) != NULL) {
5151772Sjl139090 		if (canputnext(rq)) {
5161772Sjl139090 			putnext(rq, mp);
5171772Sjl139090 		} else {
518*11311SSurya.Prakki@Sun.COM 			(void) putbq(rq, mp);
5191772Sjl139090 			break;
5201772Sjl139090 		}
5211772Sjl139090 	}
5221772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_rsrv: return\n"));
5231772Sjl139090 	return (0);
5241772Sjl139090 }
5251772Sjl139090 
5261772Sjl139090 /*
5271772Sjl139090  * dm2s_wsrv - Streams write side service procedure.
5281772Sjl139090  *
5291772Sjl139090  * All messages are transmitted in the service procedure
5301772Sjl139090  * only. This is done to simplify the streams synchronization.
5311772Sjl139090  */
5321772Sjl139090 int
dm2s_wsrv(queue_t * wq)5331772Sjl139090 dm2s_wsrv(queue_t *wq)
5341772Sjl139090 {
5351772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)wq->q_ptr;
5361772Sjl139090 
5371772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_wsrv: called\n"));
5381772Sjl139090 	ASSERT(dm2sp != NULL);
5391772Sjl139090 	/* Lets cancel any timeouts waiting to be scheduled. */
5401772Sjl139090 	if (dm2sp->ms_wq_timeoutid != 0) {
5411772Sjl139090 		DTRACE_PROBE1(dm2s_wqtimeout__cancel, dm2s_t, dm2sp);
5421772Sjl139090 		(void) quntimeout(dm2sp->ms_wq, dm2sp->ms_wq_timeoutid);
5431772Sjl139090 		dm2sp->ms_wq_timeoutid = 0;
5441772Sjl139090 	}
5451772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
5461772Sjl139090 	dm2s_start(wq, dm2sp);
5471772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
5481772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_wsrv: return\n"));
5491772Sjl139090 	return (0);
5501772Sjl139090 }
5511772Sjl139090 
5521772Sjl139090 /*
5531772Sjl139090  * dm2s_wput - Streams write side put routine.
5541772Sjl139090  *
5551772Sjl139090  * All M_DATA messages are queued so that they are transmitted in
5561772Sjl139090  * the service procedure. This is done to simplify the streams
5571772Sjl139090  * synchronization. Other messages are handled appropriately.
5581772Sjl139090  */
5591772Sjl139090 int
dm2s_wput(queue_t * wq,mblk_t * mp)5601772Sjl139090 dm2s_wput(queue_t *wq, mblk_t *mp)
5611772Sjl139090 {
5621772Sjl139090 	dm2s_t	*dm2sp = (dm2s_t *)wq->q_ptr;
5631772Sjl139090 
5641772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_wput: called\n"));
5651772Sjl139090 	if (dm2sp == NULL) {
5661772Sjl139090 		return (ENODEV);   /* Can't happen. */
5671772Sjl139090 	}
5681772Sjl139090 
5691772Sjl139090 	switch (mp->b_datap->db_type) {
5701772Sjl139090 	case (M_DATA):
5711772Sjl139090 		DPRINTF(DBG_DRV, ("dm2s_wput: M_DATA message\n"));
5721772Sjl139090 		while (mp->b_wptr == mp->b_rptr) {
5731772Sjl139090 			mblk_t *mp1;
5741772Sjl139090 
5751772Sjl139090 			mp1 = unlinkb(mp);
5761772Sjl139090 			freemsg(mp);
5771772Sjl139090 			mp = mp1;
5781772Sjl139090 			if (mp == NULL) {
5791772Sjl139090 				return (0);
5801772Sjl139090 			}
5811772Sjl139090 		}
5821772Sjl139090 
5831772Sjl139090 		/*
5841772Sjl139090 		 * Simply queue the message and handle it in the service
5851772Sjl139090 		 * procedure.
5861772Sjl139090 		 */
5871772Sjl139090 		(void) putq(wq, mp);
5881772Sjl139090 		qenable(wq);
5891772Sjl139090 		return (0);
5901772Sjl139090 
5911772Sjl139090 	case (M_PROTO):
5921772Sjl139090 		DPRINTF(DBG_DRV, ("dm2s_wput: M_PROTO message\n"));
5931772Sjl139090 		/* We don't expect this */
5941772Sjl139090 		mp->b_datap->db_type = M_ERROR;
5951772Sjl139090 		mp->b_rptr = mp->b_wptr = mp->b_datap->db_base;
5961772Sjl139090 		*mp->b_wptr++ = EPROTO;
5971772Sjl139090 		qreply(wq, mp);
5981772Sjl139090 		return (EINVAL);
5991772Sjl139090 
6001772Sjl139090 	case (M_IOCTL):
6011772Sjl139090 		DPRINTF(DBG_DRV, ("dm2s_wput: M_IOCTL message\n"));
6021772Sjl139090 		if (MBLKL(mp) < sizeof (struct iocblk)) {
6031772Sjl139090 			freemsg(mp);
6041772Sjl139090 			return (0);
6051772Sjl139090 		}
6061772Sjl139090 		/*
6071772Sjl139090 		 * No ioctls required to be supported by this driver, so
6081772Sjl139090 		 * return EINVAL for all ioctls.
6091772Sjl139090 		 */
6101772Sjl139090 		miocnak(wq, mp, 0, EINVAL);
6111772Sjl139090 		break;
6121772Sjl139090 
6131772Sjl139090 	case (M_CTL):
6141772Sjl139090 		DPRINTF(DBG_DRV, ("dm2s_wput: M_CTL message\n"));
6151772Sjl139090 		/*
6161772Sjl139090 		 * No M_CTL messages need to supported by this driver,
6171772Sjl139090 		 * so simply ignore them.
6181772Sjl139090 		 */
6191772Sjl139090 		freemsg(mp);
6201772Sjl139090 		break;
6211772Sjl139090 
6221772Sjl139090 	case (M_FLUSH):
6231772Sjl139090 		DPRINTF(DBG_DRV, (
6241772Sjl139090 		    "dm2s_wput: M_FLUSH message 0x%X\n", *mp->b_rptr));
6251772Sjl139090 		if (*mp->b_rptr & FLUSHW) {	/* Flush write-side */
6261772Sjl139090 			(void) scf_mb_flush(dm2sp->ms_target, dm2sp->ms_key,
6271772Sjl139090 			    MB_FLUSH_SEND);
6281772Sjl139090 			flushq(wq, FLUSHDATA);
6291772Sjl139090 			*mp->b_rptr &= ~FLUSHW;
6301772Sjl139090 		}
6311772Sjl139090 		if (*mp->b_rptr & FLUSHR) {
6321772Sjl139090 			(void) scf_mb_flush(dm2sp->ms_target, dm2sp->ms_key,
6331772Sjl139090 			    MB_FLUSH_RECEIVE);
6341772Sjl139090 			flushq(RD(wq), FLUSHDATA);
6351772Sjl139090 			qreply(wq, mp);
6361772Sjl139090 		} else {
6371772Sjl139090 			freemsg(mp);
6381772Sjl139090 		}
6391772Sjl139090 		break;
6401772Sjl139090 
6411772Sjl139090 	default:
6421772Sjl139090 		DPRINTF(DBG_DRV, ("dm2s_wput: UNKNOWN message\n"));
6431772Sjl139090 		freemsg(mp);
6441772Sjl139090 
6451772Sjl139090 	}
6461772Sjl139090 	return (0);
6471772Sjl139090 }
6481772Sjl139090 
6491772Sjl139090 /*
6501772Sjl139090  * dm2s_cleanup - Cleanup routine.
6511772Sjl139090  */
6521772Sjl139090 static void
dm2s_cleanup(dm2s_t * dm2sp)6531772Sjl139090 dm2s_cleanup(dm2s_t *dm2sp)
6541772Sjl139090 {
6551772Sjl139090 	char name[20];
6561772Sjl139090 
6571772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_cleanup: called\n"));
6581772Sjl139090 	ASSERT(dm2sp != NULL);
6591772Sjl139090 	if (dm2sp->ms_clean & DM2S_CLEAN_NODE) {
6601772Sjl139090 		(void) sprintf(name, "%s%d", DM2S_MODNAME, dm2sp->ms_ppa);
6611772Sjl139090 		ddi_remove_minor_node(dm2sp->ms_dip, name);
6621772Sjl139090 	}
6631772Sjl139090 	if (dm2sp->ms_clean & DM2S_CLEAN_LOCK)
6641772Sjl139090 		mutex_destroy(&dm2sp->ms_lock);
6651772Sjl139090 	if (dm2sp->ms_clean & DM2S_CLEAN_CV)
6661772Sjl139090 		cv_destroy(&dm2sp->ms_wait);
6671772Sjl139090 	ddi_set_driver_private(dm2sp->ms_dip, NULL);
6681772Sjl139090 	ddi_soft_state_free(dm2s_softstate, dm2sp->ms_ppa);
6691772Sjl139090 }
6701772Sjl139090 
6711772Sjl139090 /*
6721772Sjl139090  * dm2s_mbox_init - Mailbox specific initialization.
6731772Sjl139090  */
6741772Sjl139090 static int
dm2s_mbox_init(dm2s_t * dm2sp)6751772Sjl139090 dm2s_mbox_init(dm2s_t *dm2sp)
6761772Sjl139090 {
6771772Sjl139090 	int ret;
67811066Srafael.vanoni@sun.com 	clock_t tout = drv_usectohz(DM2S_MB_TOUT);
6791772Sjl139090 
6801772Sjl139090 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
6811772Sjl139090 	dm2sp->ms_target = DM2S_TARGET_ID;
6821772Sjl139090 	dm2sp->ms_key = DSCP_KEY;
6831772Sjl139090 	dm2sp->ms_state &= ~DM2S_MB_INITED;
6841772Sjl139090 
6851772Sjl139090 	/* Iterate until mailbox gets connected */
6861772Sjl139090 	while (!(dm2sp->ms_state & DM2S_MB_CONN)) {
6871772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_mbox_init: calling mb_init\n"));
6881772Sjl139090 		ret = scf_mb_init(dm2sp->ms_target, dm2sp->ms_key,
6891772Sjl139090 		    dm2s_event_handler, (void *)dm2sp);
6901772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_mbox_init: mb_init ret=%d\n", ret));
6911772Sjl139090 
6922126Sraghuram 		if (ret != 0) {
6932126Sraghuram 			DPRINTF(DBG_MBOX,
6942126Sraghuram 			    ("dm2s_mbox_init: failed ret =%d\n", ret));
6952126Sraghuram 			DTRACE_PROBE1(dm2s_mbox_fail, int, ret);
6962126Sraghuram 		} else {
6971772Sjl139090 			dm2sp->ms_state |= DM2S_MB_INITED;
6981772Sjl139090 
6991772Sjl139090 			/* Block until the mailbox is ready to communicate. */
7001772Sjl139090 			while (!(dm2sp->ms_state &
7011772Sjl139090 			    (DM2S_MB_CONN | DM2S_MB_DISC))) {
7021772Sjl139090 
7031772Sjl139090 				if (cv_wait_sig(&dm2sp->ms_wait,
7041772Sjl139090 				    &dm2sp->ms_lock) <= 0) {
7051772Sjl139090 					/* interrupted */
7061772Sjl139090 					ret = EINTR;
7071772Sjl139090 					break;
7081772Sjl139090 				}
7091772Sjl139090 			}
7101772Sjl139090 		}
7111772Sjl139090 
7121772Sjl139090 		if ((ret != 0) || (dm2sp->ms_state & DM2S_MB_DISC)) {
7131772Sjl139090 
7142126Sraghuram 			if (dm2sp->ms_state & DM2S_MB_INITED) {
7152126Sraghuram 				(void) scf_mb_fini(dm2sp->ms_target,
7162126Sraghuram 				    dm2sp->ms_key);
7172126Sraghuram 			}
7182126Sraghuram 			if (dm2sp->ms_state & DM2S_MB_DISC) {
7192126Sraghuram 				DPRINTF(DBG_WARN,
7202126Sraghuram 				    ("dm2s_mbox_init: mbox DISC_ERROR\n"));
7212126Sraghuram 				DTRACE_PROBE1(dm2s_mbox_fail,
7222126Sraghuram 				    int, DM2S_MB_DISC);
7232126Sraghuram 			}
7242126Sraghuram 
7252126Sraghuram 			dm2sp->ms_state &= ~(DM2S_MB_INITED | DM2S_MB_DISC |
7262126Sraghuram 			    DM2S_MB_CONN);
7272126Sraghuram 
7282126Sraghuram 			if (ret == EINTR) {
7292126Sraghuram 				return (ret);
7302126Sraghuram 			}
7311772Sjl139090 
7321772Sjl139090 			/*
7331772Sjl139090 			 * If there was failure, then wait for
7341772Sjl139090 			 * DM2S_MB_TOUT secs and retry again.
7351772Sjl139090 			 */
7361772Sjl139090 
7371772Sjl139090 			DPRINTF(DBG_MBOX, ("dm2s_mbox_init: waiting...\n"));
73811066Srafael.vanoni@sun.com 			ret = cv_reltimedwait_sig(&dm2sp->ms_wait,
73911066Srafael.vanoni@sun.com 			    &dm2sp->ms_lock, tout, TR_CLOCK_TICK);
7401772Sjl139090 			if (ret == 0) {
7411772Sjl139090 				/* if interrupted, return immediately. */
7421772Sjl139090 				DPRINTF(DBG_MBOX,
7431772Sjl139090 				    ("dm2s_mbox_init: interrupted\n"));
7441772Sjl139090 				return (EINTR);
7451772Sjl139090 			}
7461772Sjl139090 		}
7471772Sjl139090 	}
7481772Sjl139090 
7491772Sjl139090 	/*
7501772Sjl139090 	 * Obtain the max size of a single message.
7511772Sjl139090 	 * NOTE: There is no mechanism to update the
7521772Sjl139090 	 * upperlayers dynamically, so we expect this
7531772Sjl139090 	 * size to be atleast the default MTU size.
7541772Sjl139090 	 */
7551772Sjl139090 	ret = scf_mb_ctrl(dm2sp->ms_target, dm2sp->ms_key,
7561772Sjl139090 	    SCF_MBOP_MAXMSGSIZE, &dm2sp->ms_mtu);
7571772Sjl139090 
7581772Sjl139090 	if ((ret == 0) && (dm2sp->ms_mtu < DM2S_DEF_MTU)) {
7591772Sjl139090 		cmn_err(CE_WARN, "Max message size expected >= %d "
7601772Sjl139090 		    "but found %d\n", DM2S_DEF_MTU, dm2sp->ms_mtu);
7611772Sjl139090 		ret = EIO;
7621772Sjl139090 	}
7631772Sjl139090 
7641772Sjl139090 	if (ret != 0) {
7651772Sjl139090 		dm2sp->ms_state &= ~DM2S_MB_INITED;
7661772Sjl139090 		(void) scf_mb_fini(dm2sp->ms_target, dm2sp->ms_key);
7671772Sjl139090 	}
7681772Sjl139090 	DPRINTF(DBG_MBOX, ("dm2s_mbox_init: mb_init ret=%d\n", ret));
7691772Sjl139090 	return (ret);
7701772Sjl139090 }
7711772Sjl139090 
7721772Sjl139090 /*
7731772Sjl139090  * dm2s_mbox_fini - Mailbox de-initialization.
7741772Sjl139090  */
7751772Sjl139090 static void
dm2s_mbox_fini(dm2s_t * dm2sp)7761772Sjl139090 dm2s_mbox_fini(dm2s_t *dm2sp)
7771772Sjl139090 {
7781772Sjl139090 	int ret;
7791772Sjl139090 
7801772Sjl139090 	ASSERT(dm2sp != NULL);
7811772Sjl139090 	if (dm2sp->ms_state & DM2S_MB_INITED) {
7821772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_mbox_fini: calling mb_fini\n"));
7831772Sjl139090 		ret =  scf_mb_fini(dm2sp->ms_target, dm2sp->ms_key);
7841772Sjl139090 		if (ret != 0) {
7851772Sjl139090 			cmn_err(CE_WARN,
7861772Sjl139090 			    "Failed to close the Mailbox error =%d", ret);
7871772Sjl139090 		}
7881772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_mbox_fini: mb_fini ret=%d\n", ret));
7891772Sjl139090 		dm2sp->ms_state &= ~(DM2S_MB_INITED |DM2S_MB_CONN |
7901772Sjl139090 		    DM2S_MB_DISC);
7911772Sjl139090 	}
7921772Sjl139090 }
7931772Sjl139090 
7941772Sjl139090 /*
7951772Sjl139090  * dm2s_event_handler - Mailbox event handler.
7961772Sjl139090  */
7971772Sjl139090 void
dm2s_event_handler(scf_event_t event,void * arg)7981772Sjl139090 dm2s_event_handler(scf_event_t event, void *arg)
7991772Sjl139090 {
8001772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)arg;
8011772Sjl139090 	queue_t	*rq;
8021772Sjl139090 
8031772Sjl139090 	ASSERT(dm2sp != NULL);
8041772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
8051772Sjl139090 	if (!(dm2sp->ms_state & DM2S_MB_INITED)) {
8061772Sjl139090 		/*
8071772Sjl139090 		 * Ignore all events if the state flag indicates that the
8081772Sjl139090 		 * mailbox not initialized, this may happen during the close.
8091772Sjl139090 		 */
8101772Sjl139090 		mutex_exit(&dm2sp->ms_lock);
8111772Sjl139090 		DPRINTF(DBG_MBOX,
8121772Sjl139090 		    ("Event(0x%X) received - Mailbox not inited\n", event));
8131772Sjl139090 		return;
8141772Sjl139090 	}
8151772Sjl139090 	switch (event) {
8161772Sjl139090 	case SCF_MB_CONN_OK:
8171772Sjl139090 		/*
8181772Sjl139090 		 * Now the mailbox is ready to use, lets wake up
8191772Sjl139090 		 * any one waiting for this event.
8201772Sjl139090 		 */
8211772Sjl139090 		dm2sp->ms_state |= DM2S_MB_CONN;
8221772Sjl139090 		cv_broadcast(&dm2sp->ms_wait);
8231772Sjl139090 		DPRINTF(DBG_MBOX, ("Event received = CONN_OK\n"));
8241772Sjl139090 		break;
8251772Sjl139090 
8261772Sjl139090 	case SCF_MB_MSG_DATA:
8271772Sjl139090 		if (!DM2S_MBOX_READY(dm2sp)) {
8281772Sjl139090 			DPRINTF(DBG_MBOX,
8291772Sjl139090 			    ("Event(MSG_DATA) received - Mailbox not READY\n"));
8301772Sjl139090 			break;
8311772Sjl139090 		}
8321772Sjl139090 		/*
8331772Sjl139090 		 * A message is available in the mailbox.
8341772Sjl139090 		 * Lets enable the read service procedure
8351772Sjl139090 		 * to receive this message.
8361772Sjl139090 		 */
8371772Sjl139090 		if (dm2sp->ms_rq != NULL) {
8381772Sjl139090 			qenable(dm2sp->ms_rq);
8391772Sjl139090 		}
8401772Sjl139090 		DPRINTF(DBG_MBOX, ("Event received = MSG_DATA\n"));
8411772Sjl139090 		break;
8421772Sjl139090 
8431772Sjl139090 	case SCF_MB_SPACE:
8441772Sjl139090 		if (!DM2S_MBOX_READY(dm2sp)) {
8451772Sjl139090 			DPRINTF(DBG_MBOX,
8461772Sjl139090 			    ("Event(MB_SPACE) received - Mailbox not READY\n"));
8471772Sjl139090 			break;
8481772Sjl139090 		}
8491772Sjl139090 
8501772Sjl139090 		/*
8511772Sjl139090 		 * Now the mailbox is ready to transmit, lets
8521772Sjl139090 		 * schedule the write service procedure.
8531772Sjl139090 		 */
8541772Sjl139090 		if (dm2sp->ms_wq != NULL) {
8551772Sjl139090 			qenable(dm2sp->ms_wq);
8561772Sjl139090 		}
8571772Sjl139090 		DPRINTF(DBG_MBOX, ("Event received = MB_SPACE\n"));
8581772Sjl139090 		break;
8591772Sjl139090 	case SCF_MB_DISC_ERROR:
8601772Sjl139090 		dm2sp->ms_state |= DM2S_MB_DISC;
8611772Sjl139090 		if (dm2sp->ms_state & DM2S_MB_CONN) {
8621772Sjl139090 			/*
8631772Sjl139090 			 * If it was previously connected,
8641772Sjl139090 			 * then send a hangup message.
8651772Sjl139090 			 */
8661772Sjl139090 			rq = dm2sp->ms_rq;
8671772Sjl139090 			if (rq != NULL) {
8681772Sjl139090 				mutex_exit(&dm2sp->ms_lock);
8691772Sjl139090 				/*
8701772Sjl139090 				 * Send a hangup message to indicate
8711772Sjl139090 				 * disconnect event.
8721772Sjl139090 				 */
8731772Sjl139090 				(void) putctl(rq, M_HANGUP);
8741772Sjl139090 				DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp);
8751772Sjl139090 				mutex_enter(&dm2sp->ms_lock);
8761772Sjl139090 			}
8771772Sjl139090 		} else {
8781772Sjl139090 			/*
8791772Sjl139090 			 * Signal if the open is waiting for a
8801772Sjl139090 			 * connection.
8811772Sjl139090 			 */
8821772Sjl139090 			cv_broadcast(&dm2sp->ms_wait);
8831772Sjl139090 		}
8841772Sjl139090 		DPRINTF(DBG_MBOX, ("Event received = DISC_ERROR\n"));
8851772Sjl139090 		break;
8861772Sjl139090 	default:
8871772Sjl139090 		cmn_err(CE_WARN, "Unexpected event received\n");
8881772Sjl139090 		break;
8891772Sjl139090 	}
8901772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
8911772Sjl139090 }
8921772Sjl139090 
8931772Sjl139090 /*
8941772Sjl139090  * dm2s_start - Start transmission function.
8951772Sjl139090  *
8961772Sjl139090  * Send all queued messages. If the mailbox is busy, then
8971772Sjl139090  * start a timeout as a polling mechanism. The timeout is useful
8981772Sjl139090  * to not rely entirely on the SCF_MB_SPACE event.
8991772Sjl139090  */
9001772Sjl139090 void
dm2s_start(queue_t * wq,dm2s_t * dm2sp)9011772Sjl139090 dm2s_start(queue_t *wq, dm2s_t *dm2sp)
9021772Sjl139090 {
9031772Sjl139090 	mblk_t *mp;
9041772Sjl139090 	int ret;
9051772Sjl139090 
9061772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_start: called\n"));
9071772Sjl139090 	ASSERT(dm2sp != NULL);
9081772Sjl139090 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
9091772Sjl139090 
9101772Sjl139090 	while ((mp = getq(wq)) != NULL) {
9111772Sjl139090 		switch (mp->b_datap->db_type) {
9121772Sjl139090 
9131772Sjl139090 		case M_DATA:
9141772Sjl139090 			ret = dm2s_transmit(wq, mp, dm2sp->ms_target,
9151772Sjl139090 			    dm2sp->ms_key);
9161772Sjl139090 			if (ret == EBUSY || ret == ENOSPC || ret == EAGAIN) {
9171772Sjl139090 				DPRINTF(DBG_MBOX,
9181772Sjl139090 				    ("dm2s_start: recoverable err=%d\n", ret));
9191772Sjl139090 				/*
9201772Sjl139090 				 * Start a timeout to retry again.
9211772Sjl139090 				 */
9221772Sjl139090 				if (dm2sp->ms_wq_timeoutid == 0) {
9231772Sjl139090 					DTRACE_PROBE1(dm2s_wqtimeout__start,
9241772Sjl139090 					    dm2s_t, dm2sp);
9251772Sjl139090 					dm2sp->ms_wq_timeoutid = qtimeout(wq,
9261772Sjl139090 					    dm2s_wq_timeout, (void *)dm2sp,
9271772Sjl139090 					    dm2s_timeout_val(ret));
9281772Sjl139090 				}
9291772Sjl139090 				return;
9301772Sjl139090 			} else if (ret != 0) {
9311772Sjl139090 				mutex_exit(&dm2sp->ms_lock);
9321772Sjl139090 				/*
9331772Sjl139090 				 * An error occurred with the transmission,
9341772Sjl139090 				 * flush pending messages and initiate a
9351772Sjl139090 				 * hangup.
9361772Sjl139090 				 */
9371772Sjl139090 				flushq(wq, FLUSHDATA);
9381772Sjl139090 				(void) putnextctl(RD(wq), M_HANGUP);
9391772Sjl139090 				DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp);
9401772Sjl139090 				DPRINTF(DBG_WARN,
9411772Sjl139090 				    ("dm2s_start: hangup transmit err=%d\n",
9421772Sjl139090 				    ret));
9431772Sjl139090 				mutex_enter(&dm2sp->ms_lock);
9441772Sjl139090 			}
9451772Sjl139090 			break;
9461772Sjl139090 		default:
9471772Sjl139090 			/*
9481772Sjl139090 			 * At this point, we don't expect any other messages.
9491772Sjl139090 			 */
9501772Sjl139090 			freemsg(mp);
9511772Sjl139090 			break;
9521772Sjl139090 		}
9531772Sjl139090 	}
9541772Sjl139090 }
9551772Sjl139090 
9561772Sjl139090 /*
9571772Sjl139090  * dm2s_receive - Read all messages from the mailbox.
9581772Sjl139090  *
9591772Sjl139090  * This function is called from the read service procedure, to
9601772Sjl139090  * receive the messages awaiting in the mailbox.
9611772Sjl139090  */
9621772Sjl139090 void
dm2s_receive(dm2s_t * dm2sp)9631772Sjl139090 dm2s_receive(dm2s_t *dm2sp)
9641772Sjl139090 {
9651772Sjl139090 	queue_t	*rq = dm2sp->ms_rq;
9661772Sjl139090 	mblk_t	*mp;
9671772Sjl139090 	int	ret;
9681772Sjl139090 	uint32_t len;
9691772Sjl139090 
9701772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_receive: called\n"));
9711772Sjl139090 	ASSERT(dm2sp != NULL);
9721772Sjl139090 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
9731772Sjl139090 	if (rq == NULL) {
9741772Sjl139090 		return;
9751772Sjl139090 	}
9761772Sjl139090 	/*
9771772Sjl139090 	 * As the number of messages in the mailbox are pretty limited,
9781772Sjl139090 	 * it is safe to process all messages in one loop.
9791772Sjl139090 	 */
9801772Sjl139090 	while (DM2S_MBOX_READY(dm2sp) && ((ret = scf_mb_canget(dm2sp->ms_target,
9811772Sjl139090 	    dm2sp->ms_key, &len)) == 0)) {
9821772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_receive: mb_canget len=%d\n", len));
9831772Sjl139090 		if (len == 0) {
9841772Sjl139090 			break;
9851772Sjl139090 		}
9861772Sjl139090 		mp = allocb(len, BPRI_MED);
9871772Sjl139090 		if (mp == NULL) {
9881772Sjl139090 			DPRINTF(DBG_WARN, ("dm2s_receive: allocb failed\n"));
9891772Sjl139090 			/*
9901772Sjl139090 			 * Start a bufcall so that we can retry again
9911772Sjl139090 			 * when memory becomes available.
9921772Sjl139090 			 */
9931772Sjl139090 			dm2sp->ms_rbufcid = qbufcall(rq, len, BPRI_MED,
9941772Sjl139090 			    dm2s_bufcall_rcv, dm2sp);
9951772Sjl139090 			if (dm2sp->ms_rbufcid == 0) {
9961772Sjl139090 				DPRINTF(DBG_WARN,
9971772Sjl139090 				    ("dm2s_receive: qbufcall failed\n"));
9981772Sjl139090 				/*
9991772Sjl139090 				 * if bufcall fails, start a timeout to
10001772Sjl139090 				 * initiate a re-try after some time.
10011772Sjl139090 				 */
10021772Sjl139090 				DTRACE_PROBE1(dm2s_rqtimeout__start,
10031772Sjl139090 				    dm2s_t, dm2sp);
10041772Sjl139090 				dm2sp->ms_rq_timeoutid = qtimeout(rq,
10051772Sjl139090 				    dm2s_rq_timeout, (void *)dm2sp,
10061772Sjl139090 				    drv_usectohz(DM2S_SM_TOUT));
10071772Sjl139090 			}
10081772Sjl139090 			break;
10091772Sjl139090 		}
10101772Sjl139090 
10111772Sjl139090 		/*
10121772Sjl139090 		 * Only a single scatter/gather element is enough here.
10131772Sjl139090 		 */
10141772Sjl139090 		dm2sp->ms_sg_rcv.msc_dptr = (caddr_t)mp->b_wptr;
10151772Sjl139090 		dm2sp->ms_sg_rcv.msc_len = len;
10161772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_receive: calling getmsg\n"));
10171772Sjl139090 		ret = scf_mb_getmsg(dm2sp->ms_target, dm2sp->ms_key, len, 1,
10181772Sjl139090 		    &dm2sp->ms_sg_rcv, 0);
10191772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_receive: getmsg ret=%d\n", ret));
10201772Sjl139090 		if (ret != 0) {
10211772Sjl139090 			freemsg(mp);
10221772Sjl139090 			break;
10231772Sjl139090 		}
10241772Sjl139090 		DMPBYTES("dm2s: Getmsg: ", len, 1, &dm2sp->ms_sg_rcv);
10251772Sjl139090 		mp->b_wptr += len;
10261772Sjl139090 		/*
10271772Sjl139090 		 * Queue the messages in the rq, so that the service
10281772Sjl139090 		 * procedure handles sending the messages up the stream.
10291772Sjl139090 		 */
1030*11311SSurya.Prakki@Sun.COM 		(void) putq(rq, mp);
10311772Sjl139090 	}
10321772Sjl139090 
10331772Sjl139090 	if ((!DM2S_MBOX_READY(dm2sp)) || (ret != ENOMSG && ret != EMSGSIZE)) {
10341772Sjl139090 		/*
10351772Sjl139090 		 * Some thing went wrong, flush pending messages
10361772Sjl139090 		 * and initiate a hangup.
10371772Sjl139090 		 * Note: flushing the wq initiates a faster close.
10381772Sjl139090 		 */
10391772Sjl139090 		mutex_exit(&dm2sp->ms_lock);
10401772Sjl139090 		flushq(WR(rq), FLUSHDATA);
10411772Sjl139090 		(void) putnextctl(rq, M_HANGUP);
10421772Sjl139090 		DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp);
10431772Sjl139090 		mutex_enter(&dm2sp->ms_lock);
10441772Sjl139090 		DPRINTF(DBG_WARN, ("dm2s_receive: encountered unknown "
10451772Sjl139090 		    "condition - hangup ret=%d\n", ret));
10461772Sjl139090 	}
10471772Sjl139090 }
10481772Sjl139090 
10491772Sjl139090 /*
10501772Sjl139090  * dm2s_transmit - Transmit a message.
10511772Sjl139090  */
10521772Sjl139090 int
dm2s_transmit(queue_t * wq,mblk_t * mp,target_id_t target,mkey_t key)10531772Sjl139090 dm2s_transmit(queue_t *wq, mblk_t *mp, target_id_t target, mkey_t key)
10541772Sjl139090 {
10551772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)wq->q_ptr;
10561772Sjl139090 	int ret;
10571772Sjl139090 	uint32_t len;
10581772Sjl139090 	uint32_t numsg;
10591772Sjl139090 
10601772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_transmit: called\n"));
10611772Sjl139090 	ASSERT(dm2sp != NULL);
10621772Sjl139090 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
10631772Sjl139090 	/*
10641772Sjl139090 	 * Free the message if the mailbox is not in the connected state.
10651772Sjl139090 	 */
10661772Sjl139090 	if (!DM2S_MBOX_READY(dm2sp)) {
10671772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_transmit: mailbox not ready yet\n"));
10681772Sjl139090 		freemsg(mp);
10691772Sjl139090 		return (EIO);
10701772Sjl139090 	}
10711772Sjl139090 
10721772Sjl139090 	len = msgdsize(mp);
10731772Sjl139090 	if (len > dm2sp->ms_mtu) {
10741772Sjl139090 		/*
10751772Sjl139090 		 * Size is too big to send, free the message.
10761772Sjl139090 		 */
10771772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_transmit: message too large\n"));
10781772Sjl139090 		DTRACE_PROBE2(dm2s_msg_too_big, dm2s_t, dm2sp, uint32_t, len);
10791772Sjl139090 		freemsg(mp);
10801772Sjl139090 		return (0);
10811772Sjl139090 	}
10821772Sjl139090 
10831772Sjl139090 	if ((ret = dm2s_prep_scatgath(mp, &numsg, dm2sp->ms_sg_tx,
10841772Sjl139090 	    DM2S_MAX_SG)) != 0) {
10851772Sjl139090 		DPRINTF(DBG_MBOX, ("dm2s_transmit: prep_scatgath failed\n"));
1086*11311SSurya.Prakki@Sun.COM 		(void) putbq(wq, mp);
10871772Sjl139090 		return (EAGAIN);
10881772Sjl139090 	}
10891772Sjl139090 	DPRINTF(DBG_MBOX, ("dm2s_transmit: calling mb_putmsg numsg=%d len=%d\n",
10901772Sjl139090 	    numsg, len));
10911772Sjl139090 	ret = scf_mb_putmsg(target, key, len, numsg, dm2sp->ms_sg_tx, 0);
10921772Sjl139090 	if (ret == EBUSY || ret == ENOSPC) {
10931772Sjl139090 		DPRINTF(DBG_MBOX,
10941772Sjl139090 		    ("dm2s_transmit: mailbox busy ret=%d\n", ret));
10951772Sjl139090 		if (++dm2sp->ms_retries >= DM2S_MAX_RETRIES) {
10961772Sjl139090 			/*
10971772Sjl139090 			 * If maximum retries are reached, then free the
10981772Sjl139090 			 * message.
10991772Sjl139090 			 */
11001772Sjl139090 			DPRINTF(DBG_MBOX,
11011772Sjl139090 			    ("dm2s_transmit: freeing msg after max retries\n"));
11021772Sjl139090 			DTRACE_PROBE2(dm2s_retry_fail, dm2s_t, dm2sp, int, ret);
11031772Sjl139090 			freemsg(mp);
11041772Sjl139090 			dm2sp->ms_retries = 0;
11051772Sjl139090 			return (0);
11061772Sjl139090 		}
11071772Sjl139090 		DTRACE_PROBE2(dm2s_mb_busy, dm2s_t, dm2sp, int, ret);
11081772Sjl139090 		/*
11091772Sjl139090 		 * Queue it back, so that we can retry again.
11101772Sjl139090 		 */
1111*11311SSurya.Prakki@Sun.COM 		(void) putbq(wq, mp);
11121772Sjl139090 		return (ret);
11131772Sjl139090 	}
11141772Sjl139090 	DMPBYTES("dm2s: Putmsg: ", len, numsg, dm2sp->ms_sg_tx);
11151772Sjl139090 	dm2sp->ms_retries = 0;
11161772Sjl139090 	freemsg(mp);
11171772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_transmit: ret=%d\n", ret));
11181772Sjl139090 	return (ret);
11191772Sjl139090 }
11201772Sjl139090 
11211772Sjl139090 /*
11221772Sjl139090  * dm2s_bufcall_rcv - Bufcall callaback routine.
11231772Sjl139090  *
11241772Sjl139090  * It simply enables read side queue so that the service procedure
11251772Sjl139090  * can retry receive operation.
11261772Sjl139090  */
11271772Sjl139090 void
dm2s_bufcall_rcv(void * arg)11281772Sjl139090 dm2s_bufcall_rcv(void *arg)
11291772Sjl139090 {
11301772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)arg;
11311772Sjl139090 
11321772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_bufcall_rcv: called\n"));
11331772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
11341772Sjl139090 	dm2sp->ms_rbufcid = 0;
11351772Sjl139090 	if (dm2sp->ms_rq != NULL) {
11361772Sjl139090 		qenable(dm2sp->ms_rq);
11371772Sjl139090 	}
11381772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
11391772Sjl139090 }
11401772Sjl139090 
11411772Sjl139090 /*
11421772Sjl139090  * dm2s_rq_timeout - Timeout callback for the read side.
11431772Sjl139090  *
11441772Sjl139090  * It simply enables read side queue so that the service procedure
11451772Sjl139090  * can retry the receive operation.
11461772Sjl139090  */
11471772Sjl139090 void
dm2s_rq_timeout(void * arg)11481772Sjl139090 dm2s_rq_timeout(void *arg)
11491772Sjl139090 {
11501772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)arg;
11511772Sjl139090 
11521772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_rq_timeout: called\n"));
11531772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
11541772Sjl139090 	dm2sp->ms_rq_timeoutid = 0;
11551772Sjl139090 	if (dm2sp->ms_rq != NULL) {
11561772Sjl139090 		qenable(dm2sp->ms_rq);
11571772Sjl139090 	}
11581772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
11591772Sjl139090 }
11601772Sjl139090 
11611772Sjl139090 /*
11621772Sjl139090  * dm2s_wq_timeout - Timeout callback for the write.
11631772Sjl139090  *
11641772Sjl139090  * It simply enables write side queue so that the service procedure
11651772Sjl139090  * can retry the transmission operation.
11661772Sjl139090  */
11671772Sjl139090 void
dm2s_wq_timeout(void * arg)11681772Sjl139090 dm2s_wq_timeout(void *arg)
11691772Sjl139090 {
11701772Sjl139090 	dm2s_t *dm2sp = (dm2s_t *)arg;
11711772Sjl139090 
11721772Sjl139090 	DPRINTF(DBG_DRV, ("dm2s_wq_timeout: called\n"));
11731772Sjl139090 	mutex_enter(&dm2sp->ms_lock);
11741772Sjl139090 	dm2sp->ms_wq_timeoutid = 0;
11751772Sjl139090 	if (dm2sp->ms_wq != NULL) {
11761772Sjl139090 		qenable(dm2sp->ms_wq);
11771772Sjl139090 	}
11781772Sjl139090 	mutex_exit(&dm2sp->ms_lock);
11791772Sjl139090 }
11801772Sjl139090 
11811772Sjl139090 /*
11821772Sjl139090  * dm2s_prep_scatgath - Prepare scatter/gather elements for transmission
11831772Sjl139090  * of a streams message.
11841772Sjl139090  */
11851772Sjl139090 static int
dm2s_prep_scatgath(mblk_t * mp,uint32_t * numsg,mscat_gath_t * sgp,int maxsg)11861772Sjl139090 dm2s_prep_scatgath(mblk_t *mp, uint32_t *numsg, mscat_gath_t *sgp, int maxsg)
11871772Sjl139090 {
11881772Sjl139090 	uint32_t num = 0;
11891772Sjl139090 	mblk_t *tmp = mp;
11901772Sjl139090 
11911772Sjl139090 	while ((tmp != NULL) && (num < maxsg)) {
11921772Sjl139090 		sgp[num].msc_dptr = (caddr_t)tmp->b_rptr;
11931772Sjl139090 		sgp[num].msc_len = MBLKL(tmp);
11941772Sjl139090 		tmp = tmp->b_cont;
11951772Sjl139090 		num++;
11961772Sjl139090 	}
11971772Sjl139090 
11981772Sjl139090 	if (tmp != NULL) {
11991772Sjl139090 		/*
12001772Sjl139090 		 * Number of scatter/gather elements available are not
12011772Sjl139090 		 * enough, so lets pullup the msg.
12021772Sjl139090 		 */
12031772Sjl139090 		if (pullupmsg(mp, -1) != 1) {
12041772Sjl139090 			return (EAGAIN);
12051772Sjl139090 		}
12061772Sjl139090 		sgp[0].msc_dptr = (caddr_t)mp->b_rptr;
12071772Sjl139090 		sgp[0].msc_len = MBLKL(mp);
12081772Sjl139090 		num = 1;
12091772Sjl139090 	}
12101772Sjl139090 	*numsg = num;
12111772Sjl139090 	return (0);
12121772Sjl139090 }
12131772Sjl139090 
12141772Sjl139090 /*
12151772Sjl139090  * dm2s_timeout_val -- Return appropriate timeout value.
12161772Sjl139090  *
12171772Sjl139090  * A small timeout value is returned for EBUSY and EAGAIN cases. This is
12181772Sjl139090  * because the condition is expected to be recovered sooner.
12191772Sjl139090  *
12201772Sjl139090  * A larger timeout value is returned for ENOSPC case, as the condition
12211772Sjl139090  * depends on the peer to release buffer space.
12221772Sjl139090  * NOTE: there will also be an event(SCF_MB_SPACE) but a timeout is
12231772Sjl139090  * used for reliability purposes.
12241772Sjl139090  */
12251772Sjl139090 static clock_t
dm2s_timeout_val(int error)12261772Sjl139090 dm2s_timeout_val(int error)
12271772Sjl139090 {
12281772Sjl139090 	clock_t tval;
12291772Sjl139090 
12301772Sjl139090 	ASSERT(error == EBUSY || error == ENOSPC || error == EAGAIN);
12311772Sjl139090 
12321772Sjl139090 	if (error == EBUSY || error == EAGAIN) {
12331772Sjl139090 		tval = DM2S_SM_TOUT;
12341772Sjl139090 	} else {
12351772Sjl139090 		tval = DM2S_LG_TOUT;
12361772Sjl139090 	}
12371772Sjl139090 	return (drv_usectohz(tval));
12381772Sjl139090 }
12391772Sjl139090 
12401772Sjl139090 #ifdef DEBUG
12411772Sjl139090 
12421772Sjl139090 static void
dm2s_dump_bytes(char * str,uint32_t total_len,uint32_t num_sg,mscat_gath_t * sgp)12431772Sjl139090 dm2s_dump_bytes(char *str, uint32_t total_len,
12441772Sjl139090     uint32_t num_sg, mscat_gath_t *sgp)
12451772Sjl139090 {
12461772Sjl139090 	int i, j;
12471772Sjl139090 	int nsg;
12481772Sjl139090 	int len, tlen = 0;
12491772Sjl139090 	mscat_gath_t *tp;
12501772Sjl139090 	uint8_t *datap;
12511772Sjl139090 #define	BYTES_PER_LINE	20
12521772Sjl139090 	char bytestr[BYTES_PER_LINE * 3 + 1];
12531772Sjl139090 	uint32_t digest = 0;
12541772Sjl139090 
12551772Sjl139090 	if (!(dm2s_debug & DBG_MESG))
12561772Sjl139090 		return;
12571772Sjl139090 	ASSERT(num_sg != 0);
12581772Sjl139090 
12591772Sjl139090 	for (nsg = 0; (nsg < num_sg) && (tlen < total_len); nsg++) {
12601772Sjl139090 		tp = &sgp[nsg];
12611772Sjl139090 		datap = (uint8_t *)tp->msc_dptr;
12621772Sjl139090 		len = tp->msc_len;
12631772Sjl139090 		for (i = 0; i < len; i++) {
12641772Sjl139090 			digest += datap[i];
12651772Sjl139090 		}
12661772Sjl139090 		tlen += len;
12671772Sjl139090 	}
1268*11311SSurya.Prakki@Sun.COM 	(void) sprintf(bytestr, "%s Packet: Size=%d  Digest=%d\n",
12697656SSherry.Moore@Sun.COM 	    str, total_len, digest);
12701772Sjl139090 	DTRACE_PROBE1(dm2s_dump_digest, unsigned char *, bytestr);
12711772Sjl139090 
12722126Sraghuram 	tlen = 0;
12731772Sjl139090 	for (nsg = 0; (nsg < num_sg) && (tlen < total_len); nsg++) {
12741772Sjl139090 		tp = &sgp[nsg];
12751772Sjl139090 		datap = (uint8_t *)tp->msc_dptr;
12761772Sjl139090 		len = tp->msc_len;
12771772Sjl139090 		for (i = 0; i < len; ) {
12781772Sjl139090 			for (j = 0; (j < BYTES_PER_LINE) &&
12791772Sjl139090 			    (i < len); j++, i++) {
1280*11311SSurya.Prakki@Sun.COM 				(void) sprintf(&bytestr[j * 3], "%02X ",
1281*11311SSurya.Prakki@Sun.COM 				    datap[i]);
12821772Sjl139090 				digest += datap[i];
12831772Sjl139090 			}
12841772Sjl139090 			if (j != 0) {
12851772Sjl139090 				DTRACE_PROBE1(dm2s_dump, unsigned char *,
12861772Sjl139090 				    bytestr);
12871772Sjl139090 			}
12881772Sjl139090 		}
12891772Sjl139090 		tlen += i;
12901772Sjl139090 	}
12911772Sjl139090 }
12921772Sjl139090 
12931772Sjl139090 #endif	/* DEBUG */
1294