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