xref: /illumos-gate/usr/src/uts/sun4u/opl/io/dm2s.c (revision 030f3a8f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * DM2S - Domain side Mailbox to synchronous serial device driver.
30  *
31  * Description:
32  * -----------
33  * It is a streams driver which simulates a sync serial device on
34  * top of a mailbox type of communication. That is, it sends/receives
35  * frames as mailbox messages. The mailbox communication is provided
36  * by another driver, which exports the mailbox interfaces.
37  *
38  * Synchronization:
39  * ---------------
40  * This driver uses streams perimeters to simplify the synchronization.
41  * An inner perimeter D_MTPERMOD which protects the entire module,
42  * that is only one thread exists inside the perimeter, is used. As
43  * this driver supports only one instance and is not a high-performance
44  * driver, D_MTPERMOD is highly suitable.
45  *
46  * All transmission and reception of frames is done inside the service
47  * procedures so that all streams related operations are protected
48  * by the perimeters.
49  *
50  * The mailbox event handler is the only asynchronous callback which
51  * needs to be protected outside of the streams perimeters. This is
52  * done using the module private lock('ms_lock');
53  *
54  */
55 
56 #include <sys/types.h>
57 #include <sys/param.h>
58 #include <sys/stream.h>
59 #include <sys/cred.h>
60 #include <sys/systm.h>
61 #include <sys/sunddi.h>
62 #include <sys/ddi.h>
63 #include <sys/conf.h>
64 #include <sys/modctl.h>
65 #include <sys/mkdev.h>
66 #include <sys/errno.h>
67 #include <sys/debug.h>
68 #include <sys/kbio.h>
69 #include <sys/kmem.h>
70 #include <sys/consdev.h>
71 #include <sys/file.h>
72 #include <sys/stropts.h>
73 #include <sys/strsun.h>
74 #include <sys/dlpi.h>
75 #include <sys/stat.h>
76 #include <sys/ser_sync.h>
77 #include <sys/sysmacros.h>
78 #include <sys/note.h>
79 #include <sys/sdt.h>
80 
81 #include <sys/scfd/scfdscpif.h>
82 #include <sys/dm2s.h>
83 
84 
85 #define	DM2S_MODNAME	"dm2s"			/* Module name */
86 #define	DM2S_TARGET_ID	0			/* Target ID of the peer */
87 #define	DM2S_ID_NUM	0x4D53			/* 'M''S' */
88 #define	DM2S_DEF_MTU	1504			/* Def. MTU size + PPP bytes */
89 #define	DM2S_MAXPSZ	DM2S_DEF_MTU		/* Set it to the default MTU */
90 #define	DM2S_LOWAT	(4 * 1024)		/* Low water mark */
91 #define	DM2S_HIWAT	(12 * 1024)		/* High water mark */
92 #define	DM2S_SM_TOUT	5000			/* Small timeout (5msec) */
93 #define	DM2S_LG_TOUT	50000			/* Large timeout (50msec) */
94 #define	DM2S_MB_TOUT	10000000		/* Mailbox timeout (10sec) */
95 
96 /*
97  * Global variables
98  */
99 void		*dm2s_softstate = NULL;			/* Softstate pointer */
100 
101 
102 /*
103  * Prototypes for the module related functions.
104  */
105 int dm2s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
106 int dm2s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
107 int dm2s_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
108     void *arg, void **result);
109 
110 /*
111  * Prototypes for the streams related functions.
112  */
113 int dm2s_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr);
114 int dm2s_close(queue_t *rq, int flag, cred_t *cred);
115 int dm2s_wput(queue_t *wq, mblk_t *mp);
116 int dm2s_rsrv(queue_t *rq);
117 int dm2s_wsrv(queue_t *wq);
118 
119 /*
120  * Prototypes for the internal functions.
121  */
122 void dm2s_start(queue_t *wq, dm2s_t *dm2sp);
123 void dm2s_event_handler(scf_event_t event, void *arg);
124 int dm2s_transmit(queue_t *wq, mblk_t *mp, target_id_t target, mkey_t key);
125 void dm2s_receive(dm2s_t *dm2sp);
126 void dm2s_wq_timeout(void *arg);
127 void dm2s_rq_timeout(void *arg);
128 void dm2s_bufcall_rcv(void *arg);
129 static clock_t dm2s_timeout_val(int error);
130 static void dm2s_cleanup(dm2s_t *dm2sp);
131 static int dm2s_mbox_init(dm2s_t *dm2sp);
132 static void dm2s_mbox_fini(dm2s_t *dm2sp);
133 static int dm2s_prep_scatgath(mblk_t *mp, uint32_t *numsg,
134     mscat_gath_t *sgp, int maxsg);
135 
136 #ifdef DEBUG
137 uint32_t dm2s_debug = DBG_WARN;
138 #endif /* DEBUG */
139 
140 
141 /*
142  * Streams and module related structures.
143  */
144 struct module_info dm2s_module_info = {
145 	DM2S_ID_NUM,		/* module ID number */
146 	DM2S_MODNAME,		/* module name. */
147 	0,			/* Minimum packet size (none) */
148 	DM2S_MAXPSZ,		/* Maximum packet size (none) */
149 	DM2S_HIWAT,		/* queue high water mark */
150 	DM2S_LOWAT		/* queue low water mark */
151 };
152 
153 struct qinit dm2s_rinit = {
154 	putq,			/* qi_putp */
155 	dm2s_rsrv,		/* qi_srvp */
156 	dm2s_open,		/* qi_qopen */
157 	dm2s_close,		/* qi_qlcose */
158 	NULL,			/* qi_qadmin */
159 	&dm2s_module_info,	/* qi_minfo */
160 	NULL			/* qi_mstat */
161 };
162 
163 struct qinit dm2s_winit = {
164 	dm2s_wput,		/* qi_putp */
165 	dm2s_wsrv,		/* qi_srvp */
166 	NULL,			/* qi_qopen */
167 	NULL,			/* qi_qlcose */
168 	NULL,			/* qi_qadmin */
169 	&dm2s_module_info,	/* qi_minfo */
170 	NULL			/* qi_mstat */
171 };
172 
173 
174 struct streamtab dm2s_streamtab = {
175 	&dm2s_rinit,
176 	&dm2s_winit,
177 	NULL,
178 	NULL
179 };
180 
181 DDI_DEFINE_STREAM_OPS(dm2s_ops, nulldev, nulldev, dm2s_attach,		\
182 	dm2s_detach, nodev, dm2s_info, D_NEW | D_MP | D_MTPERMOD,	\
183 	&dm2s_streamtab);
184 
185 
186 struct modldrv modldrv = {
187 	&mod_driverops,
188 	"OPL Mbox to Serial Driver %I%",
189 	&dm2s_ops
190 };
191 
192 struct modlinkage modlinkage = {
193 	MODREV_1,
194 	&modldrv,
195 	NULL
196 };
197 
198 
199 /*
200  * _init - Module's init routine.
201  */
202 int
203 _init(void)
204 {
205 	int ret;
206 
207 	if (ddi_soft_state_init(&dm2s_softstate, sizeof (dm2s_t), 1) != 0) {
208 		cmn_err(CE_WARN, "softstate initialization failed\n");
209 		return (DDI_FAILURE);
210 	}
211 	if ((ret = mod_install(&modlinkage)) != 0) {
212 		cmn_err(CE_WARN, "mod_install failed, error = %d", ret);
213 		ddi_soft_state_fini(&dm2s_softstate);
214 	}
215 	return (ret);
216 }
217 
218 /*
219  * _fini - Module's fini routine.
220  */
221 int
222 _fini(void)
223 {
224 	int ret;
225 
226 	if ((ret = mod_remove(&modlinkage)) != 0) {
227 		return (ret);
228 	}
229 	ddi_soft_state_fini(&dm2s_softstate);
230 	return (ret);
231 }
232 
233 /*
234  * _info - Module's info routine.
235  */
236 int
237 _info(struct modinfo *modinfop)
238 {
239 	return (mod_info(&modlinkage, modinfop));
240 }
241 
242 /*
243  * dm2s_attach - Module's attach routine.
244  */
245 int
246 dm2s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
247 {
248 	int instance;
249 	dm2s_t *dm2sp;
250 	char name[20];
251 
252 
253 	instance = ddi_get_instance(dip);
254 
255 	/* Only one instance is supported. */
256 	if (instance != 0) {
257 		cmn_err(CE_WARN, "only one instance is supported");
258 		return (DDI_FAILURE);
259 	}
260 
261 	if (cmd != DDI_ATTACH) {
262 		return (DDI_FAILURE);
263 	}
264 	if (ddi_soft_state_zalloc(dm2s_softstate, instance) != DDI_SUCCESS) {
265 		cmn_err(CE_WARN, "softstate allocation failure");
266 		return (DDI_FAILURE);
267 	}
268 	dm2sp = (dm2s_t *)ddi_get_soft_state(dm2s_softstate, instance);
269 	if (dm2sp == NULL) {
270 		ddi_soft_state_free(dm2s_softstate, instance);
271 		cmn_err(CE_WARN, "softstate allocation failure.");
272 		return (DDI_FAILURE);
273 	}
274 	dm2sp->ms_dip = dip;
275 	dm2sp->ms_major = ddi_name_to_major(ddi_get_name(dip));
276 	dm2sp->ms_ppa = instance;
277 
278 	/*
279 	 * Get an interrupt block cookie corresponding to the
280 	 * interrupt priority of the event handler.
281 	 * Assert that the event priority is not re-defined to
282 	 * some higher priority.
283 	 */
284 	/* LINTED */
285 	ASSERT(SCF_EVENT_PRI == DDI_SOFTINT_LOW);
286 	if (ddi_get_soft_iblock_cookie(dip, SCF_EVENT_PRI,
287 	    &dm2sp->ms_ibcookie) != DDI_SUCCESS) {
288 		cmn_err(CE_WARN, "ddi_get_soft_iblock_cookie failed.");
289 		goto error;
290 	}
291 	mutex_init(&dm2sp->ms_lock, NULL, MUTEX_DRIVER,
292 	    (void *)dm2sp->ms_ibcookie);
293 
294 	dm2sp->ms_clean |= DM2S_CLEAN_LOCK;
295 	cv_init(&dm2sp->ms_wait, NULL, CV_DRIVER, NULL);
296 	dm2sp->ms_clean |= DM2S_CLEAN_CV;
297 
298 	(void) sprintf(name, "%s%d", DM2S_MODNAME, instance);
299 	if (ddi_create_minor_node(dip, name, S_IFCHR, instance,
300 	    DDI_PSEUDO, NULL) == DDI_FAILURE) {
301 		ddi_remove_minor_node(dip, NULL);
302 		cmn_err(CE_WARN, "Device node creation failed.");
303 		goto error;
304 	}
305 
306 	dm2sp->ms_clean |= DM2S_CLEAN_NODE;
307 	ddi_set_driver_private(dip, (caddr_t)dm2sp);
308 	ddi_report_dev(dip);
309 	return (DDI_SUCCESS);
310 error:
311 	dm2s_cleanup(dm2sp);
312 	return (DDI_FAILURE);
313 }
314 
315 /*
316  * dm2s_info - Module's info routine.
317  */
318 /*ARGSUSED*/
319 int
320 dm2s_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
321 {
322 	dm2s_t	*dm2sp;
323 	minor_t	minor;
324 	int	ret = DDI_FAILURE;
325 
326 	switch (infocmd) {
327 	case DDI_INFO_DEVT2DEVINFO:
328 		minor = getminor((dev_t)arg);
329 		dm2sp = (dm2s_t *)ddi_get_soft_state(dm2s_softstate, minor);
330 		if (dm2sp == NULL) {
331 			*result = NULL;
332 		} else {
333 			*result = dm2sp->ms_dip;
334 			ret = DDI_SUCCESS;
335 		}
336 		break;
337 
338 	case DDI_INFO_DEVT2INSTANCE:
339 		minor = getminor((dev_t)arg);
340 		*result = (void *)(uintptr_t)minor;
341 		ret = DDI_SUCCESS;
342 		break;
343 
344 	default:
345 		break;
346 	}
347 	return (ret);
348 }
349 
350 /*
351  * dm2s_detach - Module's detach routine.
352  */
353 int
354 dm2s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
355 {
356 	int instance;
357 	dm2s_t *dm2sp;
358 
359 	if (cmd != DDI_DETACH) {
360 		return (DDI_FAILURE);
361 	}
362 
363 	instance = ddi_get_instance(dip);
364 	dm2sp = (dm2s_t *)ddi_get_soft_state(dm2s_softstate, instance);
365 	if (dm2sp == NULL) {
366 		return (DDI_FAILURE);
367 	}
368 
369 	mutex_enter(&dm2sp->ms_lock);
370 
371 	/* Check if the mailbox is still in use. */
372 	if (dm2sp->ms_state & DM2S_MB_INITED) {
373 		mutex_exit(&dm2sp->ms_lock);
374 		cmn_err(CE_WARN, "Mailbox in use: Detach failed");
375 		return (DDI_FAILURE);
376 	}
377 	mutex_exit(&dm2sp->ms_lock);
378 	dm2s_cleanup(dm2sp);
379 	return (DDI_SUCCESS);
380 }
381 
382 /*
383  * dm2s_open - Device open routine.
384  *
385  * Only one open supported. Clone open is not supported.
386  */
387 /* ARGSUSED */
388 int
389 dm2s_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
390 {
391 	dm2s_t *dm2sp;
392 	int instance = getminor(*dev);
393 	int ret = 0;
394 
395 	DPRINTF(DBG_DRV, ("dm2s_open: called\n"));
396 	if (sflag == CLONEOPEN)	{
397 		/* Clone open not supported */
398 		DPRINTF(DBG_WARN, ("dm2s_open: clone open not supported\n"));
399 		return (ENOTSUP);
400 	}
401 
402 	if (rq->q_ptr != NULL) {
403 		DPRINTF(DBG_WARN, ("dm2s_open: already opened\n"));
404 		return (EBUSY);
405 	}
406 
407 	if ((dm2sp = ddi_get_soft_state(dm2s_softstate, instance)) == NULL) {
408 		DPRINTF(DBG_WARN, ("dm2s_open: instance not found\n"));
409 		return (ENODEV);
410 	}
411 
412 	mutex_enter(&dm2sp->ms_lock);
413 	if (dm2sp->ms_state & DM2S_OPENED) {
414 		/* Only one open supported */
415 		mutex_exit(&dm2sp->ms_lock);
416 		DPRINTF(DBG_WARN, ("dm2s_open: already opened\n"));
417 		return (EBUSY);
418 	}
419 
420 	dm2sp->ms_state |= DM2S_OPENED;
421 	/* Initialize the mailbox. */
422 	if ((ret = dm2s_mbox_init(dm2sp)) != 0) {
423 		dm2sp->ms_state = 0;
424 		mutex_exit(&dm2sp->ms_lock);
425 		return (ret);
426 	}
427 	rq->q_ptr = WR(rq)->q_ptr = (void *)dm2sp;
428 	dm2sp->ms_rq = rq;
429 	dm2sp->ms_wq = WR(rq);
430 	mutex_exit(&dm2sp->ms_lock);
431 
432 	if (ret == 0) {
433 		qprocson(rq);		/* now schedule our queue */
434 	}
435 	DPRINTF(DBG_DRV, ("dm2s_open: ret=%d\n", ret));
436 	return (ret);
437 }
438 
439 /*
440  * dm2s_close - Device close routine.
441  */
442 /* ARGSUSED */
443 int
444 dm2s_close(queue_t *rq, int flag, cred_t *cred)
445 {
446 	dm2s_t *dm2sp = (dm2s_t *)rq->q_ptr;
447 
448 	DPRINTF(DBG_DRV, ("dm2s_close: called\n"));
449 	if (dm2sp == NULL) {
450 		/* Already closed once */
451 		return (ENODEV);
452 	}
453 
454 	/* Close the lower layer first */
455 	mutex_enter(&dm2sp->ms_lock);
456 	(void) scf_mb_flush(dm2sp->ms_target, dm2sp->ms_key, MB_FLUSH_ALL);
457 	dm2s_mbox_fini(dm2sp);
458 	mutex_exit(&dm2sp->ms_lock);
459 
460 	/*
461 	 * Now we can assume that no asynchronous callbacks exist.
462 	 * Poison the stream head so that we can't be pushed again.
463 	 */
464 	(void) putnextctl(rq, M_HANGUP);
465 	qprocsoff(rq);
466 	if (dm2sp->ms_rbufcid != 0) {
467 		qunbufcall(rq, dm2sp->ms_rbufcid);
468 		dm2sp->ms_rbufcid = 0;
469 	}
470 	if (dm2sp->ms_rq_timeoutid != 0) {
471 		DTRACE_PROBE1(dm2s_rqtimeout__cancel, dm2s_t, dm2sp);
472 		(void) quntimeout(dm2sp->ms_rq, dm2sp->ms_rq_timeoutid);
473 		dm2sp->ms_rq_timeoutid = 0;
474 	}
475 	if (dm2sp->ms_wq_timeoutid != 0) {
476 		DTRACE_PROBE1(dm2s_wqtimeout__cancel, dm2s_t, dm2sp);
477 		(void) quntimeout(dm2sp->ms_wq, dm2sp->ms_wq_timeoutid);
478 		dm2sp->ms_wq_timeoutid = 0;
479 	}
480 	/*
481 	 * Now we can really mark it closed.
482 	 */
483 	mutex_enter(&dm2sp->ms_lock);
484 	dm2sp->ms_rq = dm2sp->ms_wq = NULL;
485 	dm2sp->ms_state &= ~DM2S_OPENED;
486 	mutex_exit(&dm2sp->ms_lock);
487 
488 	rq->q_ptr = WR(rq)->q_ptr = NULL;
489 	(void) qassociate(rq, -1);
490 	DPRINTF(DBG_DRV, ("dm2s_close: successfully closed\n"));
491 	return (0);
492 }
493 
494 /*
495  * dm2s_rsrv - Streams read side service procedure.
496  *
497  * All messages are received in the service procedure
498  * only. This is done to simplify the streams synchronization.
499  */
500 int
501 dm2s_rsrv(queue_t *rq)
502 {
503 	mblk_t *mp;
504 	dm2s_t *dm2sp = (dm2s_t *)rq->q_ptr;
505 
506 	DPRINTF(DBG_DRV, ("dm2s_rsrv: called\n"));
507 	ASSERT(dm2sp != NULL);
508 	mutex_enter(&dm2sp->ms_lock);
509 
510 	/* Receive if there are any messages waiting in the mailbox. */
511 	dm2s_receive(dm2sp);
512 	mutex_exit(&dm2sp->ms_lock);
513 
514 	/* Send the received messages up the stream. */
515 	while ((mp = getq(rq)) != NULL) {
516 		if (canputnext(rq)) {
517 			putnext(rq, mp);
518 		} else {
519 			putbq(rq, mp);
520 			break;
521 		}
522 	}
523 	DPRINTF(DBG_DRV, ("dm2s_rsrv: return\n"));
524 	return (0);
525 }
526 
527 /*
528  * dm2s_wsrv - Streams write side service procedure.
529  *
530  * All messages are transmitted in the service procedure
531  * only. This is done to simplify the streams synchronization.
532  */
533 int
534 dm2s_wsrv(queue_t *wq)
535 {
536 	dm2s_t *dm2sp = (dm2s_t *)wq->q_ptr;
537 
538 	DPRINTF(DBG_DRV, ("dm2s_wsrv: called\n"));
539 	ASSERT(dm2sp != NULL);
540 	/* Lets cancel any timeouts waiting to be scheduled. */
541 	if (dm2sp->ms_wq_timeoutid != 0) {
542 		DTRACE_PROBE1(dm2s_wqtimeout__cancel, dm2s_t, dm2sp);
543 		(void) quntimeout(dm2sp->ms_wq, dm2sp->ms_wq_timeoutid);
544 		dm2sp->ms_wq_timeoutid = 0;
545 	}
546 	mutex_enter(&dm2sp->ms_lock);
547 	dm2s_start(wq, dm2sp);
548 	mutex_exit(&dm2sp->ms_lock);
549 	DPRINTF(DBG_DRV, ("dm2s_wsrv: return\n"));
550 	return (0);
551 }
552 
553 /*
554  * dm2s_wput - Streams write side put routine.
555  *
556  * All M_DATA messages are queued so that they are transmitted in
557  * the service procedure. This is done to simplify the streams
558  * synchronization. Other messages are handled appropriately.
559  */
560 int
561 dm2s_wput(queue_t *wq, mblk_t *mp)
562 {
563 	dm2s_t	*dm2sp = (dm2s_t *)wq->q_ptr;
564 
565 	DPRINTF(DBG_DRV, ("dm2s_wput: called\n"));
566 	if (dm2sp == NULL) {
567 		return (ENODEV);   /* Can't happen. */
568 	}
569 
570 	switch (mp->b_datap->db_type) {
571 	case (M_DATA):
572 		DPRINTF(DBG_DRV, ("dm2s_wput: M_DATA message\n"));
573 		while (mp->b_wptr == mp->b_rptr) {
574 			mblk_t *mp1;
575 
576 			mp1 = unlinkb(mp);
577 			freemsg(mp);
578 			mp = mp1;
579 			if (mp == NULL) {
580 				return (0);
581 			}
582 		}
583 
584 		/*
585 		 * Simply queue the message and handle it in the service
586 		 * procedure.
587 		 */
588 		(void) putq(wq, mp);
589 		qenable(wq);
590 		return (0);
591 
592 	case (M_PROTO):
593 		DPRINTF(DBG_DRV, ("dm2s_wput: M_PROTO message\n"));
594 		/* We don't expect this */
595 		mp->b_datap->db_type = M_ERROR;
596 		mp->b_rptr = mp->b_wptr = mp->b_datap->db_base;
597 		*mp->b_wptr++ = EPROTO;
598 		qreply(wq, mp);
599 		return (EINVAL);
600 
601 	case (M_IOCTL):
602 		DPRINTF(DBG_DRV, ("dm2s_wput: M_IOCTL message\n"));
603 		if (MBLKL(mp) < sizeof (struct iocblk)) {
604 			freemsg(mp);
605 			return (0);
606 		}
607 		/*
608 		 * No ioctls required to be supported by this driver, so
609 		 * return EINVAL for all ioctls.
610 		 */
611 		miocnak(wq, mp, 0, EINVAL);
612 		break;
613 
614 	case (M_CTL):
615 		DPRINTF(DBG_DRV, ("dm2s_wput: M_CTL message\n"));
616 		/*
617 		 * No M_CTL messages need to supported by this driver,
618 		 * so simply ignore them.
619 		 */
620 		freemsg(mp);
621 		break;
622 
623 	case (M_FLUSH):
624 		DPRINTF(DBG_DRV, (
625 		    "dm2s_wput: M_FLUSH message 0x%X\n", *mp->b_rptr));
626 		if (*mp->b_rptr & FLUSHW) {	/* Flush write-side */
627 			(void) scf_mb_flush(dm2sp->ms_target, dm2sp->ms_key,
628 			    MB_FLUSH_SEND);
629 			flushq(wq, FLUSHDATA);
630 			*mp->b_rptr &= ~FLUSHW;
631 		}
632 		if (*mp->b_rptr & FLUSHR) {
633 			(void) scf_mb_flush(dm2sp->ms_target, dm2sp->ms_key,
634 			    MB_FLUSH_RECEIVE);
635 			flushq(RD(wq), FLUSHDATA);
636 			qreply(wq, mp);
637 		} else {
638 			freemsg(mp);
639 		}
640 		break;
641 
642 	default:
643 		DPRINTF(DBG_DRV, ("dm2s_wput: UNKNOWN message\n"));
644 		freemsg(mp);
645 
646 	}
647 	return (0);
648 }
649 
650 /*
651  * dm2s_cleanup - Cleanup routine.
652  */
653 static void
654 dm2s_cleanup(dm2s_t *dm2sp)
655 {
656 	char name[20];
657 
658 	DPRINTF(DBG_DRV, ("dm2s_cleanup: called\n"));
659 	ASSERT(dm2sp != NULL);
660 	if (dm2sp->ms_clean & DM2S_CLEAN_NODE) {
661 		(void) sprintf(name, "%s%d", DM2S_MODNAME, dm2sp->ms_ppa);
662 		ddi_remove_minor_node(dm2sp->ms_dip, name);
663 	}
664 	if (dm2sp->ms_clean & DM2S_CLEAN_LOCK)
665 		mutex_destroy(&dm2sp->ms_lock);
666 	if (dm2sp->ms_clean & DM2S_CLEAN_CV)
667 		cv_destroy(&dm2sp->ms_wait);
668 	ddi_set_driver_private(dm2sp->ms_dip, NULL);
669 	ddi_soft_state_free(dm2s_softstate, dm2sp->ms_ppa);
670 }
671 
672 /*
673  * dm2s_mbox_init - Mailbox specific initialization.
674  */
675 static int
676 dm2s_mbox_init(dm2s_t *dm2sp)
677 {
678 	int ret;
679 	clock_t tout;
680 
681 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
682 	dm2sp->ms_target = DM2S_TARGET_ID;
683 	dm2sp->ms_key = DSCP_KEY;
684 	dm2sp->ms_state &= ~DM2S_MB_INITED;
685 
686 	/* Iterate until mailbox gets connected */
687 	while (!(dm2sp->ms_state & DM2S_MB_CONN)) {
688 		DPRINTF(DBG_MBOX, ("dm2s_mbox_init: calling mb_init\n"));
689 		ret = scf_mb_init(dm2sp->ms_target, dm2sp->ms_key,
690 		    dm2s_event_handler, (void *)dm2sp);
691 		DPRINTF(DBG_MBOX, ("dm2s_mbox_init: mb_init ret=%d\n", ret));
692 
693 		if (ret != 0) {
694 			DPRINTF(DBG_MBOX,
695 			    ("dm2s_mbox_init: failed ret =%d\n", ret));
696 			DTRACE_PROBE1(dm2s_mbox_fail, int, ret);
697 		} else {
698 			dm2sp->ms_state |= DM2S_MB_INITED;
699 
700 			/* Block until the mailbox is ready to communicate. */
701 			while (!(dm2sp->ms_state &
702 			    (DM2S_MB_CONN | DM2S_MB_DISC))) {
703 
704 				if (cv_wait_sig(&dm2sp->ms_wait,
705 				    &dm2sp->ms_lock) <= 0) {
706 					/* interrupted */
707 					ret = EINTR;
708 					break;
709 				}
710 			}
711 		}
712 
713 		if ((ret != 0) || (dm2sp->ms_state & DM2S_MB_DISC)) {
714 
715 			if (dm2sp->ms_state & DM2S_MB_INITED) {
716 				(void) scf_mb_fini(dm2sp->ms_target,
717 				    dm2sp->ms_key);
718 			}
719 			if (dm2sp->ms_state & DM2S_MB_DISC) {
720 				DPRINTF(DBG_WARN,
721 				    ("dm2s_mbox_init: mbox DISC_ERROR\n"));
722 				DTRACE_PROBE1(dm2s_mbox_fail,
723 				    int, DM2S_MB_DISC);
724 			}
725 
726 			dm2sp->ms_state &= ~(DM2S_MB_INITED | DM2S_MB_DISC |
727 			    DM2S_MB_CONN);
728 
729 			if (ret == EINTR) {
730 				return (ret);
731 			}
732 
733 			/*
734 			 * If there was failure, then wait for
735 			 * DM2S_MB_TOUT secs and retry again.
736 			 */
737 
738 			DPRINTF(DBG_MBOX, ("dm2s_mbox_init: waiting...\n"));
739 			tout = ddi_get_lbolt() + drv_usectohz(DM2S_MB_TOUT);
740 			ret = cv_timedwait_sig(&dm2sp->ms_wait,
741 			    &dm2sp->ms_lock, tout);
742 			if (ret == 0) {
743 				/* if interrupted, return immediately. */
744 				DPRINTF(DBG_MBOX,
745 				    ("dm2s_mbox_init: interrupted\n"));
746 				return (EINTR);
747 			}
748 		}
749 	}
750 
751 	/*
752 	 * Obtain the max size of a single message.
753 	 * NOTE: There is no mechanism to update the
754 	 * upperlayers dynamically, so we expect this
755 	 * size to be atleast the default MTU size.
756 	 */
757 	ret = scf_mb_ctrl(dm2sp->ms_target, dm2sp->ms_key,
758 	    SCF_MBOP_MAXMSGSIZE, &dm2sp->ms_mtu);
759 
760 	if ((ret == 0) && (dm2sp->ms_mtu < DM2S_DEF_MTU)) {
761 		cmn_err(CE_WARN, "Max message size expected >= %d "
762 		    "but found %d\n", DM2S_DEF_MTU, dm2sp->ms_mtu);
763 		ret = EIO;
764 	}
765 
766 	if (ret != 0) {
767 		dm2sp->ms_state &= ~DM2S_MB_INITED;
768 		(void) scf_mb_fini(dm2sp->ms_target, dm2sp->ms_key);
769 	}
770 	DPRINTF(DBG_MBOX, ("dm2s_mbox_init: mb_init ret=%d\n", ret));
771 	return (ret);
772 }
773 
774 /*
775  * dm2s_mbox_fini - Mailbox de-initialization.
776  */
777 static void
778 dm2s_mbox_fini(dm2s_t *dm2sp)
779 {
780 	int ret;
781 
782 	ASSERT(dm2sp != NULL);
783 	if (dm2sp->ms_state & DM2S_MB_INITED) {
784 		DPRINTF(DBG_MBOX, ("dm2s_mbox_fini: calling mb_fini\n"));
785 		ret =  scf_mb_fini(dm2sp->ms_target, dm2sp->ms_key);
786 		if (ret != 0) {
787 			cmn_err(CE_WARN,
788 			    "Failed to close the Mailbox error =%d", ret);
789 		}
790 		DPRINTF(DBG_MBOX, ("dm2s_mbox_fini: mb_fini ret=%d\n", ret));
791 		dm2sp->ms_state &= ~(DM2S_MB_INITED |DM2S_MB_CONN |
792 		    DM2S_MB_DISC);
793 	}
794 }
795 
796 /*
797  * dm2s_event_handler - Mailbox event handler.
798  */
799 void
800 dm2s_event_handler(scf_event_t event, void *arg)
801 {
802 	dm2s_t *dm2sp = (dm2s_t *)arg;
803 	queue_t	*rq;
804 
805 	ASSERT(dm2sp != NULL);
806 	mutex_enter(&dm2sp->ms_lock);
807 	if (!(dm2sp->ms_state & DM2S_MB_INITED)) {
808 		/*
809 		 * Ignore all events if the state flag indicates that the
810 		 * mailbox not initialized, this may happen during the close.
811 		 */
812 		mutex_exit(&dm2sp->ms_lock);
813 		DPRINTF(DBG_MBOX,
814 		    ("Event(0x%X) received - Mailbox not inited\n", event));
815 		return;
816 	}
817 	switch (event) {
818 	case SCF_MB_CONN_OK:
819 		/*
820 		 * Now the mailbox is ready to use, lets wake up
821 		 * any one waiting for this event.
822 		 */
823 		dm2sp->ms_state |= DM2S_MB_CONN;
824 		cv_broadcast(&dm2sp->ms_wait);
825 		DPRINTF(DBG_MBOX, ("Event received = CONN_OK\n"));
826 		break;
827 
828 	case SCF_MB_MSG_DATA:
829 		if (!DM2S_MBOX_READY(dm2sp)) {
830 			DPRINTF(DBG_MBOX,
831 			    ("Event(MSG_DATA) received - Mailbox not READY\n"));
832 			break;
833 		}
834 		/*
835 		 * A message is available in the mailbox.
836 		 * Lets enable the read service procedure
837 		 * to receive this message.
838 		 */
839 		if (dm2sp->ms_rq != NULL) {
840 			qenable(dm2sp->ms_rq);
841 		}
842 		DPRINTF(DBG_MBOX, ("Event received = MSG_DATA\n"));
843 		break;
844 
845 	case SCF_MB_SPACE:
846 		if (!DM2S_MBOX_READY(dm2sp)) {
847 			DPRINTF(DBG_MBOX,
848 			    ("Event(MB_SPACE) received - Mailbox not READY\n"));
849 			break;
850 		}
851 
852 		/*
853 		 * Now the mailbox is ready to transmit, lets
854 		 * schedule the write service procedure.
855 		 */
856 		if (dm2sp->ms_wq != NULL) {
857 			qenable(dm2sp->ms_wq);
858 		}
859 		DPRINTF(DBG_MBOX, ("Event received = MB_SPACE\n"));
860 		break;
861 	case SCF_MB_DISC_ERROR:
862 		dm2sp->ms_state |= DM2S_MB_DISC;
863 		if (dm2sp->ms_state & DM2S_MB_CONN) {
864 			/*
865 			 * If it was previously connected,
866 			 * then send a hangup message.
867 			 */
868 			rq = dm2sp->ms_rq;
869 			if (rq != NULL) {
870 				mutex_exit(&dm2sp->ms_lock);
871 				/*
872 				 * Send a hangup message to indicate
873 				 * disconnect event.
874 				 */
875 				(void) putctl(rq, M_HANGUP);
876 				DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp);
877 				mutex_enter(&dm2sp->ms_lock);
878 			}
879 		} else {
880 			/*
881 			 * Signal if the open is waiting for a
882 			 * connection.
883 			 */
884 			cv_broadcast(&dm2sp->ms_wait);
885 		}
886 		DPRINTF(DBG_MBOX, ("Event received = DISC_ERROR\n"));
887 		break;
888 	default:
889 		cmn_err(CE_WARN, "Unexpected event received\n");
890 		break;
891 	}
892 	mutex_exit(&dm2sp->ms_lock);
893 }
894 
895 /*
896  * dm2s_start - Start transmission function.
897  *
898  * Send all queued messages. If the mailbox is busy, then
899  * start a timeout as a polling mechanism. The timeout is useful
900  * to not rely entirely on the SCF_MB_SPACE event.
901  */
902 void
903 dm2s_start(queue_t *wq, dm2s_t *dm2sp)
904 {
905 	mblk_t *mp;
906 	int ret;
907 
908 	DPRINTF(DBG_DRV, ("dm2s_start: called\n"));
909 	ASSERT(dm2sp != NULL);
910 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
911 
912 	while ((mp = getq(wq)) != NULL) {
913 		switch (mp->b_datap->db_type) {
914 
915 		case M_DATA:
916 			ret = dm2s_transmit(wq, mp, dm2sp->ms_target,
917 			    dm2sp->ms_key);
918 			if (ret == EBUSY || ret == ENOSPC || ret == EAGAIN) {
919 				DPRINTF(DBG_MBOX,
920 				    ("dm2s_start: recoverable err=%d\n", ret));
921 				/*
922 				 * Start a timeout to retry again.
923 				 */
924 				if (dm2sp->ms_wq_timeoutid == 0) {
925 					DTRACE_PROBE1(dm2s_wqtimeout__start,
926 					    dm2s_t, dm2sp);
927 					dm2sp->ms_wq_timeoutid = qtimeout(wq,
928 					    dm2s_wq_timeout, (void *)dm2sp,
929 					    dm2s_timeout_val(ret));
930 				}
931 				return;
932 			} else if (ret != 0) {
933 				mutex_exit(&dm2sp->ms_lock);
934 				/*
935 				 * An error occurred with the transmission,
936 				 * flush pending messages and initiate a
937 				 * hangup.
938 				 */
939 				flushq(wq, FLUSHDATA);
940 				(void) putnextctl(RD(wq), M_HANGUP);
941 				DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp);
942 				DPRINTF(DBG_WARN,
943 				    ("dm2s_start: hangup transmit err=%d\n",
944 				    ret));
945 				mutex_enter(&dm2sp->ms_lock);
946 			}
947 			break;
948 		default:
949 			/*
950 			 * At this point, we don't expect any other messages.
951 			 */
952 			freemsg(mp);
953 			break;
954 		}
955 	}
956 }
957 
958 /*
959  * dm2s_receive - Read all messages from the mailbox.
960  *
961  * This function is called from the read service procedure, to
962  * receive the messages awaiting in the mailbox.
963  */
964 void
965 dm2s_receive(dm2s_t *dm2sp)
966 {
967 	queue_t	*rq = dm2sp->ms_rq;
968 	mblk_t	*mp;
969 	int	ret;
970 	uint32_t len;
971 
972 	DPRINTF(DBG_DRV, ("dm2s_receive: called\n"));
973 	ASSERT(dm2sp != NULL);
974 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
975 	if (rq == NULL) {
976 		return;
977 	}
978 	/*
979 	 * As the number of messages in the mailbox are pretty limited,
980 	 * it is safe to process all messages in one loop.
981 	 */
982 	while (DM2S_MBOX_READY(dm2sp) && ((ret = scf_mb_canget(dm2sp->ms_target,
983 	    dm2sp->ms_key, &len)) == 0)) {
984 		DPRINTF(DBG_MBOX, ("dm2s_receive: mb_canget len=%d\n", len));
985 		if (len == 0) {
986 			break;
987 		}
988 		mp = allocb(len, BPRI_MED);
989 		if (mp == NULL) {
990 			DPRINTF(DBG_WARN, ("dm2s_receive: allocb failed\n"));
991 			/*
992 			 * Start a bufcall so that we can retry again
993 			 * when memory becomes available.
994 			 */
995 			dm2sp->ms_rbufcid = qbufcall(rq, len, BPRI_MED,
996 			    dm2s_bufcall_rcv, dm2sp);
997 			if (dm2sp->ms_rbufcid == 0) {
998 				DPRINTF(DBG_WARN,
999 				    ("dm2s_receive: qbufcall failed\n"));
1000 				/*
1001 				 * if bufcall fails, start a timeout to
1002 				 * initiate a re-try after some time.
1003 				 */
1004 				DTRACE_PROBE1(dm2s_rqtimeout__start,
1005 				    dm2s_t, dm2sp);
1006 				dm2sp->ms_rq_timeoutid = qtimeout(rq,
1007 				    dm2s_rq_timeout, (void *)dm2sp,
1008 				    drv_usectohz(DM2S_SM_TOUT));
1009 			}
1010 			break;
1011 		}
1012 
1013 		/*
1014 		 * Only a single scatter/gather element is enough here.
1015 		 */
1016 		dm2sp->ms_sg_rcv.msc_dptr = (caddr_t)mp->b_wptr;
1017 		dm2sp->ms_sg_rcv.msc_len = len;
1018 		DPRINTF(DBG_MBOX, ("dm2s_receive: calling getmsg\n"));
1019 		ret = scf_mb_getmsg(dm2sp->ms_target, dm2sp->ms_key, len, 1,
1020 		    &dm2sp->ms_sg_rcv, 0);
1021 		DPRINTF(DBG_MBOX, ("dm2s_receive: getmsg ret=%d\n", ret));
1022 		if (ret != 0) {
1023 			freemsg(mp);
1024 			break;
1025 		}
1026 		DMPBYTES("dm2s: Getmsg: ", len, 1, &dm2sp->ms_sg_rcv);
1027 		mp->b_wptr += len;
1028 		/*
1029 		 * Queue the messages in the rq, so that the service
1030 		 * procedure handles sending the messages up the stream.
1031 		 */
1032 		putq(rq, mp);
1033 	}
1034 
1035 	if ((!DM2S_MBOX_READY(dm2sp)) || (ret != ENOMSG && ret != EMSGSIZE)) {
1036 		/*
1037 		 * Some thing went wrong, flush pending messages
1038 		 * and initiate a hangup.
1039 		 * Note: flushing the wq initiates a faster close.
1040 		 */
1041 		mutex_exit(&dm2sp->ms_lock);
1042 		flushq(WR(rq), FLUSHDATA);
1043 		(void) putnextctl(rq, M_HANGUP);
1044 		DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp);
1045 		mutex_enter(&dm2sp->ms_lock);
1046 		DPRINTF(DBG_WARN, ("dm2s_receive: encountered unknown "
1047 		    "condition - hangup ret=%d\n", ret));
1048 	}
1049 }
1050 
1051 /*
1052  * dm2s_transmit - Transmit a message.
1053  */
1054 int
1055 dm2s_transmit(queue_t *wq, mblk_t *mp, target_id_t target, mkey_t key)
1056 {
1057 	dm2s_t *dm2sp = (dm2s_t *)wq->q_ptr;
1058 	int ret;
1059 	uint32_t len;
1060 	uint32_t numsg;
1061 
1062 	DPRINTF(DBG_DRV, ("dm2s_transmit: called\n"));
1063 	ASSERT(dm2sp != NULL);
1064 	ASSERT(MUTEX_HELD(&dm2sp->ms_lock));
1065 	/*
1066 	 * Free the message if the mailbox is not in the connected state.
1067 	 */
1068 	if (!DM2S_MBOX_READY(dm2sp)) {
1069 		DPRINTF(DBG_MBOX, ("dm2s_transmit: mailbox not ready yet\n"));
1070 		freemsg(mp);
1071 		return (EIO);
1072 	}
1073 
1074 	len = msgdsize(mp);
1075 	if (len > dm2sp->ms_mtu) {
1076 		/*
1077 		 * Size is too big to send, free the message.
1078 		 */
1079 		DPRINTF(DBG_MBOX, ("dm2s_transmit: message too large\n"));
1080 		DTRACE_PROBE2(dm2s_msg_too_big, dm2s_t, dm2sp, uint32_t, len);
1081 		freemsg(mp);
1082 		return (0);
1083 	}
1084 
1085 	if ((ret = dm2s_prep_scatgath(mp, &numsg, dm2sp->ms_sg_tx,
1086 	    DM2S_MAX_SG)) != 0) {
1087 		DPRINTF(DBG_MBOX, ("dm2s_transmit: prep_scatgath failed\n"));
1088 		putbq(wq, mp);
1089 		return (EAGAIN);
1090 	}
1091 	DPRINTF(DBG_MBOX, ("dm2s_transmit: calling mb_putmsg numsg=%d len=%d\n",
1092 	    numsg, len));
1093 	ret = scf_mb_putmsg(target, key, len, numsg, dm2sp->ms_sg_tx, 0);
1094 	if (ret == EBUSY || ret == ENOSPC) {
1095 		DPRINTF(DBG_MBOX,
1096 		    ("dm2s_transmit: mailbox busy ret=%d\n", ret));
1097 		if (++dm2sp->ms_retries >= DM2S_MAX_RETRIES) {
1098 			/*
1099 			 * If maximum retries are reached, then free the
1100 			 * message.
1101 			 */
1102 			DPRINTF(DBG_MBOX,
1103 			    ("dm2s_transmit: freeing msg after max retries\n"));
1104 			DTRACE_PROBE2(dm2s_retry_fail, dm2s_t, dm2sp, int, ret);
1105 			freemsg(mp);
1106 			dm2sp->ms_retries = 0;
1107 			return (0);
1108 		}
1109 		DTRACE_PROBE2(dm2s_mb_busy, dm2s_t, dm2sp, int, ret);
1110 		/*
1111 		 * Queue it back, so that we can retry again.
1112 		 */
1113 		putbq(wq, mp);
1114 		return (ret);
1115 	}
1116 	DMPBYTES("dm2s: Putmsg: ", len, numsg, dm2sp->ms_sg_tx);
1117 	dm2sp->ms_retries = 0;
1118 	freemsg(mp);
1119 	DPRINTF(DBG_DRV, ("dm2s_transmit: ret=%d\n", ret));
1120 	return (ret);
1121 }
1122 
1123 /*
1124  * dm2s_bufcall_rcv - Bufcall callaback routine.
1125  *
1126  * It simply enables read side queue so that the service procedure
1127  * can retry receive operation.
1128  */
1129 void
1130 dm2s_bufcall_rcv(void *arg)
1131 {
1132 	dm2s_t *dm2sp = (dm2s_t *)arg;
1133 
1134 	DPRINTF(DBG_DRV, ("dm2s_bufcall_rcv: called\n"));
1135 	mutex_enter(&dm2sp->ms_lock);
1136 	dm2sp->ms_rbufcid = 0;
1137 	if (dm2sp->ms_rq != NULL) {
1138 		qenable(dm2sp->ms_rq);
1139 	}
1140 	mutex_exit(&dm2sp->ms_lock);
1141 }
1142 
1143 /*
1144  * dm2s_rq_timeout - Timeout callback for the read side.
1145  *
1146  * It simply enables read side queue so that the service procedure
1147  * can retry the receive operation.
1148  */
1149 void
1150 dm2s_rq_timeout(void *arg)
1151 {
1152 	dm2s_t *dm2sp = (dm2s_t *)arg;
1153 
1154 	DPRINTF(DBG_DRV, ("dm2s_rq_timeout: called\n"));
1155 	mutex_enter(&dm2sp->ms_lock);
1156 	dm2sp->ms_rq_timeoutid = 0;
1157 	if (dm2sp->ms_rq != NULL) {
1158 		qenable(dm2sp->ms_rq);
1159 	}
1160 	mutex_exit(&dm2sp->ms_lock);
1161 }
1162 
1163 /*
1164  * dm2s_wq_timeout - Timeout callback for the write.
1165  *
1166  * It simply enables write side queue so that the service procedure
1167  * can retry the transmission operation.
1168  */
1169 void
1170 dm2s_wq_timeout(void *arg)
1171 {
1172 	dm2s_t *dm2sp = (dm2s_t *)arg;
1173 
1174 	DPRINTF(DBG_DRV, ("dm2s_wq_timeout: called\n"));
1175 	mutex_enter(&dm2sp->ms_lock);
1176 	dm2sp->ms_wq_timeoutid = 0;
1177 	if (dm2sp->ms_wq != NULL) {
1178 		qenable(dm2sp->ms_wq);
1179 	}
1180 	mutex_exit(&dm2sp->ms_lock);
1181 }
1182 
1183 /*
1184  * dm2s_prep_scatgath - Prepare scatter/gather elements for transmission
1185  * of a streams message.
1186  */
1187 static int
1188 dm2s_prep_scatgath(mblk_t *mp, uint32_t *numsg, mscat_gath_t *sgp, int maxsg)
1189 {
1190 	uint32_t num = 0;
1191 	mblk_t *tmp = mp;
1192 
1193 	while ((tmp != NULL) && (num < maxsg)) {
1194 		sgp[num].msc_dptr = (caddr_t)tmp->b_rptr;
1195 		sgp[num].msc_len = MBLKL(tmp);
1196 		tmp = tmp->b_cont;
1197 		num++;
1198 	}
1199 
1200 	if (tmp != NULL) {
1201 		/*
1202 		 * Number of scatter/gather elements available are not
1203 		 * enough, so lets pullup the msg.
1204 		 */
1205 		if (pullupmsg(mp, -1) != 1) {
1206 			return (EAGAIN);
1207 		}
1208 		sgp[0].msc_dptr = (caddr_t)mp->b_rptr;
1209 		sgp[0].msc_len = MBLKL(mp);
1210 		num = 1;
1211 	}
1212 	*numsg = num;
1213 	return (0);
1214 }
1215 
1216 /*
1217  * dm2s_timeout_val -- Return appropriate timeout value.
1218  *
1219  * A small timeout value is returned for EBUSY and EAGAIN cases. This is
1220  * because the condition is expected to be recovered sooner.
1221  *
1222  * A larger timeout value is returned for ENOSPC case, as the condition
1223  * depends on the peer to release buffer space.
1224  * NOTE: there will also be an event(SCF_MB_SPACE) but a timeout is
1225  * used for reliability purposes.
1226  */
1227 static clock_t
1228 dm2s_timeout_val(int error)
1229 {
1230 	clock_t tval;
1231 
1232 	ASSERT(error == EBUSY || error == ENOSPC || error == EAGAIN);
1233 
1234 	if (error == EBUSY || error == EAGAIN) {
1235 		tval = DM2S_SM_TOUT;
1236 	} else {
1237 		tval = DM2S_LG_TOUT;
1238 	}
1239 	return (drv_usectohz(tval));
1240 }
1241 
1242 #ifdef DEBUG
1243 
1244 static void
1245 dm2s_dump_bytes(char *str, uint32_t total_len,
1246     uint32_t num_sg, mscat_gath_t *sgp)
1247 {
1248 	int i, j;
1249 	int nsg;
1250 	int len, tlen = 0;
1251 	mscat_gath_t *tp;
1252 	uint8_t *datap;
1253 #define	BYTES_PER_LINE	20
1254 	char bytestr[BYTES_PER_LINE * 3 + 1];
1255 	uint32_t digest = 0;
1256 
1257 	if (!(dm2s_debug & DBG_MESG))
1258 		return;
1259 	ASSERT(num_sg != 0);
1260 
1261 	for (nsg = 0; (nsg < num_sg) && (tlen < total_len); nsg++) {
1262 		tp = &sgp[nsg];
1263 		datap = (uint8_t *)tp->msc_dptr;
1264 		len = tp->msc_len;
1265 		for (i = 0; i < len; i++) {
1266 			digest += datap[i];
1267 		}
1268 		tlen += len;
1269 	}
1270 	sprintf(bytestr, "%s Packet: Size=%d  Digest=%d\n",
1271 		str, total_len, digest);
1272 	DTRACE_PROBE1(dm2s_dump_digest, unsigned char *, bytestr);
1273 
1274 	tlen = 0;
1275 	for (nsg = 0; (nsg < num_sg) && (tlen < total_len); nsg++) {
1276 		tp = &sgp[nsg];
1277 		datap = (uint8_t *)tp->msc_dptr;
1278 		len = tp->msc_len;
1279 		for (i = 0; i < len; ) {
1280 			for (j = 0; (j < BYTES_PER_LINE) &&
1281 			    (i < len); j++, i++) {
1282 				sprintf(&bytestr[j * 3], "%02X ", datap[i]);
1283 				digest += datap[i];
1284 			}
1285 			if (j != 0) {
1286 				DTRACE_PROBE1(dm2s_dump, unsigned char *,
1287 				    bytestr);
1288 			}
1289 		}
1290 		tlen += i;
1291 	}
1292 }
1293 
1294 #endif	/* DEBUG */
1295