zs.c revision 1.1 1 /* $NetBSD: zs.c,v 1.1 1995/07/25 23:12:07 chuck Exp $ */
2
3 /*
4 * Copyright (c) 1993 Paul Mackerras.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software withough specific prior written permission
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*
30 * Serial I/O via an SCC,
31 */
32 #include <sys/param.h>
33 #include <sys/conf.h>
34 #include <sys/ioctl.h>
35 #include <sys/proc.h>
36 #include <sys/user.h>
37 #include <sys/tty.h>
38 #include <sys/uio.h>
39 #include <sys/callout.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/syslog.h>
43 #include <sys/fcntl.h>
44 #include <sys/device.h>
45 #include <machine/cpu.h>
46 #include <dev/cons.h>
47 #include <mvme68k/dev/iio.h>
48 #include <mvme68k/dev/scc.h>
49 #include <mvme68k/dev/pccreg.h>
50
51 #include "zs.h"
52 #if NZS > 0
53
54 /*#define PCLK_FREQ 8333333*/
55 #undef PCLK_FREQ /* XXXCDC */
56 #define PCLK_FREQ 5000000
57 #define NZSLINE (NZS*2)
58
59 #define RECV_BUF 512
60 #define ERROR_DET 0xed
61
62 #define TS_DRAIN TS_FLUSH/* waiting for output to drain */
63
64 #define splzs() spl4()
65
66 struct zs {
67 short flags; /* see below */
68 char rr0; /* holds previous CTS, DCD state */
69 unsigned char imask; /* mask for input chars */
70 int nzs_open; /* # opens as /dev/zsn */
71 int nkbd_open; /* # opens as a keyboard */
72 int gsp_unit; /* unit to send kbd chars to */
73 struct tty *tty; /* link to tty structure */
74 struct sccregs scc; /* SCC shadow registers */
75 u_char *rcv_get;
76 u_char *rcv_put;
77 u_char *rcv_end;
78 volatile int rcv_count;
79 int rcv_len;
80 char *send_ptr;
81 int send_count;
82 int sent_count;
83 volatile char modem_state;
84 volatile char modem_change;
85 volatile short hflags;
86 char rcv_buf[RECV_BUF];
87 };
88
89 /* Bits in flags */
90 #define ZS_SIDEA 1
91 #define ZS_INITED 2
92 #define ZS_INTEN 4
93 #define ZS_RESET 8
94 #define ZS_CONSOLE 0x20
95
96 /* Bits in hflags */
97 #define ZH_OBLOCK 1 /* output blocked by CTS */
98 #define ZH_SIRQ 2 /* soft interrupt request */
99 #define ZH_TXING 4 /* transmitter active */
100 #define ZH_RXOVF 8 /* receiver buffer overflow */
101
102 struct zssoftc {
103 struct device dev;
104 struct zs zs[2];
105 };
106
107 struct tty *zs_tty[NZSLINE];
108
109 struct termios zs_cons_termios;
110 int zs_cons_unit = 0;
111 int zs_is_console = 0;
112 struct sccregs *zs_cons_scc;
113
114 int zsopen __P((dev_t, int, int, struct proc *));
115 void zsstart __P((struct tty *));
116 int zsparam __P((struct tty *, struct termios *));
117 int zsirq __P((int unit));
118 void zs_softint __P((void));
119
120 unsigned long sir_zs;
121 void zs_softint();
122
123 #define zsunit(dev) (minor(dev) >> 1)
124 #define zsside(dev) (minor(dev) & 1)
125
126 /*
127 * Autoconfiguration stuff.
128 */
129 void zsattach __P((struct device *, struct device *, void *));
130 int zsmatch __P((struct device *, void *, void *));
131
132 struct cfdriver zscd = {
133 NULL, "zs", zsmatch, zsattach, DV_TTY, sizeof(struct zssoftc), 0
134 };
135
136 int
137 zsmatch(parent, vcf, args)
138 struct device *parent;
139 void *vcf, *args;
140 {
141 struct cfdata *cf = vcf;
142
143 return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
144 }
145
146 void
147 zsattach(parent, self, args)
148 struct device *parent, *self;
149 void *args;
150 {
151 struct zssoftc *dv;
152 struct zs *zp, *zc;
153 u_char ir;
154 volatile struct scc *scc;
155 int zs_level = IIO_CFLOC_LEVEL(self->dv_cfdata);
156
157 iio_print(self->dv_cfdata);
158
159 /* connect the interrupt */
160 dv = (struct zssoftc *) self;
161 pccintr_establish(PCCV_ZS, zsirq, zs_level, self->dv_unit);
162 /* XXXCDC: needs some work to handle zs1 */
163
164 zp = &dv->zs[0];
165 scc = (volatile struct scc *) IIO_CFLOC_ADDR(self->dv_cfdata);
166
167 if (zs_is_console && self->dv_unit == zsunit(zs_cons_unit)) {
168 /* SCC is the console - it's already reset */
169 zc = zp + zsside(zs_cons_unit);
170 zc->scc = *zs_cons_scc;
171 zs_cons_scc = &zc->scc;
172 zc->flags |= ZS_CONSOLE;
173 } else {
174 /* reset the SCC */
175 scc->cr = 0;
176 scc->cr = 9;
177 scc->cr = 0xC0; /* hardware reset of SCC, both sides */
178 }
179
180 /* side A */
181 zp->scc.s_adr = scc + 1;
182 zp->flags |= ZS_SIDEA | ZS_RESET;
183
184 /* side B */
185 ++zp;
186 zp->scc.s_adr = scc;
187 zp->flags |= ZS_RESET;
188
189 if (sir_zs == 0)
190 sir_zs = allocate_sir(zs_softint, 0);
191 printf("\n");
192
193 ir = sys_pcc->zs_int;
194 if ((ir & PCC_IMASK) != 0 && (ir & PCC_IMASK) != zs_level)
195 panic("zs configured at different IPLs");
196 sys_pcc->zs_int = zs_level | PCC_IENABLE | PCC_ZSEXTERN;
197 }
198
199 zs_ttydef(struct zs *zp)
200 {
201 struct tty *tp = zp->tty;
202
203 if ((zp->flags & ZS_CONSOLE) == 0) {
204 tp->t_iflag = TTYDEF_IFLAG;
205 tp->t_oflag = TTYDEF_OFLAG;
206 tp->t_cflag = TTYDEF_CFLAG;
207 tp->t_lflag = TTYDEF_LFLAG;
208 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
209 } else
210 tp->t_termios = zs_cons_termios;
211 ttychars(tp);
212 ttsetwater(tp);
213 tp->t_oproc = zsstart;
214 tp->t_param = zsparam;
215
216 zp->rcv_get = zp->rcv_buf;
217 zp->rcv_put = zp->rcv_buf;
218 zp->rcv_end = zp->rcv_buf + sizeof(zp->rcv_buf);
219 zp->rcv_len = sizeof(zp->rcv_buf) / 2;
220 }
221
222 struct tty *
223 zstty(dev)
224 dev_t dev;
225 {
226
227 if (minor(dev) < NZSLINE)
228 return (zs_tty[minor(dev)]);
229
230 return (NULL);
231 }
232
233 /* ARGSUSED */
234 zsopen(dev_t dev, int flag, int mode, struct proc * p)
235 {
236 register struct tty *tp;
237 int error;
238 struct zs *zp;
239 struct zssoftc *dv;
240
241 if (zsunit(dev) > zscd.cd_ndevs
242 || (dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)]) == NULL)
243 return ENODEV;
244
245 zp = &dv->zs[zsside(dev)];
246 if (zp->tty == NULL) {
247 zp->tty = ttymalloc();
248 zs_ttydef(zp);
249 if (minor(dev) < NZSLINE)
250 zs_tty[minor(dev)] = zp->tty;
251 }
252 tp = zp->tty;
253 tp->t_dev = dev;
254
255 if ((tp->t_state & TS_ISOPEN) == 0) {
256 tp->t_state |= TS_WOPEN;
257 zs_init(zp);
258 if ((zp->modem_state & SCC_DCD) != 0)
259 tp->t_state |= TS_CARR_ON;
260 } else
261 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
262 return (EBUSY);
263
264 error = ((*linesw[tp->t_line].l_open) (dev, tp));
265
266 if (error == 0)
267 ++zp->nzs_open;
268 return error;
269 }
270
271 int
272 zsclose(dev, flag, mode, p)
273 dev_t dev;
274 int flag, mode;
275 struct proc *p;
276 {
277 struct zs *zp;
278 struct tty *tp;
279 struct zssoftc *dv;
280 int s;
281
282 if (zsunit(dev) > zscd.cd_ndevs
283 || (dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)]) == NULL)
284 return ENODEV;
285 zp = &dv->zs[zsside(dev)];
286 tp = zp->tty;
287
288 if (zp->nkbd_open == 0) {
289 (*linesw[tp->t_line].l_close) (tp, flag);
290 s = splzs();
291 if ((zp->flags & ZS_CONSOLE) == 0 && (tp->t_cflag & HUPCL) != 0)
292 ZBIC(&zp->scc, 5, 0x82); /* drop DTR, RTS */
293 ZBIC(&zp->scc, 3, 1); /* disable receiver */
294 splx(s);
295 ttyclose(tp);
296 }
297 zp->nzs_open = 0;
298 return (0);
299 }
300
301 /*ARGSUSED*/
302 zsread(dev, uio, flag)
303 dev_t dev;
304 struct uio *uio;
305 int flag;
306 {
307 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)];
308 struct zs *zp = &dv->zs[zsside(dev)];
309 struct tty *tp = zp->tty;
310
311 return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
312 }
313
314 /*ARGSUSED*/
315 zswrite(dev, uio, flag)
316 dev_t dev;
317 struct uio *uio;
318 int flag;
319 {
320 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)];
321 struct zs *zp = &dv->zs[zsside(dev)];
322 struct tty *tp = zp->tty;
323
324 return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
325 }
326
327 zsioctl(dev, cmd, data, flag, p)
328 dev_t dev;
329 caddr_t data;
330 int cmd, flag;
331 struct proc *p;
332 {
333 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(dev)];
334 struct zs *zp = &dv->zs[zsside(dev)];
335 struct tty *tp = zp->tty;
336 register struct sccregs *scc = &zp->scc;
337 register int error, s;
338
339 error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag, p);
340 if (error >= 0)
341 return (error);
342 error = ttioctl(tp, cmd, data, flag, p);
343 if (error >= 0)
344 return (error);
345 error = 0;
346 s = splzs();
347 switch (cmd) {
348 case TIOCSDTR:
349 ZBIS(scc, 5, 0x80);
350 break;
351 case TIOCCDTR:
352 ZBIC(scc, 5, 0x80);
353 break;
354 case TIOCSBRK:
355 splx(s);
356 zs_drain(zp);
357 s = splzs();
358 ZBIS(scc, 5, 0x10);
359 spltty();
360 zs_unblock(tp);
361 break;
362 case TIOCCBRK:
363 ZBIC(scc, 5, 0x10);
364 break;
365 case TIOCMGET:
366 *(int *) data = zscc_mget(scc);
367 break;
368 case TIOCMSET:
369 zscc_mset(scc, *(int *) data);
370 zscc_mclr(scc, ~*(int *) data);
371 break;
372 case TIOCMBIS:
373 zscc_mset(scc, *(int *) data);
374 break;
375 case TIOCMBIC:
376 zscc_mclr(scc, *(int *) data);
377 break;
378 default:
379 error = ENOTTY;
380 }
381 splx(s);
382 return error;
383 }
384
385 zsparam(tp, t)
386 struct tty *tp;
387 struct termios *t;
388 {
389 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(tp->t_dev)];
390 struct zs *zp = &dv->zs[zsside(tp->t_dev)];
391 register int s;
392
393 zs_drain(zp);
394 s = splzs();
395 zp->imask = zscc_params(&zp->scc, t);
396 tp->t_ispeed = t->c_ispeed;
397 tp->t_ospeed = t->c_ospeed;
398 tp->t_cflag = t->c_cflag;
399 if ((tp->t_cflag & CCTS_OFLOW) == 0)
400 zp->hflags &= ~ZH_OBLOCK;
401 else
402 if ((zp->modem_state & 0x20) == 0)
403 zp->hflags |= ZH_OBLOCK;
404 spltty();
405 zs_unblock(tp);
406 splx(s);
407 return 0;
408 }
409
410 void
411 zsstart(tp)
412 struct tty *tp;
413 {
414 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(tp->t_dev)];
415 struct zs *zp = &dv->zs[zsside(tp->t_dev)];
416 register int s, n;
417
418 s = spltty();
419 if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_DRAIN)) == 0) {
420 n = ndqb(&tp->t_outq, 0);
421 if (n > 0) {
422 tp->t_state |= TS_BUSY;
423 splzs();
424 zp->hflags |= ZH_TXING;
425 zp->send_ptr = tp->t_outq.c_cf;
426 zp->send_count = n;
427 zp->sent_count = 0;
428 zs_txint(zp);
429 spltty();
430 }
431 }
432 splx(s);
433 }
434
435 zsstop(struct tty * tp, int flag)
436 {
437 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(tp->t_dev)];
438 struct zs *zp = &dv->zs[zsside(tp->t_dev)];
439 int s, n;
440
441 s = splzs();
442 zp->send_count = 0;
443 n = zp->sent_count;
444 zp->sent_count = 0;
445 if ((tp->t_state & TS_BUSY) != 0 && (flag & FWRITE) == 0) {
446 tp->t_state &= ~TS_BUSY;
447 spltty();
448 ndflush(&tp->t_outq, n);
449 if (tp->t_outq.c_cc <= tp->t_lowat) {
450 if (tp->t_state & TS_ASLEEP) {
451 tp->t_state &= ~TS_ASLEEP;
452 wakeup((caddr_t) & tp->t_outq);
453 }
454 selwakeup(&tp->t_wsel);
455 }
456 }
457 splx(s);
458 }
459
460 zs_init(zp)
461 struct zs *zp;
462 {
463 register int s;
464
465 s = splzs();
466 zscc_init(zp, &zp->tty->t_termios);
467 zp->rr0 = zp->modem_state = ZREAD0(&zp->scc);
468 ZBIS(&zp->scc, 1, 0x13);/* ints on tx, rx and ext/status */
469 ZBIS(&zp->scc, 9, 8); /* enable ints */
470 zp->flags |= ZS_INTEN;
471 splx(s);
472 }
473
474 zscc_init(zp, par)
475 struct zs *zp;
476 struct termios *par;
477 {
478 struct sccregs *scc;
479
480 scc = &zp->scc;
481 ZWRITE(scc, 2, 0);
482 ZWRITE(scc, 10, 0);
483 ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
484 ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
485 zp->imask = zscc_params(scc, par);
486 ZBIS(scc, 5, 0x82); /* set DTR and RTS */
487 zp->flags |= ZS_INITED;
488 }
489
490 int
491 zscc_params(scc, par)
492 struct sccregs *scc;
493 struct termios *par;
494 {
495 unsigned divisor, speed;
496 int spd, imask, ints;
497
498 speed = par->c_ospeed;
499 if (speed == 0) {
500 /* disconnect - drop DTR & RTS, disable receiver */
501 ZBIC(scc, 5, 0x82);
502 ZBIC(scc, 3, 1);
503 return 0xFF;
504 }
505 if ((par->c_cflag & CREAD) == 0)
506 ZBIC(scc, 3, 1);/* disable receiver */
507 divisor = (PCLK_FREQ / 32 + (speed >> 1)) / speed - 2;
508 ZWRITE(scc, 12, divisor);
509 ZWRITE(scc, 13, divisor >> 8);
510 switch (par->c_cflag & CSIZE) {
511 case CS5:
512 spd = 0;
513 imask = 0x1F;
514 break;
515 case CS6:
516 spd = 0x40;
517 imask = 0x3F;
518 break;
519 case CS7:
520 spd = 0x20;
521 imask = 0x7F;
522 break;
523 default:
524 spd = 0x60;
525 imask = 0xFF;
526 }
527 ZWRITE(scc, 5, (scc->s_val[5] & ~0x60) | spd);
528 ZWRITE(scc, 3, (scc->s_val[3] & ~0xC0) | (spd << 1));
529 spd = par->c_cflag & CSTOPB ? 8 : 0;
530 spd |= par->c_cflag & PARENB ? par->c_cflag & PARODD ? 1 : 3 : 0;
531 ZWRITE(scc, 4, 0x44 | spd);
532 ZBIS(scc, 5, 8); /* enable transmitter */
533 if ((par->c_cflag & CREAD) != 0)
534 ZBIS(scc, 3, 1);/* enable receiver */
535 ints = 0;
536 if ((par->c_cflag & CLOCAL) == 0)
537 ints |= SCC_DCD;
538 if ((par->c_cflag & CCTS_OFLOW) != 0)
539 ints |= SCC_CTS;
540 ZWRITE(scc, 15, ints);
541 return imask;
542 }
543
544 zscc_mget(register struct sccregs * scc)
545 {
546 int bits = 0, rr0;
547
548 if ((scc->s_val[3] & SCC_RCVEN) != 0)
549 bits |= TIOCM_LE;
550 if ((scc->s_val[5] & SCC_DTR) != 0)
551 bits |= TIOCM_DTR;
552 if ((scc->s_val[5] & SCC_RTS) != 0)
553 bits |= TIOCM_RTS;
554 rr0 = ZREAD0(scc);
555 if ((rr0 & SCC_CTS) != 0)
556 bits |= TIOCM_CTS;
557 if ((rr0 & SCC_DCD) != 0)
558 bits |= TIOCM_CAR;
559 return bits;
560 }
561
562 zscc_mset(register struct sccregs * scc, int bits)
563 {
564 if ((bits & TIOCM_LE) != 0)
565 ZBIS(scc, 3, SCC_RCVEN);
566 if ((bits & TIOCM_DTR) != 0)
567 ZBIS(scc, 5, SCC_DTR);
568 if ((bits & TIOCM_RTS) != 0)
569 ZBIS(scc, 5, SCC_RTS);
570 }
571
572 zscc_mclr(register struct sccregs * scc, int bits)
573 {
574 if ((bits & TIOCM_LE) != 0)
575 ZBIC(scc, 3, SCC_RCVEN);
576 if ((bits & TIOCM_DTR) != 0)
577 ZBIC(scc, 5, TIOCM_DTR);
578 if ((bits & TIOCM_RTS) != 0)
579 ZBIC(scc, 5, SCC_RTS);
580 }
581
582 zs_drain(register struct zs * zp)
583 {
584 register int s;
585
586 zp->tty->t_state |= TS_DRAIN;
587 /* wait for Tx buffer empty and All sent bits to be set */
588 s = splzs();
589 while ((ZREAD0(&zp->scc) & SCC_TXRDY) == 0
590 || (ZREAD(&zp->scc, 1) & 1) == 0) {
591 splx(s);
592 DELAY(100);
593 s = splzs();
594 }
595 splx(s);
596 }
597
598 zs_unblock(register struct tty * tp)
599 {
600 tp->t_state &= ~TS_DRAIN;
601 if (tp->t_outq.c_cc != 0)
602 zsstart(tp);
603 }
604
605 /*
606 * Hardware interrupt from an SCC.
607 */
608 int
609 zsirq(int unit)
610 {
611 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[unit];
612 register struct zs *zp = &dv->zs[0];
613 register int ipend, x;
614 register volatile struct scc *scc;
615
616 x = splzs();
617 scc = zp->scc.s_adr;
618 scc->cr = 3; /* read int pending from A side */
619 DELAY(5);
620 ipend = scc->cr;
621 if ((ipend & 0x20) != 0)
622 zs_rxint(zp);
623 if ((ipend & 0x10) != 0)
624 zs_txint(zp);
625 if ((ipend & 0x8) != 0)
626 zs_extint(zp);
627 ++zp; /* now look for B side ints */
628 if ((ipend & 0x4) != 0)
629 zs_rxint(zp);
630 if ((ipend & 0x2) != 0)
631 zs_txint(zp);
632 if ((ipend & 0x1) != 0)
633 zs_extint(zp);
634 splx(x);
635 return ipend != 0;
636 }
637
638 zs_txint(register struct zs * zp)
639 {
640 struct tty *tp = zp->tty;
641 struct sccregs *scc;
642 int c;
643 u_char *get;
644
645 scc = &zp->scc;
646 ZWRITE0(scc, 0x28); /* reset Tx interrupt */
647 if ((zp->hflags & ZH_OBLOCK) == 0) {
648 get = zp->send_ptr;
649 while ((ZREAD0(scc) & SCC_TXRDY) != 0 && zp->send_count > 0) {
650 c = *get++;
651 ZWRITED(scc, c);
652 --zp->send_count;
653 ++zp->sent_count;
654 }
655 zp->send_ptr = get;
656 if (zp->send_count == 0 && (zp->hflags & ZH_TXING) != 0) {
657 zp->hflags &= ~ZH_TXING;
658 zp->hflags |= ZH_SIRQ;
659 setsoftint(sir_zs);
660 }
661 }
662 }
663
664 zs_rxint(register struct zs * zp)
665 {
666 register int stat, c, n, extra;
667 u_char *put;
668
669 put = zp->rcv_put;
670 n = zp->rcv_count;
671 for (;;) {
672 if ((ZREAD0(&zp->scc) & SCC_RXFULL) == 0) /* check Rx full */
673 break;
674 stat = ZREAD(&zp->scc, 1) & 0x70;
675 c = ZREADD(&zp->scc) & zp->imask;
676 /* stat encodes parity, overrun, framing errors */
677 if (stat != 0)
678 ZWRITE0(&zp->scc, 0x30); /* reset error */
679 if ((zp->hflags & ZH_RXOVF) != 0) {
680 zp->hflags &= ~ZH_RXOVF;
681 stat |= 0x20;
682 }
683 extra = (stat != 0 || c == ERROR_DET) ? 2 : 0;
684 if (n + extra + 1 < zp->rcv_len) {
685 if (extra != 0) {
686 *put++ = ERROR_DET;
687 if (put >= zp->rcv_end)
688 put = zp->rcv_buf;
689 *put++ = stat;
690 if (put >= zp->rcv_end)
691 put = zp->rcv_buf;
692 n += 2;
693 }
694 *put++ = c;
695 if (put >= zp->rcv_end)
696 put = zp->rcv_buf;
697 ++n;
698 } else
699 zp->hflags |= ZH_RXOVF;
700 }
701 if (n > zp->rcv_count) {
702 zp->rcv_put = put;
703 zp->rcv_count = n;
704 zp->hflags |= ZH_SIRQ;
705 setsoftint(sir_zs);
706 }
707 }
708
709 /* Ext/status interrupt */
710 zs_extint(register struct zs * zp)
711 {
712 int rr0;
713 struct tty *tp = zp->tty;
714
715 rr0 = ZREAD0(&zp->scc);
716 ZWRITE0(&zp->scc, 0x10);/* reset ext/status int */
717 if ((tp->t_cflag & CCTS_OFLOW) != 0) {
718 if ((rr0 & 0x20) == 0)
719 zp->hflags |= ZH_OBLOCK;
720 else {
721 zp->hflags &= ~ZH_OBLOCK;
722 if ((rr0 & SCC_TXRDY) != 0)
723 zs_txint(zp);
724 }
725 }
726 zp->modem_change |= rr0 ^ zp->modem_state;
727 zp->modem_state = rr0;
728 zp->hflags |= ZH_SIRQ;
729 setsoftint(sir_zs);
730 }
731
732 void
733 zs_softint()
734 {
735 int s, n, n0, c, stat, rr0;
736 struct zs *zp;
737 struct tty *tp;
738 u_char *get;
739 int unit, side;
740
741 s = splzs();
742 for (unit = 0; unit < zscd.cd_ndevs; ++unit) {
743 if (zscd.cd_devs[unit] == NULL)
744 continue;
745 zp = &((struct zssoftc *) zscd.cd_devs[unit])->zs[0];
746 for (side = 0; side < 2; ++side, ++zp) {
747 if ((zp->hflags & ZH_SIRQ) == 0)
748 continue;
749 zp->hflags &= ~ZH_SIRQ;
750 tp = zp->tty;
751
752 /* check for tx done */
753 spltty();
754 if (tp != NULL && zp->send_count == 0
755 && (tp->t_state & TS_BUSY) != 0) {
756 tp->t_state &= ~(TS_BUSY | TS_FLUSH);
757 ndflush(&tp->t_outq, zp->sent_count);
758 if (tp->t_outq.c_cc <= tp->t_lowat) {
759 if (tp->t_state & TS_ASLEEP) {
760 tp->t_state &= ~TS_ASLEEP;
761 wakeup((caddr_t) & tp->t_outq);
762 }
763 selwakeup(&tp->t_wsel);
764 }
765 if (tp->t_line != 0)
766 (*linesw[tp->t_line].l_start) (tp);
767 else
768 zsstart(tp);
769 }
770 splzs();
771
772 /* check for received characters */
773 get = zp->rcv_get;
774 while (zp->rcv_count > 0) {
775 c = *get++;
776 if (get >= zp->rcv_end)
777 get = zp->rcv_buf;
778 if (c == ERROR_DET) {
779 stat = *get++;
780 if (get >= zp->rcv_end)
781 get = zp->rcv_buf;
782 c = *get++;
783 if (get >= zp->rcv_end)
784 get = zp->rcv_buf;
785 zp->rcv_count -= 3;
786 } else {
787 stat = 0;
788 --zp->rcv_count;
789 }
790 spltty();
791 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
792 continue;
793 if (zp->nzs_open == 0) {
794 #ifdef notdef
795 if (stat == 0)
796 kbd_newchar(zp->gsp_unit, c);
797 #endif
798 } else {
799 if ((stat & 0x10) != 0)
800 c |= TTY_PE;
801 if ((stat & 0x20) != 0) {
802 log(LOG_WARNING, "zs: fifo overflow\n");
803 c |= TTY_FE; /* need some error for
804 * slip stuff */
805 }
806 if ((stat & 0x40) != 0)
807 c |= TTY_FE;
808 (*linesw[tp->t_line].l_rint) (c, tp);
809 }
810 splzs();
811 }
812 zp->rcv_get = get;
813
814 /* check for modem lines changing */
815 while (zp->modem_change != 0 || zp->modem_state != zp->rr0) {
816 rr0 = zp->rr0 ^ zp->modem_change;
817 zp->modem_change = rr0 ^ zp->modem_state;
818
819 /* Check if DCD (carrier detect) has changed */
820 if (tp != NULL && (rr0 & 8) != (zp->rr0 & 8)) {
821 spltty();
822 ttymodem(tp, rr0 & 8);
823 /* XXX possibly should disable line if
824 * return value is 0 */
825 splzs();
826 }
827 zp->rr0 = rr0;
828 }
829 }
830 }
831 splx(s);
832 }
833
834 /*
835 * Routines to divert an SCC channel to the input side of /dev/gsp
836 * for the keyboard.
837 */
838 int
839 zs_kbdopen(int unit, int gsp_unit, struct termios * tiop, struct proc * p)
840 {
841 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(unit)];
842 struct zs *zp = &dv->zs[zsside(unit)];
843 int error;
844
845 error = zsopen(unit, 0, 0, p);
846 if (error != 0)
847 return error;
848 ++zp->nkbd_open;
849 --zp->nzs_open;
850 zsparam(zp->tty, tiop);
851 zp->gsp_unit = gsp_unit;
852 return 0;
853 }
854
855 void
856 zs_kbdclose(int unit)
857 {
858 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(unit)];
859 struct zs *zp = &dv->zs[zsside(unit)];
860
861 zp->nkbd_open = 0;
862 if (zp->nzs_open == 0)
863 zsclose(unit, 0, 0, 0);
864 }
865
866 void
867 zs_kbdput(int unit, int c)
868 {
869 struct zssoftc *dv = (struct zssoftc *) zscd.cd_devs[zsunit(unit)];
870 struct zs *zp = &dv->zs[zsside(unit)];
871 struct tty *tp = zp->tty;
872
873 putc(c, &tp->t_outq);
874 zsstart(tp);
875 }
876
877 /*
878 * Routines for using side A of the first SCC as a console.
879 */
880
881 /* probe for the SCC; should check hardware */
882 zscnprobe(cp)
883 struct consdev *cp;
884 {
885 int maj;
886 char *prom_cons;
887 extern char *prom_getvar();
888
889 /* locate the major number */
890 for (maj = 0; maj < nchrdev; maj++)
891 if (cdevsw[maj].d_open == zsopen)
892 break;
893
894 /* initialize required fields */
895 cp->cn_dev = makedev(maj, 0);
896 cp->cn_pri = CN_NORMAL;
897
898 return 1;
899 }
900
901 /* initialize the keyboard for use as the console */
902 struct termios zscn_termios = {
903 TTYDEF_IFLAG,
904 TTYDEF_OFLAG,
905 TTYDEF_CFLAG,
906 TTYDEF_LFLAG,
907 {0},
908 TTYDEF_SPEED,
909 TTYDEF_SPEED
910 };
911
912 struct sccregs zs_cons_sccregs;
913 int zs_cons_imask;
914
915 unsigned zs_cons_addrs[] = {ZS0_PHYS, ZS1_PHYS};
916
917
918 zscninit()
919 {
920 zs_cnsetup(0, &zscn_termios);
921 }
922
923 /* Polling routine for console input from a serial port. */
924 int
925 zscngetc(dev_t dev)
926 {
927 register struct sccregs *scc = zs_cons_scc;
928 int c, s, stat;
929
930 s = splzs();
931 for (;;) {
932 while ((ZREAD0(scc) & SCC_RXFULL) == 0) /* wait for Rx full */
933 ;
934 stat = ZREAD(scc, 1) & 0x70;
935 c = ZREADD(scc) & zs_cons_imask;
936 /* stat encodes parity, overrun, framing errors */
937 if (stat == 0)
938 break;
939 ZWRITE0(scc, 0x30); /* reset error */
940 }
941 splx(s);
942 return c;
943 }
944
945 zscnputc(dev_t dev, int c)
946 {
947 register struct sccregs *scc = zs_cons_scc;
948 int s;
949
950 s = splzs();
951 while ((ZREAD0(scc) & SCC_TXRDY) == 0);
952 ZWRITED(scc, c);
953 splx(s);
954 }
955
956 zs_cnsetup(int unit, struct termios * tiop)
957 {
958 register volatile struct scc *scc_adr;
959 register struct sccregs *scc;
960
961 zs_cons_unit = unit;
962 zs_is_console = 1;
963 zs_cons_scc = scc = &zs_cons_sccregs;
964
965 scc_adr = (volatile struct scc *) IIOV(zs_cons_addrs[zsunit(unit)]);
966
967 scc_adr[1].cr = 0;
968 scc_adr[1].cr = 9;
969 scc_adr[1].cr = 0xC0; /* hardware reset of SCC, both sides */
970 if (!zsside(unit))
971 ++scc_adr;
972
973 scc->s_adr = scc_adr;
974 ZWRITE(scc, 2, 0);
975 ZWRITE(scc, 10, 0);
976 ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
977 ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
978 zs_cons_imask = zscc_params(scc, tiop);
979 ZBIS(scc, 5, 0x82); /* set DTR and RTS */
980
981 zs_cons_termios = *tiop;/* save for later */
982 }
983
984 /*
985 * Routines for using the keyboard SCC as the input side of
986 * the 'gsp' console device.
987 */
988
989 /* probe for the keyboard; should check hardware */
990 zs_kbdcnprobe(cp, unit)
991 struct consdev *cp;
992 int unit;
993 {
994 return (unsigned) unit < NZSLINE;
995 }
996 #endif /* NZS */
997