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