xref: /titanic_41/usr/src/uts/sun/io/zs_hdlc.c (revision df8bdeb362277e8d95a74d6c097341fe97409948)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *	HDLC protocol handler for Z8530 SCC.
31  */
32 
33 #include	<sys/param.h>
34 #include	<sys/systm.h>
35 #include	<sys/types.h>
36 #include	<sys/sysmacros.h>
37 #include	<sys/kmem.h>
38 #include	<sys/stropts.h>
39 #include	<sys/stream.h>
40 #include	<sys/strsun.h>
41 #include	<sys/stat.h>
42 #include	<sys/cred.h>
43 #include	<sys/user.h>
44 #include	<sys/proc.h>
45 #include	<sys/file.h>
46 #include	<sys/uio.h>
47 #include	<sys/buf.h>
48 #include	<sys/mkdev.h>
49 #include	<sys/cmn_err.h>
50 #include	<sys/errno.h>
51 #include	<sys/fcntl.h>
52 
53 #include	<sys/zsdev.h>
54 #include	<sys/ser_sync.h>
55 #include	<sys/conf.h>
56 #include	<sys/ddi.h>
57 #include	<sys/sunddi.h>
58 #include	<sys/dlpi.h>
59 
60 #define	ZSH_TRACING
61 #ifdef	ZSH_TRACING
62 #include	<sys/vtrace.h>
63 
64 /*
65  * Temp tracepoint definitions
66  */
67 #define	TR_ZSH		50
68 
69 #define	TR_ZSH_TXINT	1
70 #define	TR_ZSH_XSINT	2
71 #define	TR_ZSH_RXINT	3
72 #define	TR_ZSH_SRINT	4
73 
74 #define	TR_ZSH_WPUT_START		5
75 #define	TR_ZSH_WPUT_END			6
76 #define	TR_ZSH_START_START		7
77 #define	TR_ZSH_START_END		8
78 #define	TR_ZSH_SOFT_START		9
79 #define	TR_ZSH_SOFT_END			10
80 
81 #define	TR_ZSH_OPEN	 11
82 #define	TR_ZSH_CLOSE	12
83 
84 #endif	/* ZSH_TRACING */
85 
86 /*
87  * Logging definitions
88  */
89 
90 /*
91  * #define	ZSH_DEBUG
92  */
93 #ifdef ZSH_DEBUG
94 
95 #ifdef ZS_DEBUG_ALL
96 extern	char	zs_h_log[];
97 extern	int	zs_h_log_n;
98 #define	zsh_h_log_add(c) \
99 	{ \
100 		if (zs_h_log_n >= ZS_H_LOG_MAX) \
101 			zs_h_log_n = 0; \
102 		zs_h_log[zs_h_log_n++] = 'A' + zs->zs_unit; \
103 		zs_h_log[zs_h_log_n++] = c; \
104 		zs_h_log[zs_h_log_n] = '\0'; \
105 	}
106 #define	zsh_h_log_clear
107 #else
108 #define	ZSH_H_LOG_MAX   0x8000
109 char zsh_h_log[2][ZSH_H_LOG_MAX +10];
110 int zsh_h_log_n[2];
111 #define	zsh_h_log_add(c) \
112 	{ \
113 		if (zsh_h_log_n[zs->zs_unit] >= ZSH_H_LOG_MAX) \
114 			zsh_h_log_n[zs->zs_unit] = 0; \
115 		zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]++] = c; \
116 		zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]] = '\0'; \
117 	}
118 
119 #define	zsh_h_log_clear \
120 	{ register char *p; \
121 	for (p = &zsh_h_log[zs->zs_unit][ZSH_H_LOG_MAX]; \
122 		p >= &zsh_h_log[zs->zs_unit][0]; p--) \
123 		*p = '\0'; \
124 	zsh_h_log_n[zs->zs_unit] = 0; \
125 	}
126 #endif
127 
128 #define	ZSH_R0_LOG(r0)  { \
129 	if (r0 & ZSRR0_RX_READY) zsh_h_log_add('R'); \
130 	if (r0 & ZSRR0_TIMER) zsh_h_log_add('Z'); \
131 	if (r0 & ZSRR0_TX_READY) zsh_h_log_add('T'); \
132 	if (r0 & ZSRR0_CD) zsh_h_log_add('D'); \
133 	if (r0 & ZSRR0_SYNC) zsh_h_log_add('S'); \
134 	if (r0 & ZSRR0_CTS) zsh_h_log_add('C'); \
135 	if (r0 & ZSRR0_TXUNDER) zsh_h_log_add('U'); \
136 	if (r0 & ZSRR0_BREAK) zsh_h_log_add('B'); \
137 	}
138 #endif
139 
140 
141 char _depends_on[] = "drv/zs";
142 
143 #ifndef	MAXZSH
144 #define	MAXZSH	2
145 #define	MAXZSHCLONES	(80)	/* three clone opens per instance */
146 #endif	/* MAXZSH */
147 
148 int maxzsh = MAXZSH;
149 
150 int zsh_timer_count = 10;
151 int zsh_default_mru = 1024;
152 
153 struct ser_str *zsh_str = NULL;
154 unsigned char zsh_usedminor[MAXZSHCLONES];
155 
156 
157 /*
158  * The HDLC protocol
159  */
160 int zsh_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result);
161 static int  zsh_probe(dev_info_t *dev);
162 static int  zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd);
163 static int  zsh_detach(dev_info_t *dev, ddi_detach_cmd_t cmd);
164 static int  zsh_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr);
165 static int  zsh_close(queue_t *rq, int flag);
166 static void zsh_wput(queue_t *wq, mblk_t *mp);
167 static int zsh_start(struct zscom *zs, struct syncline *zss);
168 static void zsh_ioctl(queue_t *wq, mblk_t *mp);
169 
170 static struct module_info hdlc_minfo = {
171 	0x5a48,		/* module ID number: "ZH" */
172 	"zsh",		/* module name */
173 	0,		/* minimum packet size accepted */
174 	INFPSZ,		/* maximum packet size accepted */
175 	12*1024,	/* queue high water mark (bytes) */
176 	4*1024		/* queue low water mark (bytes) */
177 };
178 
179 static struct qinit hdlc_rinit = {
180 	putq,		/* input put procedure */
181 	NULL,		/* input service procedure */
182 	zsh_open,	/* open procedure */
183 	zsh_close,	/* close procedure */
184 	NULL,		/* reserved */
185 	&hdlc_minfo,	/* module info */
186 	NULL		/* reserved */
187 };
188 
189 static struct qinit hdlc_winit = {
190 	(int (*)())zsh_wput,	/* output put procedure */
191 	NULL,		/* output service procedure */
192 	NULL,		/* open procedure */
193 	NULL,		/* close procedure */
194 	NULL,		/* reserved */
195 	&hdlc_minfo,	/* module info */
196 	NULL		/* reserved */
197 };
198 
199 struct streamtab hdlctab = {
200 	&hdlc_rinit,	/* initialize read queue */
201 	&hdlc_winit,	/* initialize write queue */
202 	NULL,		/* mux read qinit */
203 	NULL		/* mux write qinit */
204 };
205 
206 DDI_DEFINE_STREAM_OPS(zsh_ops, nulldev, zsh_probe, zsh_attach,
207     zsh_detach, nodev, zsh_info, D_MP, &hdlctab);
208 
209 /*
210  * This is the loadable module wrapper.
211  */
212 
213 #include	<sys/errno.h>
214 #include	<sys/modctl.h>
215 
216 /*
217  * Module linkage information for the kernel.
218  */
219 
220 static struct modldrv modldrv = {
221 	&mod_driverops, /* Type of module.  This one is a driver */
222 	"Z8530 serial HDLC drv V%I%",
223 	&zsh_ops,	/* our own ops for this module */
224 };
225 
226 static struct modlinkage modlinkage = {
227 	MODREV_1,
228 	(void *)&modldrv,
229 	NULL
230 };
231 
232 int
233 _init(void)
234 {
235 	return (mod_install(&modlinkage));
236 }
237 
238 int
239 _fini(void)
240 {
241 	return (mod_remove(&modlinkage));
242 }
243 
244 int
245 _info(struct modinfo *modinfop)
246 {
247 	return (mod_info(&modlinkage, modinfop));
248 }
249 
250 
251 /*
252  * The HDLC interrupt entry points.
253  */
254 static void	zsh_txint(struct zscom *zs);
255 static void	zsh_xsint(struct zscom *zs);
256 static void	zsh_rxint(struct zscom *zs);
257 static void	zsh_srint(struct zscom *zs);
258 static int	zsh_softint(struct zscom *zs);
259 
260 struct zsops zsops_hdlc = {
261 	zsh_txint,
262 	zsh_xsint,
263 	zsh_rxint,
264 	zsh_srint,
265 	zsh_softint,
266 	NULL,
267 	NULL
268 };
269 
270 static int	zsh_program(struct zscom *zs, struct scc_mode *sm);
271 static void	zsh_setmstat(struct zscom *zs, int event);
272 static void	zsh_rxbad(struct zscom *zs, struct syncline *zss);
273 static void	zsh_txbad(struct zscom *zs, struct syncline *zss);
274 static void	zsh_watchdog(void *);
275 static void	zsh_callback(void *);
276 static int	zsh_hdp_ok_or_rts_state(struct zscom *zs, struct syncline *zss);
277 static void	zsh_init_port(struct zscom *zs, struct syncline *zss);
278 static int	zsh_setmode(struct zscom *zs, struct syncline *zss,
279 			struct scc_mode *sm);
280 
281 
282 /*
283  * The HDLC Driver.
284  */
285 
286 
287 /*
288  * Special macros to handle STREAMS operations.
289  * These are required to address memory leakage problems.
290  * WARNING : the macro do NOT call ZSSETSOFT
291  */
292 
293 /*
294  * Should be called holding only the adaptive (zs_excl) mutex.
295  */
296 #define	ZSH_GETBLOCK(zs, allocbcount) \
297 { \
298 	register int n = ZSH_MAX_RSTANDBY; \
299 	while (--n >= 0) { \
300 	    if (!zss->sl_rstandby[n]) { \
301 		if ((zss->sl_rstandby[n] = \
302 		    allocb(zss->sl_mru, BPRI_MED)) == NULL) { \
303 		    if (zss->sl_bufcid == 0) { \
304 			mutex_enter(zs->zs_excl_hi); \
305 			if (zss->sl_txstate != TX_OFF) { \
306 			    mutex_exit(zs->zs_excl_hi); \
307 			    zss->sl_bufcid = bufcall(zss->sl_mru, \
308 				    BPRI_MED, zsh_callback, zs); \
309 			    break; \
310 			} else \
311 				mutex_exit(zs->zs_excl_hi); \
312 		    } \
313 		} \
314 		allocbcount--; \
315 	    } \
316 	} \
317 }
318 
319 /*
320  * Should be called holding the spin (zs_excl_hi) mutex.
321  */
322 #define	ZSH_ALLOCB(mp) \
323 { \
324 	register int n = ZSH_MAX_RSTANDBY; \
325 	mp = NULL; \
326 	while (--n >= 0)  { \
327 		if ((mp = zss->sl_rstandby[n]) != NULL) { \
328 			zss->sl_rstandby[n] = NULL; \
329 			break; \
330 		} \
331 	} \
332 }
333 
334 #define	ZSH_PUTQ(mp) \
335 { \
336 	register int wptr, rptr;  \
337 	wptr = zss->sl_rdone_wptr; \
338 	rptr = zss->sl_rdone_rptr; \
339 	zss->sl_rdone[wptr] = mp; \
340 	if ((wptr) + 1 == ZSH_RDONE_MAX) \
341 		zss->sl_rdone_wptr = wptr = 0; \
342 	else \
343 		zss->sl_rdone_wptr = ++wptr; \
344 	if (wptr == rptr) {  /* Should never occur */ \
345 		SCC_BIC(1, ZSWR1_INIT); \
346 		zss->sl_m_error = ENOSR; \
347 		ZSSETSOFT(zs); \
348 	} \
349 }
350 
351 #define	ZSH_FREEMSG(mp) \
352 { \
353 	ZSH_PUTQ(mp); \
354 }
355 
356 
357 /*
358  * Should be called holding only the adaptive (zs_excl) mutex.
359  */
360 #define	ZSH_GETQ(mp) \
361 { \
362 	if (zss->sl_rdone_rptr != zss->sl_rdone_wptr) { \
363 		mp = zss->sl_rdone[zss->sl_rdone_rptr++]; \
364 		if (zss->sl_rdone_rptr == ZSH_RDONE_MAX) \
365 				zss->sl_rdone_rptr = 0; \
366 	} else \
367 		mp = NULL; \
368 }
369 
370 #define	ZSH_FLUSHQ \
371 { \
372 	register mblk_t *tmp; \
373 	for (;;) { \
374 		ZSH_GETQ(tmp); \
375 		if (!(tmp)) \
376 			break; \
377 		freemsg(tmp); \
378 	} \
379 }
380 
381 /*ARGSUSED*/
382 static int
383 zsh_probe(dev_info_t *dev)
384 {
385 	return (DDI_PROBE_DONTCARE);
386 }
387 
388 /*ARGSUSED*/
389 static int
390 zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd)
391 {
392 	register int	unit;
393 	char		name[3] = {
394 		'\0', '\0', '\0' 	};
395 
396 	/*
397 	 * Since zsh is a child of the "pseudo" nexus, we can expect the
398 	 * attach routine to be called only once.  We need to create all
399 	 * necessary devices in one shot.  There is never more than one
400 	 * SCC chip that supports zsh devices.
401 	 */
402 
403 	if (cmd != DDI_ATTACH)
404 		return (DDI_FAILURE);
405 	if (zscom == NULL)
406 		return (DDI_FAILURE);	/* zsattach not done */
407 	unit = 2 * ddi_get_instance(dev);
408 	if (unit > 1)
409 		return (DDI_FAILURE);	/* only use cpu ports */
410 
411 	if (ddi_create_minor_node(dev, "zsh", S_IFCHR,
412 	    NULL, DDI_PSEUDO, CLONE_DEV) == DDI_FAILURE) {
413 		ddi_remove_minor_node(dev, NULL);
414 		cmn_err(CE_WARN, "zsh clone device creation failed.");
415 		return (DDI_FAILURE);
416 	}
417 
418 	for (; unit < maxzsh/2; unit++) {
419 		zscom[unit].zs_hdlc_dip = dev;
420 
421 		(void) sprintf(name, "%d", unit);
422 		if (ddi_create_minor_node(dev, name, S_IFCHR,
423 		    2*unit, DDI_PSEUDO, NULL) == DDI_FAILURE) {
424 			ddi_remove_minor_node(dev, NULL);
425 			return (DDI_FAILURE);
426 		}
427 		unit++;
428 		(void) sprintf(name, "%d", unit);
429 		if (ddi_create_minor_node(dev, name, S_IFCHR,
430 		    2*(unit-1)+1, DDI_PSEUDO, NULL) == DDI_FAILURE) {
431 			ddi_remove_minor_node(dev, NULL);
432 			return (DDI_FAILURE);
433 		}
434 	}
435 
436 	return (DDI_SUCCESS);
437 }
438 
439 /* ARGSUSED */
440 int
441 zsh_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
442 void **result)
443 {
444 	register dev_t dev = (dev_t)arg;
445 	register int unit, error;
446 	register struct zscom *zs;
447 
448 	if ((unit = UNIT(dev)) >= nzs)
449 		return (DDI_FAILURE);
450 
451 	switch (infocmd) {
452 	case DDI_INFO_DEVT2DEVINFO:
453 		if (zscom == NULL) {
454 			error = DDI_FAILURE;
455 		} else {
456 			zs = &zscom[unit];
457 			*result = zs->zs_hdlc_dip;
458 			error = DDI_SUCCESS;
459 		}
460 		break;
461 	case DDI_INFO_DEVT2INSTANCE:
462 		*result = (void *)(uintptr_t)(unit / 2);
463 		error = DDI_SUCCESS;
464 		break;
465 	default:
466 		error = DDI_FAILURE;
467 	}
468 	return (error);
469 }
470 
471 static int
472 zsh_detach(dev_info_t *dev, ddi_detach_cmd_t cmd)
473 {
474 	if (cmd != DDI_DETACH)
475 		return (DDI_FAILURE);
476 
477 	ddi_remove_minor_node(dev, NULL);
478 
479 	return (DDI_SUCCESS);
480 }
481 
482 static void
483 zsh_init_port(struct zscom *zs, struct syncline *zss)
484 {
485 	register uchar_t s0;
486 
487 	SCC_WRITE(3, (ZSWR3_RX_ENABLE | ZSWR3_RXCRC_ENABLE | ZSWR3_RX_8));
488 	SCC_WRITE(5, (ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_TXCRC_ENABLE));
489 	zss->sl_rr0 = SCC_READ0();
490 	if (zss->sl_flags & SF_FDXPTP) {
491 		SCC_BIS(5, ZSWR5_TX_ENABLE);
492 		SCC_BIS(5, ZSWR5_RTS);
493 		s0 = SCC_READ0();
494 		if ((s0 & ZSRR0_CTS) ||
495 		    !(zss->sl_mode.sm_config & (CONN_SIGNAL | CONN_IBM))) {
496 			/*
497 			 * send msg that CTS is up
498 			 */
499 			zss->sl_rr0 |= ZSRR0_CTS;
500 			zss->sl_txstate = TX_IDLE;
501 		} else {
502 			zss->sl_flags |= SF_XMT_INPROG;
503 			zss->sl_txstate = TX_RTS;
504 			zss->sl_rr0 &= ~ZSRR0_CTS;
505 			zss->sl_wd_count = zsh_timer_count;
506 			if (!zss->sl_wd_id)
507 				zss->sl_wd_id = timeout(zsh_watchdog,
508 				    zs, SIO_WATCHDOG_TICK);
509 		}
510 	} else {
511 		SCC_BIC(15, ZSR15_CTS);
512 		SCC_BIC(5, ZSWR5_TX_ENABLE);
513 		SCC_BIC(5, ZSWR5_RTS);
514 		zss->sl_flags &= ~SF_FLUSH_WQ;
515 	}
516 }
517 
518 /*
519  * Open routine.
520  */
521 
522 /*ARGSUSED*/
523 static int
524 zsh_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
525 {
526 	register struct zscom *zs;
527 	register struct syncline *zss;
528 	register struct ser_str *stp;
529 	register int	unit;
530 	register int 	tmp;
531 
532 	if (sflag != CLONEOPEN) {
533 		if (rq->q_ptr)
534 			return (EBUSY);  /* We got a stream that is in use */
535 
536 		unit = UNIT(*dev);
537 		if (unit >= maxzsh)
538 			return (ENXIO);  /* unit not configured */
539 
540 		if (zscom == NULL)
541 			return (ENXIO);  /* device not found by autoconfig */
542 		zs = &zscom[unit];
543 
544 		if (zs->zs_ops == NULL) {
545 			return (ENXIO);  /* device not found by autoconfig */
546 		}
547 
548 		TRACE_1(TR_ZSH, TR_ZSH_OPEN, "zsh_open:unit = %d", unit);
549 
550 		mutex_enter(zs->zs_excl);
551 		if ((zs->zs_ops != &zsops_null) &&
552 		    (zs->zs_ops != &zsops_hdlc)) {
553 			mutex_exit(zs->zs_excl);
554 			return (EBUSY);	 /* another protocol got here first */
555 		}
556 
557 		/* Mark device as busy (for power management) */
558 		(void) pm_busy_component(zs->zs_dip, unit%2+1);
559 		(void) ddi_dev_is_needed(zs->zs_dip, unit%2+1, 1);
560 
561 		zsopinit(zs, &zsops_hdlc);
562 
563 		zss = (struct syncline *)&zscom[unit].zs_priv_str;
564 		stp = &zss->sl_stream;
565 		stp->str_state = NULL;
566 		stp->str_com = (caddr_t)zs;
567 
568 		zss->sl_xhead = NULL;
569 		zss->sl_xactb = NULL;
570 		zs->zs_wr_cur = NULL;
571 		zs->zs_wr_lim = NULL;
572 		zs->zs_wr_cur = NULL;
573 		zs->zs_wr_lim = NULL;
574 		zss->sl_rhead = NULL;
575 		zss->sl_ractb = NULL;
576 		zs->zs_rd_cur = NULL;
577 		zs->zs_rd_lim = NULL;
578 		zss->sl_mstat = NULL;
579 		zss->sl_xstandby = NULL;
580 		zss->sl_wd_id = 0;
581 		zss->sl_soft_active = 0;
582 		zss->sl_stream.str_rq = NULL;
583 
584 		zs->zs_priv = (caddr_t)zss;
585 
586 		zss->sl_mru = zsh_default_mru;
587 		tmp = ZSH_MAX_RSTANDBY;
588 		ZSH_GETBLOCK(zs, tmp);
589 		if (zss->sl_rstandby[0] == NULL) {
590 		    cmn_err(CE_WARN, "zsh_open: can't alloc message block");
591 		    mutex_exit(zs->zs_excl);
592 		    return (ENOSR);
593 		}
594 		mutex_enter(zs->zs_excl_hi);
595 		ZSH_ALLOCB(zss->sl_ractb);
596 		zss->sl_txstate = TX_OFF;
597 		zss->sl_rr0 = SCC_READ0();
598 		zss->sl_flags &= (SF_INITIALIZED | SF_FDXPTP);
599 		if (zss->sl_flags & SF_INITIALIZED)
600 			zsh_init_port(zs, zss);
601 		mutex_exit(zs->zs_excl_hi);
602 		mutex_exit(zs->zs_excl);
603 	} else {   /* CLONEOPEN */
604 		mutex_enter(&zs_curr_lock);
605 		for (unit = maxzsh; unit < MAXZSHCLONES; unit++)
606 			if (!zsh_usedminor[unit]) {
607 				zsh_usedminor[unit] = (unsigned char)unit;
608 				break;
609 			}
610 		mutex_exit(&zs_curr_lock);
611 		if (unit >= MAXZSHCLONES)	/* no slots available */
612 			return (ENODEV);
613 		*dev = makedevice(getmajor(*dev), unit);
614 
615 		stp = kmem_zalloc(sizeof (struct ser_str), KM_NOSLEEP);
616 		if (stp == NULL) {
617 			cmn_err(CE_WARN,
618 			    "zsh clone open failed, no memory, rq=%p\n",
619 			    (void *)rq);
620 			return (ENOMEM);
621 		}
622 		stp->str_state = STR_CLONE;
623 		stp->str_com = NULL;	/* can't determine without ppa */
624 	}
625 	stp->str_rq = rq;
626 	stp->str_inst = unit;
627 
628 	rq->q_ptr = WR(rq)->q_ptr = (caddr_t)stp;
629 	qprocson(rq);
630 	return (0);
631 }
632 
633 /*
634  * Close routine.
635  */
636 int zsh_tx_enable_in_close = 0;
637 
638 /*ARGSUSED*/
639 static int
640 zsh_close(queue_t *rq, int flag)
641 {
642 	struct ser_str *stp;
643 	struct zscom *zs;
644 	struct syncline *zss;
645 	mblk_t	*mp;
646 	int i;
647 	timeout_id_t sl_wd_id;
648 	bufcall_id_t sl_bufcid;
649 
650 	/*
651 	 * Note that a close is only called on the last close of a
652 	 * particular stream.  Assume that we need to do it all.
653 	 */
654 	qprocsoff(rq);				/* no new business after this */
655 
656 	stp = (struct ser_str *)rq->q_ptr;
657 	if (stp == NULL)
658 		return (0);			/* already been closed once */
659 
660 	if (stp->str_state == STR_CLONE) {
661 		zsh_usedminor[stp->str_inst] = 0;
662 	} else {
663 		zs = (struct zscom *)stp->str_com;
664 		if (zs == NULL)
665 			goto out;
666 
667 		TRACE_1(TR_ZSH, TR_ZSH_CLOSE, "zs = %p", zs);
668 
669 		zss = (struct syncline *)zs->zs_priv;
670 		mutex_enter(zs->zs_excl);
671 		flushq(WR(rq), FLUSHALL);
672 		mutex_enter(zs->zs_excl_hi);
673 		if (zss->sl_xstandby) {
674 			zss->sl_xstandby->b_wptr = zss->sl_xstandby->b_rptr;
675 			ZSH_FREEMSG(zss->sl_xstandby);
676 			zss->sl_xstandby = NULL;
677 		}
678 		mutex_exit(zs->zs_excl_hi);
679 
680 		ZSH_FLUSHQ;
681 
682 		/*
683 		 * Stop the Watchdog Timer.
684 		 */
685 		if ((sl_wd_id = zss->sl_wd_id) != 0)
686 			zss->sl_wd_id = 0;
687 
688 		/*
689 		 * Cancel outstanding "bufcall" request.
690 		 */
691 		if ((sl_bufcid = zss->sl_bufcid) != 0)
692 			zss->sl_bufcid = 0;
693 
694 		mutex_enter(zs->zs_excl_hi);
695 		if (zs->zs_wr_cur) {
696 			zs->zs_wr_cur = NULL;
697 			zs->zs_wr_lim = NULL;
698 			SCC_WRITE0(ZSWR0_SEND_ABORT);
699 			ZSDELAY();
700 			ZSDELAY();
701 		}
702 		zss->sl_txstate = TX_OFF;	/* so it can't rearm in close */
703 
704 		zs->zs_wr_cur = NULL;
705 		zs->zs_wr_lim = NULL;
706 		SCC_BIC(15,
707 		    (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC | ZSR15_CTS));
708 		SCC_WRITE(3, 0);		/* Quiesce receiver */
709 		if (zsh_tx_enable_in_close && !(zss->sl_flags & SF_FDXPTP)) {
710 			SCC_BIS(5, ZSWR5_TX_ENABLE);
711 		} else
712 			SCC_BIC(5, ZSWR5_TX_ENABLE);
713 
714 		SCC_BIC(5,  (ZSWR5_DTR | ZSWR5_RTS | ZSWR5_TXCRC_ENABLE));
715 		SCC_WRITE0(ZSWR0_RESET_TXINT);		/* reset TX */
716 		SCC_WRITE0(ZSWR0_RESET_STATUS);		/* reset XS */
717 		SCC_WRITE0(ZSWR0_RESET_ERRORS);
718 		(void) SCC_READDATA();			/* reset RX */
719 		ZSDELAY();
720 		(void) SCC_READDATA();
721 		ZSDELAY();
722 		(void) SCC_READDATA();
723 		ZSDELAY();
724 
725 
726 		/*
727 		 * Free up everything we ever allocated.
728 		 */
729 		if ((mp = zss->sl_rhead) != NULL) {
730 			zss->sl_ractb = NULL;	/* already freed */
731 			zs->zs_rd_cur = NULL;
732 			zs->zs_rd_lim = NULL;
733 			zss->sl_rhead = NULL;
734 		}
735 		mutex_exit(zs->zs_excl_hi);
736 		if (mp)
737 			freemsg(mp);
738 
739 		mutex_enter(zs->zs_excl_hi);
740 		if ((mp = zss->sl_ractb) != NULL) {
741 			zs->zs_rd_cur = NULL;
742 			zs->zs_rd_lim = NULL;
743 			zss->sl_ractb = NULL;
744 		}
745 		mutex_exit(zs->zs_excl_hi);
746 		if (mp)
747 			freemsg(mp);
748 
749 		for (i = 0; i < ZSH_MAX_RSTANDBY; i++) {
750 			mutex_enter(zs->zs_excl_hi);
751 			mp = zss->sl_rstandby[i];
752 			zss->sl_rstandby[i] = NULL;
753 			mutex_exit(zs->zs_excl_hi);
754 			if (mp)
755 				freemsg(mp);
756 		}
757 
758 		mutex_enter(zs->zs_excl_hi);
759 		if ((mp = zss->sl_xhead) != NULL) {
760 			zss->sl_xhead = NULL;
761 			zss->sl_xactb = NULL;
762 		}
763 		mutex_exit(zs->zs_excl_hi);
764 		if (mp)
765 			freemsg(mp);
766 
767 		ZSH_FLUSHQ;
768 
769 		mutex_enter(zs->zs_excl_hi);
770 		if ((mp = zss->sl_xstandby) != NULL)
771 			zss->sl_xstandby = NULL;
772 		mutex_exit(zs->zs_excl_hi);
773 		if (mp)
774 			freemsg(mp);
775 
776 		mutex_enter(zs->zs_excl_hi);
777 		if ((mp = zss->sl_mstat) != NULL)
778 			zss->sl_mstat = NULL;
779 		zss->sl_txstate = TX_OFF;	/* so it can't rearm in close */
780 		mutex_exit(zs->zs_excl_hi);
781 		if (mp)
782 			freemsg(mp);
783 
784 		zss->sl_stream.str_rq = NULL;
785 		zsopinit(zs, &zsops_null);
786 		mutex_exit(zs->zs_excl);
787 		if (sl_wd_id)
788 			(void) untimeout(sl_wd_id);
789 		if (sl_bufcid)
790 			unbufcall(sl_bufcid);
791 		while (zss->sl_soft_active)
792 			drv_usecwait(1);
793 
794 		/* Mark device as available for power management */
795 		(void) pm_idle_component(zs->zs_dip, zs->zs_unit%2+1);
796 	}
797 
798 	if (stp->str_state == STR_CLONE)
799 		kmem_free(stp, sizeof (struct ser_str));
800 
801 out:
802 	rq->q_ptr = WR(rq)->q_ptr = NULL;
803 
804 	return (0);
805 }
806 
807 static int
808 zsh_hdp_ok_or_rts_state(struct zscom *zs, struct syncline *zss)
809 {
810 	register uchar_t s0;
811 
812 	SCC_BIS(15, ZSR15_CTS);
813 	SCC_BIS(5, ZSWR5_RTS);
814 	s0 = SCC_READ0();
815 	if (s0 & ZSRR0_CTS) {
816 		SCC_BIS(5, ZSWR5_TX_ENABLE);
817 		zss->sl_rr0 |= ZSRR0_CTS;
818 		return (1);
819 	}
820 	zss->sl_flags |= SF_XMT_INPROG;
821 	zss->sl_txstate = TX_RTS;
822 	zss->sl_rr0 &= ~ZSRR0_CTS;
823 	zss->sl_wd_count = zsh_timer_count;
824 	return (0);
825 }
826 
827 /*
828  * Put procedure for write queue.
829  */
830 static void
831 zsh_wput(queue_t *wq, mblk_t *mp)
832 {
833 	register struct ser_str *stp = (struct ser_str *)wq->q_ptr;
834 	register struct zscom *zs;
835 	register struct syncline *zss = NULL;
836 	register ulong_t prim, error = 0;
837 	register union DL_primitives *dlp;
838 	register int	ppa;
839 	register mblk_t *tmp;
840 	register struct copyresp	*resp;
841 
842 	/*
843 	 * stp->str_com supplied by open or DLPI attach.
844 	 */
845 	if (stp == NULL) {
846 		freemsg(mp);
847 		return;
848 	}
849 	zs = (struct zscom *)stp->str_com;
850 
851 	TRACE_0(TR_ZSH, TR_ZSH_WPUT_START, "zsh_wput start");
852 
853 	if ((mp->b_datap->db_type == M_FLUSH) &&
854 		    (stp->str_state == STR_CLONE)) {
855 		if (*mp->b_rptr & FLUSHW) {
856 			flushq(wq, FLUSHDATA);
857 			*mp->b_rptr &= ~FLUSHW;
858 		}
859 		if (*mp->b_rptr & FLUSHR)
860 			qreply(wq, mp);  /* let the read queues have at it */
861 		else
862 			freemsg(mp);
863 		return;
864 	}
865 
866 	if ((zs == NULL) && (mp->b_datap->db_type != M_PROTO)) {
867 	    freemsg(mp);
868 	    cmn_err(CE_WARN,
869 		"zsh: clone device %d must be attached before use!",
870 		stp->str_inst);
871 	    (void) putnextctl1(RD(wq), M_ERROR, EPROTO);
872 	    return;
873 	}
874 
875 	if (stp->str_state == STR_CLONE) {	/* Clone opened, limited. */
876 		if ((mp->b_datap->db_type != M_PROTO) &&
877 		    (mp->b_datap->db_type != M_IOCTL) &&
878 		    (mp->b_datap->db_type != M_IOCDATA)) {
879 			freemsg(mp);
880 			cmn_err(CE_WARN,
881 			    "zsh%x: invalid operation for clone dev.\n",
882 			    stp->str_inst);
883 			(void) putnextctl1(RD(wq), M_ERROR, EPROTO);
884 			return;
885 		}
886 	} else {
887 		zss = (struct syncline *)zs->zs_priv;
888 	}
889 
890 	switch (mp->b_datap->db_type) {
891 
892 	case M_DATA:
893 		/*
894 		 * Queue the message up to be transmitted.
895 		 * Set "in progress" flag and call the start routine.
896 		 */
897 		mutex_enter(zs->zs_excl_hi);
898 		if (!(zss->sl_flags & SF_INITIALIZED)) {
899 			mutex_exit(zs->zs_excl_hi);
900 			cmn_err(CE_WARN,
901 			    "zsh%x not initialized, can't send message",
902 			    zs->zs_unit);
903 			freemsg(mp);
904 			(void) putnextctl1(RD(wq), M_ERROR, ECOMM);
905 			return;
906 		}
907 		mutex_exit(zs->zs_excl_hi);
908 		if (zs->zs_flags & ZS_NEEDSOFT) {
909 			zs->zs_flags &= ~ZS_NEEDSOFT;
910 			(void) zsh_softint(zs);
911 		}
912 		while (mp->b_wptr == mp->b_rptr) {
913 			register mblk_t *mp1;
914 			mp1 = unlinkb(mp);
915 			freemsg(mp);
916 			mp = mp1;
917 			if (mp == NULL)
918 				return;
919 		}
920 		mutex_enter(zs->zs_excl);
921 		(void) putq(wq, mp);
922 		mutex_enter(zs->zs_excl_hi);
923 		if (zss->sl_flags & SF_FLUSH_WQ) {
924 			mutex_exit(zs->zs_excl_hi);
925 			flushq(wq, FLUSHDATA);
926 			mutex_exit(zs->zs_excl);
927 
928 			TRACE_1(TR_ZSH, TR_ZSH_WPUT_END,
929 			    "zsh_wput end: zs = %p", zs);
930 
931 			return;
932 		}
933 		tmp = NULL;
934 again:
935 		if (!zss->sl_xstandby) {
936 			if (tmp)
937 				zss->sl_xstandby = tmp;
938 			else {
939 				mutex_exit(zs->zs_excl_hi);
940 				tmp = getq(wq);
941 				mutex_enter(zs->zs_excl_hi);
942 				if (tmp)
943 					goto again;
944 			}
945 		} else if (tmp) {
946 			mutex_exit(zs->zs_excl_hi);
947 			(void) putbq(wq, tmp);
948 			mutex_enter(zs->zs_excl_hi);
949 		}
950 
951 		if (zss->sl_flags & SF_XMT_INPROG) {
952 			mutex_exit(zs->zs_excl_hi);
953 			mutex_exit(zs->zs_excl);
954 
955 			TRACE_1(TR_ZSH, TR_ZSH_WPUT_END,
956 			    "zsh_wput end: zs = %p", zs);
957 
958 			return;
959 		}
960 
961 		if (!zss->sl_wd_id) {
962 			zss->sl_wd_count = zsh_timer_count;
963 			zss->sl_txstate = TX_IDLE;
964 			mutex_exit(zs->zs_excl_hi);
965 			zss->sl_wd_id = timeout(zsh_watchdog, zs,
966 			    SIO_WATCHDOG_TICK);
967 			mutex_enter(zs->zs_excl_hi);
968 		}
969 
970 		zss->sl_flags |= SF_XMT_INPROG;
971 		if ((zss->sl_flags & SF_FDXPTP) ||
972 		    zsh_hdp_ok_or_rts_state(zs, zss))
973 			(void) zsh_start(zs, zss);
974 		mutex_exit(zs->zs_excl_hi);
975 		mutex_exit(zs->zs_excl);
976 		break;
977 
978 	case M_PROTO:
979 		/*
980 		 * Here is where a clone device finds out about the
981 		 * hardware it is going to attach to.  The request is
982 		 * validated and a ppa is extracted from it and validated.
983 		 * This number is used to index the hardware data structure
984 		 * and the protocol data structure, in case the latter
985 		 * was not provided by a data-path open before this.
986 		 */
987 		if (stp->str_state != STR_CLONE) {
988 			freemsg(mp);
989 			return;
990 		}
991 
992 		if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
993 			prim = DL_ATTACH_REQ;
994 			error = DL_BADPRIM;
995 			goto end_proto;
996 		}
997 		dlp = (union DL_primitives *)mp->b_rptr;
998 		prim = dlp->dl_primitive;
999 		if (prim != DL_ATTACH_REQ) {
1000 			error = DL_BADPRIM;
1001 			goto end_proto;
1002 		}
1003 		ppa = dlp->attach_req.dl_ppa;
1004 		ppa = (ppa%2) ? ((ppa-1)*2 +1) : (ppa*2);
1005 		if (ppa >= maxzsh) {
1006 			error = DL_BADPPA;
1007 			goto end_proto;
1008 		}
1009 		zs = &zscom[ppa];
1010 		if (zs->zs_ops == NULL) {
1011 			error = ENXIO;
1012 			goto end_proto;
1013 		}
1014 		mutex_enter(zs->zs_excl);
1015 		if ((zs->zs_ops != &zsops_null) &&
1016 		    (zs->zs_ops != &zsops_hdlc)) {
1017 			/*
1018 			 * another protocol got here first
1019 			 */
1020 			error = (EBUSY);
1021 			mutex_exit(zs->zs_excl);
1022 			goto end_proto;
1023 
1024 		}
1025 
1026 		stp->str_com = (caddr_t)zs;
1027 		mutex_exit(zs->zs_excl);
1028 end_proto:
1029 		if (error)
1030 			dlerrorack(wq, mp, prim, error, 0);
1031 		else
1032 			dlokack(wq, mp, DL_ATTACH_REQ);
1033 		break;
1034 
1035 	case M_IOCTL:
1036 		zsh_ioctl(wq, mp);
1037 		break;
1038 
1039 	case M_IOCDATA:
1040 		resp = (struct copyresp *)mp->b_rptr;
1041 		if (resp->cp_rval) {
1042 			/*
1043 			 * Just free message on failure.
1044 			 */
1045 			freemsg(mp);
1046 			break;
1047 		}
1048 
1049 		switch (resp->cp_cmd) {
1050 
1051 		case S_IOCGETMODE:
1052 		case S_IOCGETSTATS:
1053 		case S_IOCGETSPEED:
1054 		case S_IOCGETMCTL:
1055 		case S_IOCGETMRU:
1056 			mioc2ack(mp, NULL, 0, 0);
1057 			qreply(wq, mp);
1058 			break;
1059 
1060 		case S_IOCSETMODE:
1061 			zss  = (struct syncline *)&zs->zs_priv_str;
1062 			mutex_enter(zs->zs_excl);
1063 			error = zsh_setmode(zs, zss,
1064 				(struct scc_mode *)mp->b_cont->b_rptr);
1065 			if (error) {
1066 				register struct iocblk  *iocp =
1067 					(struct iocblk *)mp->b_rptr;
1068 				mp->b_datap->db_type = M_IOCNAK;
1069 				iocp->ioc_error = error;
1070 			} else
1071 				mioc2ack(mp, NULL, 0, 0);
1072 			mutex_exit(zs->zs_excl);
1073 			qreply(wq, mp);
1074 			break;
1075 
1076 		case S_IOCSETMRU:
1077 			zss  = (struct syncline *)&zs->zs_priv_str;
1078 			mutex_enter(zs->zs_excl);
1079 			zss->sl_mru = *(int *)mp->b_cont->b_rptr;
1080 			mutex_exit(zs->zs_excl);
1081 			mioc2ack(mp, NULL, 0, 0);
1082 			qreply(wq, mp);
1083 			break;
1084 		default:
1085 			freemsg(mp);
1086 		}
1087 		break;
1088 
1089 		/*
1090 		 * We're at the bottom of the food chain, so we flush our
1091 		 * write queue, clear the FLUSHW bit so it doesn't go round
1092 		 * and round forever, then flush our read queue (since there's
1093 		 * no read put procedure down here) and pass it up for any
1094 		 * higher modules to deal with in their own way.
1095 		 */
1096 	case M_FLUSH:
1097 		if (*mp->b_rptr & FLUSHW) {
1098 			mutex_enter(zs->zs_excl);
1099 			flushq(wq, FLUSHDATA);
1100 			mutex_enter(zs->zs_excl_hi);
1101 			tmp = zss->sl_xstandby;
1102 			zss->sl_xstandby = NULL;
1103 			mutex_exit(zs->zs_excl_hi);
1104 			if (tmp)
1105 				freemsg(tmp);
1106 			mutex_exit(zs->zs_excl);
1107 			*mp->b_rptr &= ~FLUSHW;
1108 		}
1109 
1110 		if (*mp->b_rptr & FLUSHR) {
1111 			mutex_enter(zs->zs_excl);
1112 			ZSH_FLUSHQ;
1113 			mutex_exit(zs->zs_excl);
1114 			qreply(wq, mp);  /* let the read queues have at it */
1115 		} else
1116 			freemsg(mp);
1117 		break;
1118 
1119 	default:
1120 		/*
1121 		 * "No, I don't want a subscription to Chain Store Age,
1122 		 * thank you anyway."
1123 		 */
1124 		freemsg(mp);
1125 		break;
1126 	}
1127 
1128 	TRACE_1(TR_ZSH, TR_ZSH_WPUT_END, "zsh_wput end: zs = %p", zs);
1129 }
1130 
1131 /*
1132  * Get the next message from the write queue, set up the necessary pointers,
1133  * state info, etc., and start the transmit "engine" by sending the first
1134  * character.  We'll then rotate through txint until done, then get an xsint.
1135  */
1136 static int
1137 zsh_start(struct zscom *zs, struct syncline *zss)
1138 {
1139 	register mblk_t *mp;
1140 	register uchar_t *wptr;
1141 	register uchar_t *rptr;
1142 	register uchar_t sl_flags = zss->sl_flags;
1143 
1144 	/*
1145 	 * Attempt to grab the next M_DATA message off the queue (that's
1146 	 * all that will be left after wput) and begin transmission.
1147 	 * This routine is normally called after completion of a previous
1148 	 * frame, or when zsh_wput gets a new message.  If we are in a
1149 	 * mode that put us in the TX_RTS state, waiting for CTS, and CTS
1150 	 * is not up yet, we have no business here.  Ditto if we're in
1151 	 * either the TX_ACTIVE or TX_CRC states.  In these cases we
1152 	 * don't clear SF_CALLSTART, so we don't forget there's work to do.
1153 	 */
1154 
1155 	TRACE_1(TR_ZSH, TR_ZSH_START_START,
1156 	    "zsh_start start: zs = %p", zs);
1157 
1158 	if (sl_flags & SF_PHONY) {
1159 		sl_flags &= ~SF_PHONY;
1160 		SCC_BIC(15, ZSR15_CTS);
1161 		SCC_BIC(5, ZSWR5_RTS);
1162 		SCC_WRITE0(ZSWR0_RESET_TXINT);
1163 		SCC_BIC(5, ZSWR5_TX_ENABLE);
1164 		zss->sl_rr0 &= ~ZSRR0_CTS;
1165 		zss->sl_txstate = TX_IDLE;
1166 		/*
1167 		 * if we get another msg by chance zsh_watchog will start
1168 		 */
1169 		sl_flags &= ~SF_XMT_INPROG;
1170 		zss->sl_flags = sl_flags;
1171 
1172 		TRACE_1(TR_ZSH, TR_ZSH_START_END,
1173 		    "zsh_start end: zs = %d", zs);
1174 
1175 		return (0);
1176 	}
1177 	mp = zss->sl_xstandby;
1178 	if (mp == NULL) {
1179 		if (!(sl_flags & SF_FDXPTP)) {
1180 			sl_flags |= SF_PHONY;
1181 			ZSH_ALLOCB(mp);
1182 			if (!mp)
1183 				return (0);
1184 			mp->b_datap->db_type = M_RSE;
1185 			mp->b_wptr = mp->b_rptr + 1;
1186 			goto transmit;
1187 		}
1188 		sl_flags &= ~SF_XMT_INPROG;
1189 		zss->sl_flags = sl_flags;
1190 
1191 		TRACE_1(TR_ZSH, TR_ZSH_START_END,
1192 		    "zsh_start end: zs = %p", zs);
1193 
1194 		return (0);
1195 	}
1196 
1197 transmit:
1198 	zss->sl_xstandby = NULL;
1199 	rptr = mp->b_rptr;
1200 	wptr = mp->b_wptr;
1201 	ZSSETSOFT(zs);
1202 
1203 #ifdef ZSH_DEBUG
1204 	if (zss->sl_xhead || zss->sl_xactb) {
1205 		debug_enter("xhead1");
1206 	}
1207 #endif
1208 
1209 	zss->sl_xhead = mp;
1210 	zss->sl_xactb = mp;
1211 	zss->sl_wd_count = zsh_timer_count;
1212 	zss->sl_txstate = TX_ACTIVE;
1213 	zss->sl_ocnt = 0;
1214 	SCC_BIS(10, ZSWR10_UNDERRUN_ABORT);	/* abort on underrun */
1215 	SCC_WRITE0(ZSWR0_RESET_TXCRC);		/* reset transmit CRC */
1216 	zss->sl_ocnt = wptr - rptr;
1217 	mp->b_wptr = rptr; /* to tell soft to free this msg */
1218 	SCC_WRITEDATA(*rptr++);    /* resets TXINT */
1219 	zs->zs_wr_cur = rptr;
1220 	zs->zs_wr_lim = wptr;
1221 
1222 	SCC_WRITE0(ZSWR0_RESET_EOM);
1223 
1224 	TRACE_1(TR_ZSH, TR_ZSH_START_END,
1225 	    "zsh_start end: zs = %p", zs);
1226 
1227 	zss->sl_flags = sl_flags;
1228 	return (1);
1229 }
1230 
1231 
1232 /*
1233  * Process an "ioctl" message sent down to us.
1234  */
1235 static void
1236 zsh_ioctl(queue_t *wq, mblk_t *mp)
1237 {
1238 	register struct ser_str *stp = (struct ser_str *)wq->q_ptr;
1239 	register struct zscom *zs = (struct zscom *)stp->str_com;
1240 	register struct syncline *zss  = (struct syncline *)&zs->zs_priv_str;
1241 	register struct iocblk   *iocp = (struct iocblk *)mp->b_rptr;
1242 	register struct scc_mode *sm;
1243 	register struct sl_stats *st;
1244 	register uchar_t	 *msignals;
1245 	register mblk_t		 *tmp;
1246 	register int		 error = 0;
1247 
1248 	mutex_enter(zs->zs_excl);
1249 	if ((zs->zs_ops != &zsops_null) &&
1250 	    (zs->zs_ops != &zsops_hdlc)) {
1251 		/*
1252 		 * another protocol got here first
1253 		 */
1254 		error = (EBUSY);
1255 		goto end_zsh_ioctl;
1256 	}
1257 
1258 
1259 	switch (iocp->ioc_cmd) {
1260 
1261 	case S_IOCGETMODE:
1262 		tmp = allocb(sizeof (struct scc_mode), BPRI_MED);
1263 		if (tmp == NULL) {
1264 			error = EAGAIN;
1265 			break;
1266 		}
1267 		if (iocp->ioc_count != TRANSPARENT)
1268 			mioc2ack(mp, tmp, sizeof (struct scc_mode), 0);
1269 		else
1270 			mcopyout(mp, NULL, sizeof (struct scc_mode), NULL, tmp);
1271 		sm = (struct scc_mode *)mp->b_cont->b_rptr;
1272 		bcopy(&zss->sl_mode, sm, sizeof (struct scc_mode));
1273 		break;
1274 
1275 	case S_IOCGETSTATS:
1276 		tmp = allocb(sizeof (struct sl_stats), BPRI_MED);
1277 		if (tmp == NULL) {
1278 			error = EAGAIN;
1279 			break;
1280 		}
1281 		if (iocp->ioc_count != TRANSPARENT)
1282 			mioc2ack(mp, tmp, sizeof (struct sl_stats), 0);
1283 		else
1284 			mcopyout(mp, NULL, sizeof (struct sl_stats), NULL, tmp);
1285 		st = (struct sl_stats *)mp->b_cont->b_rptr;
1286 		bcopy(&zss->sl_st, st, sizeof (struct sl_stats));
1287 		break;
1288 
1289 	case S_IOCGETSPEED:
1290 		tmp = allocb(sizeof (int), BPRI_MED);
1291 		if (tmp == NULL) {
1292 			error = EAGAIN;
1293 			break;
1294 		}
1295 		if (iocp->ioc_count != TRANSPARENT)
1296 			mioc2ack(mp, tmp, sizeof (int), 0);
1297 		else
1298 			mcopyout(mp, NULL, sizeof (int), NULL, tmp);
1299 		*(int *)mp->b_cont->b_rptr = zss->sl_mode.sm_baudrate;
1300 		break;
1301 
1302 	case S_IOCGETMCTL:
1303 		tmp = allocb(sizeof (char), BPRI_MED);
1304 		if (tmp == NULL) {
1305 			error = EAGAIN;
1306 			break;
1307 		}
1308 		if (iocp->ioc_count != TRANSPARENT)
1309 			mioc2ack(mp, tmp, sizeof (char), 0);
1310 		else
1311 			mcopyout(mp, NULL, sizeof (char), NULL, tmp);
1312 		msignals = (uchar_t *)mp->b_cont->b_rptr;
1313 		*msignals = zss->sl_rr0 & (ZSRR0_CD | ZSRR0_CTS);
1314 		break;
1315 
1316 	case S_IOCGETMRU:
1317 		tmp = allocb(sizeof (int), BPRI_MED);
1318 		if (tmp == NULL) {
1319 			error = EAGAIN;
1320 			break;
1321 		}
1322 		if (iocp->ioc_count != TRANSPARENT)
1323 			mioc2ack(mp, tmp, sizeof (int), 0);
1324 		else
1325 			mcopyout(mp, NULL, sizeof (int), NULL, tmp);
1326 		*(int *)mp->b_cont->b_rptr = zss->sl_mru;
1327 		break;
1328 
1329 	case S_IOCSETMODE:
1330 		if (iocp->ioc_count != TRANSPARENT) {
1331 			error = miocpullup(mp, sizeof (struct scc_mode));
1332 			if (error != 0)
1333 				break;
1334 			error = zsh_setmode(zs, zss,
1335 			    (struct scc_mode *)mp->b_cont->b_rptr);
1336 			if (error == 0)
1337 				mioc2ack(mp, NULL, 0, 0);
1338 		} else
1339 			mcopyin(mp, NULL, sizeof (struct scc_mode), NULL);
1340 		break;
1341 
1342 	case S_IOCCLRSTATS:
1343 		mutex_enter(zs->zs_excl_hi);
1344 		bzero(&zss->sl_st, sizeof (struct sl_stats));
1345 		mutex_exit(zs->zs_excl_hi);
1346 		mioc2ack(mp, NULL, 0, 0);
1347 		break;
1348 
1349 	case S_IOCSETMRU:
1350 		if (iocp->ioc_count != TRANSPARENT) {
1351 			error = miocpullup(mp, sizeof (int));
1352 			if (error != 0)
1353 				break;
1354 			zss->sl_mru = *(int *)mp->b_cont->b_rptr;
1355 			mioc2ack(mp, NULL, 0, 0);
1356 		} else
1357 			mcopyin(mp, NULL, sizeof (int), NULL);
1358 		break;
1359 
1360 	case S_IOCSETDTR:
1361 		/*
1362 		 * The first integer of the M_DATA block that should
1363 		 * follow indicate if DTR must be set or reset
1364 		 */
1365 		error = miocpullup(mp, sizeof (int));
1366 		if (error != 0)
1367 			break;
1368 
1369 		mutex_enter(zs->zs_excl_hi);
1370 		if (*(int *)mp->b_cont->b_rptr != 0)
1371 			(void) zsmctl(zs, ZSWR5_DTR, DMBIS);
1372 		else
1373 			(void) zsmctl(zs, ZSWR5_DTR, DMBIC);
1374 		mutex_exit(zs->zs_excl_hi);
1375 		break;
1376 
1377 	default:
1378 		error = EINVAL;
1379 
1380 	}
1381 end_zsh_ioctl:
1382 	iocp->ioc_error = error;
1383 	mp->b_datap->db_type = (error) ? M_IOCNAK : M_IOCACK;
1384 	mutex_exit(zs->zs_excl);
1385 	qreply(wq, mp);
1386 }
1387 
1388 /*
1389  * Set the mode of the zsh port
1390  */
1391 
1392 int
1393 zsh_setmode(struct zscom *zs, struct syncline *zss, struct scc_mode *sm)
1394 {
1395 	register int error = 0;
1396 	register mblk_t *mp;
1397 
1398 	mutex_enter(zs->zs_excl_hi);
1399 	if (sm->sm_rxclock == RXC_IS_PLL) {
1400 		zss->sl_mode.sm_retval = SMERR_RXC;
1401 		mutex_exit(zs->zs_excl_hi);
1402 		return (EINVAL);		/* not supported */
1403 	} else {
1404 		if (((zss->sl_mode.sm_config ^ sm->sm_config) &
1405 			CONN_SIGNAL) != 0) { /* Changing, going... */
1406 			if (sm->sm_config & CONN_SIGNAL) { /* ...up. */
1407 				if (zss->sl_mstat == NULL) {
1408 				    mutex_exit(zs->zs_excl_hi);
1409 				    mp = allocb(
1410 					sizeof (struct sl_status), BPRI_MED);
1411 				    mutex_enter(zs->zs_excl_hi);
1412 				    zss->sl_mstat = mp;
1413 				}
1414 			} else {			/* ...down. */
1415 				if ((mp = zss->sl_mstat) != NULL)
1416 					zss->sl_mstat = NULL;
1417 				mutex_exit(zs->zs_excl_hi);
1418 				if (mp)
1419 					freemsg(mp);
1420 				mutex_enter(zs->zs_excl_hi);
1421 			}
1422 		}
1423 		if (!(sm->sm_config & CONN_IBM)) {
1424 			if (sm->sm_config & CONN_HDX) {
1425 				zss->sl_mode.sm_retval = SMERR_HDX;
1426 				mutex_exit(zs->zs_excl_hi);
1427 				return (EINVAL);
1428 			}
1429 			if (sm->sm_config & CONN_MPT) {
1430 				zss->sl_mode.sm_retval = SMERR_MPT;
1431 				mutex_exit(zs->zs_excl_hi);
1432 				return (EINVAL);
1433 			}
1434 		}
1435 		zss->sl_flags &= ~SF_FDXPTP;		/* "conmode" */
1436 		if ((sm->sm_config & (CONN_HDX | CONN_MPT)) == 0)
1437 			zss->sl_flags |= SF_FDXPTP;
1438 
1439 		error = zsh_program(zs, sm);
1440 		if (!error && (zs->zs_ops != &zsops_null))
1441 			zsh_init_port(zs, zss);
1442 	}
1443 	mutex_exit(zs->zs_excl_hi);
1444 
1445 	return (error);
1446 }
1447 
1448 /*
1449  * Transmit interrupt service procedure
1450  */
1451 
1452 static void
1453 zsh_txint(struct zscom *zs)
1454 {
1455 	register struct syncline *zss;
1456 	register mblk_t *mp;
1457 	register int tmp;
1458 	register uchar_t *wr_cur;
1459 
1460 	TRACE_1(TR_ZSH, TR_ZSH_TXINT, "zsh_txint: zs = %p", zs);
1461 
1462 	if ((wr_cur =  zs->zs_wr_cur) != NULL && (wr_cur <  zs->zs_wr_lim)) {
1463 		SCC_WRITEDATA(*wr_cur++);
1464 		zs->zs_wr_cur = wr_cur;
1465 		return;
1466 	}
1467 
1468 
1469 	zss = (struct syncline *)&zs->zs_priv_str;
1470 
1471 	switch (zss->sl_txstate) {
1472 
1473 	/*
1474 	 * we here because end of message block lim = cur
1475 	 */
1476 	case TX_ACTIVE:
1477 
1478 		mp = zss->sl_xactb;
1479 
1480 again_txint:
1481 		mp = mp->b_cont;
1482 		if (mp) {
1483 			zss->sl_xactb = mp;
1484 			zss->sl_ocnt += tmp = mp->b_wptr - mp->b_rptr;
1485 			if (!tmp)
1486 				goto again_txint;
1487 			zs->zs_wr_cur = mp->b_rptr;
1488 			zs->zs_wr_lim = mp->b_wptr;
1489 			SCC_WRITEDATA(*zs->zs_wr_cur++);
1490 			return;
1491 		}
1492 
1493 		/*
1494 		 * This is where the fun starts.  At this point the
1495 		 * last character in the frame has been sent.  We
1496 		 * issue a RESET_TXINT so we won't get another txint
1497 		 * until the CRC has been completely sent.  Also we
1498 		 * reset the Abort-On-Underrun bit so that CRC is
1499 		 * sent at EOM, rather than an Abort.
1500 		 */
1501 		zs->zs_wr_cur = zs->zs_wr_lim = NULL;
1502 		zss->sl_txstate = TX_CRC;
1503 		SCC_WRITE0(ZSWR0_RESET_TXINT);
1504 		if (!(zss->sl_flags & SF_PHONY)) {
1505 			SCC_BIC(10, ZSWR10_UNDERRUN_ABORT);
1506 			zss->sl_st.opack++;
1507 			zss->sl_st.ochar += zss->sl_ocnt;
1508 		}
1509 		zss->sl_ocnt = 0;
1510 		ZSH_FREEMSG(zss->sl_xhead);
1511 		zss->sl_xhead = zss->sl_xactb = NULL;
1512 		ZSSETSOFT(zs);
1513 		break;
1514 	/*
1515 	 * This txint means we have sent the CRC bytes at EOF.
1516 	 * The next txint will mean we are sending or have sent the
1517 	 * flag character at EOF, but we handle that differently, and
1518 	 * enter different states,depending on whether we're IBM or not.
1519 	 */
1520 	case TX_CRC:
1521 		if (!(zss->sl_flags & SF_FDXPTP)) {
1522 			zss->sl_txstate = TX_FLAG;	/* HDX path */
1523 		} else {	/* FDX path */
1524 			if (!zsh_start(zs, zss)) {
1525 				zss->sl_txstate = TX_IDLE;
1526 				SCC_WRITE0(ZSWR0_RESET_TXINT);
1527 			}
1528 		}
1529 		break;
1530 
1531 	/*
1532 	 * This txint means the closing flag byte is going out the door.
1533 	 * We use this state to allow this to complete before dropping RTS.
1534 	 */
1535 	case TX_FLAG:
1536 		zss->sl_txstate = TX_LAST;
1537 		(void) zsh_start(zs, zss);
1538 		break;
1539 
1540 	/*
1541 	 * Arriving here means the flag should be out and it's finally
1542 	 * time to close the barn door.
1543 	 */
1544 	case TX_LAST:
1545 		zss->sl_txstate = TX_IDLE;
1546 		SCC_WRITE0(ZSWR0_RESET_TXINT);
1547 		break;
1548 
1549 	/*
1550 	 * If transmit was aborted, do nothing - watchdog will recover.
1551 	 */
1552 	case TX_ABORTED:
1553 		SCC_WRITE0(ZSWR0_RESET_TXINT);
1554 		break;
1555 
1556 	default:
1557 		SCC_WRITE0(ZSWR0_RESET_TXINT);
1558 		break;
1559 	}
1560 }
1561 
1562 /*
1563  * External Status Change interrupt service procedure
1564  */
1565 static void
1566 zsh_xsint(struct zscom *zs)
1567 {
1568 	register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1569 	register uchar_t s0, x0;
1570 
1571 	TRACE_1(TR_ZSH, TR_ZSH_XSINT, "zsh_xsint: zs = %p", zs);
1572 
1573 	s0 = SCC_READ0();
1574 	x0 = s0 ^ zss->sl_rr0;
1575 	zss->sl_rr0 = s0;
1576 	SCC_WRITE0(ZSWR0_RESET_STATUS);
1577 
1578 	if (s0 & ZSRR0_TXUNDER) {
1579 		switch (zss->sl_txstate) {
1580 		/*
1581 		 * A transmitter underrun has occurred.  If we are not
1582 		 * here as the result of an abort sent by the watchdog
1583 		 * timeout routine, we need to send an abort to flush
1584 		 * the transmitter.  Otherwise there is a danger of
1585 		 * trashing the next frame but still sending a good crc.
1586 		 * The TX_ABORTED flag is set so that the watchdog
1587 		 * routine can initiate recovery.
1588 		 */
1589 		case TX_ACTIVE:
1590 			SCC_WRITE0(ZSWR0_SEND_ABORT);
1591 			SCC_WRITE0(ZSWR0_RESET_TXINT);
1592 			zss->sl_st.underrun++;
1593 			zsh_txbad(zs, zss);
1594 
1595 			zss->sl_txstate = TX_ABORTED;
1596 			zss->sl_wd_count = 0;
1597 			break;
1598 
1599 		case TX_CRC:
1600 			break;
1601 
1602 		case TX_FLAG:
1603 			break;
1604 
1605 		case TX_ABORTED:
1606 			break;
1607 
1608 		case TX_OFF:
1609 			break;
1610 
1611 		case TX_LAST:
1612 			break;
1613 
1614 		default:
1615 			break;
1616 		}
1617 	}
1618 
1619 	if ((x0 & ZSRR0_BREAK) && (s0 & ZSRR0_BREAK) && zs->zs_rd_cur) {
1620 		zss->sl_st.abort++;
1621 		zsh_rxbad(zs, zss);
1622 	} else if ((s0 & ZSRR0_SYNC) && (zs->zs_rd_cur)) {
1623 		/*
1624 		 * Tricky code to avoid disaster in the case where
1625 		 * an abort was detected while receiving a packet,
1626 		 * but the abort did not last long enough to be
1627 		 * detected by zsh_xsint - this can happen since
1628 		 * the ZSRR0_BREAK is not latched.  Since an abort
1629 		 * will automatically cause the SCC to enter
1630 		 * hunt mode, hopefully, the sync/hunt bit will be
1631 		 * set in this case (although if the interrupt is
1632 		 * sufficiently delayed, the SCC may have sync'ed
1633 		 * in again if it has detected a flag).
1634 		 */
1635 		zss->sl_st.abort++;
1636 		zsh_rxbad(zs, zss);
1637 	}
1638 
1639 	if (x0 & s0 & ZSRR0_CTS) {
1640 	    if (zss->sl_txstate == TX_RTS) {
1641 		if (!(zss->sl_flags & SF_FDXPTP)) {
1642 			SCC_BIS(5, ZSWR5_TX_ENABLE);
1643 		}
1644 		(void) zsh_start(zs, zss);
1645 	    } else if ((zss->sl_mode.sm_config & (CONN_IBM | CONN_SIGNAL))) {
1646 		zss->sl_flags &= ~SF_FLUSH_WQ;
1647 		zsh_setmstat(zs, CS_CTS_UP);
1648 	    }
1649 	}
1650 
1651 	/*
1652 	 * We don't care about CTS transitions unless we are in either
1653 	 * IBM or SIGNAL mode, or both.  So, if we see CTS drop, and we
1654 	 * care, and we are not idle, send up a report message.
1655 	 */
1656 	if ((x0 & ZSRR0_CTS) && ((s0 & ZSRR0_CTS) == 0) &&
1657 	    (zss->sl_txstate != TX_OFF) &&
1658 	    (zss->sl_mode.sm_config & (CONN_IBM | CONN_SIGNAL))) {
1659 		SCC_BIC(15, ZSR15_CTS);
1660 		zsh_setmstat(zs, CS_CTS_DOWN);
1661 		zss->sl_flags &= ~SF_XMT_INPROG;
1662 		zss->sl_flags |= SF_FLUSH_WQ;
1663 		zss->sl_st.cts++;
1664 		if (zss->sl_txstate != TX_IDLE)
1665 			SCC_WRITE0(ZSWR0_SEND_ABORT);
1666 		SCC_WRITE0(ZSWR0_RESET_ERRORS);
1667 		SCC_WRITE0(ZSWR0_RESET_TXINT);
1668 		zss->sl_wd_count = 0;
1669 		zsh_txbad(zs, zss);
1670 	}
1671 }
1672 
1673 
1674 /*
1675  * Receive interrupt service procedure
1676  */
1677 static void
1678 zsh_rxint(struct zscom *zs)
1679 {
1680 	register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1681 	register mblk_t *bp = zss->sl_ractb;
1682 	unsigned char *rd_cur;
1683 
1684 	TRACE_1(TR_ZSH, TR_ZSH_RXINT, "zsh_rxint: zs = %p", zs);
1685 
1686 	if (((rd_cur = zs->zs_rd_cur) != NULL) && rd_cur < zs->zs_rd_lim) {
1687 		*rd_cur++ = SCC_READDATA();
1688 		zs->zs_rd_cur = rd_cur;
1689 		return;
1690 	}
1691 
1692 	if (!rd_cur) { /* Beginning of frame */
1693 		if (!bp) {
1694 			ZSH_ALLOCB(bp);
1695 			zss->sl_ractb = bp;
1696 		}
1697 		zss->sl_rhead = bp;
1698 	} else {	/* end of data block should be cur==lim */
1699 		bp->b_wptr = zs->zs_rd_cur;
1700 		ZSH_ALLOCB(bp->b_cont);
1701 		bp = zss->sl_ractb = bp->b_cont;
1702 	}
1703 	if (!bp) {
1704 		zss->sl_st.nobuffers++;
1705 		zsh_rxbad(zs, zss);
1706 		return;
1707 	}
1708 	zs->zs_rd_cur = bp->b_wptr;
1709 	zs->zs_rd_lim = bp->b_datap->db_lim;
1710 	*zs->zs_rd_cur++ = SCC_READDATA(); /* Also resets interrupt */
1711 }
1712 
1713 
1714 /*
1715  * Special Receive Condition Interrupt routine
1716  */
1717 static void
1718 zsh_srint(struct zscom *zs)
1719 {
1720 	register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1721 	register uchar_t s1;
1722 	register uchar_t *rd_cur;
1723 
1724 	TRACE_1(TR_ZSH, TR_ZSH_SRINT, "zsh_srint: zs = %p", zs);
1725 
1726 	SCC_READ(1, s1);
1727 
1728 	if (s1 & ZSRR1_RXEOF) {			/* end of frame */
1729 		(void) SCC_READDATA();
1730 		SCC_WRITE0(ZSWR0_RESET_ERRORS);
1731 		if (s1 & ZSRR1_FE) {		/* bad CRC */
1732 			zss->sl_st.crc++;
1733 			zsh_rxbad(zs, zss);
1734 			return;
1735 		}
1736 
1737 		if ((rd_cur = zs->zs_rd_cur) == NULL)
1738 			return;
1739 
1740 		/*
1741 		 * Drop one CRC byte from length because it came in
1742 		 * before the special interrupt got here.
1743 		 */
1744 		zss->sl_ractb->b_wptr = rd_cur - 1;
1745 
1746 		/*
1747 		 * put on done queue
1748 		 */
1749 		ZSH_PUTQ(zss->sl_rhead);
1750 		zss->sl_rhead = NULL;
1751 		zss->sl_ractb = NULL;
1752 		zs->zs_rd_cur = NULL;
1753 		zs->zs_rd_lim = NULL;
1754 		ZSSETSOFT(zs);
1755 
1756 	} else if (s1 & ZSRR1_DO) {
1757 		(void) SCC_READDATA();
1758 		SCC_WRITE0(ZSWR0_RESET_ERRORS);
1759 		zss->sl_st.overrun++;
1760 		zsh_rxbad(zs, zss);
1761 	} else
1762 		SCC_WRITE0(ZSWR0_RESET_ERRORS);
1763 }
1764 
1765 /*
1766  * Handle a second stage interrupt.
1767  * Does mostly lower priority buffer management stuff.
1768  */
1769 static int
1770 zsh_softint(struct zscom *zs)
1771 {
1772 	register struct syncline *zss;
1773 	register queue_t *q;
1774 	register mblk_t *mp, *tmp;
1775 	register mblk_t *head = NULL, *tail = NULL;
1776 	register int allocbcount = 0;
1777 	int m_error;
1778 
1779 	TRACE_1(TR_ZSH, TR_ZSH_SOFT_START, "zsh_soft start: zs = %p", zs);
1780 
1781 	mutex_enter(zs->zs_excl);
1782 	zss = (struct syncline *)zs->zs_priv;
1783 	if (!zss || (q = zss->sl_stream.str_rq) == NULL) {
1784 		mutex_exit(zs->zs_excl);
1785 		return (0);
1786 	}
1787 	m_error = zss->sl_m_error;
1788 
1789 	zss->sl_m_error = 0;
1790 
1791 
1792 	if (!zss->sl_mstat)
1793 		zss->sl_mstat = allocb(sizeof (struct sl_status), BPRI_MED);
1794 
1795 	mutex_enter(zs->zs_excl_hi);
1796 	if (zss->sl_flags & SF_FLUSH_WQ) {
1797 		if (!(zss->sl_flags & SF_FDXPTP)) {
1798 			zss->sl_flags &= ~SF_FLUSH_WQ;
1799 		} else {
1800 			register uchar_t s0;
1801 
1802 			s0 = SCC_READ0();
1803 			if (s0 & ZSRR0_CTS) {
1804 				zss->sl_rr0 |= ZSRR0_CTS;
1805 				SCC_BIS(15, ZSR15_CTS);
1806 				zss->sl_flags &= ~SF_FLUSH_WQ;
1807 				zsh_setmstat(zs, CS_CTS_UP);
1808 			}
1809 			if (zss->sl_flags & SF_FLUSH_WQ) {
1810 				mutex_exit(zs->zs_excl_hi);
1811 				flushq(WR(q), FLUSHDATA);
1812 				goto next;
1813 			}
1814 		}
1815 	}
1816 	mutex_exit(zs->zs_excl_hi);
1817 
1818 next:
1819 	for (;;) {
1820 		ZSH_GETQ(mp);
1821 		if (!mp)
1822 			break;
1823 
1824 		if (mp->b_rptr == mp->b_wptr) {
1825 			if (mp->b_datap->db_type == M_RSE) {
1826 				allocbcount++;
1827 			}
1828 			freemsg(mp);
1829 			continue;
1830 		}
1831 		if (mp->b_datap->db_type == M_DATA) {
1832 			zss->sl_st.ichar += msgdsize(mp);
1833 			zss->sl_st.ipack++;
1834 			if (!(canputnext(q))) {
1835 				zss->sl_st.ierror++;
1836 				allocbcount++;
1837 				freemsg(mp);
1838 				continue;
1839 			}
1840 		} else if (mp->b_datap->db_type == M_PROTO) {
1841 			if (!(canputnext(q))) {
1842 				freemsg(mp);
1843 				continue;
1844 			}
1845 		}
1846 		if (!head) {
1847 			allocbcount++;
1848 			zss->sl_soft_active = 1;
1849 			head = mp;
1850 		} else {
1851 			if (!tail)
1852 				tail = head;
1853 			tail->b_next = mp;
1854 			tail = mp;
1855 		}
1856 	}
1857 	if (allocbcount)
1858 		ZSH_GETBLOCK(zs, allocbcount);
1859 
1860 	tmp = NULL;
1861 again:
1862 	mutex_enter(zs->zs_excl_hi);
1863 	if (!zss->sl_xstandby) {
1864 		if (tmp) {
1865 			zss->sl_xstandby = tmp;
1866 			mutex_exit(zs->zs_excl_hi);
1867 		} else {
1868 			mutex_exit(zs->zs_excl_hi);
1869 			if (tmp = getq(WR(q)))
1870 				goto again;
1871 		}
1872 	} else {
1873 		mutex_exit(zs->zs_excl_hi);
1874 		if (tmp)
1875 			(void) putbq(WR(q), tmp);
1876 	}
1877 
1878 	mutex_exit(zs->zs_excl);
1879 
1880 	while (head) {
1881 		if (!tail) {
1882 			putnext(q, head);
1883 			break;
1884 		}
1885 		mp = head;
1886 		head = head->b_next;
1887 		mp->b_next = NULL;
1888 		putnext(q, mp);
1889 
1890 	}
1891 
1892 	if (m_error)
1893 		(void) putnextctl1(q, M_ERROR, m_error);
1894 
1895 	zss->sl_soft_active = 0;
1896 
1897 	TRACE_1(TR_ZSH, TR_ZSH_SOFT_END, "zsh_soft end: zs = %p", zs);
1898 
1899 	return (0);
1900 }
1901 
1902 /*
1903  * Initialization routine.
1904  * Sets Clock sources, baud rate, modes and miscellaneous parameters.
1905  */
1906 static int
1907 zsh_program(struct zscom *zs, struct scc_mode *sm)
1908 {
1909 	register struct syncline *zss  = (struct syncline *)&zs->zs_priv_str;
1910 	register struct zs_prog *zspp;
1911 	register ushort_t	tconst = 0;
1912 	register int	wr11 = 0;
1913 	register int	baud = 0;
1914 	register int	pll = 0;
1915 	register int	speed = 0;
1916 	register int	flags = ZSP_SYNC;
1917 	int		err = 0;
1918 
1919 	ZSSETSOFT(zs); /* get our house in order */
1920 
1921 	switch (sm->sm_txclock) {
1922 	case TXC_IS_TXC:
1923 		wr11 |= ZSWR11_TXCLK_TRXC;
1924 		break;
1925 	case TXC_IS_RXC:
1926 		wr11 |= ZSWR11_TXCLK_RTXC;
1927 		break;
1928 	case TXC_IS_BAUD:
1929 		wr11 |= ZSWR11_TXCLK_BAUD;
1930 		wr11 |= ZSWR11_TRXC_OUT_ENA + ZSWR11_TRXC_XMIT;
1931 		baud++;
1932 		break;
1933 	case TXC_IS_PLL:
1934 		wr11 |= ZSWR11_TXCLK_DPLL;
1935 		pll++;
1936 		break;
1937 	default:
1938 		zss->sl_mode.sm_retval = SMERR_TXC;
1939 		err = EINVAL;
1940 		goto out;
1941 	}
1942 	switch (sm->sm_rxclock) {
1943 	case RXC_IS_RXC:
1944 		wr11 |= ZSWR11_RXCLK_RTXC;
1945 		break;
1946 	case RXC_IS_TXC:
1947 		wr11 |= ZSWR11_RXCLK_TRXC;
1948 		break;
1949 	case RXC_IS_BAUD:
1950 		wr11 |= ZSWR11_RXCLK_BAUD;
1951 		baud++;
1952 		break;
1953 	case RXC_IS_PLL:
1954 		wr11 |= ZSWR11_RXCLK_DPLL;
1955 		pll++;
1956 		break;
1957 	default:
1958 		zss->sl_mode.sm_retval = SMERR_RXC;
1959 		err = EINVAL;
1960 		goto out;
1961 	}
1962 	if (baud && pll) {
1963 		zss->sl_mode.sm_retval = SMERR_PLL;
1964 		err = EINVAL;
1965 		goto out;
1966 	}
1967 	if (pll && !(sm->sm_config & CONN_NRZI)) {
1968 		zss->sl_mode.sm_retval = SMERR_PLL;
1969 		err = EINVAL;
1970 		goto out;
1971 	}
1972 
1973 	/*
1974 	 * If we're going to use the BRG and the speed we want is != 0...
1975 	 */
1976 	if (baud && (speed = sm->sm_baudrate)) {
1977 		tconst = (PCLK + speed) / (2 * speed) - 2;
1978 		if (tconst == 0) {
1979 			zss->sl_mode.sm_retval = SMERR_BAUDRATE;
1980 			err = EINVAL;
1981 			goto out;
1982 		}
1983 		sm->sm_baudrate = PCLK / (2 * ((int)tconst + 2));
1984 	} else {
1985 		tconst = 0;	/* Stop BRG.  Also quiesces pin 24. */
1986 	}
1987 
1988 	if (pll) {
1989 		if ((speed  = sm->sm_baudrate * 32) != 0)
1990 			tconst = (PCLK + speed) / (2 * speed) - 2;
1991 		else
1992 			tconst = 0;
1993 		if (tconst == 0) {
1994 			zss->sl_mode.sm_retval = SMERR_BAUDRATE;
1995 			err = EINVAL;
1996 			goto out;
1997 		}
1998 		speed = PCLK / (2 * ((int)tconst + 2));
1999 		sm->sm_baudrate = speed / 32;
2000 		flags |= ZSP_PLL;
2001 	}
2002 
2003 	if ((sm->sm_config & (CONN_LPBK|CONN_ECHO)) == (CONN_LPBK|CONN_ECHO)) {
2004 		zss->sl_mode.sm_retval = SMERR_LPBKS;
2005 		err = EINVAL;
2006 		goto out;
2007 	}
2008 	if (sm->sm_config & CONN_LPBK)
2009 		flags |= ZSP_LOOP;
2010 	if (sm->sm_config & CONN_NRZI)
2011 		flags |= ZSP_NRZI;
2012 	if (sm->sm_config & CONN_ECHO)
2013 		flags |= ZSP_ECHO;
2014 
2015 	zspp = &zs_prog[zs->zs_unit];
2016 
2017 	zspp->zs = zs;
2018 	zspp->flags = (uchar_t)flags;
2019 	zspp->wr4 = ZSWR4_SDLC;
2020 	zspp->wr11 = (uchar_t)wr11;
2021 	zspp->wr12 = (uchar_t)(tconst & 0xff);
2022 	zspp->wr13 = (uchar_t)((tconst >> 8) & 0xff);
2023 	zspp->wr3 = (uchar_t)(ZSWR3_RX_ENABLE | ZSWR3_RXCRC_ENABLE |
2024 	    ZSWR3_RX_8);
2025 	zspp->wr5 = (uchar_t)(ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_TXCRC_ENABLE);
2026 
2027 	if (zss->sl_flags & SF_FDXPTP) {
2028 		zspp->wr5 |= ZSWR5_RTS;
2029 		zss->sl_rr0 |= ZSRR0_CTS;		/* Assume CTS is high */
2030 	}
2031 	if (sm->sm_config & CONN_IBM) {
2032 		zspp->wr15 = (uchar_t)
2033 		    (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC | ZSR15_CTS);
2034 		if (!(zss->sl_flags & SF_FDXPTP))
2035 			zspp->wr15 &= ~ZSR15_CTS;
2036 	} else {
2037 		zspp->wr5 |= ZSWR5_TX_ENABLE;
2038 		zspp->wr15 = (uchar_t)
2039 		    (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC);
2040 		if (sm->sm_config & CONN_SIGNAL)
2041 			zspp->wr15 |= ZSR15_CTS;
2042 	}
2043 
2044 	zs_program(zspp);
2045 	SCC_WRITE0(ZSWR0_RESET_STATUS);		/* reset XS */
2046 	SCC_WRITE0(ZSWR0_RESET_STATUS);		/* reset XS */
2047 	zss->sl_flags |= SF_INITIALIZED;
2048 	bzero(&zss->sl_st, sizeof (struct sl_stats));
2049 	bcopy(sm, &zss->sl_mode, sizeof (struct scc_mode));
2050 	zss->sl_mode.sm_retval = 0;	/* successful */
2051 out:
2052 	return (err);
2053 }
2054 
2055 /*
2056  * Function to store modem signal changes in sl_mstat field.
2057  * Note that these events are supposed to be so far apart in time that
2058  * we should always be able to send up the event and allocate a message
2059  * block before another one happens.  If not, we'll overwrite this one.
2060  */
2061 static void
2062 zsh_setmstat(struct zscom *zs, int event)
2063 {
2064 	register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
2065 	register struct sl_status *mstat;
2066 	register mblk_t *mp;
2067 
2068 	if (((mp = zss->sl_mstat) != NULL) &&
2069 	    (zss->sl_mode.sm_config & (CONN_SIGNAL))) {
2070 		mstat = (struct sl_status *)mp->b_wptr;
2071 		mstat->type = (zss->sl_mode.sm_config & CONN_IBM) ?
2072 		    SLS_LINKERR : SLS_MDMSTAT;
2073 		mstat->status = event;
2074 		gethrestime(&mstat->tstamp);
2075 		mp->b_wptr += sizeof (struct sl_status);
2076 		mp->b_datap->db_type = M_PROTO;
2077 		ZSH_PUTQ(mp);
2078 		zss->sl_mstat = NULL;
2079 		ZSSETSOFT(zs);
2080 	}
2081 }
2082 
2083 /*
2084  * Received Bad Frame procedure
2085  */
2086 static void
2087 zsh_rxbad(struct zscom *zs, struct syncline *zss)
2088 {
2089 	/*
2090 	 * swallow bad characters
2091 	 */
2092 	(void) SCC_READDATA();
2093 	(void) SCC_READDATA();
2094 	(void) SCC_READDATA();
2095 
2096 	SCC_BIS(3, ZSWR3_HUNT);	/* enter hunt mode - ignores rest of frame */
2097 
2098 	zss->sl_st.ierror++;
2099 
2100 	/*
2101 	 * Free active receive message.
2102 	 */
2103 	if (zss->sl_rhead) {
2104 		zss->sl_rhead->b_wptr = zss->sl_rhead->b_rptr;
2105 		zss->sl_rhead->b_datap->db_type = M_RSE;
2106 		ZSH_FREEMSG(zss->sl_rhead);
2107 		zss->sl_ractb = NULL;
2108 		zs->zs_rd_cur = NULL;
2109 		zs->zs_rd_lim = NULL;
2110 	}
2111 	if (zss->sl_rhead) {
2112 		zss->sl_rhead = NULL;
2113 		ZSH_ALLOCB(zss->sl_ractb);
2114 		zs->zs_rd_cur = NULL;
2115 		zs->zs_rd_lim = NULL;
2116 	}
2117 
2118 	ZSSETSOFT(zs);
2119 }
2120 
2121 /*
2122  * Transmit error procedure
2123  */
2124 static void
2125 zsh_txbad(struct zscom *zs, struct syncline *zss)
2126 {
2127 	if (zss->sl_xhead) {		/* free the message we were sending */
2128 		zss->sl_xhead->b_wptr = zss->sl_xhead->b_rptr;
2129 		ZSH_FREEMSG(zss->sl_xhead);
2130 		zss->sl_xactb = NULL;
2131 		zs->zs_wr_cur = NULL;
2132 		zs->zs_wr_lim = NULL;
2133 	}
2134 	zss->sl_xhead = NULL;
2135 
2136 	if (!(zss->sl_flags & SF_FDXPTP)) {
2137 		/*
2138 		 * drop RTS and our notion of CTS
2139 		 */
2140 		SCC_BIC(5, ZSWR5_RTS);
2141 		SCC_BIC(5, ZSWR5_TX_ENABLE);
2142 		zss->sl_rr0 &= ~ZSRR0_CTS;
2143 	}
2144 	zss->sl_txstate = TX_IDLE;
2145 	if (!(zss->sl_flags & SF_PHONY))
2146 		zss->sl_st.oerror++;
2147 }
2148 
2149 /*
2150  * Transmitter watchdog timeout routine
2151  */
2152 static void
2153 zsh_watchdog(void *arg)
2154 {
2155 	struct zscom *zs = arg;
2156 	struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
2157 	queue_t *wq;
2158 	mblk_t *mp;
2159 	int warning = 0;
2160 	uchar_t s0;
2161 	int do_flushwq = 0;
2162 
2163 	/*
2164 	 * The main reason for this routine is because, under some
2165 	 * circumstances, a transmit interrupt may get lost (ie., if
2166 	 * underrun occurs after the last character has been sent, and
2167 	 * the tx interrupt following the abort gets scheduled before
2168 	 * the current tx interrupt has been serviced).  Transmit can
2169 	 * also get hung if the cable is pulled out and the clock was
2170 	 * coming in from the modem.
2171 	 */
2172 
2173 	mutex_enter(zs->zs_excl);
2174 	if (zss->sl_stream.str_rq)
2175 		wq = WR(zss->sl_stream.str_rq);
2176 	else {
2177 		mutex_exit(zs->zs_excl);
2178 		return;		/* guard against close/callback race */
2179 	}
2180 
2181 	mutex_enter(zs->zs_excl_hi);
2182 	if (!(zss->sl_flags & SF_XMT_INPROG) && wq->q_first) {
2183 		zss->sl_flags |= SF_XMT_INPROG;
2184 		if ((zss->sl_flags & SF_FDXPTP) ||
2185 		    zsh_hdp_ok_or_rts_state(zs, zss))
2186 			(void) zsh_start(zs, zss);
2187 		goto end_watchdog;
2188 	}
2189 
2190 	if (zss->sl_wd_count-- > 0)
2191 		goto end_watchdog;
2192 
2193 	if (zss->sl_flags & SF_FLUSH_WQ) {
2194 		if (!(zss->sl_flags & SF_FDXPTP))
2195 			zss->sl_flags &= ~SF_FLUSH_WQ;
2196 		else {
2197 			s0 = SCC_READ0();
2198 			if (s0 & ZSRR0_CTS) {
2199 				zss->sl_rr0 |= ZSRR0_CTS;
2200 				SCC_BIS(15, ZSR15_CTS);
2201 				zss->sl_flags &= ~SF_FLUSH_WQ;
2202 				zsh_setmstat(zs, CS_CTS_UP);
2203 			}
2204 		}
2205 	}
2206 
2207 	switch (zss->sl_txstate) {
2208 
2209 	case TX_ABORTED:
2210 		/*
2211 		 * Transmitter was hung ... try restarting it.
2212 		 */
2213 		if (zss->sl_flags & SF_FDXPTP) {
2214 			zss->sl_flags |= SF_XMT_INPROG;
2215 			(void) zsh_start(zs, zss);
2216 		} else
2217 			do_flushwq = 1;
2218 		break;
2219 
2220 	case TX_ACTIVE:
2221 	case TX_CRC:
2222 		/*
2223 		 * Transmit is hung for some reason. Reset tx interrupt.
2224 		 * Flush transmit fifo by sending an abort command
2225 		 * which also sets the Underrun/EOM latch in WR0 and in
2226 		 * turn generates an External Status interrupt that
2227 		 * will reset the necessary message buffer pointers.
2228 		 * The watchdog timer will cycle again to allow the SCC
2229 		 * to settle down after the abort command.  The next
2230 		 * time through we'll see that the state is now TX_ABORTED
2231 		 * and call zsh_start to grab a new message.
2232 		 */
2233 		if (--zss->sl_wd_count <= 0) {
2234 			SCC_WRITE0(ZSWR0_SEND_ABORT);
2235 			SCC_WRITE0(ZSWR0_RESET_ERRORS);
2236 			SCC_WRITE0(ZSWR0_RESET_TXINT);
2237 			zsh_txbad(zs, zss);
2238 			zss->sl_txstate = TX_ABORTED; /* must be after txbad */
2239 			warning = 1;
2240 		}
2241 		break;
2242 
2243 	case TX_RTS:
2244 		/*
2245 		 * Timer expired after we raised RTS.  CTS never came up.
2246 		 */
2247 		zss->sl_st.cts++;
2248 
2249 		zsh_setmstat(zs, CS_CTS_TO);
2250 		zss->sl_flags &= ~SF_XMT_INPROG;
2251 		zss->sl_flags |= SF_FLUSH_WQ;
2252 		ZSSETSOFT(zs);
2253 		break;
2254 
2255 	default:
2256 		/*
2257 		 * If we time out in an inactive state we set a soft
2258 		 * interrupt.  This will call zsh_start which will
2259 		 * clear SF_XMT_INPROG if the queue is empty.
2260 		 */
2261 		break;
2262 	}
2263 end_watchdog:
2264 	if (zss->sl_txstate != TX_OFF) {
2265 		mutex_exit(zs->zs_excl_hi);
2266 		zss->sl_wd_id = timeout(zsh_watchdog, zs, SIO_WATCHDOG_TICK);
2267 	} else {
2268 		zss->sl_wd_id = 0;	/* safety */
2269 		mutex_exit(zs->zs_excl_hi);
2270 	}
2271 	if (warning || do_flushwq) {
2272 		flushq(wq, FLUSHDATA);
2273 		mutex_enter(zs->zs_excl_hi);
2274 		if ((mp = zss->sl_xstandby) != NULL)
2275 			zss->sl_xstandby = NULL;
2276 		mutex_exit(zs->zs_excl_hi);
2277 		if (mp)
2278 			freemsg(mp);
2279 	}
2280 	mutex_exit(zs->zs_excl);
2281 	if (warning)
2282 		cmn_err(CE_WARN, "zsh%x: transmit hung", zs->zs_unit);
2283 }
2284 
2285 static void
2286 zsh_callback(void *arg)
2287 {
2288 	struct zscom *zs = arg;
2289 	struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
2290 	int tmp = ZSH_MAX_RSTANDBY;
2291 
2292 	mutex_enter(zs->zs_excl);
2293 	if (zss->sl_bufcid) {
2294 		zss->sl_bufcid = 0;
2295 		ZSH_GETBLOCK(zs, tmp);
2296 	}
2297 	mutex_exit(zs->zs_excl);
2298 }
2299