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