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 */
26
27
28 /*
29 * HDLC protocol handler for Z8530 SCC.
30 */
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/types.h>
35 #include <sys/sysmacros.h>
36 #include <sys/kmem.h>
37 #include <sys/stropts.h>
38 #include <sys/stream.h>
39 #include <sys/strsun.h>
40 #include <sys/stat.h>
41 #include <sys/cred.h>
42 #include <sys/user.h>
43 #include <sys/proc.h>
44 #include <sys/file.h>
45 #include <sys/uio.h>
46 #include <sys/buf.h>
47 #include <sys/mkdev.h>
48 #include <sys/cmn_err.h>
49 #include <sys/errno.h>
50 #include <sys/fcntl.h>
51
52 #include <sys/zsdev.h>
53 #include <sys/ser_sync.h>
54 #include <sys/conf.h>
55 #include <sys/ddi.h>
56 #include <sys/sunddi.h>
57 #include <sys/dlpi.h>
58
59 #define ZSH_TRACING
60 #ifdef ZSH_TRACING
61 #include <sys/vtrace.h>
62
63 /*
64 * Temp tracepoint definitions
65 */
66 #define TR_ZSH 50
67
68 #define TR_ZSH_TXINT 1
69 #define TR_ZSH_XSINT 2
70 #define TR_ZSH_RXINT 3
71 #define TR_ZSH_SRINT 4
72
73 #define TR_ZSH_WPUT_START 5
74 #define TR_ZSH_WPUT_END 6
75 #define TR_ZSH_START_START 7
76 #define TR_ZSH_START_END 8
77 #define TR_ZSH_SOFT_START 9
78 #define TR_ZSH_SOFT_END 10
79
80 #define TR_ZSH_OPEN 11
81 #define TR_ZSH_CLOSE 12
82
83 #endif /* ZSH_TRACING */
84
85 /*
86 * Logging definitions
87 */
88
89 /*
90 * #define ZSH_DEBUG
91 */
92 #ifdef ZSH_DEBUG
93
94 #ifdef ZS_DEBUG_ALL
95 extern char zs_h_log[];
96 extern int zs_h_log_n;
97 #define zsh_h_log_add(c) \
98 { \
99 if (zs_h_log_n >= ZS_H_LOG_MAX) \
100 zs_h_log_n = 0; \
101 zs_h_log[zs_h_log_n++] = 'A' + zs->zs_unit; \
102 zs_h_log[zs_h_log_n++] = c; \
103 zs_h_log[zs_h_log_n] = '\0'; \
104 }
105 #define zsh_h_log_clear
106 #else
107 #define ZSH_H_LOG_MAX 0x8000
108 char zsh_h_log[2][ZSH_H_LOG_MAX +10];
109 int zsh_h_log_n[2];
110 #define zsh_h_log_add(c) \
111 { \
112 if (zsh_h_log_n[zs->zs_unit] >= ZSH_H_LOG_MAX) \
113 zsh_h_log_n[zs->zs_unit] = 0; \
114 zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]++] = c; \
115 zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]] = '\0'; \
116 }
117
118 #define zsh_h_log_clear \
119 { register char *p; \
120 for (p = &zsh_h_log[zs->zs_unit][ZSH_H_LOG_MAX]; \
121 p >= &zsh_h_log[zs->zs_unit][0]; p--) \
122 *p = '\0'; \
123 zsh_h_log_n[zs->zs_unit] = 0; \
124 }
125 #endif
126
127 #define ZSH_R0_LOG(r0) { \
128 if (r0 & ZSRR0_RX_READY) zsh_h_log_add('R'); \
129 if (r0 & ZSRR0_TIMER) zsh_h_log_add('Z'); \
130 if (r0 & ZSRR0_TX_READY) zsh_h_log_add('T'); \
131 if (r0 & ZSRR0_CD) zsh_h_log_add('D'); \
132 if (r0 & ZSRR0_SYNC) zsh_h_log_add('S'); \
133 if (r0 & ZSRR0_CTS) zsh_h_log_add('C'); \
134 if (r0 & ZSRR0_TXUNDER) zsh_h_log_add('U'); \
135 if (r0 & ZSRR0_BREAK) zsh_h_log_add('B'); \
136 }
137 #endif
138
139 #ifndef MAXZSH
140 #define MAXZSH 2
141 #define MAXZSHCLONES (80) /* three clone opens per instance */
142 #endif /* MAXZSH */
143
144 int maxzsh = MAXZSH;
145
146 int zsh_timer_count = 10;
147 int zsh_default_mru = 1024;
148
149 struct ser_str *zsh_str = NULL;
150 unsigned char zsh_usedminor[MAXZSHCLONES];
151
152
153 /*
154 * The HDLC protocol
155 */
156 int zsh_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result);
157 static int zsh_probe(dev_info_t *dev);
158 static int zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd);
159 static int zsh_detach(dev_info_t *dev, ddi_detach_cmd_t cmd);
160 static int zsh_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr);
161 static int zsh_close(queue_t *rq, int flag);
162 static void zsh_wput(queue_t *wq, mblk_t *mp);
163 static int zsh_start(struct zscom *zs, struct syncline *zss);
164 static void zsh_ioctl(queue_t *wq, mblk_t *mp);
165
166 static struct module_info hdlc_minfo = {
167 0x5a48, /* module ID number: "ZH" */
168 "zsh", /* module name */
169 0, /* minimum packet size accepted */
170 INFPSZ, /* maximum packet size accepted */
171 12*1024, /* queue high water mark (bytes) */
172 4*1024 /* queue low water mark (bytes) */
173 };
174
175 static struct qinit hdlc_rinit = {
176 putq, /* input put procedure */
177 NULL, /* input service procedure */
178 zsh_open, /* open procedure */
179 zsh_close, /* close procedure */
180 NULL, /* reserved */
181 &hdlc_minfo, /* module info */
182 NULL /* reserved */
183 };
184
185 static struct qinit hdlc_winit = {
186 (int (*)())zsh_wput, /* output put procedure */
187 NULL, /* output service procedure */
188 NULL, /* open procedure */
189 NULL, /* close procedure */
190 NULL, /* reserved */
191 &hdlc_minfo, /* module info */
192 NULL /* reserved */
193 };
194
195 struct streamtab hdlctab = {
196 &hdlc_rinit, /* initialize read queue */
197 &hdlc_winit, /* initialize write queue */
198 NULL, /* mux read qinit */
199 NULL /* mux write qinit */
200 };
201
202 DDI_DEFINE_STREAM_OPS(zsh_ops, nulldev, zsh_probe, zsh_attach,
203 zsh_detach, nodev, zsh_info, D_MP, &hdlctab, ddi_quiesce_not_supported);
204
205 /*
206 * This is the loadable module wrapper.
207 */
208
209 #include <sys/errno.h>
210 #include <sys/modctl.h>
211
212 /*
213 * Module linkage information for the kernel.
214 */
215
216 static struct modldrv modldrv = {
217 &mod_driverops, /* Type of module. This one is a driver */
218 "Z8530 serial HDLC drv",
219 &zsh_ops, /* our own ops for this module */
220 };
221
222 static struct modlinkage modlinkage = {
223 MODREV_1,
224 (void *)&modldrv,
225 NULL
226 };
227
228 int
_init(void)229 _init(void)
230 {
231 return (mod_install(&modlinkage));
232 }
233
234 int
_fini(void)235 _fini(void)
236 {
237 return (mod_remove(&modlinkage));
238 }
239
240 int
_info(struct modinfo * modinfop)241 _info(struct modinfo *modinfop)
242 {
243 return (mod_info(&modlinkage, modinfop));
244 }
245
246
247 /*
248 * The HDLC interrupt entry points.
249 */
250 static void zsh_txint(struct zscom *zs);
251 static void zsh_xsint(struct zscom *zs);
252 static void zsh_rxint(struct zscom *zs);
253 static void zsh_srint(struct zscom *zs);
254 static int zsh_softint(struct zscom *zs);
255
256 struct zsops zsops_hdlc = {
257 zsh_txint,
258 zsh_xsint,
259 zsh_rxint,
260 zsh_srint,
261 zsh_softint,
262 NULL,
263 NULL
264 };
265
266 static int zsh_program(struct zscom *zs, struct scc_mode *sm);
267 static void zsh_setmstat(struct zscom *zs, int event);
268 static void zsh_rxbad(struct zscom *zs, struct syncline *zss);
269 static void zsh_txbad(struct zscom *zs, struct syncline *zss);
270 static void zsh_watchdog(void *);
271 static void zsh_callback(void *);
272 static int zsh_hdp_ok_or_rts_state(struct zscom *zs, struct syncline *zss);
273 static void zsh_init_port(struct zscom *zs, struct syncline *zss);
274 static int zsh_setmode(struct zscom *zs, struct syncline *zss,
275 struct scc_mode *sm);
276
277
278 /*
279 * The HDLC Driver.
280 */
281
282
283 /*
284 * Special macros to handle STREAMS operations.
285 * These are required to address memory leakage problems.
286 * WARNING : the macro do NOT call ZSSETSOFT
287 */
288
289 /*
290 * Should be called holding only the adaptive (zs_excl) mutex.
291 */
292 #define ZSH_GETBLOCK(zs, allocbcount) \
293 { \
294 register int n = ZSH_MAX_RSTANDBY; \
295 while (--n >= 0) { \
296 if (!zss->sl_rstandby[n]) { \
297 if ((zss->sl_rstandby[n] = \
298 allocb(zss->sl_mru, BPRI_MED)) == NULL) { \
299 if (zss->sl_bufcid == 0) { \
300 mutex_enter(zs->zs_excl_hi); \
301 if (zss->sl_txstate != TX_OFF) { \
302 mutex_exit(zs->zs_excl_hi); \
303 zss->sl_bufcid = bufcall(zss->sl_mru, \
304 BPRI_MED, zsh_callback, zs); \
305 break; \
306 } else \
307 mutex_exit(zs->zs_excl_hi); \
308 } \
309 } \
310 allocbcount--; \
311 } \
312 } \
313 }
314
315 /*
316 * Should be called holding the spin (zs_excl_hi) mutex.
317 */
318 #define ZSH_ALLOCB(mp) \
319 { \
320 register int n = ZSH_MAX_RSTANDBY; \
321 mp = NULL; \
322 while (--n >= 0) { \
323 if ((mp = zss->sl_rstandby[n]) != NULL) { \
324 zss->sl_rstandby[n] = NULL; \
325 break; \
326 } \
327 } \
328 }
329
330 #define ZSH_PUTQ(mp) \
331 { \
332 register int wptr, rptr; \
333 wptr = zss->sl_rdone_wptr; \
334 rptr = zss->sl_rdone_rptr; \
335 zss->sl_rdone[wptr] = mp; \
336 if ((wptr) + 1 == ZSH_RDONE_MAX) \
337 zss->sl_rdone_wptr = wptr = 0; \
338 else \
339 zss->sl_rdone_wptr = ++wptr; \
340 if (wptr == rptr) { /* Should never occur */ \
341 SCC_BIC(1, ZSWR1_INIT); \
342 zss->sl_m_error = ENOSR; \
343 ZSSETSOFT(zs); \
344 } \
345 }
346
347 #define ZSH_FREEMSG(mp) \
348 { \
349 ZSH_PUTQ(mp); \
350 }
351
352
353 /*
354 * Should be called holding only the adaptive (zs_excl) mutex.
355 */
356 #define ZSH_GETQ(mp) \
357 { \
358 if (zss->sl_rdone_rptr != zss->sl_rdone_wptr) { \
359 mp = zss->sl_rdone[zss->sl_rdone_rptr++]; \
360 if (zss->sl_rdone_rptr == ZSH_RDONE_MAX) \
361 zss->sl_rdone_rptr = 0; \
362 } else \
363 mp = NULL; \
364 }
365
366 #define ZSH_FLUSHQ \
367 { \
368 register mblk_t *tmp; \
369 for (;;) { \
370 ZSH_GETQ(tmp); \
371 if (!(tmp)) \
372 break; \
373 freemsg(tmp); \
374 } \
375 }
376
377 /*ARGSUSED*/
378 static int
zsh_probe(dev_info_t * dev)379 zsh_probe(dev_info_t *dev)
380 {
381 return (DDI_PROBE_DONTCARE);
382 }
383
384 /*ARGSUSED*/
385 static int
zsh_attach(dev_info_t * dev,ddi_attach_cmd_t cmd)386 zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd)
387 {
388 register int unit;
389 char name[3] = {
390 '\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 NULL, 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, NULL) == 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, NULL) == 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 register dev_t dev = (dev_t)arg;
441 register int unit, error;
442 register 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 register 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)
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 register struct zscom *zs;
523 register struct syncline *zss;
524 register struct ser_str *stp;
525 register int unit;
526 register 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 = NULL;
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]) {
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)636 zsh_close(queue_t *rq, int flag)
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 register 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 void
zsh_wput(queue_t * wq,mblk_t * mp)827 zsh_wput(queue_t *wq, mblk_t *mp)
828 {
829 register struct ser_str *stp = (struct ser_str *)wq->q_ptr;
830 register struct zscom *zs;
831 register struct syncline *zss = NULL;
832 register ulong_t prim, error = 0;
833 register union DL_primitives *dlp;
834 register int ppa;
835 register mblk_t *tmp;
836 register 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;
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;
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;
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;
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;
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 register mblk_t *mp1;
910 mp1 = unlinkb(mp);
911 freemsg(mp);
912 mp = mp1;
913 if (mp == NULL)
914 return;
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;
928 }
929 tmp = NULL;
930 again:
931 if (!zss->sl_xstandby) {
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;
955 }
956
957 if (!zss->sl_wd_id) {
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;
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 register 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 }
1126
1127 /*
1128 * Get the next message from the write queue, set up the necessary pointers,
1129 * state info, etc., and start the transmit "engine" by sending the first
1130 * character. We'll then rotate through txint until done, then get an xsint.
1131 */
1132 static int
zsh_start(struct zscom * zs,struct syncline * zss)1133 zsh_start(struct zscom *zs, struct syncline *zss)
1134 {
1135 register mblk_t *mp;
1136 register uchar_t *wptr;
1137 register uchar_t *rptr;
1138 register uchar_t sl_flags = zss->sl_flags;
1139
1140 /*
1141 * Attempt to grab the next M_DATA message off the queue (that's
1142 * all that will be left after wput) and begin transmission.
1143 * This routine is normally called after completion of a previous
1144 * frame, or when zsh_wput gets a new message. If we are in a
1145 * mode that put us in the TX_RTS state, waiting for CTS, and CTS
1146 * is not up yet, we have no business here. Ditto if we're in
1147 * either the TX_ACTIVE or TX_CRC states. In these cases we
1148 * don't clear SF_CALLSTART, so we don't forget there's work to do.
1149 */
1150
1151 TRACE_1(TR_ZSH, TR_ZSH_START_START,
1152 "zsh_start start: zs = %p", zs);
1153
1154 if (sl_flags & SF_PHONY) {
1155 sl_flags &= ~SF_PHONY;
1156 SCC_BIC(15, ZSR15_CTS);
1157 SCC_BIC(5, ZSWR5_RTS);
1158 SCC_WRITE0(ZSWR0_RESET_TXINT);
1159 SCC_BIC(5, ZSWR5_TX_ENABLE);
1160 zss->sl_rr0 &= ~ZSRR0_CTS;
1161 zss->sl_txstate = TX_IDLE;
1162 /*
1163 * if we get another msg by chance zsh_watchog will start
1164 */
1165 sl_flags &= ~SF_XMT_INPROG;
1166 zss->sl_flags = sl_flags;
1167
1168 TRACE_1(TR_ZSH, TR_ZSH_START_END,
1169 "zsh_start end: zs = %d", zs);
1170
1171 return (0);
1172 }
1173 mp = zss->sl_xstandby;
1174 if (mp == NULL) {
1175 if (!(sl_flags & SF_FDXPTP)) {
1176 sl_flags |= SF_PHONY;
1177 ZSH_ALLOCB(mp);
1178 if (!mp)
1179 return (0);
1180 mp->b_datap->db_type = M_RSE;
1181 mp->b_wptr = mp->b_rptr + 1;
1182 goto transmit;
1183 }
1184 sl_flags &= ~SF_XMT_INPROG;
1185 zss->sl_flags = sl_flags;
1186
1187 TRACE_1(TR_ZSH, TR_ZSH_START_END,
1188 "zsh_start end: zs = %p", zs);
1189
1190 return (0);
1191 }
1192
1193 transmit:
1194 zss->sl_xstandby = NULL;
1195 rptr = mp->b_rptr;
1196 wptr = mp->b_wptr;
1197 ZSSETSOFT(zs);
1198
1199 #ifdef ZSH_DEBUG
1200 if (zss->sl_xhead || zss->sl_xactb) {
1201 debug_enter("xhead1");
1202 }
1203 #endif
1204
1205 zss->sl_xhead = mp;
1206 zss->sl_xactb = mp;
1207 zss->sl_wd_count = zsh_timer_count;
1208 zss->sl_txstate = TX_ACTIVE;
1209 zss->sl_ocnt = 0;
1210 SCC_BIS(10, ZSWR10_UNDERRUN_ABORT); /* abort on underrun */
1211 SCC_WRITE0(ZSWR0_RESET_TXCRC); /* reset transmit CRC */
1212 zss->sl_ocnt = wptr - rptr;
1213 mp->b_wptr = rptr; /* to tell soft to free this msg */
1214 SCC_WRITEDATA(*rptr++); /* resets TXINT */
1215 zs->zs_wr_cur = rptr;
1216 zs->zs_wr_lim = wptr;
1217
1218 SCC_WRITE0(ZSWR0_RESET_EOM);
1219
1220 TRACE_1(TR_ZSH, TR_ZSH_START_END,
1221 "zsh_start end: zs = %p", zs);
1222
1223 zss->sl_flags = sl_flags;
1224 return (1);
1225 }
1226
1227
1228 /*
1229 * Process an "ioctl" message sent down to us.
1230 */
1231 static void
zsh_ioctl(queue_t * wq,mblk_t * mp)1232 zsh_ioctl(queue_t *wq, mblk_t *mp)
1233 {
1234 register struct ser_str *stp = (struct ser_str *)wq->q_ptr;
1235 register struct zscom *zs = (struct zscom *)stp->str_com;
1236 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1237 register struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
1238 register struct scc_mode *sm;
1239 register struct sl_stats *st;
1240 register uchar_t *msignals;
1241 register mblk_t *tmp;
1242 register int error = 0;
1243
1244 mutex_enter(zs->zs_excl);
1245 if ((zs->zs_ops != &zsops_null) &&
1246 (zs->zs_ops != &zsops_hdlc)) {
1247 /*
1248 * another protocol got here first
1249 */
1250 error = (EBUSY);
1251 goto end_zsh_ioctl;
1252 }
1253
1254
1255 switch (iocp->ioc_cmd) {
1256
1257 case S_IOCGETMODE:
1258 tmp = allocb(sizeof (struct scc_mode), BPRI_MED);
1259 if (tmp == NULL) {
1260 error = EAGAIN;
1261 break;
1262 }
1263 if (iocp->ioc_count != TRANSPARENT)
1264 mioc2ack(mp, tmp, sizeof (struct scc_mode), 0);
1265 else
1266 mcopyout(mp, NULL, sizeof (struct scc_mode), NULL, tmp);
1267 sm = (struct scc_mode *)mp->b_cont->b_rptr;
1268 bcopy(&zss->sl_mode, sm, sizeof (struct scc_mode));
1269 break;
1270
1271 case S_IOCGETSTATS:
1272 tmp = allocb(sizeof (struct sl_stats), BPRI_MED);
1273 if (tmp == NULL) {
1274 error = EAGAIN;
1275 break;
1276 }
1277 if (iocp->ioc_count != TRANSPARENT)
1278 mioc2ack(mp, tmp, sizeof (struct sl_stats), 0);
1279 else
1280 mcopyout(mp, NULL, sizeof (struct sl_stats), NULL, tmp);
1281 st = (struct sl_stats *)mp->b_cont->b_rptr;
1282 bcopy(&zss->sl_st, st, sizeof (struct sl_stats));
1283 break;
1284
1285 case S_IOCGETSPEED:
1286 tmp = allocb(sizeof (int), BPRI_MED);
1287 if (tmp == NULL) {
1288 error = EAGAIN;
1289 break;
1290 }
1291 if (iocp->ioc_count != TRANSPARENT)
1292 mioc2ack(mp, tmp, sizeof (int), 0);
1293 else
1294 mcopyout(mp, NULL, sizeof (int), NULL, tmp);
1295 *(int *)mp->b_cont->b_rptr = zss->sl_mode.sm_baudrate;
1296 break;
1297
1298 case S_IOCGETMCTL:
1299 tmp = allocb(sizeof (char), BPRI_MED);
1300 if (tmp == NULL) {
1301 error = EAGAIN;
1302 break;
1303 }
1304 if (iocp->ioc_count != TRANSPARENT)
1305 mioc2ack(mp, tmp, sizeof (char), 0);
1306 else
1307 mcopyout(mp, NULL, sizeof (char), NULL, tmp);
1308 msignals = (uchar_t *)mp->b_cont->b_rptr;
1309 *msignals = zss->sl_rr0 & (ZSRR0_CD | ZSRR0_CTS);
1310 break;
1311
1312 case S_IOCGETMRU:
1313 tmp = allocb(sizeof (int), BPRI_MED);
1314 if (tmp == NULL) {
1315 error = EAGAIN;
1316 break;
1317 }
1318 if (iocp->ioc_count != TRANSPARENT)
1319 mioc2ack(mp, tmp, sizeof (int), 0);
1320 else
1321 mcopyout(mp, NULL, sizeof (int), NULL, tmp);
1322 *(int *)mp->b_cont->b_rptr = zss->sl_mru;
1323 break;
1324
1325 case S_IOCSETMODE:
1326 if (iocp->ioc_count != TRANSPARENT) {
1327 error = miocpullup(mp, sizeof (struct scc_mode));
1328 if (error != 0)
1329 break;
1330 error = zsh_setmode(zs, zss,
1331 (struct scc_mode *)mp->b_cont->b_rptr);
1332 if (error == 0)
1333 mioc2ack(mp, NULL, 0, 0);
1334 } else
1335 mcopyin(mp, NULL, sizeof (struct scc_mode), NULL);
1336 break;
1337
1338 case S_IOCCLRSTATS:
1339 mutex_enter(zs->zs_excl_hi);
1340 bzero(&zss->sl_st, sizeof (struct sl_stats));
1341 mutex_exit(zs->zs_excl_hi);
1342 mioc2ack(mp, NULL, 0, 0);
1343 break;
1344
1345 case S_IOCSETMRU:
1346 if (iocp->ioc_count != TRANSPARENT) {
1347 error = miocpullup(mp, sizeof (int));
1348 if (error != 0)
1349 break;
1350 zss->sl_mru = *(int *)mp->b_cont->b_rptr;
1351 mioc2ack(mp, NULL, 0, 0);
1352 } else
1353 mcopyin(mp, NULL, sizeof (int), NULL);
1354 break;
1355
1356 case S_IOCSETDTR:
1357 /*
1358 * The first integer of the M_DATA block that should
1359 * follow indicate if DTR must be set or reset
1360 */
1361 error = miocpullup(mp, sizeof (int));
1362 if (error != 0)
1363 break;
1364
1365 mutex_enter(zs->zs_excl_hi);
1366 if (*(int *)mp->b_cont->b_rptr != 0)
1367 (void) zsmctl(zs, ZSWR5_DTR, DMBIS);
1368 else
1369 (void) zsmctl(zs, ZSWR5_DTR, DMBIC);
1370 mutex_exit(zs->zs_excl_hi);
1371 break;
1372
1373 default:
1374 error = EINVAL;
1375
1376 }
1377 end_zsh_ioctl:
1378 iocp->ioc_error = error;
1379 mp->b_datap->db_type = (error) ? M_IOCNAK : M_IOCACK;
1380 mutex_exit(zs->zs_excl);
1381 qreply(wq, mp);
1382 }
1383
1384 /*
1385 * Set the mode of the zsh port
1386 */
1387
1388 int
zsh_setmode(struct zscom * zs,struct syncline * zss,struct scc_mode * sm)1389 zsh_setmode(struct zscom *zs, struct syncline *zss, struct scc_mode *sm)
1390 {
1391 register int error = 0;
1392 register mblk_t *mp;
1393
1394 mutex_enter(zs->zs_excl_hi);
1395 if (sm->sm_rxclock == RXC_IS_PLL) {
1396 zss->sl_mode.sm_retval = SMERR_RXC;
1397 mutex_exit(zs->zs_excl_hi);
1398 return (EINVAL); /* not supported */
1399 } else {
1400 if (((zss->sl_mode.sm_config ^ sm->sm_config) &
1401 CONN_SIGNAL) != 0) { /* Changing, going... */
1402 if (sm->sm_config & CONN_SIGNAL) { /* ...up. */
1403 if (zss->sl_mstat == NULL) {
1404 mutex_exit(zs->zs_excl_hi);
1405 mp = allocb(
1406 sizeof (struct sl_status),
1407 BPRI_MED);
1408 mutex_enter(zs->zs_excl_hi);
1409 zss->sl_mstat = mp;
1410 }
1411 } else { /* ...down. */
1412 if ((mp = zss->sl_mstat) != NULL)
1413 zss->sl_mstat = NULL;
1414 mutex_exit(zs->zs_excl_hi);
1415 if (mp)
1416 freemsg(mp);
1417 mutex_enter(zs->zs_excl_hi);
1418 }
1419 }
1420 if (!(sm->sm_config & CONN_IBM)) {
1421 if (sm->sm_config & CONN_HDX) {
1422 zss->sl_mode.sm_retval = SMERR_HDX;
1423 mutex_exit(zs->zs_excl_hi);
1424 return (EINVAL);
1425 }
1426 if (sm->sm_config & CONN_MPT) {
1427 zss->sl_mode.sm_retval = SMERR_MPT;
1428 mutex_exit(zs->zs_excl_hi);
1429 return (EINVAL);
1430 }
1431 }
1432 zss->sl_flags &= ~SF_FDXPTP; /* "conmode" */
1433 if ((sm->sm_config & (CONN_HDX | CONN_MPT)) == 0)
1434 zss->sl_flags |= SF_FDXPTP;
1435
1436 error = zsh_program(zs, sm);
1437 if (!error && (zs->zs_ops != &zsops_null))
1438 zsh_init_port(zs, zss);
1439 }
1440 mutex_exit(zs->zs_excl_hi);
1441
1442 return (error);
1443 }
1444
1445 /*
1446 * Transmit interrupt service procedure
1447 */
1448
1449 static void
zsh_txint(struct zscom * zs)1450 zsh_txint(struct zscom *zs)
1451 {
1452 register struct syncline *zss;
1453 register mblk_t *mp;
1454 register int tmp;
1455 register uchar_t *wr_cur;
1456
1457 TRACE_1(TR_ZSH, TR_ZSH_TXINT, "zsh_txint: zs = %p", zs);
1458
1459 if ((wr_cur = zs->zs_wr_cur) != NULL && (wr_cur < zs->zs_wr_lim)) {
1460 SCC_WRITEDATA(*wr_cur++);
1461 zs->zs_wr_cur = wr_cur;
1462 return;
1463 }
1464
1465
1466 zss = (struct syncline *)&zs->zs_priv_str;
1467
1468 switch (zss->sl_txstate) {
1469
1470 /*
1471 * we here because end of message block lim = cur
1472 */
1473 case TX_ACTIVE:
1474
1475 mp = zss->sl_xactb;
1476
1477 again_txint:
1478 mp = mp->b_cont;
1479 if (mp) {
1480 zss->sl_xactb = mp;
1481 zss->sl_ocnt += tmp = mp->b_wptr - mp->b_rptr;
1482 if (!tmp)
1483 goto again_txint;
1484 zs->zs_wr_cur = mp->b_rptr;
1485 zs->zs_wr_lim = mp->b_wptr;
1486 SCC_WRITEDATA(*zs->zs_wr_cur++);
1487 return;
1488 }
1489
1490 /*
1491 * This is where the fun starts. At this point the
1492 * last character in the frame has been sent. We
1493 * issue a RESET_TXINT so we won't get another txint
1494 * until the CRC has been completely sent. Also we
1495 * reset the Abort-On-Underrun bit so that CRC is
1496 * sent at EOM, rather than an Abort.
1497 */
1498 zs->zs_wr_cur = zs->zs_wr_lim = NULL;
1499 zss->sl_txstate = TX_CRC;
1500 SCC_WRITE0(ZSWR0_RESET_TXINT);
1501 if (!(zss->sl_flags & SF_PHONY)) {
1502 SCC_BIC(10, ZSWR10_UNDERRUN_ABORT);
1503 zss->sl_st.opack++;
1504 zss->sl_st.ochar += zss->sl_ocnt;
1505 }
1506 zss->sl_ocnt = 0;
1507 ZSH_FREEMSG(zss->sl_xhead);
1508 zss->sl_xhead = zss->sl_xactb = NULL;
1509 ZSSETSOFT(zs);
1510 break;
1511 /*
1512 * This txint means we have sent the CRC bytes at EOF.
1513 * The next txint will mean we are sending or have sent the
1514 * flag character at EOF, but we handle that differently, and
1515 * enter different states,depending on whether we're IBM or not.
1516 */
1517 case TX_CRC:
1518 if (!(zss->sl_flags & SF_FDXPTP)) {
1519 zss->sl_txstate = TX_FLAG; /* HDX path */
1520 } else { /* FDX path */
1521 if (!zsh_start(zs, zss)) {
1522 zss->sl_txstate = TX_IDLE;
1523 SCC_WRITE0(ZSWR0_RESET_TXINT);
1524 }
1525 }
1526 break;
1527
1528 /*
1529 * This txint means the closing flag byte is going out the door.
1530 * We use this state to allow this to complete before dropping RTS.
1531 */
1532 case TX_FLAG:
1533 zss->sl_txstate = TX_LAST;
1534 (void) zsh_start(zs, zss);
1535 break;
1536
1537 /*
1538 * Arriving here means the flag should be out and it's finally
1539 * time to close the barn door.
1540 */
1541 case TX_LAST:
1542 zss->sl_txstate = TX_IDLE;
1543 SCC_WRITE0(ZSWR0_RESET_TXINT);
1544 break;
1545
1546 /*
1547 * If transmit was aborted, do nothing - watchdog will recover.
1548 */
1549 case TX_ABORTED:
1550 SCC_WRITE0(ZSWR0_RESET_TXINT);
1551 break;
1552
1553 default:
1554 SCC_WRITE0(ZSWR0_RESET_TXINT);
1555 break;
1556 }
1557 }
1558
1559 /*
1560 * External Status Change interrupt service procedure
1561 */
1562 static void
zsh_xsint(struct zscom * zs)1563 zsh_xsint(struct zscom *zs)
1564 {
1565 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1566 register uchar_t s0, x0;
1567
1568 TRACE_1(TR_ZSH, TR_ZSH_XSINT, "zsh_xsint: zs = %p", zs);
1569
1570 s0 = SCC_READ0();
1571 x0 = s0 ^ zss->sl_rr0;
1572 zss->sl_rr0 = s0;
1573 SCC_WRITE0(ZSWR0_RESET_STATUS);
1574
1575 if (s0 & ZSRR0_TXUNDER) {
1576 switch (zss->sl_txstate) {
1577 /*
1578 * A transmitter underrun has occurred. If we are not
1579 * here as the result of an abort sent by the watchdog
1580 * timeout routine, we need to send an abort to flush
1581 * the transmitter. Otherwise there is a danger of
1582 * trashing the next frame but still sending a good crc.
1583 * The TX_ABORTED flag is set so that the watchdog
1584 * routine can initiate recovery.
1585 */
1586 case TX_ACTIVE:
1587 SCC_WRITE0(ZSWR0_SEND_ABORT);
1588 SCC_WRITE0(ZSWR0_RESET_TXINT);
1589 zss->sl_st.underrun++;
1590 zsh_txbad(zs, zss);
1591
1592 zss->sl_txstate = TX_ABORTED;
1593 zss->sl_wd_count = 0;
1594 break;
1595
1596 case TX_CRC:
1597 break;
1598
1599 case TX_FLAG:
1600 break;
1601
1602 case TX_ABORTED:
1603 break;
1604
1605 case TX_OFF:
1606 break;
1607
1608 case TX_LAST:
1609 break;
1610
1611 default:
1612 break;
1613 }
1614 }
1615
1616 if ((x0 & ZSRR0_BREAK) && (s0 & ZSRR0_BREAK) && zs->zs_rd_cur) {
1617 zss->sl_st.abort++;
1618 zsh_rxbad(zs, zss);
1619 } else if ((s0 & ZSRR0_SYNC) && (zs->zs_rd_cur)) {
1620 /*
1621 * Tricky code to avoid disaster in the case where
1622 * an abort was detected while receiving a packet,
1623 * but the abort did not last long enough to be
1624 * detected by zsh_xsint - this can happen since
1625 * the ZSRR0_BREAK is not latched. Since an abort
1626 * will automatically cause the SCC to enter
1627 * hunt mode, hopefully, the sync/hunt bit will be
1628 * set in this case (although if the interrupt is
1629 * sufficiently delayed, the SCC may have sync'ed
1630 * in again if it has detected a flag).
1631 */
1632 zss->sl_st.abort++;
1633 zsh_rxbad(zs, zss);
1634 }
1635
1636 if (x0 & s0 & ZSRR0_CTS) {
1637 if (zss->sl_txstate == TX_RTS) {
1638 if (!(zss->sl_flags & SF_FDXPTP)) {
1639 SCC_BIS(5, ZSWR5_TX_ENABLE);
1640 }
1641 (void) zsh_start(zs, zss);
1642 } else if ((zss->sl_mode.sm_config &
1643 (CONN_IBM | CONN_SIGNAL))) {
1644 zss->sl_flags &= ~SF_FLUSH_WQ;
1645 zsh_setmstat(zs, CS_CTS_UP);
1646 }
1647 }
1648
1649 /*
1650 * We don't care about CTS transitions unless we are in either
1651 * IBM or SIGNAL mode, or both. So, if we see CTS drop, and we
1652 * care, and we are not idle, send up a report message.
1653 */
1654 if ((x0 & ZSRR0_CTS) && ((s0 & ZSRR0_CTS) == 0) &&
1655 (zss->sl_txstate != TX_OFF) &&
1656 (zss->sl_mode.sm_config & (CONN_IBM | CONN_SIGNAL))) {
1657 SCC_BIC(15, ZSR15_CTS);
1658 zsh_setmstat(zs, CS_CTS_DOWN);
1659 zss->sl_flags &= ~SF_XMT_INPROG;
1660 zss->sl_flags |= SF_FLUSH_WQ;
1661 zss->sl_st.cts++;
1662 if (zss->sl_txstate != TX_IDLE)
1663 SCC_WRITE0(ZSWR0_SEND_ABORT);
1664 SCC_WRITE0(ZSWR0_RESET_ERRORS);
1665 SCC_WRITE0(ZSWR0_RESET_TXINT);
1666 zss->sl_wd_count = 0;
1667 zsh_txbad(zs, zss);
1668 }
1669 }
1670
1671
1672 /*
1673 * Receive interrupt service procedure
1674 */
1675 static void
zsh_rxint(struct zscom * zs)1676 zsh_rxint(struct zscom *zs)
1677 {
1678 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1679 register mblk_t *bp = zss->sl_ractb;
1680 unsigned char *rd_cur;
1681
1682 TRACE_1(TR_ZSH, TR_ZSH_RXINT, "zsh_rxint: zs = %p", zs);
1683
1684 if (((rd_cur = zs->zs_rd_cur) != NULL) && rd_cur < zs->zs_rd_lim) {
1685 *rd_cur++ = SCC_READDATA();
1686 zs->zs_rd_cur = rd_cur;
1687 return;
1688 }
1689
1690 if (!rd_cur) { /* Beginning of frame */
1691 if (!bp) {
1692 ZSH_ALLOCB(bp);
1693 zss->sl_ractb = bp;
1694 }
1695 zss->sl_rhead = bp;
1696 } else { /* end of data block should be cur==lim */
1697 bp->b_wptr = zs->zs_rd_cur;
1698 ZSH_ALLOCB(bp->b_cont);
1699 bp = zss->sl_ractb = bp->b_cont;
1700 }
1701 if (!bp) {
1702 zss->sl_st.nobuffers++;
1703 zsh_rxbad(zs, zss);
1704 return;
1705 }
1706 zs->zs_rd_cur = bp->b_wptr;
1707 zs->zs_rd_lim = bp->b_datap->db_lim;
1708 *zs->zs_rd_cur++ = SCC_READDATA(); /* Also resets interrupt */
1709 }
1710
1711
1712 /*
1713 * Special Receive Condition Interrupt routine
1714 */
1715 static void
zsh_srint(struct zscom * zs)1716 zsh_srint(struct zscom *zs)
1717 {
1718 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1719 register uchar_t s1;
1720 register uchar_t *rd_cur;
1721
1722 TRACE_1(TR_ZSH, TR_ZSH_SRINT, "zsh_srint: zs = %p", zs);
1723
1724 SCC_READ(1, s1);
1725
1726 if (s1 & ZSRR1_RXEOF) { /* end of frame */
1727 (void) SCC_READDATA();
1728 SCC_WRITE0(ZSWR0_RESET_ERRORS);
1729 if (s1 & ZSRR1_FE) { /* bad CRC */
1730 zss->sl_st.crc++;
1731 zsh_rxbad(zs, zss);
1732 return;
1733 }
1734
1735 if ((rd_cur = zs->zs_rd_cur) == NULL)
1736 return;
1737
1738 /*
1739 * Drop one CRC byte from length because it came in
1740 * before the special interrupt got here.
1741 */
1742 zss->sl_ractb->b_wptr = rd_cur - 1;
1743
1744 /*
1745 * put on done queue
1746 */
1747 ZSH_PUTQ(zss->sl_rhead);
1748 zss->sl_rhead = NULL;
1749 zss->sl_ractb = NULL;
1750 zs->zs_rd_cur = NULL;
1751 zs->zs_rd_lim = NULL;
1752 ZSSETSOFT(zs);
1753
1754 } else if (s1 & ZSRR1_DO) {
1755 (void) SCC_READDATA();
1756 SCC_WRITE0(ZSWR0_RESET_ERRORS);
1757 zss->sl_st.overrun++;
1758 zsh_rxbad(zs, zss);
1759 } else
1760 SCC_WRITE0(ZSWR0_RESET_ERRORS);
1761 }
1762
1763 /*
1764 * Handle a second stage interrupt.
1765 * Does mostly lower priority buffer management stuff.
1766 */
1767 static int
zsh_softint(struct zscom * zs)1768 zsh_softint(struct zscom *zs)
1769 {
1770 register struct syncline *zss;
1771 register queue_t *q;
1772 register mblk_t *mp, *tmp;
1773 register mblk_t *head = NULL, *tail = NULL;
1774 register int allocbcount = 0;
1775 int m_error;
1776
1777 TRACE_1(TR_ZSH, TR_ZSH_SOFT_START, "zsh_soft start: zs = %p", zs);
1778
1779 mutex_enter(zs->zs_excl);
1780 zss = (struct syncline *)zs->zs_priv;
1781 if (!zss || (q = zss->sl_stream.str_rq) == NULL) {
1782 mutex_exit(zs->zs_excl);
1783 return (0);
1784 }
1785 m_error = zss->sl_m_error;
1786
1787 zss->sl_m_error = 0;
1788
1789
1790 if (!zss->sl_mstat)
1791 zss->sl_mstat = allocb(sizeof (struct sl_status), BPRI_MED);
1792
1793 mutex_enter(zs->zs_excl_hi);
1794 if (zss->sl_flags & SF_FLUSH_WQ) {
1795 if (!(zss->sl_flags & SF_FDXPTP)) {
1796 zss->sl_flags &= ~SF_FLUSH_WQ;
1797 } else {
1798 register uchar_t s0;
1799
1800 s0 = SCC_READ0();
1801 if (s0 & ZSRR0_CTS) {
1802 zss->sl_rr0 |= ZSRR0_CTS;
1803 SCC_BIS(15, ZSR15_CTS);
1804 zss->sl_flags &= ~SF_FLUSH_WQ;
1805 zsh_setmstat(zs, CS_CTS_UP);
1806 }
1807 if (zss->sl_flags & SF_FLUSH_WQ) {
1808 mutex_exit(zs->zs_excl_hi);
1809 flushq(WR(q), FLUSHDATA);
1810 goto next;
1811 }
1812 }
1813 }
1814 mutex_exit(zs->zs_excl_hi);
1815
1816 next:
1817 for (;;) {
1818 ZSH_GETQ(mp);
1819 if (!mp)
1820 break;
1821
1822 if (mp->b_rptr == mp->b_wptr) {
1823 if (mp->b_datap->db_type == M_RSE) {
1824 allocbcount++;
1825 }
1826 freemsg(mp);
1827 continue;
1828 }
1829 if (mp->b_datap->db_type == M_DATA) {
1830 zss->sl_st.ichar += msgdsize(mp);
1831 zss->sl_st.ipack++;
1832 if (!(canputnext(q))) {
1833 zss->sl_st.ierror++;
1834 allocbcount++;
1835 freemsg(mp);
1836 continue;
1837 }
1838 } else if (mp->b_datap->db_type == M_PROTO) {
1839 if (!(canputnext(q))) {
1840 freemsg(mp);
1841 continue;
1842 }
1843 }
1844 if (!head) {
1845 allocbcount++;
1846 zss->sl_soft_active = 1;
1847 head = mp;
1848 } else {
1849 if (!tail)
1850 tail = head;
1851 tail->b_next = mp;
1852 tail = mp;
1853 }
1854 }
1855 if (allocbcount)
1856 ZSH_GETBLOCK(zs, allocbcount);
1857
1858 tmp = NULL;
1859 again:
1860 mutex_enter(zs->zs_excl_hi);
1861 if (!zss->sl_xstandby) {
1862 if (tmp) {
1863 zss->sl_xstandby = tmp;
1864 mutex_exit(zs->zs_excl_hi);
1865 } else {
1866 mutex_exit(zs->zs_excl_hi);
1867 if (tmp = getq(WR(q)))
1868 goto again;
1869 }
1870 } else {
1871 mutex_exit(zs->zs_excl_hi);
1872 if (tmp)
1873 (void) putbq(WR(q), tmp);
1874 }
1875
1876 mutex_exit(zs->zs_excl);
1877
1878 while (head) {
1879 if (!tail) {
1880 putnext(q, head);
1881 break;
1882 }
1883 mp = head;
1884 head = head->b_next;
1885 mp->b_next = NULL;
1886 putnext(q, mp);
1887
1888 }
1889
1890 if (m_error)
1891 (void) putnextctl1(q, M_ERROR, m_error);
1892
1893 zss->sl_soft_active = 0;
1894
1895 TRACE_1(TR_ZSH, TR_ZSH_SOFT_END, "zsh_soft end: zs = %p", zs);
1896
1897 return (0);
1898 }
1899
1900 /*
1901 * Initialization routine.
1902 * Sets Clock sources, baud rate, modes and miscellaneous parameters.
1903 */
1904 static int
zsh_program(struct zscom * zs,struct scc_mode * sm)1905 zsh_program(struct zscom *zs, struct scc_mode *sm)
1906 {
1907 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
1908 register struct zs_prog *zspp;
1909 register ushort_t tconst = 0;
1910 register int wr11 = 0;
1911 register int baud = 0;
1912 register int pll = 0;
1913 register int speed = 0;
1914 register int flags = ZSP_SYNC;
1915 int err = 0;
1916
1917 ZSSETSOFT(zs); /* get our house in order */
1918
1919 switch (sm->sm_txclock) {
1920 case TXC_IS_TXC:
1921 wr11 |= ZSWR11_TXCLK_TRXC;
1922 break;
1923 case TXC_IS_RXC:
1924 wr11 |= ZSWR11_TXCLK_RTXC;
1925 break;
1926 case TXC_IS_BAUD:
1927 wr11 |= ZSWR11_TXCLK_BAUD;
1928 wr11 |= ZSWR11_TRXC_OUT_ENA + ZSWR11_TRXC_XMIT;
1929 baud++;
1930 break;
1931 case TXC_IS_PLL:
1932 wr11 |= ZSWR11_TXCLK_DPLL;
1933 pll++;
1934 break;
1935 default:
1936 zss->sl_mode.sm_retval = SMERR_TXC;
1937 err = EINVAL;
1938 goto out;
1939 }
1940 switch (sm->sm_rxclock) {
1941 case RXC_IS_RXC:
1942 wr11 |= ZSWR11_RXCLK_RTXC;
1943 break;
1944 case RXC_IS_TXC:
1945 wr11 |= ZSWR11_RXCLK_TRXC;
1946 break;
1947 case RXC_IS_BAUD:
1948 wr11 |= ZSWR11_RXCLK_BAUD;
1949 baud++;
1950 break;
1951 case RXC_IS_PLL:
1952 wr11 |= ZSWR11_RXCLK_DPLL;
1953 pll++;
1954 break;
1955 default:
1956 zss->sl_mode.sm_retval = SMERR_RXC;
1957 err = EINVAL;
1958 goto out;
1959 }
1960 if (baud && pll) {
1961 zss->sl_mode.sm_retval = SMERR_PLL;
1962 err = EINVAL;
1963 goto out;
1964 }
1965 if (pll && !(sm->sm_config & CONN_NRZI)) {
1966 zss->sl_mode.sm_retval = SMERR_PLL;
1967 err = EINVAL;
1968 goto out;
1969 }
1970
1971 /*
1972 * If we're going to use the BRG and the speed we want is != 0...
1973 */
1974 if (baud && (speed = sm->sm_baudrate)) {
1975 tconst = (PCLK + speed) / (2 * speed) - 2;
1976 if (tconst == 0) {
1977 zss->sl_mode.sm_retval = SMERR_BAUDRATE;
1978 err = EINVAL;
1979 goto out;
1980 }
1981 sm->sm_baudrate = PCLK / (2 * ((int)tconst + 2));
1982 } else {
1983 tconst = 0; /* Stop BRG. Also quiesces pin 24. */
1984 }
1985
1986 if (pll) {
1987 if ((speed = sm->sm_baudrate * 32) != 0)
1988 tconst = (PCLK + speed) / (2 * speed) - 2;
1989 else
1990 tconst = 0;
1991 if (tconst == 0) {
1992 zss->sl_mode.sm_retval = SMERR_BAUDRATE;
1993 err = EINVAL;
1994 goto out;
1995 }
1996 speed = PCLK / (2 * ((int)tconst + 2));
1997 sm->sm_baudrate = speed / 32;
1998 flags |= ZSP_PLL;
1999 }
2000
2001 if ((sm->sm_config & (CONN_LPBK|CONN_ECHO)) == (CONN_LPBK|CONN_ECHO)) {
2002 zss->sl_mode.sm_retval = SMERR_LPBKS;
2003 err = EINVAL;
2004 goto out;
2005 }
2006 if (sm->sm_config & CONN_LPBK)
2007 flags |= ZSP_LOOP;
2008 if (sm->sm_config & CONN_NRZI)
2009 flags |= ZSP_NRZI;
2010 if (sm->sm_config & CONN_ECHO)
2011 flags |= ZSP_ECHO;
2012
2013 zspp = &zs_prog[zs->zs_unit];
2014
2015 zspp->zs = zs;
2016 zspp->flags = (uchar_t)flags;
2017 zspp->wr4 = ZSWR4_SDLC;
2018 zspp->wr11 = (uchar_t)wr11;
2019 zspp->wr12 = (uchar_t)(tconst & 0xff);
2020 zspp->wr13 = (uchar_t)((tconst >> 8) & 0xff);
2021 zspp->wr3 = (uchar_t)(ZSWR3_RX_ENABLE | ZSWR3_RXCRC_ENABLE |
2022 ZSWR3_RX_8);
2023 zspp->wr5 = (uchar_t)(ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_TXCRC_ENABLE);
2024
2025 if (zss->sl_flags & SF_FDXPTP) {
2026 zspp->wr5 |= ZSWR5_RTS;
2027 zss->sl_rr0 |= ZSRR0_CTS; /* Assume CTS is high */
2028 }
2029 if (sm->sm_config & CONN_IBM) {
2030 zspp->wr15 = (uchar_t)
2031 (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC | ZSR15_CTS);
2032 if (!(zss->sl_flags & SF_FDXPTP))
2033 zspp->wr15 &= ~ZSR15_CTS;
2034 } else {
2035 zspp->wr5 |= ZSWR5_TX_ENABLE;
2036 zspp->wr15 = (uchar_t)
2037 (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC);
2038 if (sm->sm_config & CONN_SIGNAL)
2039 zspp->wr15 |= ZSR15_CTS;
2040 }
2041
2042 zs_program(zspp);
2043 SCC_WRITE0(ZSWR0_RESET_STATUS); /* reset XS */
2044 SCC_WRITE0(ZSWR0_RESET_STATUS); /* reset XS */
2045 zss->sl_flags |= SF_INITIALIZED;
2046 bzero(&zss->sl_st, sizeof (struct sl_stats));
2047 bcopy(sm, &zss->sl_mode, sizeof (struct scc_mode));
2048 zss->sl_mode.sm_retval = 0; /* successful */
2049 out:
2050 return (err);
2051 }
2052
2053 /*
2054 * Function to store modem signal changes in sl_mstat field.
2055 * Note that these events are supposed to be so far apart in time that
2056 * we should always be able to send up the event and allocate a message
2057 * block before another one happens. If not, we'll overwrite this one.
2058 */
2059 static void
zsh_setmstat(struct zscom * zs,int event)2060 zsh_setmstat(struct zscom *zs, int event)
2061 {
2062 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
2063 register struct sl_status *mstat;
2064 register mblk_t *mp;
2065
2066 if (((mp = zss->sl_mstat) != NULL) &&
2067 (zss->sl_mode.sm_config & (CONN_SIGNAL))) {
2068 mstat = (struct sl_status *)mp->b_wptr;
2069 mstat->type = (zss->sl_mode.sm_config & CONN_IBM) ?
2070 SLS_LINKERR : SLS_MDMSTAT;
2071 mstat->status = event;
2072 gethrestime(&mstat->tstamp);
2073 mp->b_wptr += sizeof (struct sl_status);
2074 mp->b_datap->db_type = M_PROTO;
2075 ZSH_PUTQ(mp);
2076 zss->sl_mstat = NULL;
2077 ZSSETSOFT(zs);
2078 }
2079 }
2080
2081 /*
2082 * Received Bad Frame procedure
2083 */
2084 static void
zsh_rxbad(struct zscom * zs,struct syncline * zss)2085 zsh_rxbad(struct zscom *zs, struct syncline *zss)
2086 {
2087 /*
2088 * swallow bad characters
2089 */
2090 (void) SCC_READDATA();
2091 (void) SCC_READDATA();
2092 (void) SCC_READDATA();
2093
2094 SCC_BIS(3, ZSWR3_HUNT); /* enter hunt mode - ignores rest of frame */
2095
2096 zss->sl_st.ierror++;
2097
2098 /*
2099 * Free active receive message.
2100 */
2101 if (zss->sl_rhead) {
2102 zss->sl_rhead->b_wptr = zss->sl_rhead->b_rptr;
2103 zss->sl_rhead->b_datap->db_type = M_RSE;
2104 ZSH_FREEMSG(zss->sl_rhead);
2105 zss->sl_ractb = NULL;
2106 zs->zs_rd_cur = NULL;
2107 zs->zs_rd_lim = NULL;
2108 }
2109 if (zss->sl_rhead) {
2110 zss->sl_rhead = NULL;
2111 ZSH_ALLOCB(zss->sl_ractb);
2112 zs->zs_rd_cur = NULL;
2113 zs->zs_rd_lim = NULL;
2114 }
2115
2116 ZSSETSOFT(zs);
2117 }
2118
2119 /*
2120 * Transmit error procedure
2121 */
2122 static void
zsh_txbad(struct zscom * zs,struct syncline * zss)2123 zsh_txbad(struct zscom *zs, struct syncline *zss)
2124 {
2125 if (zss->sl_xhead) { /* free the message we were sending */
2126 zss->sl_xhead->b_wptr = zss->sl_xhead->b_rptr;
2127 ZSH_FREEMSG(zss->sl_xhead);
2128 zss->sl_xactb = NULL;
2129 zs->zs_wr_cur = NULL;
2130 zs->zs_wr_lim = NULL;
2131 }
2132 zss->sl_xhead = NULL;
2133
2134 if (!(zss->sl_flags & SF_FDXPTP)) {
2135 /*
2136 * drop RTS and our notion of CTS
2137 */
2138 SCC_BIC(5, ZSWR5_RTS);
2139 SCC_BIC(5, ZSWR5_TX_ENABLE);
2140 zss->sl_rr0 &= ~ZSRR0_CTS;
2141 }
2142 zss->sl_txstate = TX_IDLE;
2143 if (!(zss->sl_flags & SF_PHONY))
2144 zss->sl_st.oerror++;
2145 }
2146
2147 /*
2148 * Transmitter watchdog timeout routine
2149 */
2150 static void
zsh_watchdog(void * arg)2151 zsh_watchdog(void *arg)
2152 {
2153 struct zscom *zs = arg;
2154 struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
2155 queue_t *wq;
2156 mblk_t *mp;
2157 int warning = 0;
2158 uchar_t s0;
2159 int do_flushwq = 0;
2160
2161 /*
2162 * The main reason for this routine is because, under some
2163 * circumstances, a transmit interrupt may get lost (ie., if
2164 * underrun occurs after the last character has been sent, and
2165 * the tx interrupt following the abort gets scheduled before
2166 * the current tx interrupt has been serviced). Transmit can
2167 * also get hung if the cable is pulled out and the clock was
2168 * coming in from the modem.
2169 */
2170
2171 mutex_enter(zs->zs_excl);
2172 if (zss->sl_stream.str_rq)
2173 wq = WR(zss->sl_stream.str_rq);
2174 else {
2175 mutex_exit(zs->zs_excl);
2176 return; /* guard against close/callback race */
2177 }
2178
2179 mutex_enter(zs->zs_excl_hi);
2180 if (!(zss->sl_flags & SF_XMT_INPROG) && wq->q_first) {
2181 zss->sl_flags |= SF_XMT_INPROG;
2182 if ((zss->sl_flags & SF_FDXPTP) ||
2183 zsh_hdp_ok_or_rts_state(zs, zss))
2184 (void) zsh_start(zs, zss);
2185 goto end_watchdog;
2186 }
2187
2188 if (zss->sl_wd_count-- > 0)
2189 goto end_watchdog;
2190
2191 if (zss->sl_flags & SF_FLUSH_WQ) {
2192 if (!(zss->sl_flags & SF_FDXPTP))
2193 zss->sl_flags &= ~SF_FLUSH_WQ;
2194 else {
2195 s0 = SCC_READ0();
2196 if (s0 & ZSRR0_CTS) {
2197 zss->sl_rr0 |= ZSRR0_CTS;
2198 SCC_BIS(15, ZSR15_CTS);
2199 zss->sl_flags &= ~SF_FLUSH_WQ;
2200 zsh_setmstat(zs, CS_CTS_UP);
2201 }
2202 }
2203 }
2204
2205 switch (zss->sl_txstate) {
2206
2207 case TX_ABORTED:
2208 /*
2209 * Transmitter was hung ... try restarting it.
2210 */
2211 if (zss->sl_flags & SF_FDXPTP) {
2212 zss->sl_flags |= SF_XMT_INPROG;
2213 (void) zsh_start(zs, zss);
2214 } else
2215 do_flushwq = 1;
2216 break;
2217
2218 case TX_ACTIVE:
2219 case TX_CRC:
2220 /*
2221 * Transmit is hung for some reason. Reset tx interrupt.
2222 * Flush transmit fifo by sending an abort command
2223 * which also sets the Underrun/EOM latch in WR0 and in
2224 * turn generates an External Status interrupt that
2225 * will reset the necessary message buffer pointers.
2226 * The watchdog timer will cycle again to allow the SCC
2227 * to settle down after the abort command. The next
2228 * time through we'll see that the state is now TX_ABORTED
2229 * and call zsh_start to grab a new message.
2230 */
2231 if (--zss->sl_wd_count <= 0) {
2232 SCC_WRITE0(ZSWR0_SEND_ABORT);
2233 SCC_WRITE0(ZSWR0_RESET_ERRORS);
2234 SCC_WRITE0(ZSWR0_RESET_TXINT);
2235 zsh_txbad(zs, zss);
2236 zss->sl_txstate = TX_ABORTED; /* must be after txbad */
2237 warning = 1;
2238 }
2239 break;
2240
2241 case TX_RTS:
2242 /*
2243 * Timer expired after we raised RTS. CTS never came up.
2244 */
2245 zss->sl_st.cts++;
2246
2247 zsh_setmstat(zs, CS_CTS_TO);
2248 zss->sl_flags &= ~SF_XMT_INPROG;
2249 zss->sl_flags |= SF_FLUSH_WQ;
2250 ZSSETSOFT(zs);
2251 break;
2252
2253 default:
2254 /*
2255 * If we time out in an inactive state we set a soft
2256 * interrupt. This will call zsh_start which will
2257 * clear SF_XMT_INPROG if the queue is empty.
2258 */
2259 break;
2260 }
2261 end_watchdog:
2262 if (zss->sl_txstate != TX_OFF) {
2263 mutex_exit(zs->zs_excl_hi);
2264 zss->sl_wd_id = timeout(zsh_watchdog, zs, SIO_WATCHDOG_TICK);
2265 } else {
2266 zss->sl_wd_id = 0; /* safety */
2267 mutex_exit(zs->zs_excl_hi);
2268 }
2269 if (warning || do_flushwq) {
2270 flushq(wq, FLUSHDATA);
2271 mutex_enter(zs->zs_excl_hi);
2272 if ((mp = zss->sl_xstandby) != NULL)
2273 zss->sl_xstandby = NULL;
2274 mutex_exit(zs->zs_excl_hi);
2275 if (mp)
2276 freemsg(mp);
2277 }
2278 mutex_exit(zs->zs_excl);
2279 if (warning)
2280 cmn_err(CE_WARN, "zsh%x: transmit hung", zs->zs_unit);
2281 }
2282
2283 static void
zsh_callback(void * arg)2284 zsh_callback(void *arg)
2285 {
2286 struct zscom *zs = arg;
2287 struct syncline *zss = (struct syncline *)&zs->zs_priv_str;
2288 int tmp = ZSH_MAX_RSTANDBY;
2289
2290 mutex_enter(zs->zs_excl);
2291 if (zss->sl_bufcid) {
2292 zss->sl_bufcid = 0;
2293 ZSH_GETBLOCK(zs, tmp);
2294 }
2295 mutex_exit(zs->zs_excl);
2296 }
2297