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 *	HDLC protocol handler for Z8530 SCC.
29 */
30
31#include	<sys/param.h>
32#include	<sys/systm.h>
33#include	<sys/types.h>
34#include	<sys/sysmacros.h>
35#include	<sys/kmem.h>
36#include	<sys/stropts.h>
37#include	<sys/stream.h>
38#include	<sys/strsun.h>
39#include	<sys/stat.h>
40#include	<sys/cred.h>
41#include	<sys/user.h>
42#include	<sys/proc.h>
43#include	<sys/file.h>
44#include	<sys/uio.h>
45#include	<sys/buf.h>
46#include	<sys/mkdev.h>
47#include	<sys/cmn_err.h>
48#include	<sys/errno.h>
49#include	<sys/fcntl.h>
50
51#include	<sys/zsdev.h>
52#include	<sys/ser_sync.h>
53#include	<sys/conf.h>
54#include	<sys/ddi.h>
55#include	<sys/sunddi.h>
56#include	<sys/dlpi.h>
57
58#define	ZSH_TRACING
59#ifdef	ZSH_TRACING
60#include	<sys/vtrace.h>
61
62/*
63 * Temp tracepoint definitions
64 */
65#define	TR_ZSH		50
66
67#define	TR_ZSH_TXINT	1
68#define	TR_ZSH_XSINT	2
69#define	TR_ZSH_RXINT	3
70#define	TR_ZSH_SRINT	4
71
72#define	TR_ZSH_WPUT_START		5
73#define	TR_ZSH_WPUT_END			6
74#define	TR_ZSH_START_START		7
75#define	TR_ZSH_START_END		8
76#define	TR_ZSH_SOFT_START		9
77#define	TR_ZSH_SOFT_END			10
78
79#define	TR_ZSH_OPEN	 11
80#define	TR_ZSH_CLOSE	12
81
82#endif	/* ZSH_TRACING */
83
84/*
85 * Logging definitions
86 */
87
88/*
89 * #define	ZSH_DEBUG
90 */
91#ifdef ZSH_DEBUG
92
93#ifdef ZS_DEBUG_ALL
94extern	char	zs_h_log[];
95extern	int	zs_h_log_n;
96#define	zsh_h_log_add(c) \
97	{ \
98		if (zs_h_log_n >= ZS_H_LOG_MAX) \
99			zs_h_log_n = 0; \
100		zs_h_log[zs_h_log_n++] = 'A' + zs->zs_unit; \
101		zs_h_log[zs_h_log_n++] = c; \
102		zs_h_log[zs_h_log_n] = '\0'; \
103	}
104#define	zsh_h_log_clear
105#else
106#define	ZSH_H_LOG_MAX   0x8000
107char zsh_h_log[2][ZSH_H_LOG_MAX +10];
108int zsh_h_log_n[2];
109#define	zsh_h_log_add(c) \
110	{ \
111		if (zsh_h_log_n[zs->zs_unit] >= ZSH_H_LOG_MAX) \
112			zsh_h_log_n[zs->zs_unit] = 0; \
113		zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]++] = c; \
114		zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]] = '\0'; \
115	}
116
117#define	zsh_h_log_clear \
118	{ register char *p; \
119	for (p = &zsh_h_log[zs->zs_unit][ZSH_H_LOG_MAX]; \
120		p >= &zsh_h_log[zs->zs_unit][0]; p--) \
121		*p = '\0'; \
122	zsh_h_log_n[zs->zs_unit] = 0; \
123	}
124#endif
125
126#define	ZSH_R0_LOG(r0)  { \
127	if (r0 & ZSRR0_RX_READY) zsh_h_log_add('R'); \
128	if (r0 & ZSRR0_TIMER) zsh_h_log_add('Z'); \
129	if (r0 & ZSRR0_TX_READY) zsh_h_log_add('T'); \
130	if (r0 & ZSRR0_CD) zsh_h_log_add('D'); \
131	if (r0 & ZSRR0_SYNC) zsh_h_log_add('S'); \
132	if (r0 & ZSRR0_CTS) zsh_h_log_add('C'); \
133	if (r0 & ZSRR0_TXUNDER) zsh_h_log_add('U'); \
134	if (r0 & ZSRR0_BREAK) zsh_h_log_add('B'); \
135	}
136#endif
137
138
139char _depends_on[] = "drv/zs";
140
141#ifndef	MAXZSH
142#define	MAXZSH	2
143#define	MAXZSHCLONES	(80)	/* three clone opens per instance */
144#endif	/* MAXZSH */
145
146int maxzsh = MAXZSH;
147
148int zsh_timer_count = 10;
149int zsh_default_mru = 1024;
150
151struct ser_str *zsh_str = NULL;
152unsigned char zsh_usedminor[MAXZSHCLONES];
153
154
155/*
156 * The HDLC protocol
157 */
158int zsh_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result);
159static int  zsh_probe(dev_info_t *dev);
160static int  zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd);
161static int  zsh_detach(dev_info_t *dev, ddi_detach_cmd_t cmd);
162static int  zsh_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr);
163static int  zsh_close(queue_t *rq, int flag);
164static void zsh_wput(queue_t *wq, mblk_t *mp);
165static int zsh_start(struct zscom *zs, struct syncline *zss);
166static void zsh_ioctl(queue_t *wq, mblk_t *mp);
167
168static struct module_info hdlc_minfo = {
169	0x5a48,		/* module ID number: "ZH" */
170	"zsh",		/* module name */
171	0,		/* minimum packet size accepted */
172	INFPSZ,		/* maximum packet size accepted */
173	12*1024,	/* queue high water mark (bytes) */
174	4*1024		/* queue low water mark (bytes) */
175};
176
177static struct qinit hdlc_rinit = {
178	putq,		/* input put procedure */
179	NULL,		/* input service procedure */
180	zsh_open,	/* open procedure */
181	zsh_close,	/* close procedure */
182	NULL,		/* reserved */
183	&hdlc_minfo,	/* module info */
184	NULL		/* reserved */
185};
186
187static struct qinit hdlc_winit = {
188	(int (*)())zsh_wput,	/* output put procedure */
189	NULL,		/* output service procedure */
190	NULL,		/* open procedure */
191	NULL,		/* close procedure */
192	NULL,		/* reserved */
193	&hdlc_minfo,	/* module info */
194	NULL		/* reserved */
195};
196
197struct streamtab hdlctab = {
198	&hdlc_rinit,	/* initialize read queue */
199	&hdlc_winit,	/* initialize write queue */
200	NULL,		/* mux read qinit */
201	NULL		/* mux write qinit */
202};
203
204DDI_DEFINE_STREAM_OPS(zsh_ops, nulldev, zsh_probe, zsh_attach,
205    zsh_detach, nodev, zsh_info, D_MP, &hdlctab, ddi_quiesce_not_supported);
206
207/*
208 * This is the loadable module wrapper.
209 */
210
211#include	<sys/errno.h>
212#include	<sys/modctl.h>
213
214/*
215 * Module linkage information for the kernel.
216 */
217
218static struct modldrv modldrv = {
219	&mod_driverops, /* Type of module.  This one is a driver */
220	"Z8530 serial HDLC drv",
221	&zsh_ops,	/* our own ops for this module */
222};
223
224static struct modlinkage modlinkage = {
225	MODREV_1,
226	(void *)&modldrv,
227	NULL
228};
229
230int
231_init(void)
232{
233	return (mod_install(&modlinkage));
234}
235
236int
237_fini(void)
238{
239	return (mod_remove(&modlinkage));
240}
241
242int
243_info(struct modinfo *modinfop)
244{
245	return (mod_info(&modlinkage, modinfop));
246}
247
248
249/*
250 * The HDLC interrupt entry points.
251 */
252static void	zsh_txint(struct zscom *zs);
253static void	zsh_xsint(struct zscom *zs);
254static void	zsh_rxint(struct zscom *zs);
255static void	zsh_srint(struct zscom *zs);
256static int	zsh_softint(struct zscom *zs);
257
258struct zsops zsops_hdlc = {
259	zsh_txint,
260	zsh_xsint,
261	zsh_rxint,
262	zsh_srint,
263	zsh_softint,
264	NULL,
265	NULL
266};
267
268static int	zsh_program(struct zscom *zs, struct scc_mode *sm);
269static void	zsh_setmstat(struct zscom *zs, int event);
270static void	zsh_rxbad(struct zscom *zs, struct syncline *zss);
271static void	zsh_txbad(struct zscom *zs, struct syncline *zss);
272static void	zsh_watchdog(void *);
273static void	zsh_callback(void *);
274static int	zsh_hdp_ok_or_rts_state(struct zscom *zs, struct syncline *zss);
275static void	zsh_init_port(struct zscom *zs, struct syncline *zss);
276static int	zsh_setmode(struct zscom *zs, struct syncline *zss,
277			struct scc_mode *sm);
278
279
280/*
281 * The HDLC Driver.
282 */
283
284
285/*
286 * Special macros to handle STREAMS operations.
287 * These are required to address memory leakage problems.
288 * WARNING : the macro do NOT call ZSSETSOFT
289 */
290
291/*
292 * Should be called holding only the adaptive (zs_excl) mutex.
293 */
294#define	ZSH_GETBLOCK(zs, allocbcount) \
295{ \
296	register int n = ZSH_MAX_RSTANDBY; \
297	while (--n >= 0) { \
298	    if (!zss->sl_rstandby[n]) { \
299		if ((zss->sl_rstandby[n] = \
300		    allocb(zss->sl_mru, BPRI_MED)) == NULL) { \
301		    if (zss->sl_bufcid == 0) { \
302			mutex_enter(zs->zs_excl_hi); \
303			if (zss->sl_txstate != TX_OFF) { \
304			    mutex_exit(zs->zs_excl_hi); \
305			    zss->sl_bufcid = bufcall(zss->sl_mru, \
306				    BPRI_MED, zsh_callback, zs); \
307			    break; \
308			} else \
309				mutex_exit(zs->zs_excl_hi); \
310		    } \
311		} \
312		allocbcount--; \
313	    } \
314	} \
315}
316
317/*
318 * Should be called holding the spin (zs_excl_hi) mutex.
319 */
320#define	ZSH_ALLOCB(mp) \
321{ \
322	register int n = ZSH_MAX_RSTANDBY; \
323	mp = NULL; \
324	while (--n >= 0)  { \
325		if ((mp = zss->sl_rstandby[n]) != NULL) { \
326			zss->sl_rstandby[n] = NULL; \
327			break; \
328		} \
329	} \
330}
331
332#define	ZSH_PUTQ(mp) \
333{ \
334	register int wptr, rptr;  \
335	wptr = zss->sl_rdone_wptr; \
336	rptr = zss->sl_rdone_rptr; \
337	zss->sl_rdone[wptr] = mp; \
338	if ((wptr) + 1 == ZSH_RDONE_MAX) \
339		zss->sl_rdone_wptr = wptr = 0; \
340	else \
341		zss->sl_rdone_wptr = ++wptr; \
342	if (wptr == rptr) {  /* Should never occur */ \
343		SCC_BIC(1, ZSWR1_INIT); \
344		zss->sl_m_error = ENOSR; \
345		ZSSETSOFT(zs); \
346	} \
347}
348
349#define	ZSH_FREEMSG(mp) \
350{ \
351	ZSH_PUTQ(mp); \
352}
353
354
355/*
356 * Should be called holding only the adaptive (zs_excl) mutex.
357 */
358#define	ZSH_GETQ(mp) \
359{ \
360	if (zss->sl_rdone_rptr != zss->sl_rdone_wptr) { \
361		mp = zss->sl_rdone[zss->sl_rdone_rptr++]; \
362		if (zss->sl_rdone_rptr == ZSH_RDONE_MAX) \
363				zss->sl_rdone_rptr = 0; \
364	} else \
365		mp = NULL; \
366}
367
368#define	ZSH_FLUSHQ \
369{ \
370	register mblk_t *tmp; \
371	for (;;) { \
372		ZSH_GETQ(tmp); \
373		if (!(tmp)) \
374			break; \
375		freemsg(tmp); \
376	} \
377}
378
379/*ARGSUSED*/
380static int
381zsh_probe(dev_info_t *dev)
382{
383	return (DDI_PROBE_DONTCARE);
384}
385
386/*ARGSUSED*/
387static int
388zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd)
389{
390	register int	unit;
391	char		name[3] = {
392		'\0', '\0', '\0' 	};
393
394	/*
395	 * Since zsh is a child of the "pseudo" nexus, we can expect the
396	 * attach routine to be called only once.  We need to create all
397	 * necessary devices in one shot.  There is never more than one
398	 * SCC chip that supports zsh devices.
399	 */
400
401	if (cmd != DDI_ATTACH)
402		return (DDI_FAILURE);
403	if (zscom == NULL)
404		return (DDI_FAILURE);	/* zsattach not done */
405	unit = 2 * ddi_get_instance(dev);
406	if (unit > 1)
407		return (DDI_FAILURE);	/* only use cpu ports */
408
409	if (ddi_create_minor_node(dev, "zsh", S_IFCHR,
410	    NULL, DDI_PSEUDO, CLONE_DEV) == DDI_FAILURE) {
411		ddi_remove_minor_node(dev, NULL);
412		cmn_err(CE_WARN, "zsh clone device creation failed.");
413		return (DDI_FAILURE);
414	}
415
416	for (; unit < maxzsh/2; unit++) {
417		zscom[unit].zs_hdlc_dip = dev;
418
419		(void) sprintf(name, "%d", unit);
420		if (ddi_create_minor_node(dev, name, S_IFCHR,
421		    2*unit, DDI_PSEUDO, NULL) == DDI_FAILURE) {
422			ddi_remove_minor_node(dev, NULL);
423			return (DDI_FAILURE);
424		}
425		unit++;
426		(void) sprintf(name, "%d", unit);
427		if (ddi_create_minor_node(dev, name, S_IFCHR,
428		    2*(unit-1)+1, DDI_PSEUDO, NULL) == DDI_FAILURE) {
429			ddi_remove_minor_node(dev, NULL);
430			return (DDI_FAILURE);
431		}
432	}
433
434	return (DDI_SUCCESS);
435}
436
437/* ARGSUSED */
438int
439zsh_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
440void **result)
441{
442	register dev_t dev = (dev_t)arg;
443	register int unit, error;
444	register struct zscom *zs;
445
446	if ((unit = UNIT(dev)) >= nzs)
447		return (DDI_FAILURE);
448
449	switch (infocmd) {
450	case DDI_INFO_DEVT2DEVINFO:
451		if (zscom == NULL) {
452			error = DDI_FAILURE;
453		} else {
454			zs = &zscom[unit];
455			*result = zs->zs_hdlc_dip;
456			error = DDI_SUCCESS;
457		}
458		break;
459	case DDI_INFO_DEVT2INSTANCE:
460		*result = (void *)(uintptr_t)(unit / 2);
461		error = DDI_SUCCESS;
462		break;
463	default:
464		error = DDI_FAILURE;
465	}
466	return (error);
467}
468
469static int
470zsh_detach(dev_info_t *dev, ddi_detach_cmd_t cmd)
471{
472	if (cmd != DDI_DETACH)
473		return (DDI_FAILURE);
474
475	ddi_remove_minor_node(dev, NULL);
476
477	return (DDI_SUCCESS);
478}
479
480static void
481zsh_init_port(struct zscom *zs, struct syncline *zss)
482{
483	register uchar_t s0;
484
485	SCC_WRITE(3, (ZSWR3_RX_ENABLE | ZSWR3_RXCRC_ENABLE | ZSWR3_RX_8));
486	SCC_WRITE(5, (ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_TXCRC_ENABLE));
487	zss->sl_rr0 = SCC_READ0();
488	if (zss->sl_flags & SF_FDXPTP) {
489		SCC_BIS(5, ZSWR5_TX_ENABLE);
490		SCC_BIS(5, ZSWR5_RTS);
491		s0 = SCC_READ0();
492		if ((s0 & ZSRR0_CTS) ||
493		    !(zss->sl_mode.sm_config & (CONN_SIGNAL | CONN_IBM))) {
494			/*
495			 * send msg that CTS is up
496			 */
497			zss->sl_rr0 |= ZSRR0_CTS;
498			zss->sl_txstate = TX_IDLE;
499		} else {
500			zss->sl_flags |= SF_XMT_INPROG;
501			zss->sl_txstate = TX_RTS;
502			zss->sl_rr0 &= ~ZSRR0_CTS;
503			zss->sl_wd_count = zsh_timer_count;
504			if (!zss->sl_wd_id)
505				zss->sl_wd_id = timeout(zsh_watchdog,
506				    zs, SIO_WATCHDOG_TICK);
507		}
508	} else {
509		SCC_BIC(15, ZSR15_CTS);
510		SCC_BIC(5, ZSWR5_TX_ENABLE);
511		SCC_BIC(5, ZSWR5_RTS);
512		zss->sl_flags &= ~SF_FLUSH_WQ;
513	}
514}
515
516/*
517 * Open routine.
518 */
519
520/*ARGSUSED*/
521static int
522zsh_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
523{
524	register struct zscom *zs;
525	register struct syncline *zss;
526	register struct ser_str *stp;
527	register int	unit;
528	register int 	tmp;
529
530	if (sflag != CLONEOPEN) {
531		if (rq->q_ptr)
532			return (EBUSY);  /* We got a stream that is in use */
533
534		unit = UNIT(*dev);
535		if (unit >= maxzsh)
536			return (ENXIO);  /* unit not configured */
537
538		if (zscom == NULL)
539			return (ENXIO);  /* device not found by autoconfig */
540		zs = &zscom[unit];
541
542		if (zs->zs_ops == NULL) {
543			return (ENXIO);  /* device not found by autoconfig */
544		}
545
546		TRACE_1(TR_ZSH, TR_ZSH_OPEN, "zsh_open:unit = %d", unit);
547
548		mutex_enter(zs->zs_excl);
549		if ((zs->zs_ops != &zsops_null) &&
550		    (zs->zs_ops != &zsops_hdlc)) {
551			mutex_exit(zs->zs_excl);
552			return (EBUSY);	 /* another protocol got here first */
553		}
554
555		/* Mark device as busy (for power management) */
556		(void) pm_busy_component(zs->zs_dip, unit%2+1);
557		(void) ddi_dev_is_needed(zs->zs_dip, unit%2+1, 1);
558
559		zsopinit(zs, &zsops_hdlc);
560
561		zss = (struct syncline *)&zscom[unit].zs_priv_str;
562		stp = &zss->sl_stream;
563		stp->str_state = NULL;
564		stp->str_com = (caddr_t)zs;
565
566		zss->sl_xhead = NULL;
567		zss->sl_xactb = NULL;
568		zs->zs_wr_cur = NULL;
569		zs->zs_wr_lim = NULL;
570		zs->zs_wr_cur = NULL;
571		zs->zs_wr_lim = NULL;
572		zss->sl_rhead = NULL;
573		zss->sl_ractb = NULL;
574		zs->zs_rd_cur = NULL;
575		zs->zs_rd_lim = NULL;
576		zss->sl_mstat = NULL;
577		zss->sl_xstandby = NULL;
578		zss->sl_wd_id = 0;
579		zss->sl_soft_active = 0;
580		zss->sl_stream.str_rq = NULL;
581
582		zs->zs_priv = (caddr_t)zss;
583
584		zss->sl_mru = zsh_default_mru;
585		tmp = ZSH_MAX_RSTANDBY;
586		ZSH_GETBLOCK(zs, tmp);
587		if (zss->sl_rstandby[0] == NULL) {
588			cmn_err(CE_WARN, "zsh_open: can't alloc message block");
589			mutex_exit(zs->zs_excl);
590			return (ENOSR);
591		}
592		mutex_enter(zs->zs_excl_hi);
593		ZSH_ALLOCB(zss->sl_ractb);
594		zss->sl_txstate = TX_OFF;
595		zss->sl_rr0 = SCC_READ0();
596		zss->sl_flags &= (SF_INITIALIZED | SF_FDXPTP);
597		if (zss->sl_flags & SF_INITIALIZED)
598			zsh_init_port(zs, zss);
599		mutex_exit(zs->zs_excl_hi);
600		mutex_exit(zs->zs_excl);
601	} else {   /* CLONEOPEN */
602		mutex_enter(&zs_curr_lock);
603		for (unit = maxzsh; unit < MAXZSHCLONES; unit++)
604			if (!zsh_usedminor[unit]) {
605				zsh_usedminor[unit] = (unsigned char)unit;
606				break;
607			}
608		mutex_exit(&zs_curr_lock);
609		if (unit >= MAXZSHCLONES)	/* no slots available */
610			return (ENODEV);
611		*dev = makedevice(getmajor(*dev), unit);
612
613		stp = kmem_zalloc(sizeof (struct ser_str), KM_NOSLEEP);
614		if (stp == NULL) {
615			cmn_err(CE_WARN,
616			    "zsh clone open failed, no memory, rq=%p\n",
617			    (void *)rq);
618			return (ENOMEM);
619		}
620		stp->str_state = STR_CLONE;
621		stp->str_com = NULL;	/* can't determine without ppa */
622	}
623	stp->str_rq = rq;
624	stp->str_inst = unit;
625
626	rq->q_ptr = WR(rq)->q_ptr = (caddr_t)stp;
627	qprocson(rq);
628	return (0);
629}
630
631/*
632 * Close routine.
633 */
634int zsh_tx_enable_in_close = 0;
635
636/*ARGSUSED*/
637static int
638zsh_close(queue_t *rq, int flag)
639{
640	struct ser_str *stp;
641	struct zscom *zs;
642	struct syncline *zss;
643	mblk_t	*mp;
644	int i;
645	timeout_id_t sl_wd_id;
646	bufcall_id_t sl_bufcid;
647
648	/*
649	 * Note that a close is only called on the last close of a
650	 * particular stream.  Assume that we need to do it all.
651	 */
652	qprocsoff(rq);				/* no new business after this */
653
654	stp = (struct ser_str *)rq->q_ptr;
655	if (stp == NULL)
656		return (0);			/* already been closed once */
657
658	if (stp->str_state == STR_CLONE) {
659		zsh_usedminor[stp->str_inst] = 0;
660	} else {
661		zs = (struct zscom *)stp->str_com;
662		if (zs == NULL)
663			goto out;
664
665		TRACE_1(TR_ZSH, TR_ZSH_CLOSE, "zs = %p", zs);
666
667		zss = (struct syncline *)zs->zs_priv;
668		mutex_enter(zs->zs_excl);
669		flushq(WR(rq), FLUSHALL);
670		mutex_enter(zs->zs_excl_hi);
671		if (zss->sl_xstandby) {
672			zss->sl_xstandby->b_wptr = zss->sl_xstandby->b_rptr;
673			ZSH_FREEMSG(zss->sl_xstandby);
674			zss->sl_xstandby = NULL;
675		}
676		mutex_exit(zs->zs_excl_hi);
677
678		ZSH_FLUSHQ;
679
680		/*
681		 * Stop the Watchdog Timer.
682		 */
683		if ((sl_wd_id = zss->sl_wd_id) != 0)
684			zss->sl_wd_id = 0;
685
686		/*
687		 * Cancel outstanding "bufcall" request.
688		 */
689		if ((sl_bufcid = zss->sl_bufcid) != 0)
690			zss->sl_bufcid = 0;
691
692		mutex_enter(zs->zs_excl_hi);
693		if (zs->zs_wr_cur) {
694			zs->zs_wr_cur = NULL;
695			zs->zs_wr_lim = NULL;
696			SCC_WRITE0(ZSWR0_SEND_ABORT);
697			ZSDELAY();
698			ZSDELAY();
699		}
700		zss->sl_txstate = TX_OFF;	/* so it can't rearm in close */
701
702		zs->zs_wr_cur = NULL;
703		zs->zs_wr_lim = NULL;
704		SCC_BIC(15,
705		    (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC | ZSR15_CTS));
706		SCC_WRITE(3, 0);		/* Quiesce receiver */
707		if (zsh_tx_enable_in_close && !(zss->sl_flags & SF_FDXPTP)) {
708			SCC_BIS(5, ZSWR5_TX_ENABLE);
709		} else
710			SCC_BIC(5, ZSWR5_TX_ENABLE);
711
712		SCC_BIC(5,  (ZSWR5_DTR | ZSWR5_RTS | ZSWR5_TXCRC_ENABLE));
713		SCC_WRITE0(ZSWR0_RESET_TXINT);		/* reset TX */
714		SCC_WRITE0(ZSWR0_RESET_STATUS);		/* reset XS */
715		SCC_WRITE0(ZSWR0_RESET_ERRORS);
716		(void) SCC_READDATA();			/* reset RX */
717		ZSDELAY();
718		(void) SCC_READDATA();
719		ZSDELAY();
720		(void) SCC_READDATA();
721		ZSDELAY();
722
723
724		/*
725		 * Free up everything we ever allocated.
726		 */
727		if ((mp = zss->sl_rhead) != NULL) {
728			zss->sl_ractb = NULL;	/* already freed */
729			zs->zs_rd_cur = NULL;
730			zs->zs_rd_lim = NULL;
731			zss->sl_rhead = NULL;
732		}
733		mutex_exit(zs->zs_excl_hi);
734		if (mp)
735			freemsg(mp);
736
737		mutex_enter(zs->zs_excl_hi);
738		if ((mp = zss->sl_ractb) != NULL) {
739			zs->zs_rd_cur = NULL;
740			zs->zs_rd_lim = NULL;
741			zss->sl_ractb = NULL;
742		}
743		mutex_exit(zs->zs_excl_hi);
744		if (mp)
745			freemsg(mp);
746
747		for (i = 0; i < ZSH_MAX_RSTANDBY; i++) {
748			mutex_enter(zs->zs_excl_hi);
749			mp = zss->sl_rstandby[i];
750			zss->sl_rstandby[i] = NULL;
751			mutex_exit(zs->zs_excl_hi);
752			if (mp)
753				freemsg(mp);
754		}
755
756		mutex_enter(zs->zs_excl_hi);
757		if ((mp = zss->sl_xhead) != NULL) {
758			zss->sl_xhead = NULL;
759			zss->sl_xactb = NULL;
760		}
761		mutex_exit(zs->zs_excl_hi);
762		if (mp)
763			freemsg(mp);
764
765		ZSH_FLUSHQ;
766
767		mutex_enter(zs->zs_excl_hi);
768		if ((mp = zss->sl_xstandby) != NULL)
769			zss->sl_xstandby = NULL;
770		mutex_exit(zs->zs_excl_hi);
771		if (mp)
772			freemsg(mp);
773
774		mutex_enter(zs->zs_excl_hi);
775		if ((mp = zss->sl_mstat) != NULL)
776			zss->sl_mstat = NULL;
777		zss->sl_txstate = TX_OFF;	/* so it can't rearm in close */
778		mutex_exit(zs->zs_excl_hi);
779		if (mp)
780			freemsg(mp);
781
782		zss->sl_stream.str_rq = NULL;
783		zsopinit(zs, &zsops_null);
784		mutex_exit(zs->zs_excl);
785		if (sl_wd_id)
786			(void) untimeout(sl_wd_id);
787		if (sl_bufcid)
788			unbufcall(sl_bufcid);
789		while (zss->sl_soft_active)
790			drv_usecwait(1);
791
792		/* Mark device as available for power management */
793		(void) pm_idle_component(zs->zs_dip, zs->zs_unit%2+1);
794	}
795
796	if (stp->str_state == STR_CLONE)
797		kmem_free(stp, sizeof (struct ser_str));
798
799out:
800	rq->q_ptr = WR(rq)->q_ptr = NULL;
801
802	return (0);
803}
804
805static int
806zsh_hdp_ok_or_rts_state(struct zscom *zs, struct syncline *zss)
807{
808	register uchar_t s0;
809
810	SCC_BIS(15, ZSR15_CTS);
811	SCC_BIS(5, ZSWR5_RTS);
812	s0 = SCC_READ0();
813	if (s0 & ZSRR0_CTS) {
814		SCC_BIS(5, ZSWR5_TX_ENABLE);
815		zss->sl_rr0 |= ZSRR0_CTS;
816		return (1);
817	}
818	zss->sl_flags |= SF_XMT_INPROG;
819	zss->sl_txstate = TX_RTS;
820	zss->sl_rr0 &= ~ZSRR0_CTS;
821	zss->sl_wd_count = zsh_timer_count;
822	return (0);
823}
824
825/*
826 * Put procedure for write queue.
827 */
828static void
829zsh_wput(queue_t *wq, mblk_t *mp)
830{
831	register struct ser_str *stp = (struct ser_str *)wq->q_ptr;
832	register struct zscom *zs;
833	register struct syncline *zss = NULL;
834	register ulong_t prim, error = 0;
835	register union DL_primitives *dlp;
836	register int	ppa;
837	register mblk_t *tmp;
838	register struct copyresp	*resp;
839
840	/*
841	 * stp->str_com supplied by open or DLPI attach.
842	 */
843	if (stp == NULL) {
844		freemsg(mp);
845		return;
846	}
847	zs = (struct zscom *)stp->str_com;
848
849	TRACE_0(TR_ZSH, TR_ZSH_WPUT_START, "zsh_wput start");
850
851	if ((mp->b_datap->db_type == M_FLUSH) &&
852	    (stp->str_state == STR_CLONE)) {
853		if (*mp->b_rptr & FLUSHW) {
854			flushq(wq, FLUSHDATA);
855			*mp->b_rptr &= ~FLUSHW;
856		}
857		if (*mp->b_rptr & FLUSHR)
858			qreply(wq, mp);  /* let the read queues have at it */
859		else
860			freemsg(mp);
861		return;
862	}
863
864	if ((zs == NULL) && (mp->b_datap->db_type != M_PROTO)) {
865		freemsg(mp);
866		cmn_err(CE_WARN,
867		    "zsh: clone device %d must be attached before use!",
868		    stp->str_inst);
869		(void) putnextctl1(RD(wq), M_ERROR, EPROTO);
870		return;
871	}
872
873	if (stp->str_state == STR_CLONE) {	/* Clone opened, limited. */
874		if ((mp->b_datap->db_type != M_PROTO) &&
875		    (mp->b_datap->db_type != M_IOCTL) &&
876		    (mp->b_datap->db_type != M_IOCDATA)) {
877			freemsg(mp);
878			cmn_err(CE_WARN,
879			    "zsh%x: invalid operation for clone dev.\n",
880			    stp->str_inst);
881			(void) putnextctl1(RD(wq), M_ERROR, EPROTO);
882			return;
883		}
884	} else {
885		zss = (struct syncline *)zs->zs_priv;
886	}
887
888	switch (mp->b_datap->db_type) {
889
890	case M_DATA:
891		/*
892		 * Queue the message up to be transmitted.
893		 * Set "in progress" flag and call the start routine.
894		 */
895		mutex_enter(zs->zs_excl_hi);
896		if (!(zss->sl_flags & SF_INITIALIZED)) {
897			mutex_exit(zs->zs_excl_hi);
898			cmn_err(CE_WARN,
899			    "zsh%x not initialized, can't send message",
900			    zs->zs_unit);
901			freemsg(mp);
902			(void) putnextctl1(RD(wq), M_ERROR, ECOMM);
903			return;
904		}
905		mutex_exit(zs->zs_excl_hi);
906		if (zs->zs_flags & ZS_NEEDSOFT) {
907			zs->zs_flags &= ~ZS_NEEDSOFT;
908			(void) zsh_softint(zs);
909		}
910		while (mp->b_wptr == mp->b_rptr) {
911			register mblk_t *mp1;
912			mp1 = unlinkb(mp);
913			freemsg(mp);
914			mp = mp1;
915			if (mp == NULL)
916				return;
917		}
918		mutex_enter(zs->zs_excl);
919		(void) putq(wq, mp);
920		mutex_enter(zs->zs_excl_hi);
921		if (zss->sl_flags & SF_FLUSH_WQ) {
922			mutex_exit(zs->zs_excl_hi);
923			flushq(wq, FLUSHDATA);
924			mutex_exit(zs->zs_excl);
925
926			TRACE_1(TR_ZSH, TR_ZSH_WPUT_END,
927			    "zsh_wput end: zs = %p", zs);
928
929			return;
930		}
931		tmp = NULL;
932again:
933		if (!zss->sl_xstandby) {
934			if (tmp)
935				zss->sl_xstandby = tmp;
936			else {
937				mutex_exit(zs->zs_excl_hi);
938				tmp = getq(wq);
939				mutex_enter(zs->zs_excl_hi);
940				if (tmp)
941					goto again;
942			}
943		} else if (tmp) {
944			mutex_exit(zs->zs_excl_hi);
945			(void) putbq(wq, tmp);
946			mutex_enter(zs->zs_excl_hi);
947		}
948
949		if (zss->sl_flags & SF_XMT_INPROG) {
950			mutex_exit(zs->zs_excl_hi);
951			mutex_exit(zs->zs_excl);
952
953			TRACE_1(TR_ZSH, TR_ZSH_WPUT_END,
954			    "zsh_wput end: zs = %p", zs);
955
956			return;
957		}
958
959		if (!zss->sl_wd_id) {
960			zss->sl_wd_count = zsh_timer_count;
961			zss->sl_txstate = TX_IDLE;
962			mutex_exit(zs->zs_excl_hi);
963			zss->sl_wd_id = timeout(zsh_watchdog, zs,
964			    SIO_WATCHDOG_TICK);
965			mutex_enter(zs->zs_excl_hi);
966		}
967
968		zss->sl_flags |= SF_XMT_INPROG;
969		if ((zss->sl_flags & SF_FDXPTP) ||
970		    zsh_hdp_ok_or_rts_state(zs, zss))
971			(void) zsh_start(zs, zss);
972		mutex_exit(zs->zs_excl_hi);
973		mutex_exit(zs->zs_excl);
974		break;
975
976	case M_PROTO:
977		/*
978		 * Here is where a clone device finds out about the
979		 * hardware it is going to attach to.  The request is
980		 * validated and a ppa is extracted from it and validated.
981		 * This number is used to index the hardware data structure
982		 * and the protocol data structure, in case the latter
983		 * was not provided by a data-path open before this.
984		 */
985		if (stp->str_state != STR_CLONE) {
986			freemsg(mp);
987			return;
988		}
989
990		if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
991			prim = DL_ATTACH_REQ;
992			error = DL_BADPRIM;
993			goto end_proto;
994		}
995		dlp = (union DL_primitives *)mp->b_rptr;
996		prim = dlp->dl_primitive;
997		if (prim != DL_ATTACH_REQ) {
998			error = DL_BADPRIM;
999			goto end_proto;
1000		}
1001		ppa = dlp->attach_req.dl_ppa;
1002		ppa = (ppa%2) ? ((ppa-1)*2 +1) : (ppa*2);
1003		if (ppa >= maxzsh) {
1004			error = DL_BADPPA;
1005			goto end_proto;
1006		}
1007		zs = &zscom[ppa];
1008		if (zs->zs_ops == NULL) {
1009			error = ENXIO;
1010			goto end_proto;
1011		}
1012		mutex_enter(zs->zs_excl);
1013		if ((zs->zs_ops != &zsops_null) &&
1014		    (zs->zs_ops != &zsops_hdlc)) {
1015			/*
1016			 * another protocol got here first
1017			 */
1018			error = (EBUSY);
1019			mutex_exit(zs->zs_excl);
1020			goto end_proto;
1021
1022		}
1023
1024		stp->str_com = (caddr_t)zs;
1025		mutex_exit(zs->zs_excl);
1026end_proto:
1027		if (error)
1028			dlerrorack(wq, mp, prim, error, 0);
1029		else
1030			dlokack(wq, mp, DL_ATTACH_REQ);
1031		break;
1032
1033	case M_IOCTL:
1034		zsh_ioctl(wq, mp);
1035		break;
1036
1037	case M_IOCDATA:
1038		resp = (struct copyresp *)mp->b_rptr;
1039		if (resp->cp_rval) {
1040			/*
1041			 * Just free message on failure.
1042			 */
1043			freemsg(mp);
1044			break;
1045		}
1046
1047		switch (resp->cp_cmd) {
1048
1049		case S_IOCGETMODE:
1050		case S_IOCGETSTATS:
1051		case S_IOCGETSPEED:
1052		case S_IOCGETMCTL:
1053		case S_IOCGETMRU:
1054			mioc2ack(mp, NULL, 0, 0);
1055			qreply(wq, mp);
1056			break;
1057
1058		case S_IOCSETMODE:
1059			zss  = (struct syncline *)&zs->zs_priv_str;
1060			mutex_enter(zs->zs_excl);
1061			error = zsh_setmode(zs, zss,
1062			    (struct scc_mode *)mp->b_cont->b_rptr);
1063			if (error) {
1064				register struct iocblk  *iocp =
1065				    (struct iocblk *)mp->b_rptr;
1066				mp->b_datap->db_type = M_IOCNAK;
1067				iocp->ioc_error = error;
1068			} else
1069				mioc2ack(mp, NULL, 0, 0);
1070			mutex_exit(zs->zs_excl);
1071			qreply(wq, mp);
1072			break;
1073
1074		case S_IOCSETMRU:
1075			zss  = (struct syncline *)&zs->zs_priv_str;
1076			mutex_enter(zs->zs_excl);
1077			zss->sl_mru = *(int *)mp->b_cont->b_rptr;
1078			mutex_exit(zs->zs_excl);
1079			mioc2ack(mp, NULL, 0, 0);
1080			qreply(wq, mp);
1081			break;
1082		default:
1083			freemsg(mp);
1084		}
1085		break;
1086
1087		/*
1088		 * We're at the bottom of the food chain, so we flush our
1089		 * write queue, clear the FLUSHW bit so it doesn't go round
1090		 * and round forever, then flush our read queue (since there's
1091		 * no read put procedure down here) and pass it up for any
1092		 * higher modules to deal with in their own way.
1093		 */
1094	case M_FLUSH:
1095		if (*mp->b_rptr & FLUSHW) {
1096			mutex_enter(zs->zs_excl);
1097			flushq(wq, FLUSHDATA);
1098			mutex_enter(zs->zs_excl_hi);
1099			tmp = zss->sl_xstandby;
1100			zss->sl_xstandby = NULL;
1101			mutex_exit(zs->zs_excl_hi);
1102			if (tmp)
1103				freemsg(tmp);
1104			mutex_exit(zs->zs_excl);
1105			*mp->b_rptr &= ~FLUSHW;
1106		}
1107
1108		if (*mp->b_rptr & FLUSHR) {
1109			mutex_enter(zs->zs_excl);
1110			ZSH_FLUSHQ;
1111			mutex_exit(zs->zs_excl);
1112			qreply(wq, mp);  /* let the read queues have at it */
1113		} else
1114			freemsg(mp);
1115		break;
1116
1117	default:
1118		/*
1119		 * "No, I don't want a subscription to Chain Store Age,
1120		 * thank you anyway."
1121		 */
1122		freemsg(mp);
1123		break;
1124	}
1125
1126	TRACE_1(TR_ZSH, TR_ZSH_WPUT_END, "zsh_wput end: zs = %p", zs);
1127}
1128
1129/*
1130 * Get the next message from the write queue, set up the necessary pointers,
1131 * state info, etc., and start the transmit "engine" by sending the first
1132 * character.  We'll then rotate through txint until done, then get an xsint.
1133 */
1134static int
1135zsh_start(struct zscom *zs, struct syncline *zss)
1136{
1137	register mblk_t *mp;
1138	register uchar_t *wptr;
1139	register uchar_t *rptr;
1140	register uchar_t sl_flags = zss->sl_flags;
1141
1142	/*
1143	 * Attempt to grab the next M_DATA message off the queue (that's
1144	 * all that will be left after wput) and begin transmission.
1145	 * This routine is normally called after completion of a previous
1146	 * frame, or when zsh_wput gets a new message.  If we are in a
1147	 * mode that put us in the TX_RTS state, waiting for CTS, and CTS
1148	 * is not up yet, we have no business here.  Ditto if we're in
1149	 * either the TX_ACTIVE or TX_CRC states.  In these cases we
1150	 * don't clear SF_CALLSTART, so we don't forget there's work to do.
1151	 */
1152
1153	TRACE_1(TR_ZSH, TR_ZSH_START_START,
1154	    "zsh_start start: zs = %p", zs);
1155
1156	if (sl_flags & SF_PHONY) {
1157		sl_flags &= ~SF_PHONY;
1158		SCC_BIC(15, ZSR15_CTS);
1159		SCC_BIC(5, ZSWR5_RTS);
1160		SCC_WRITE0(ZSWR0_RESET_TXINT);
1161		SCC_BIC(5, ZSWR5_TX_ENABLE);
1162		zss->sl_rr0 &= ~ZSRR0_CTS;
1163		zss->sl_txstate = TX_IDLE;
1164		/*
1165		 * if we get another msg by chance zsh_watchog will start
1166		 */
1167		sl_flags &= ~SF_XMT_INPROG;
1168		zss->sl_flags = sl_flags;
1169
1170		TRACE_1(TR_ZSH, TR_ZSH_START_END,
1171		    "zsh_start end: zs = %d", zs);
1172
1173		return (0);
1174	}
1175	mp = zss->sl_xstandby;
1176	if (mp == NULL) {
1177		if (!(sl_flags & SF_FDXPTP)) {
1178			sl_flags |= SF_PHONY;
1179			ZSH_ALLOCB(mp);
1180			if (!mp)
1181				return (0);
1182			mp->b_datap->db_type = M_RSE;
1183			mp->b_wptr = mp->b_rptr + 1;
1184			goto transmit;
1185		}
1186		sl_flags &= ~SF_XMT_INPROG;
1187		zss->sl_flags = sl_flags;
1188
1189		TRACE_1(TR_ZSH, TR_ZSH_START_END,
1190		    "zsh_start end: zs = %p", zs);
1191
1192		return (0);
1193	}
1194
1195transmit:
1196	zss->sl_xstandby = NULL;
1197	rptr = mp->b_rptr;
1198	wptr = mp->b_wptr;
1199	ZSSETSOFT(zs);
1200
1201#ifdef ZSH_DEBUG
1202	if (zss->sl_xhead || zss->sl_xactb) {
1203		debug_enter("xhead1");
1204	}
1205#endif
1206
1207	zss->sl_xhead = mp;
1208	zss->sl_xactb = mp;
1209	zss->sl_wd_count = zsh_timer_count;
1210	zss->sl_txstate = TX_ACTIVE;
1211	zss->sl_ocnt = 0;
1212	SCC_BIS(10, ZSWR10_UNDERRUN_ABORT);	/* abort on underrun */
1213	SCC_WRITE0(ZSWR0_RESET_TXCRC);		/* reset transmit CRC */
1214	zss->sl_ocnt = wptr - rptr;
1215	mp->b_wptr = rptr; /* to tell soft to free this msg */
1216	SCC_WRITEDATA(*rptr++);    /* resets TXINT */
1217	zs->zs_wr_cur = rptr;
1218	zs->zs_wr_lim = wptr;
1219
1220	SCC_WRITE0(ZSWR0_RESET_EOM);
1221
1222	TRACE_1(TR_ZSH, TR_ZSH_START_END,
1223	    "zsh_start end: zs = %p", zs);
1224
1225	zss->sl_flags = sl_flags;
1226	return (1);
1227}
1228
1229
1230/*
1231 * Process an "ioctl" message sent down to us.
1232 */
1233static void
1234zsh_ioctl(queue_t *wq, mblk_t *mp)
1235{
1236	register struct ser_str *stp = (struct ser_str *)wq->q_ptr;
1237	register struct zscom *zs = (struct zscom *)stp->str_com;
1238	register struct syncline *zss  = (struct syncline *)&zs->zs_priv_str;
1239	register struct iocblk   *iocp = (struct iocblk *)mp->b_rptr;
1240	register struct scc_mode *sm;
1241	register struct sl_stats *st;
1242	register uchar_t	 *msignals;
1243	register mblk_t		 *tmp;
1244	register int		 error = 0;
1245
1246	mutex_enter(zs->zs_excl);
1247	if ((zs->zs_ops != &zsops_null) &&
1248	    (zs->zs_ops != &zsops_hdlc)) {
1249		/*
1250		 * another protocol got here first
1251		 */
1252		error = (EBUSY);
1253		goto end_zsh_ioctl;
1254	}
1255
1256
1257	switch (iocp->ioc_cmd) {
1258
1259	case S_IOCGETMODE:
1260		tmp = allocb(sizeof (struct scc_mode), BPRI_MED);
1261		if (tmp == NULL) {
1262			error = EAGAIN;
1263			break;
1264		}
1265		if (iocp->ioc_count != TRANSPARENT)
1266			mioc2ack(mp, tmp, sizeof (struct scc_mode), 0);
1267		else
1268			mcopyout(mp, NULL, sizeof (struct scc_mode), NULL, tmp);
1269		sm = (struct scc_mode *)mp->b_cont->b_rptr;
1270		bcopy(&zss->sl_mode, sm, sizeof (struct scc_mode));
1271		break;
1272
1273	case S_IOCGETSTATS:
1274		tmp = allocb(sizeof (struct sl_stats), BPRI_MED);
1275		if (tmp == NULL) {
1276			error = EAGAIN;
1277			break;
1278		}
1279		if (iocp->ioc_count != TRANSPARENT)
1280			mioc2ack(mp, tmp, sizeof (struct sl_stats), 0);
1281		else
1282			mcopyout(mp, NULL, sizeof (struct sl_stats), NULL, tmp);
1283		st = (struct sl_stats *)mp->b_cont->b_rptr;
1284		bcopy(&zss->sl_st, st, sizeof (struct sl_stats));
1285		break;
1286
1287	case S_IOCGETSPEED:
1288		tmp = allocb(sizeof (int), BPRI_MED);
1289		if (tmp == NULL) {
1290			error = EAGAIN;
1291			break;
1292		}
1293		if (iocp->ioc_count != TRANSPARENT)
1294			mioc2ack(mp, tmp, sizeof (int), 0);
1295		else
1296			mcopyout(mp, NULL, sizeof (int), NULL, tmp);
1297		*(int *)mp->b_cont->b_rptr = zss->sl_mode.sm_baudrate;
1298		break;
1299
1300	case S_IOCGETMCTL:
1301		tmp = allocb(sizeof (char), BPRI_MED);
1302		if (tmp == NULL) {
1303			error = EAGAIN;
1304			break;
1305		}
1306		if (iocp->ioc_count != TRANSPARENT)
1307			mioc2ack(mp, tmp, sizeof (char), 0);
1308		else
1309			mcopyout(mp, NULL, sizeof (char), NULL, tmp);
1310		msignals = (uchar_t *)mp->b_cont->b_rptr;
1311		*msignals = zss->sl_rr0 & (ZSRR0_CD | ZSRR0_CTS);
1312		break;
1313
1314	case S_IOCGETMRU:
1315		tmp = allocb(sizeof (int), BPRI_MED);
1316		if (tmp == NULL) {
1317			error = EAGAIN;
1318			break;
1319		}
1320		if (iocp->ioc_count != TRANSPARENT)
1321			mioc2ack(mp, tmp, sizeof (int), 0);
1322		else
1323			mcopyout(mp, NULL, sizeof (int), NULL, tmp);
1324		*(int *)mp->b_cont->b_rptr = zss->sl_mru;
1325		break;
1326
1327	case S_IOCSETMODE:
1328		if (iocp->ioc_count != TRANSPARENT) {
1329			error = miocpullup(mp, sizeof (struct scc_mode));
1330			if (error != 0)
1331				break;
1332			error = zsh_setmode(zs, zss,
1333			    (struct scc_mode *)mp->b_cont->b_rptr);
1334			if (error == 0)
1335				mioc2ack(mp, NULL, 0, 0);
1336		} else
1337			mcopyin(mp, NULL, sizeof (struct scc_mode), NULL);
1338		break;
1339
1340	case S_IOCCLRSTATS:
1341		mutex_enter(zs->zs_excl_hi);
1342		bzero(&zss->sl_st, sizeof (struct sl_stats));
1343		mutex_exit(zs->zs_excl_hi);
1344		mioc2ack(mp, NULL, 0, 0);
1345		break;
1346
1347	case S_IOCSETMRU:
1348		if (iocp->ioc_count != TRANSPARENT) {
1349			error = miocpullup(mp, sizeof (int));
1350			if (error != 0)
1351				break;
1352			zss->sl_mru = *(int *)mp->b_cont->b_rptr;
1353			mioc2ack(mp, NULL, 0, 0);
1354		} else
1355			mcopyin(mp, NULL, sizeof (int), NULL);
1356		break;
1357
1358	case S_IOCSETDTR:
1359		/*
1360		 * The first integer of the M_DATA block that should
1361		 * follow indicate if DTR must be set or reset
1362		 */
1363		error = miocpullup(mp, sizeof (int));
1364		if (error != 0)
1365			break;
1366
1367		mutex_enter(zs->zs_excl_hi);
1368		if (*(int *)mp->b_cont->b_rptr != 0)
1369			(void) zsmctl(zs, ZSWR5_DTR, DMBIS);
1370		else
1371			(void) zsmctl(zs, ZSWR5_DTR, DMBIC);
1372		mutex_exit(zs->zs_excl_hi);
1373		break;
1374
1375	default:
1376		error = EINVAL;
1377
1378	}
1379end_zsh_ioctl:
1380	iocp->ioc_error = error;
1381	mp->b_datap->db_type = (error) ? M_IOCNAK : M_IOCACK;
1382	mutex_exit(zs->zs_excl);
1383	qreply(wq, mp);
1384}
1385
1386/*
1387 * Set the mode of the zsh port
1388 */
1389
1390int
1391zsh_setmode(struct zscom *zs, struct syncline *zss, struct scc_mode *sm)
1392{
1393	register int error = 0;
1394	register mblk_t *mp;
1395
1396	mutex_enter(zs->zs_excl_hi);
1397	if (sm->sm_rxclock == RXC_IS_PLL) {
1398		zss->sl_mode.sm_retval = SMERR_RXC;
1399		mutex_exit(zs->zs_excl_hi);
1400		return (EINVAL);		/* not supported */
1401	} else {
1402		if (((zss->sl_mode.sm_config ^ sm->sm_config) &
1403		    CONN_SIGNAL) != 0) { /* Changing, going... */
1404			if (sm->sm_config & CONN_SIGNAL) { /* ...up. */
1405				if (zss->sl_mstat == NULL) {
1406					mutex_exit(zs->zs_excl_hi);
1407					mp = allocb(
1408					    sizeof (struct sl_status),
1409					    BPRI_MED);
1410					mutex_enter(zs->zs_excl_hi);
1411					zss->sl_mstat = mp;
1412				}
1413			} else {			/* ...down. */
1414				if ((mp = zss->sl_mstat) != NULL)
1415					zss->sl_mstat = NULL;
1416				mutex_exit(zs->zs_excl_hi);
1417				if (mp)
1418					freemsg(mp);
1419				mutex_enter(zs->zs_excl_hi);
1420			}
1421		}
1422		if (!(sm->sm_config & CONN_IBM)) {
1423			if (sm->sm_config & CONN_HDX) {
1424				zss->sl_mode.sm_retval = SMERR_HDX;
1425				mutex_exit(zs->zs_excl_hi);
1426				return (EINVAL);
1427			}
1428			if (sm->sm_config & CONN_MPT) {
1429				zss->sl_mode.sm_retval = SMERR_MPT;
1430				mutex_exit(zs->zs_excl_hi);
1431				return (EINVAL);
1432			}
1433		}
1434		zss->sl_flags &= ~SF_FDXPTP;		/* "conmode" */
1435		if ((sm->sm_config & (CONN_HDX | CONN_MPT)) == 0)
1436			zss->sl_flags |= SF_FDXPTP;
1437
1438		error = zsh_program(zs, sm);
1439		if (!error && (zs->zs_ops != &zsops_null))
1440			zsh_init_port(zs, zss);
1441	}
1442	mutex_exit(zs->zs_excl_hi);
1443
1444	return (error);
1445}
1446
1447/*
1448 * Transmit interrupt service procedure
1449 */
1450
1451static void
1452zsh_txint(struct zscom *zs)
1453{
1454	register struct syncline *zss;
1455	register mblk_t *mp;
1456	register int tmp;
1457	register uchar_t *wr_cur;
1458
1459	TRACE_1(TR_ZSH, TR_ZSH_TXINT, "zsh_txint: zs = %p", zs);
1460
1461	if ((wr_cur =  zs->zs_wr_cur) != NULL && (wr_cur <  zs->zs_wr_lim)) {
1462		SCC_WRITEDATA(*wr_cur++);
1463		zs->zs_wr_cur = wr_cur;
1464		return;
1465	}
1466
1467
1468	zss = (struct syncline *)&zs->zs_priv_str;
1469
1470	switch (zss->sl_txstate) {
1471
1472	/*
1473	 * we here because end of message block lim = cur
1474	 */
1475	case TX_ACTIVE:
1476
1477		mp = zss->sl_xactb;
1478
1479again_txint:
1480		mp = mp->b_cont;
1481		if (mp) {
1482			zss->sl_xactb = mp;
1483			zss->sl_ocnt += tmp = mp->b_wptr - mp->b_rptr;
1484			if (!tmp)
1485				goto again_txint;
1486			zs->zs_wr_cur = mp->b_rptr;
1487			zs->zs_wr_lim = mp->b_wptr;
1488			SCC_WRITEDATA(*zs->zs_wr_cur++);
1489			return;
1490		}
1491
1492		/*
1493		 * This is where the fun starts.  At this point the
1494		 * last character in the frame has been sent.  We
1495		 * issue a RESET_TXINT so we won't get another txint
1496		 * until the CRC has been completely sent.  Also we
1497		 * reset the Abort-On-Underrun bit so that CRC is
1498		 * sent at EOM, rather than an Abort.
1499		 */
1500		zs->zs_wr_cur = zs->zs_wr_lim = NULL;
1501		zss->sl_txstate = TX_CRC;
1502		SCC_WRITE0(ZSWR0_RESET_TXINT);
1503		if (!(zss->sl_flags & SF_PHONY)) {
1504			SCC_BIC(10, ZSWR10_UNDERRUN_ABORT);
1505			zss->sl_st.opack++;
1506			zss->sl_st.ochar += zss->sl_ocnt;
1507		}
1508		zss->sl_ocnt = 0;
1509		ZSH_FREEMSG(zss->sl_xhead);
1510		zss->sl_xhead = zss->sl_xactb = NULL;
1511		ZSSETSOFT(zs);
1512		break;
1513	/*
1514	 * This txint means we have sent the CRC bytes at EOF.
1515	 * The next txint will mean we are sending or have sent the
1516	 * flag character at EOF, but we handle that differently, and
1517	 * enter different states,depending on whether we're IBM or not.
1518	 */
1519	case TX_CRC:
1520		if (!(zss->sl_flags & SF_FDXPTP)) {
1521			zss->sl_txstate = TX_FLAG;	/* HDX path */
1522		} else {	/* FDX path */
1523			if (!zsh_start(zs, zss)) {
1524				zss->sl_txstate = TX_IDLE;
1525				SCC_WRITE0(ZSWR0_RESET_TXINT);
1526			}
1527		}
1528		break;
1529
1530	/*
1531	 * This txint means the closing flag byte is going out the door.
1532	 * We use this state to allow this to complete before dropping RTS.
1533	 */
1534	case TX_FLAG:
1535		zss->sl_txstate = TX_LAST;
1536		(void) zsh_start(zs, zss);
1537		break;
1538
1539	/*
1540	 * Arriving here means the flag should be out and it's finally
1541	 * time to close the barn door.
1542	 */
1543	case TX_LAST:
1544		zss->sl_txstate = TX_IDLE;
1545		SCC_WRITE0(ZSWR0_RESET_TXINT);
1546		break;
1547
1548	/*
1549	 * If transmit was aborted, do nothing - watchdog will recover.
1550	 */
1551	case TX_ABORTED:
1552		SCC_WRITE0(ZSWR0_RESET_TXINT);
1553		break;
1554
1555	default:
1556		SCC_WRITE0(ZSWR0_RESET_TXINT);
1557		break;
1558	}
1559}
1560
1561/*
1562 * External Status Change interrupt service procedure
1563 */
1564static void
1565zsh_xsint(struct zscom *zs)
1566{
1567	register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1568	register uchar_t s0, x0;
1569
1570	TRACE_1(TR_ZSH, TR_ZSH_XSINT, "zsh_xsint: zs = %p", zs);
1571
1572	s0 = SCC_READ0();
1573	x0 = s0 ^ zss->sl_rr0;
1574	zss->sl_rr0 = s0;
1575	SCC_WRITE0(ZSWR0_RESET_STATUS);
1576
1577	if (s0 & ZSRR0_TXUNDER) {
1578		switch (zss->sl_txstate) {
1579		/*
1580		 * A transmitter underrun has occurred.  If we are not
1581		 * here as the result of an abort sent by the watchdog
1582		 * timeout routine, we need to send an abort to flush
1583		 * the transmitter.  Otherwise there is a danger of
1584		 * trashing the next frame but still sending a good crc.
1585		 * The TX_ABORTED flag is set so that the watchdog
1586		 * routine can initiate recovery.
1587		 */
1588		case TX_ACTIVE:
1589			SCC_WRITE0(ZSWR0_SEND_ABORT);
1590			SCC_WRITE0(ZSWR0_RESET_TXINT);
1591			zss->sl_st.underrun++;
1592			zsh_txbad(zs, zss);
1593
1594			zss->sl_txstate = TX_ABORTED;
1595			zss->sl_wd_count = 0;
1596			break;
1597
1598		case TX_CRC:
1599			break;
1600
1601		case TX_FLAG:
1602			break;
1603
1604		case TX_ABORTED:
1605			break;
1606
1607		case TX_OFF:
1608			break;
1609
1610		case TX_LAST:
1611			break;
1612
1613		default:
1614			break;
1615		}
1616	}
1617
1618	if ((x0 & ZSRR0_BREAK) && (s0 & ZSRR0_BREAK) && zs->zs_rd_cur) {
1619		zss->sl_st.abort++;
1620		zsh_rxbad(zs, zss);
1621	} else if ((s0 & ZSRR0_SYNC) && (zs->zs_rd_cur)) {
1622		/*
1623		 * Tricky code to avoid disaster in the case where
1624		 * an abort was detected while receiving a packet,
1625		 * but the abort did not last long enough to be
1626		 * detected by zsh_xsint - this can happen since
1627		 * the ZSRR0_BREAK is not latched.  Since an abort
1628		 * will automatically cause the SCC to enter
1629		 * hunt mode, hopefully, the sync/hunt bit will be
1630		 * set in this case (although if the interrupt is
1631		 * sufficiently delayed, the SCC may have sync'ed
1632		 * in again if it has detected a flag).
1633		 */
1634		zss->sl_st.abort++;
1635		zsh_rxbad(zs, zss);
1636	}
1637
1638	if (x0 & s0 & ZSRR0_CTS) {
1639		if (zss->sl_txstate == TX_RTS) {
1640			if (!(zss->sl_flags & SF_FDXPTP)) {
1641				SCC_BIS(5, ZSWR5_TX_ENABLE);
1642			}
1643			(void) zsh_start(zs, zss);
1644		} else if ((zss->sl_mode.sm_config &
1645		    (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 */
1677static void
1678zsh_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 */
1717static void
1718zsh_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 */
1769static int
1770zsh_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
1818next:
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;
1861again:
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 */
1906static int
1907zsh_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 */
2051out:
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 */
2061static void
2062zsh_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 */
2086static void
2087zsh_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 */
2124static void
2125zsh_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 */
2152static void
2153zsh_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	}
2263end_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
2285static void
2286zsh_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