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