xref: /csrg-svn/sys/sparc/dev/zs.c (revision 55107)
1*55107Storek /*
2*55107Storek  * Copyright (c) 1992 The Regents of the University of California.
3*55107Storek  * All rights reserved.
4*55107Storek  *
5*55107Storek  * This software was developed by the Computer Systems Engineering group
6*55107Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7*55107Storek  * contributed to Berkeley.
8*55107Storek  *
9*55107Storek  * %sccs.include.redist.c%
10*55107Storek  *
11*55107Storek  *	@(#)zs.c	7.1 (Berkeley) 07/13/92
12*55107Storek  *
13*55107Storek  * from: $Header: zs.c,v 1.24 92/06/30 02:24:21 torek Exp $
14*55107Storek  */
15*55107Storek 
16*55107Storek /*
17*55107Storek  * Zilog Z8530 (ZSCC) driver.
18*55107Storek  *
19*55107Storek  * Runs two tty ports (ttya and ttyb) on zs0,
20*55107Storek  * and runs a keyboard and mouse on zs1.
21*55107Storek  *
22*55107Storek  * This driver knows far too much about chip to usage mappings.
23*55107Storek  */
24*55107Storek #define	NZS	2		/* XXX */
25*55107Storek 
26*55107Storek #include "sys/param.h"
27*55107Storek #include "sys/proc.h"
28*55107Storek #include "sys/device.h"
29*55107Storek #include "sys/conf.h"
30*55107Storek #include "sys/file.h"
31*55107Storek #include "sys/ioctl.h"
32*55107Storek #include "sys/tty.h"
33*55107Storek #include "sys/time.h"
34*55107Storek #include "sys/kernel.h"
35*55107Storek #include "sys/syslog.h"
36*55107Storek 
37*55107Storek #include "machine/autoconf.h"
38*55107Storek #include "machine/cpu.h"
39*55107Storek 
40*55107Storek #include "kbd.h"
41*55107Storek #include "zsreg.h"
42*55107Storek #include "zsvar.h"
43*55107Storek 
44*55107Storek #ifdef KGDB
45*55107Storek #include "machine/remote-sl.h"
46*55107Storek #endif
47*55107Storek 
48*55107Storek #define	ZSMAJOR	12		/* XXX */
49*55107Storek 
50*55107Storek #define	ZS_KBD		2	/* XXX */
51*55107Storek #define	ZS_MOUSE	3	/* XXX */
52*55107Storek 
53*55107Storek /* the magic number below was stolen from the Sprite source. */
54*55107Storek #define PCLK	(19660800/4)	/* PCLK pin input clock rate */
55*55107Storek 
56*55107Storek /*
57*55107Storek  * Select software interrupt bit based on TTY ipl.
58*55107Storek  */
59*55107Storek #if PIL_TTY == 1
60*55107Storek # define IE_ZSSOFT IE_L1
61*55107Storek #elif PIL_TTY == 4
62*55107Storek # define IE_ZSSOFT IE_L4
63*55107Storek #elif PIL_TTY == 6
64*55107Storek # define IE_ZSSOFT IE_L6
65*55107Storek #else
66*55107Storek # error "no suitable software interrupt bit"
67*55107Storek #endif
68*55107Storek 
69*55107Storek /*
70*55107Storek  * Software state per found chip.  This would be called `zs_softc',
71*55107Storek  * but the previous driver had a rather different zs_softc....
72*55107Storek  */
73*55107Storek struct zsinfo {
74*55107Storek 	struct	device zi_dev;		/* base device */
75*55107Storek 	volatile struct zsdevice *zi_zs;/* chip registers */
76*55107Storek 	struct	zs_chanstate zi_cs[2];	/* channel A and B software state */
77*55107Storek };
78*55107Storek 
79*55107Storek struct tty zs_tty[NZS * 2];		/* XXX should be dynamic */
80*55107Storek 
81*55107Storek /* Definition of the driver for autoconfig. */
82*55107Storek static int	zsmatch(struct device *, struct cfdata *, void *);
83*55107Storek static void	zsattach(struct device *, struct device *, void *);
84*55107Storek struct cfdriver zscd =
85*55107Storek     { NULL, "zs", zsmatch, zsattach, DV_TTY, sizeof(struct zsinfo) };
86*55107Storek 
87*55107Storek /* Interrupt handlers. */
88*55107Storek static int	zshard(void *);
89*55107Storek static struct intrhand levelhard = { zshard };
90*55107Storek static int	zssoft(void *);
91*55107Storek static struct intrhand levelsoft = { zssoft };
92*55107Storek 
93*55107Storek struct zs_chanstate *zslist;
94*55107Storek 
95*55107Storek /* Routines called from other code. */
96*55107Storek static void	zsiopen(struct tty *);
97*55107Storek static void	zsiclose(struct tty *);
98*55107Storek static void	zsstart(struct tty *);
99*55107Storek static void	zsstop(struct tty *, int);
100*55107Storek static int	zsparam(struct tty *, struct termios *);
101*55107Storek 
102*55107Storek /* Routines purely local to this driver. */
103*55107Storek static int	zs_getspeed(volatile struct zschan *);
104*55107Storek static void	zs_reset(volatile struct zschan *, int, int);
105*55107Storek static void	zs_modem(struct zs_chanstate *, int);
106*55107Storek static void	zs_loadchannelregs(volatile struct zschan *, u_char *);
107*55107Storek 
108*55107Storek /* Console stuff. */
109*55107Storek static struct tty *zs_ctty;	/* console `struct tty *' */
110*55107Storek static int zs_consin = -1, zs_consout = -1;
111*55107Storek static int zscnputc(int);	/* console putc function */
112*55107Storek static volatile struct zschan *zs_conschan;
113*55107Storek static struct tty *zs_checkcons(struct zsinfo *, int, struct zs_chanstate *);
114*55107Storek 
115*55107Storek #ifdef KGDB
116*55107Storek /* KGDB stuff.  Must reboot to change zs_kgdbunit. */
117*55107Storek extern int kgdb_dev, kgdb_rate;
118*55107Storek static int zs_kgdb_savedspeed;
119*55107Storek static void zs_checkkgdb(int, struct zs_chanstate *, struct tty *);
120*55107Storek #endif
121*55107Storek 
122*55107Storek extern volatile struct zsdevice *findzs(int);
123*55107Storek static volatile struct zsdevice *zsaddr[NZS];	/* XXX, but saves work */
124*55107Storek 
125*55107Storek /*
126*55107Storek  * Console keyboard L1-A processing is done in the hardware interrupt code,
127*55107Storek  * so we need to duplicate some of the console keyboard decode state.  (We
128*55107Storek  * must not use the regular state as the hardware code keeps ahead of the
129*55107Storek  * software state: the software state tracks the most recent ring input but
130*55107Storek  * the hardware state tracks the most recent ZSCC input.)  See also kbd.h.
131*55107Storek  */
132*55107Storek static struct conk_state {	/* console keyboard state */
133*55107Storek 	char	conk_id;	/* true => ID coming up (console only) */
134*55107Storek 	char	conk_l1;	/* true => L1 pressed (console only) */
135*55107Storek } zsconk_state;
136*55107Storek 
137*55107Storek /*
138*55107Storek  * Match slave number to zs unit number, so that misconfiguration will
139*55107Storek  * not set up the keyboard as ttya, etc.
140*55107Storek  */
141*55107Storek static int
142*55107Storek zsmatch(struct device *parent, struct cfdata *cf, void *aux)
143*55107Storek {
144*55107Storek 	struct romaux *ra = aux;
145*55107Storek 
146*55107Storek 	return (getpropint(ra->ra_node, "slave", -2) == cf->cf_unit);
147*55107Storek }
148*55107Storek 
149*55107Storek /*
150*55107Storek  * Attach a found zs.
151*55107Storek  *
152*55107Storek  * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR
153*55107Storek  * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE?
154*55107Storek  */
155*55107Storek static void
156*55107Storek zsattach(struct device *parent, struct device *dev, void *aux)
157*55107Storek {
158*55107Storek 	register int zs = dev->dv_unit, unit;
159*55107Storek 	register struct zsinfo *zi;
160*55107Storek 	register struct zs_chanstate *cs;
161*55107Storek 	register volatile struct zsdevice *addr;
162*55107Storek 	register struct tty *tp, *ctp;
163*55107Storek 	register struct romaux *ra = aux;
164*55107Storek 	int pri, softcar;
165*55107Storek 	static int didintr, prevpri;
166*55107Storek 
167*55107Storek 	if ((addr = zsaddr[zs]) == NULL)
168*55107Storek 		addr = zsaddr[zs] = findzs(zs);
169*55107Storek 	if ((void *)addr != ra->ra_vaddr)
170*55107Storek 		panic("zsattach");
171*55107Storek 	if (ra->ra_nintr != 1) {
172*55107Storek 		printf(": expected 1 interrupt, got %d\n", ra->ra_nintr);
173*55107Storek 		return;
174*55107Storek 	}
175*55107Storek 	pri = ra->ra_intr[0].int_pri;
176*55107Storek 	printf(" pri %d, softpri %d\n", pri, PIL_TTY);
177*55107Storek 	if (!didintr) {
178*55107Storek 		didintr = 1;
179*55107Storek 		prevpri = pri;
180*55107Storek 		intr_establish(pri, &levelhard);
181*55107Storek 		intr_establish(PIL_TTY, &levelsoft);
182*55107Storek 	} else if (pri != prevpri)
183*55107Storek 		panic("broken zs interrupt scheme");
184*55107Storek 	zi = (struct zsinfo *)dev;
185*55107Storek 	zi->zi_zs = addr;
186*55107Storek 	unit = zs * 2;
187*55107Storek 	cs = zi->zi_cs;
188*55107Storek 	tp = &zs_tty[unit];
189*55107Storek 
190*55107Storek 	if (unit == 0) {
191*55107Storek 		/* Get software carrier flags from options node in OPENPROM. */
192*55107Storek 		extern int optionsnode;
193*55107Storek 
194*55107Storek 		softcar = 0;
195*55107Storek 		if (*getpropstring(optionsnode, "ttya-ignore-cd") == 't')
196*55107Storek 			softcar |= 1;
197*55107Storek 		if (*getpropstring(optionsnode, "ttyb-ignore-cd") == 't')
198*55107Storek 			softcar |= 2;
199*55107Storek 	} else
200*55107Storek 		softcar = dev->dv_cfdata->cf_flags;
201*55107Storek 
202*55107Storek 	/* link into interrupt list with order (A,B) (B=A+1) */
203*55107Storek 	cs[0].cs_next = &cs[1];
204*55107Storek 	cs[1].cs_next = zslist;
205*55107Storek 	zslist = cs;
206*55107Storek 
207*55107Storek 	cs->cs_unit = unit;
208*55107Storek 	cs->cs_speed = zs_getspeed(&addr->zs_chan[CHAN_A]);
209*55107Storek 	cs->cs_softcar = softcar & 1;
210*55107Storek 	cs->cs_zc = &addr->zs_chan[CHAN_A];
211*55107Storek 	tp->t_dev = makedev(ZSMAJOR, unit);
212*55107Storek 	tp->t_oproc = zsstart;
213*55107Storek 	tp->t_param = zsparam;
214*55107Storek 	tp->t_stop = zsstop;
215*55107Storek 	if ((ctp = zs_checkcons(zi, unit, cs)) != NULL)
216*55107Storek 		tp = ctp;
217*55107Storek 	cs->cs_ttyp = tp;
218*55107Storek #ifdef KGDB
219*55107Storek 	if (ctp == NULL)
220*55107Storek 		zs_checkkgdb(unit, cs, tp);
221*55107Storek 	else
222*55107Storek #endif
223*55107Storek 		zs_reset(&addr->zs_chan[CHAN_A], 0, cs->cs_speed);
224*55107Storek 	if (unit == ZS_KBD) {
225*55107Storek 		/*
226*55107Storek 		 * Keyboard: tell /dev/kbd driver how to talk to us.
227*55107Storek 		 */
228*55107Storek 		tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
229*55107Storek 		tp->t_cflag = CS8;
230*55107Storek 		kbd_serial(tp, zsiopen, zsiclose);
231*55107Storek 		cs->cs_conk = 1;		/* do L1-A processing */
232*55107Storek 	}
233*55107Storek 	unit++;
234*55107Storek 	cs++;
235*55107Storek 	tp++;
236*55107Storek 	cs->cs_unit = unit;
237*55107Storek 	cs->cs_speed = zs_getspeed(&addr->zs_chan[CHAN_B]);
238*55107Storek 	cs->cs_softcar = softcar & 2;
239*55107Storek 	cs->cs_zc = &addr->zs_chan[CHAN_B];
240*55107Storek 	tp->t_dev = makedev(ZSMAJOR, unit);
241*55107Storek 	tp->t_oproc = zsstart;
242*55107Storek 	tp->t_param = zsparam;
243*55107Storek 	tp->t_stop = zsstop;
244*55107Storek 	if ((ctp = zs_checkcons(zi, unit, cs)) != NULL)
245*55107Storek 		tp = ctp;
246*55107Storek 	cs->cs_ttyp = tp;
247*55107Storek #ifdef KGDB
248*55107Storek 	if (ctp == NULL)
249*55107Storek 		zs_checkkgdb(unit, cs, tp);
250*55107Storek 	else
251*55107Storek #endif
252*55107Storek 		zs_reset(&addr->zs_chan[CHAN_B], 0, cs->cs_speed);
253*55107Storek 	if (unit == ZS_MOUSE) {
254*55107Storek 		/*
255*55107Storek 		 * Mouse: tell /dev/mouse driver how to talk to us.
256*55107Storek 		 */
257*55107Storek 		tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
258*55107Storek 		tp->t_cflag = CS8;
259*55107Storek 		ms_serial(tp, zsiopen, zsiclose);
260*55107Storek 	}
261*55107Storek }
262*55107Storek 
263*55107Storek /*
264*55107Storek  * Put a channel in a known state.  Interrupts may be left disabled
265*55107Storek  * or enabled, as desired.
266*55107Storek  */
267*55107Storek static void
268*55107Storek zs_reset(zc, inten, speed)
269*55107Storek 	volatile struct zschan *zc;
270*55107Storek 	int inten, speed;
271*55107Storek {
272*55107Storek 	int tconst;
273*55107Storek 	static u_char reg[16] = {
274*55107Storek 		0,
275*55107Storek 		0,
276*55107Storek 		0,
277*55107Storek 		ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
278*55107Storek 		ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
279*55107Storek 		ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
280*55107Storek 		0,
281*55107Storek 		0,
282*55107Storek 		0,
283*55107Storek 		0,
284*55107Storek 		ZSWR10_NRZ,
285*55107Storek 		ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
286*55107Storek 		0,
287*55107Storek 		0,
288*55107Storek 		ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
289*55107Storek 		ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
290*55107Storek 	};
291*55107Storek 
292*55107Storek 	reg[9] = inten ? ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR : ZSWR9_NO_VECTOR;
293*55107Storek 	tconst = BPS_TO_TCONST(PCLK / 16, speed);
294*55107Storek 	reg[12] = tconst;
295*55107Storek 	reg[13] = tconst >> 8;
296*55107Storek 	zs_loadchannelregs(zc, reg);
297*55107Storek }
298*55107Storek 
299*55107Storek /*
300*55107Storek  * Declare the given tty (which is in fact &cons) as a console input
301*55107Storek  * or output.  This happens before the zs chip is attached; the hookup
302*55107Storek  * is finished later, in zs_setcons() below.
303*55107Storek  *
304*55107Storek  * This is used only for ports a and b.  The console keyboard is decoded
305*55107Storek  * independently (we always send unit-2 input to /dev/kbd, which will
306*55107Storek  * direct it to /dev/console if appropriate).
307*55107Storek  */
308*55107Storek void
309*55107Storek zsconsole(tp, unit, out)
310*55107Storek 	register struct tty *tp;
311*55107Storek 	register int unit;
312*55107Storek 	int out;
313*55107Storek {
314*55107Storek 	extern int (*v_putc)();
315*55107Storek 	int zs;
316*55107Storek 	volatile struct zsdevice *addr;
317*55107Storek 
318*55107Storek 	if (unit >= ZS_KBD)
319*55107Storek 		panic("zsconsole");
320*55107Storek 	if (out) {
321*55107Storek 		zs_consout = unit;
322*55107Storek 		zs = unit >> 1;
323*55107Storek 		if ((addr = zsaddr[zs]) == NULL)
324*55107Storek 			addr = zsaddr[zs] = findzs(zs);
325*55107Storek 		zs_conschan = (unit & 1) == 0 ? &addr->zs_chan[CHAN_A] :
326*55107Storek 		    &addr->zs_chan[CHAN_B];
327*55107Storek 		v_putc = zscnputc;
328*55107Storek 	} else
329*55107Storek 		zs_consin = unit;
330*55107Storek 	zs_ctty = tp;
331*55107Storek }
332*55107Storek 
333*55107Storek /*
334*55107Storek  * Polled console output putchar.
335*55107Storek  */
336*55107Storek static int
337*55107Storek zscnputc(c)
338*55107Storek 	int c;
339*55107Storek {
340*55107Storek 	register volatile struct zschan *zc = zs_conschan;
341*55107Storek 	register int s;
342*55107Storek 
343*55107Storek 	/*
344*55107Storek 	 * Must block output interrupts (i.e., raise to >= splzs) without
345*55107Storek 	 * lowering current ipl.  Need a better way.
346*55107Storek 	 */
347*55107Storek 	s = splhigh();
348*55107Storek #ifdef sun4c		/* XXX */
349*55107Storek 	if (s <= (12 << 8))
350*55107Storek 		(void) splzs();
351*55107Storek #endif
352*55107Storek 	while ((zc->zc_csr & ZSRR0_TX_READY) == 0)
353*55107Storek 		continue;
354*55107Storek 	zc->zc_data = c;
355*55107Storek 	splx(s);
356*55107Storek }
357*55107Storek 
358*55107Storek /*
359*55107Storek  * Set up the given unit as console input, output, both, or neither, as
360*55107Storek  * needed.  Return console tty if it is to receive console input.
361*55107Storek  */
362*55107Storek static struct tty *
363*55107Storek zs_checkcons(struct zsinfo *zi, int unit, struct zs_chanstate *cs)
364*55107Storek {
365*55107Storek 	register struct tty *tp;
366*55107Storek 	char *i, *o;
367*55107Storek 
368*55107Storek 	if ((tp = zs_ctty) == NULL)
369*55107Storek 		return (0);
370*55107Storek 	i = zs_consin == unit ? "input" : NULL;
371*55107Storek 	o = zs_consout == unit ? "output" : NULL;
372*55107Storek 	if (i == NULL && o == NULL)
373*55107Storek 		return (0);
374*55107Storek 
375*55107Storek 	/* rewire the minor device (gack) */
376*55107Storek 	tp->t_dev = makedev(major(tp->t_dev), unit);
377*55107Storek 
378*55107Storek 	/*
379*55107Storek 	 * Rewire input and/or output.  Note that baud rate reflects
380*55107Storek 	 * input settings, not output settings, but we can do no better
381*55107Storek 	 * if the console is split across two ports.
382*55107Storek 	 */
383*55107Storek 	if (i) {
384*55107Storek 		tp->t_param = zsparam;
385*55107Storek 		tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
386*55107Storek 		tp->t_cflag = CS8;
387*55107Storek 		ttsetwater(tp);
388*55107Storek 	}
389*55107Storek 	if (o) {
390*55107Storek 		tp->t_oproc = zsstart;
391*55107Storek 		tp->t_stop = zsstop;
392*55107Storek 	}
393*55107Storek 	printf("%s%c: console %s\n",
394*55107Storek 	    zi->zi_dev.dv_xname, (unit & 1) + 'a', i ? (o ? "i/o" : i) : o);
395*55107Storek 	cs->cs_consio = 1;
396*55107Storek 	cs->cs_brkabort = 1;
397*55107Storek 	return (i ? tp : NULL);
398*55107Storek }
399*55107Storek 
400*55107Storek #ifdef KGDB
401*55107Storek /*
402*55107Storek  * The kgdb zs port, if any, was altered at boot time (see zs_kgdb_init).
403*55107Storek  * Pick up the current speed and character size and restore the original
404*55107Storek  * speed.
405*55107Storek  */
406*55107Storek static void
407*55107Storek zs_checkkgdb(int unit, struct zs_chanstate *cs, struct tty *tp)
408*55107Storek {
409*55107Storek 
410*55107Storek 	if (kgdb_dev == makedev(ZSMAJOR, unit)) {
411*55107Storek 		tp->t_ispeed = tp->t_ospeed = kgdb_rate;
412*55107Storek 		tp->t_cflag = CS8;
413*55107Storek 		cs->cs_kgdb = 1;
414*55107Storek 		cs->cs_speed = zs_kgdb_savedspeed;
415*55107Storek 		(void) zsparam(tp, &tp->t_termios);
416*55107Storek 	}
417*55107Storek }
418*55107Storek #endif
419*55107Storek 
420*55107Storek /*
421*55107Storek  * Compute the current baud rate given a ZSCC channel.
422*55107Storek  */
423*55107Storek static int
424*55107Storek zs_getspeed(zc)
425*55107Storek 	register volatile struct zschan *zc;
426*55107Storek {
427*55107Storek 	register int tconst;
428*55107Storek 
429*55107Storek 	tconst = ZS_READ(zc, 12);
430*55107Storek 	tconst |= ZS_READ(zc, 13) << 8;
431*55107Storek 	return (TCONST_TO_BPS(PCLK / 16, tconst));
432*55107Storek }
433*55107Storek 
434*55107Storek 
435*55107Storek /*
436*55107Storek  * Do an internal open.
437*55107Storek  */
438*55107Storek static void
439*55107Storek zsiopen(struct tty *tp)
440*55107Storek {
441*55107Storek 
442*55107Storek 	(void) zsparam(tp, &tp->t_termios);
443*55107Storek 	ttsetwater(tp);
444*55107Storek 	tp->t_state = TS_ISOPEN | TS_CARR_ON;
445*55107Storek }
446*55107Storek 
447*55107Storek /*
448*55107Storek  * Do an internal close.  Eventually we should shut off the chip when both
449*55107Storek  * ports on it are closed.
450*55107Storek  */
451*55107Storek static void
452*55107Storek zsiclose(struct tty *tp)
453*55107Storek {
454*55107Storek 
455*55107Storek 	ttylclose(tp, 0);	/* ??? */
456*55107Storek 	ttyclose(tp);		/* ??? */
457*55107Storek 	tp->t_state = 0;
458*55107Storek }
459*55107Storek 
460*55107Storek 
461*55107Storek /*
462*55107Storek  * Open a zs serial port.  This interface may not be used to open
463*55107Storek  * the keyboard and mouse ports. (XXX)
464*55107Storek  */
465*55107Storek int
466*55107Storek zsopen(dev_t dev, int flags, int mode, struct proc *p)
467*55107Storek {
468*55107Storek 	register struct tty *tp;
469*55107Storek 	register struct zs_chanstate *cs;
470*55107Storek 	struct zsinfo *zi;
471*55107Storek 	int unit = minor(dev), zs = unit >> 1, error, s;
472*55107Storek 
473*55107Storek 	if (zs >= zscd.cd_ndevs || (zi = zscd.cd_devs[zs]) == NULL ||
474*55107Storek 	    unit == ZS_KBD || unit == ZS_MOUSE)
475*55107Storek 		return (ENXIO);
476*55107Storek 	cs = &zi->zi_cs[unit & 1];
477*55107Storek 	if (cs->cs_consio)
478*55107Storek 		return (ENXIO);		/* ??? */
479*55107Storek 	tp = cs->cs_ttyp;
480*55107Storek 	s = spltty();
481*55107Storek 	if ((tp->t_state & TS_ISOPEN) == 0) {
482*55107Storek 		ttychars(tp);
483*55107Storek 		if (tp->t_ispeed == 0) {
484*55107Storek 			tp->t_iflag = TTYDEF_IFLAG;
485*55107Storek 			tp->t_oflag = TTYDEF_OFLAG;
486*55107Storek 			tp->t_cflag = TTYDEF_CFLAG;
487*55107Storek 			tp->t_lflag = TTYDEF_LFLAG;
488*55107Storek 			tp->t_ispeed = tp->t_ospeed = cs->cs_speed;
489*55107Storek 		}
490*55107Storek 		(void) zsparam(tp, &tp->t_termios);
491*55107Storek 		ttsetwater(tp);
492*55107Storek 	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
493*55107Storek 		splx(s);
494*55107Storek 		return (EBUSY);
495*55107Storek 	}
496*55107Storek 	error = 0;
497*55107Storek 	for (;;) {
498*55107Storek 		/* loop, turning on the device, until carrier present */
499*55107Storek 		zs_modem(cs, 1);
500*55107Storek 		if (cs->cs_softcar)
501*55107Storek 			tp->t_state |= TS_CARR_ON;
502*55107Storek 		if (flags & O_NONBLOCK || tp->t_cflag & CLOCAL ||
503*55107Storek 		    tp->t_state & TS_CARR_ON)
504*55107Storek 			break;
505*55107Storek 		tp->t_state |= TS_WOPEN;
506*55107Storek 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
507*55107Storek 		    ttopen, 0))
508*55107Storek 			break;
509*55107Storek 	}
510*55107Storek 	splx(s);
511*55107Storek 	if (error == 0)
512*55107Storek 		error = (*linesw[tp->t_line].l_open)(dev, tp);
513*55107Storek 	if (error)
514*55107Storek 		zs_modem(cs, 0);
515*55107Storek 	return (error);
516*55107Storek }
517*55107Storek 
518*55107Storek /*
519*55107Storek  * Close a zs serial port.
520*55107Storek  */
521*55107Storek int
522*55107Storek zsclose(dev_t dev, int flags, int mode, struct proc *p)
523*55107Storek {
524*55107Storek 	register struct zs_chanstate *cs;
525*55107Storek 	register struct tty *tp;
526*55107Storek 	struct zsinfo *zi;
527*55107Storek 	int unit = minor(dev), s;
528*55107Storek 
529*55107Storek 	zi = zscd.cd_devs[unit >> 1];
530*55107Storek 	cs = &zi->zi_cs[unit & 1];
531*55107Storek 	tp = cs->cs_ttyp;
532*55107Storek 	(*linesw[tp->t_line].l_close)(tp, flags);
533*55107Storek 	if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
534*55107Storek 	    (tp->t_state & TS_ISOPEN) == 0) {
535*55107Storek 		zs_modem(cs, 0);
536*55107Storek 		/* hold low for 1 second */
537*55107Storek 		(void) tsleep((caddr_t)cs, TTIPRI, ttclos, hz);
538*55107Storek 	}
539*55107Storek 	ttyclose(tp);
540*55107Storek #ifdef KGDB
541*55107Storek 	/* Reset the speed if we're doing kgdb on this port */
542*55107Storek 	if (cs->cs_kgdb) {
543*55107Storek 		tp->t_ispeed = tp->t_ospeed = kgdb_rate;
544*55107Storek 		(void) zsparam(tp, &tp->t_termios);
545*55107Storek 	}
546*55107Storek #endif
547*55107Storek 	return (0);
548*55107Storek }
549*55107Storek 
550*55107Storek /*
551*55107Storek  * Read/write zs serial port.
552*55107Storek  */
553*55107Storek int
554*55107Storek zsread(dev_t dev, struct uio *uio, int flags)
555*55107Storek {
556*55107Storek 	register struct tty *tp = &zs_tty[minor(dev)];
557*55107Storek 
558*55107Storek 	return (linesw[tp->t_line].l_read(tp, uio, flags));
559*55107Storek }
560*55107Storek 
561*55107Storek int
562*55107Storek zswrite(dev_t dev, struct uio *uio, int flags)
563*55107Storek {
564*55107Storek 	register struct tty *tp = &zs_tty[minor(dev)];
565*55107Storek 
566*55107Storek 	return (linesw[tp->t_line].l_write(tp, uio, flags));
567*55107Storek }
568*55107Storek 
569*55107Storek /*
570*55107Storek  * ZS hardware interrupt.  Scan all ZS channels.  NB: we know here that
571*55107Storek  * channels are kept in (A,B) pairs.
572*55107Storek  *
573*55107Storek  * Do just a little, then get out; set a software interrupt if more
574*55107Storek  * work is needed.
575*55107Storek  *
576*55107Storek  * We deliberately ignore the vectoring Zilog gives us, and match up
577*55107Storek  * only the number of `reset interrupt under service' operations, not
578*55107Storek  * the order.
579*55107Storek  */
580*55107Storek /* ARGSUSED */
581*55107Storek int
582*55107Storek zshard(void *intrarg)
583*55107Storek {
584*55107Storek 	register struct zs_chanstate *a;
585*55107Storek #define	b (a + 1)
586*55107Storek 	register int rr3, intflags = 0;
587*55107Storek 	static int zsrint(struct zs_chanstate *);
588*55107Storek 	static int zsxint(struct zs_chanstate *);
589*55107Storek 	static int zssint(struct zs_chanstate *);
590*55107Storek 
591*55107Storek 	for (a = zslist; a != NULL; a = b->cs_next) {
592*55107Storek 		rr3 = ZS_READ(a->cs_zc, 3);
593*55107Storek 		if (rr3 == 0)
594*55107Storek 			continue;
595*55107Storek 		intflags |= 2;		/* took an interrupt */
596*55107Storek 		if (rr3 & ZSRR3_IP_A_RX)
597*55107Storek 			intflags |= zsrint(a);
598*55107Storek 		if (rr3 & ZSRR3_IP_B_RX)
599*55107Storek 			intflags |= zsrint(b);
600*55107Storek 		if (rr3 & ZSRR3_IP_A_TX)
601*55107Storek 			intflags |= zsxint(a);
602*55107Storek 		if (rr3 & ZSRR3_IP_B_TX)
603*55107Storek 			intflags |= zsxint(b);
604*55107Storek 		if (rr3 & ZSRR3_IP_A_STAT)
605*55107Storek 			intflags |= zssint(a);
606*55107Storek 		if (rr3 & ZSRR3_IP_B_STAT)
607*55107Storek 			intflags |= zssint(b);
608*55107Storek 	}
609*55107Storek #undef b
610*55107Storek 	if (intflags & 1) {
611*55107Storek #if sun4c /* XXX -- but this will go away when zshard moves to locore.s */
612*55107Storek 		struct clockframe *p = intrarg;
613*55107Storek 
614*55107Storek 		if ((p->psr & PSR_PIL) < (PIL_TTY << 8)) {
615*55107Storek 			(void) spltty();
616*55107Storek 			return (zssoft(intrarg));
617*55107Storek 		}
618*55107Storek #endif
619*55107Storek 		ienab_bis(IE_ZSSOFT);
620*55107Storek 	}
621*55107Storek 	return (intflags & 2);
622*55107Storek }
623*55107Storek 
624*55107Storek static int
625*55107Storek zsrint(register struct zs_chanstate *cs)
626*55107Storek {
627*55107Storek 	register volatile struct zschan *zc = cs->cs_zc;
628*55107Storek 	register int c = zc->zc_data, i;
629*55107Storek 
630*55107Storek 
631*55107Storek 	if (cs->cs_conk) {
632*55107Storek 		register struct conk_state *conk = &zsconk_state;
633*55107Storek 
634*55107Storek 		/*
635*55107Storek 		 * Check here for console abort function, so that we
636*55107Storek 		 * can abort even when interrupts are locking up the
637*55107Storek 		 * machine.
638*55107Storek 		 */
639*55107Storek 		if (c == KBD_RESET) {
640*55107Storek 			conk->conk_id = 1;	/* ignore next byte */
641*55107Storek 			conk->conk_l1 = 0;
642*55107Storek 		} else if (conk->conk_id)
643*55107Storek 			conk->conk_id = 0;	/* stop ignoring bytes */
644*55107Storek 		else if (c == KBD_L1)
645*55107Storek 			conk->conk_l1 = 1;	/* L1 went down */
646*55107Storek 		else if (c == (KBD_L1|KBD_UP))
647*55107Storek 			conk->conk_l1 = 0;	/* L1 went up */
648*55107Storek 		else if (c == KBD_A && conk->conk_l1) {
649*55107Storek 			zsabort();
650*55107Storek 			conk->conk_l1 = 0;	/* we never see the up */
651*55107Storek 			goto clearit;		/* eat the A after L1-A */
652*55107Storek 		}
653*55107Storek 	}
654*55107Storek #ifdef KGDB
655*55107Storek 	if (c == FRAME_START && cs->cs_kgdb &&
656*55107Storek 	    (cs->cs_ttyp->t_state & TS_ISOPEN) == 0) {
657*55107Storek 		zskgdb(cs->cs_unit);
658*55107Storek 		goto clearit;
659*55107Storek 	}
660*55107Storek #endif
661*55107Storek 	/* store receive character and status into ring */
662*55107Storek 	i = cs->cs_rbput;
663*55107Storek 	cs->cs_rbput = i + 1;
664*55107Storek 	c <<= 8;
665*55107Storek 	c |= ZS_READ(zc, 1);
666*55107Storek 	cs->cs_rbuf[i & ZLRB_RING_MASK] = c;
667*55107Storek 
668*55107Storek 	/* clear receive error & interrupt condition */
669*55107Storek 	zc->zc_csr = ZSWR0_RESET_ERRORS;
670*55107Storek 	zc->zc_csr = ZSWR0_CLR_INTR;
671*55107Storek 	return (1);
672*55107Storek 
673*55107Storek clearit:
674*55107Storek 	zc->zc_csr = ZSWR0_RESET_ERRORS;
675*55107Storek 	zc->zc_csr = ZSWR0_CLR_INTR;
676*55107Storek 	return (0);
677*55107Storek }
678*55107Storek 
679*55107Storek static int
680*55107Storek zsxint(register struct zs_chanstate *cs)
681*55107Storek {
682*55107Storek 	register volatile struct zschan *zc = cs->cs_zc;
683*55107Storek 	register int c, i = cs->cs_tbc;
684*55107Storek 
685*55107Storek 	if (i == 0) {
686*55107Storek 		zc->zc_csr = ZSWR0_RESET_TXINT;
687*55107Storek 		zc->zc_csr = ZSWR0_CLR_INTR;
688*55107Storek 		cs->cs_txint = 1;
689*55107Storek 		return (1);
690*55107Storek 	}
691*55107Storek 	cs->cs_tbc = i - 1;
692*55107Storek 	zc->zc_data = *cs->cs_tba++;
693*55107Storek 	zc->zc_csr = ZSWR0_CLR_INTR;
694*55107Storek 	return (0);
695*55107Storek }
696*55107Storek 
697*55107Storek static int
698*55107Storek zssint(register struct zs_chanstate *cs)
699*55107Storek {
700*55107Storek 	register volatile struct zschan *zc = cs->cs_zc;
701*55107Storek 	register int i;
702*55107Storek 
703*55107Storek 	i = zc->zc_csr;
704*55107Storek 	zc->zc_csr = ZSWR0_RESET_STATUS;
705*55107Storek 	zc->zc_csr = ZSWR0_CLR_INTR;
706*55107Storek 	if ((i & ZSRR0_BREAK) && cs->cs_brkabort)
707*55107Storek 		zsabort();
708*55107Storek 	else if (! cs->cs_softcar) {
709*55107Storek 		cs->cs_rr0 = i | 0x100;
710*55107Storek 		return (1);
711*55107Storek 	}
712*55107Storek 	return (0);
713*55107Storek }
714*55107Storek 
715*55107Storek zsabort()
716*55107Storek {
717*55107Storek 
718*55107Storek 	printf("stopping on keyboard abort\n");
719*55107Storek 	callrom();
720*55107Storek }
721*55107Storek 
722*55107Storek #ifdef KGDB
723*55107Storek /*
724*55107Storek  * KGDB framing character received: enter kernel debugger.  This probably
725*55107Storek  * should time out after a few seconds to avoid hanging on spurious input.
726*55107Storek  */
727*55107Storek zskgdb(int unit)
728*55107Storek {
729*55107Storek 
730*55107Storek 	printf("zs%d%c: kgdb interrupt\n", unit >> 1, (unit & 1) + 'a');
731*55107Storek 	kgdb_connect(1);
732*55107Storek }
733*55107Storek #endif
734*55107Storek 
735*55107Storek /*
736*55107Storek  * Print out a ring or fifo overrun error message.
737*55107Storek  */
738*55107Storek static void
739*55107Storek zsoverrun(int unit, long *ptime, char *what)
740*55107Storek {
741*55107Storek 
742*55107Storek 	if (*ptime != time.tv_sec) {
743*55107Storek 		*ptime = time.tv_sec;
744*55107Storek 		log(LOG_WARNING, "zs%d%c: input %s overrun\n", unit >> 1,
745*55107Storek 		    (unit & 1) + 'a', what);
746*55107Storek 	}
747*55107Storek }
748*55107Storek 
749*55107Storek /*
750*55107Storek  * ZS software interrupt.  Scan both ZS chips.
751*55107Storek  */
752*55107Storek int
753*55107Storek zssoft(void *arg)
754*55107Storek {
755*55107Storek 	register struct zs_chanstate *cs;
756*55107Storek 	register volatile struct zschan *zc;
757*55107Storek 	register struct tty *tp;
758*55107Storek 	register int get, n, c, cc, rr0, txint, unit, s;
759*55107Storek 
760*55107Storek 	for (cs = zslist; cs; cs = cs->cs_next) {
761*55107Storek 		unit = cs->cs_unit;
762*55107Storek 		zc = cs->cs_zc;
763*55107Storek 		tp = cs->cs_ttyp;
764*55107Storek 		/*
765*55107Storek 		 * Scan receive ring.  This involves calling ttyinput(),
766*55107Storek 		 * which is quite slow, so we loop until we have caught
767*55107Storek 		 * up with the receiver.  (XXX should test effectiveness)
768*55107Storek 		 * If we are not interested, discard the input right away.
769*55107Storek 		 *
770*55107Storek 		 * XXX this will have to be broken up so that we can get
771*55107Storek 		 * ^S stops out reasonably quickly....
772*55107Storek 		 */
773*55107Storek 		for (;;) {
774*55107Storek 			n = cs->cs_rbput;	/* atomic */
775*55107Storek 			get = cs->cs_rbget;
776*55107Storek 			if (get == n)
777*55107Storek 				break;
778*55107Storek 			/*
779*55107Storek 			 * Compute the number of characters in the receive
780*55107Storek 			 * ring; drain them.  If the count is overlarge, we
781*55107Storek 			 * lost some receive data, and must advance to the
782*55107Storek 			 * first still-extant character.  It may get
783*55107Storek 			 * overwritten if more data are arriving, but this
784*55107Storek 			 * is too expensive to check and gains nothing (we
785*55107Storek 			 * already lost out; all we can do at this point is
786*55107Storek 			 * trade one kind of loss for another).
787*55107Storek 			 *
788*55107Storek 			 * XXX	should do flow control if ring is
789*55107Storek 			 *	getting full ... needs more thought; will
790*55107Storek 			 *	require locking against zshard().
791*55107Storek 			 */
792*55107Storek 			n -= get;
793*55107Storek 			if (n > ZLRB_RING_SIZE) {
794*55107Storek 				zsoverrun(unit, &cs->cs_rotime, "ring");
795*55107Storek 				get += n - ZLRB_RING_SIZE;
796*55107Storek 				n = ZLRB_RING_SIZE;
797*55107Storek 			}
798*55107Storek 			while (--n >= 0) {
799*55107Storek 				/* race to keep ahead of incoming data */
800*55107Storek 				c = cs->cs_rbuf[get++ & ZLRB_RING_MASK];
801*55107Storek 				if (c & ZSRR1_DO)
802*55107Storek 					zsoverrun(unit, &cs->cs_fotime, "fifo");
803*55107Storek 				cc = c >> 8;
804*55107Storek 				if (c & ZSRR1_FE)
805*55107Storek 					cc |= TTY_FE;
806*55107Storek 				if (c & ZSRR1_PE)
807*55107Storek 					cc |= TTY_PE;
808*55107Storek 				/*
809*55107Storek 				 * this should be done through
810*55107Storek 				 * bstreams	XXX gag choke
811*55107Storek 				 */
812*55107Storek 				if (unit == ZS_KBD)
813*55107Storek 					kbd_rint(cc);
814*55107Storek 				else if (unit == ZS_MOUSE)
815*55107Storek 					ms_rint(cc);
816*55107Storek 				else
817*55107Storek 					(*linesw[tp->t_line].l_rint)(cc, tp);
818*55107Storek 			}
819*55107Storek 			cs->cs_rbget = get;
820*55107Storek 		}
821*55107Storek check_xmit:
822*55107Storek 		/*
823*55107Storek 		 * Atomically get and clear transmit and status change
824*55107Storek 		 * interrupts.
825*55107Storek 		 */
826*55107Storek 		s = splzs();
827*55107Storek 		txint = cs->cs_txint;
828*55107Storek 		rr0 = cs->cs_rr0;
829*55107Storek 		if (txint)
830*55107Storek 			cs->cs_txint = 0;
831*55107Storek 		if (rr0 & 0x100)
832*55107Storek 			cs->cs_rr0 = rr0 & 255;
833*55107Storek 		splx(s);
834*55107Storek 
835*55107Storek 		/*
836*55107Storek 		 * Check for status changes.  If carrier has changed,
837*55107Storek 		 * and we want CTS output flow control, we have to fiddle
838*55107Storek 		 * the HFC bit (see zsparam).  If carrier is gone, and
839*55107Storek 		 * linesw l_modem returns 0, drop DTR.
840*55107Storek 		 */
841*55107Storek 		if (rr0 & 0x100) {
842*55107Storek 			if (rr0 & ZSRR0_DCD) {
843*55107Storek 				(void) splzs();
844*55107Storek 				if (tp->t_cflag & CCTS_OFLOW &&
845*55107Storek 				    (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
846*55107Storek 					cs->cs_creg[3] |= ZSWR3_HFC;
847*55107Storek 					ZS_WRITE(zc, 3, cs->cs_creg[3]);
848*55107Storek 				}
849*55107Storek 				splx(s);
850*55107Storek 				(void) (*linesw[tp->t_line].l_modem)(tp, 1);
851*55107Storek 			} else {
852*55107Storek 				(void) splzs();
853*55107Storek 				if (cs->cs_creg[3] & ZSWR3_HFC) {
854*55107Storek 					cs->cs_creg[3] &= ~ZSWR3_HFC;
855*55107Storek 					ZS_WRITE(zc, 3, cs->cs_creg[3]);
856*55107Storek 				}
857*55107Storek 				splx(s);
858*55107Storek 				if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
859*55107Storek 					zs_modem(cs, 0);
860*55107Storek 			}
861*55107Storek 		}
862*55107Storek 
863*55107Storek 		if (txint) {
864*55107Storek 			/*
865*55107Storek 			 * Transmit done: change registers and resume
866*55107Storek 			 * or clear BUSY.
867*55107Storek 			 */
868*55107Storek 			if (cs->cs_heldchange) {
869*55107Storek 				s = splzs();
870*55107Storek 				if ((rr0 & ZSRR0_DCD) == 0)
871*55107Storek 					cs->cs_preg[3] &= ~ZSWR3_HFC;
872*55107Storek 				bcopy((caddr_t)cs->cs_preg,
873*55107Storek 				    (caddr_t)cs->cs_creg, 16);
874*55107Storek 				zs_loadchannelregs(cs->cs_zc, cs->cs_creg);
875*55107Storek 				splx(s);
876*55107Storek 				cs->cs_heldchange = 0;
877*55107Storek 				if (cs->cs_heldtbc &&
878*55107Storek 				    (tp->t_state & TS_TTSTOP) == 0) {
879*55107Storek 					cs->cs_tbc = cs->cs_heldtbc - 1;
880*55107Storek 					zc->zc_data = *cs->cs_tba++;
881*55107Storek 					continue;
882*55107Storek 				}
883*55107Storek 			}
884*55107Storek 			tp->t_state &= ~TS_BUSY;
885*55107Storek 			if (tp->t_state & TS_FLUSH)
886*55107Storek 				tp->t_state &= ~TS_FLUSH;
887*55107Storek 			else
888*55107Storek 				ndflush(&tp->t_outq,
889*55107Storek 				    cs->cs_tba - tp->t_outq.c_cf);
890*55107Storek 			(*linesw[tp->t_line].l_start)(tp);
891*55107Storek 		}
892*55107Storek 	}
893*55107Storek 	return (1);
894*55107Storek }
895*55107Storek 
896*55107Storek int
897*55107Storek zsioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
898*55107Storek {
899*55107Storek 	int unit = minor(dev);
900*55107Storek 	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
901*55107Storek 	register struct tty *tp = zi->zi_cs[unit & 1].cs_ttyp;
902*55107Storek 	register int error;
903*55107Storek 
904*55107Storek 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
905*55107Storek 	if (error >= 0)
906*55107Storek 		return (error);
907*55107Storek 	error = ttioctl(tp, cmd, data, flag);
908*55107Storek 	if (error >= 0)
909*55107Storek 		return (error);
910*55107Storek 
911*55107Storek 	switch (cmd) {
912*55107Storek 
913*55107Storek 	case TIOCSBRK:
914*55107Storek 		/* FINISH ME ... need implicit TIOCCBRK in zsclose as well */
915*55107Storek 
916*55107Storek 	case TIOCCBRK:
917*55107Storek 
918*55107Storek 	case TIOCSDTR:
919*55107Storek 
920*55107Storek 	case TIOCCDTR:
921*55107Storek 
922*55107Storek 	case TIOCMSET:
923*55107Storek 
924*55107Storek 	case TIOCMBIS:
925*55107Storek 
926*55107Storek 	case TIOCMBIC:
927*55107Storek 
928*55107Storek 	case TIOCMGET:
929*55107Storek 
930*55107Storek 	default:
931*55107Storek 		return (ENOTTY);
932*55107Storek 	}
933*55107Storek 	return (0);
934*55107Storek }
935*55107Storek 
936*55107Storek /*
937*55107Storek  * Start or restart transmission.
938*55107Storek  */
939*55107Storek static void
940*55107Storek zsstart(register struct tty *tp)
941*55107Storek {
942*55107Storek 	register struct zs_chanstate *cs;
943*55107Storek 	register int s, nch;
944*55107Storek 	int unit = minor(tp->t_dev);
945*55107Storek 	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
946*55107Storek 
947*55107Storek 	cs = &zi->zi_cs[unit & 1];
948*55107Storek 	s = spltty();
949*55107Storek 
950*55107Storek 	/*
951*55107Storek 	 * If currently active or delaying, no need to do anything.
952*55107Storek 	 */
953*55107Storek 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
954*55107Storek 		goto out;
955*55107Storek 
956*55107Storek 	/*
957*55107Storek 	 * If there are sleepers, and output has drained below low
958*55107Storek 	 * water mark, awaken.
959*55107Storek 	 */
960*55107Storek 	if (tp->t_outq.c_cc <= tp->t_lowat) {
961*55107Storek 		if (tp->t_state & TS_ASLEEP) {
962*55107Storek 			tp->t_state &= ~TS_ASLEEP;
963*55107Storek 			wakeup((caddr_t)&tp->t_outq);
964*55107Storek 		}
965*55107Storek 		selwakeup(&tp->t_wsel);
966*55107Storek 	}
967*55107Storek 
968*55107Storek 	nch = ndqb(&tp->t_outq, 0);	/* XXX */
969*55107Storek 	if (nch) {
970*55107Storek 		register char *p = tp->t_outq.c_cf;
971*55107Storek 
972*55107Storek 		/* mark busy, enable tx done interrupts, & send first byte */
973*55107Storek 		tp->t_state |= TS_BUSY;
974*55107Storek 		(void) splzs();
975*55107Storek 		cs->cs_preg[1] |= ZSWR1_TIE;
976*55107Storek 		cs->cs_creg[1] |= ZSWR1_TIE;
977*55107Storek 		ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
978*55107Storek 		cs->cs_zc->zc_data = *p;
979*55107Storek 		cs->cs_tba = p + 1;
980*55107Storek 		cs->cs_tbc = nch - 1;
981*55107Storek 	} else {
982*55107Storek 		/*
983*55107Storek 		 * Nothing to send, turn off transmit done interrupts.
984*55107Storek 		 * This is useful if something is doing polled output.
985*55107Storek 		 */
986*55107Storek 		(void) splzs();
987*55107Storek 		cs->cs_preg[1] &= ~ZSWR1_TIE;
988*55107Storek 		cs->cs_creg[1] &= ~ZSWR1_TIE;
989*55107Storek 		ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
990*55107Storek 	}
991*55107Storek out:
992*55107Storek 	splx(s);
993*55107Storek }
994*55107Storek 
995*55107Storek /*
996*55107Storek  * Stop output, e.g., for ^S or output flush.
997*55107Storek  */
998*55107Storek static void
999*55107Storek zsstop(register struct tty *tp, int flag)
1000*55107Storek {
1001*55107Storek 	register struct zs_chanstate *cs;
1002*55107Storek 	register int s, unit = minor(tp->t_dev);
1003*55107Storek 	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
1004*55107Storek 
1005*55107Storek 	cs = &zi->zi_cs[unit & 1];
1006*55107Storek 	s = splzs();
1007*55107Storek 	if (tp->t_state & TS_BUSY) {
1008*55107Storek 		/*
1009*55107Storek 		 * Device is transmitting; must stop it.
1010*55107Storek 		 */
1011*55107Storek 		cs->cs_tbc = 0;
1012*55107Storek 		if ((tp->t_state & TS_TTSTOP) == 0)
1013*55107Storek 			tp->t_state |= TS_FLUSH;
1014*55107Storek 	}
1015*55107Storek 	splx(s);
1016*55107Storek }
1017*55107Storek 
1018*55107Storek /*
1019*55107Storek  * Set ZS tty parameters from termios.
1020*55107Storek  *
1021*55107Storek  * This routine makes use of the fact that only registers
1022*55107Storek  * 1, 3, 4, 5, 9, 10, 11, 12, 13, 14, and 15 are written.
1023*55107Storek  */
1024*55107Storek static int
1025*55107Storek zsparam(register struct tty *tp, register struct termios *t)
1026*55107Storek {
1027*55107Storek 	int unit = minor(tp->t_dev);
1028*55107Storek 	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
1029*55107Storek 	register struct zs_chanstate *cs = &zi->zi_cs[unit & 1];
1030*55107Storek 	register int tmp, tmp5, cflag, s;
1031*55107Storek 
1032*55107Storek 	/*
1033*55107Storek 	 * Because PCLK is only run at 4.9 MHz, the fastest we
1034*55107Storek 	 * can go is 51200 baud (this corresponds to TC=1).
1035*55107Storek 	 * This is somewhat unfortunate as there is no real
1036*55107Storek 	 * reason we should not be able to handle higher rates.
1037*55107Storek 	 */
1038*55107Storek 	tmp = t->c_ospeed;
1039*55107Storek 	if (tmp < 0 || (t->c_ispeed && t->c_ispeed != tmp))
1040*55107Storek 		return (EINVAL);
1041*55107Storek 	if (tmp == 0) {
1042*55107Storek 		/* stty 0 => drop DTR and RTS */
1043*55107Storek 		zs_modem(cs, 0);
1044*55107Storek 		return (0);
1045*55107Storek 	}
1046*55107Storek 	tmp = BPS_TO_TCONST(PCLK / 16, tmp);
1047*55107Storek 	if (tmp < 2)
1048*55107Storek 		return (EINVAL);
1049*55107Storek 
1050*55107Storek 	cflag = t->c_cflag;
1051*55107Storek 	tp->t_ispeed = tp->t_ospeed = TCONST_TO_BPS(PCLK / 16, tmp);
1052*55107Storek 	tp->t_cflag = cflag;
1053*55107Storek 
1054*55107Storek 	/*
1055*55107Storek 	 * Block interrupts so that state will not
1056*55107Storek 	 * be altered until we are done setting it up.
1057*55107Storek 	 */
1058*55107Storek 	s = splzs();
1059*55107Storek 	cs->cs_preg[12] = tmp;
1060*55107Storek 	cs->cs_preg[13] = tmp >> 8;
1061*55107Storek 	cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE;
1062*55107Storek 	switch (cflag & CSIZE) {
1063*55107Storek 	case CS5:
1064*55107Storek 		tmp = ZSWR3_RX_5;
1065*55107Storek 		tmp5 = ZSWR5_TX_5;
1066*55107Storek 		break;
1067*55107Storek 	case CS6:
1068*55107Storek 		tmp = ZSWR3_RX_6;
1069*55107Storek 		tmp5 = ZSWR5_TX_6;
1070*55107Storek 		break;
1071*55107Storek 	case CS7:
1072*55107Storek 		tmp = ZSWR3_RX_7;
1073*55107Storek 		tmp5 = ZSWR5_TX_7;
1074*55107Storek 		break;
1075*55107Storek 	case CS8:
1076*55107Storek 	default:
1077*55107Storek 		tmp = ZSWR3_RX_8;
1078*55107Storek 		tmp5 = ZSWR5_TX_8;
1079*55107Storek 		break;
1080*55107Storek 	}
1081*55107Storek 
1082*55107Storek 	/*
1083*55107Storek 	 * Output hardware flow control on the chip is horrendous: if
1084*55107Storek 	 * carrier detect drops, the receiver is disabled.  Hence we
1085*55107Storek 	 * can only do this when the carrier is on.
1086*55107Storek 	 */
1087*55107Storek 	if (cflag & CCTS_OFLOW && cs->cs_zc->zc_csr & ZSRR0_DCD)
1088*55107Storek 		tmp |= ZSWR3_HFC | ZSWR3_RX_ENABLE;
1089*55107Storek 	else
1090*55107Storek 		tmp |= ZSWR3_RX_ENABLE;
1091*55107Storek 	cs->cs_preg[3] = tmp;
1092*55107Storek 	cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
1093*55107Storek 
1094*55107Storek 	tmp = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
1095*55107Storek 	if ((cflag & PARODD) == 0)
1096*55107Storek 		tmp |= ZSWR4_EVENP;
1097*55107Storek 	if (cflag & PARENB)
1098*55107Storek 		tmp |= ZSWR4_PARENB;
1099*55107Storek 	cs->cs_preg[4] = tmp;
1100*55107Storek 	cs->cs_preg[9] = ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR;
1101*55107Storek 	cs->cs_preg[10] = ZSWR10_NRZ;
1102*55107Storek 	cs->cs_preg[11] = ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD;
1103*55107Storek 	cs->cs_preg[14] = ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA;
1104*55107Storek 	cs->cs_preg[15] = ZSWR15_BREAK_IE | ZSWR15_DCD_IE;
1105*55107Storek 
1106*55107Storek 	/*
1107*55107Storek 	 * If nothing is being transmitted, set up new current values,
1108*55107Storek 	 * else mark them as pending.
1109*55107Storek 	 */
1110*55107Storek 	if (cs->cs_heldchange == 0) {
1111*55107Storek 		if (cs->cs_ttyp->t_state & TS_BUSY) {
1112*55107Storek 			cs->cs_heldtbc = cs->cs_tbc;
1113*55107Storek 			cs->cs_tbc = 0;
1114*55107Storek 			cs->cs_heldchange = 1;
1115*55107Storek 		} else {
1116*55107Storek 			bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16);
1117*55107Storek 			zs_loadchannelregs(cs->cs_zc, cs->cs_creg);
1118*55107Storek 		}
1119*55107Storek 	}
1120*55107Storek 	splx(s);
1121*55107Storek 	return (0);
1122*55107Storek }
1123*55107Storek 
1124*55107Storek /*
1125*55107Storek  * Raise or lower modem control (DTR/RTS) signals.  If a character is
1126*55107Storek  * in transmission, the change is deferred.
1127*55107Storek  */
1128*55107Storek static void
1129*55107Storek zs_modem(struct zs_chanstate *cs, int onoff)
1130*55107Storek {
1131*55107Storek 	int s, bis, and;
1132*55107Storek 
1133*55107Storek 	if (onoff) {
1134*55107Storek 		bis = ZSWR5_DTR | ZSWR5_RTS;
1135*55107Storek 		and = ~0;
1136*55107Storek 	} else {
1137*55107Storek 		bis = 0;
1138*55107Storek 		and = ~(ZSWR5_DTR | ZSWR5_RTS);
1139*55107Storek 	}
1140*55107Storek 	s = splzs();
1141*55107Storek 	cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
1142*55107Storek 	if (cs->cs_heldchange == 0) {
1143*55107Storek 		if (cs->cs_ttyp->t_state & TS_BUSY) {
1144*55107Storek 			cs->cs_heldtbc = cs->cs_tbc;
1145*55107Storek 			cs->cs_tbc = 0;
1146*55107Storek 			cs->cs_heldchange = 1;
1147*55107Storek 		} else {
1148*55107Storek 			cs->cs_creg[5] = (cs->cs_creg[5] | bis) & and;
1149*55107Storek 			ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
1150*55107Storek 		}
1151*55107Storek 	}
1152*55107Storek 	splx(s);
1153*55107Storek }
1154*55107Storek 
1155*55107Storek /*
1156*55107Storek  * Write the given register set to the given zs channel in the proper order.
1157*55107Storek  * The channel must not be transmitting at the time.  The receiver will
1158*55107Storek  * be disabled for the time it takes to write all the registers.
1159*55107Storek  */
1160*55107Storek static void
1161*55107Storek zs_loadchannelregs(volatile struct zschan *zc, u_char *reg)
1162*55107Storek {
1163*55107Storek 	int i;
1164*55107Storek 
1165*55107Storek 	zc->zc_csr = ZSM_RESET_ERR;	/* reset error condition */
1166*55107Storek 	i = zc->zc_data;		/* drain fifo */
1167*55107Storek 	i = zc->zc_data;
1168*55107Storek 	i = zc->zc_data;
1169*55107Storek 	ZS_WRITE(zc, 4, reg[4]);
1170*55107Storek 	ZS_WRITE(zc, 10, reg[10]);
1171*55107Storek 	ZS_WRITE(zc, 3, reg[3] & ~ZSWR3_RX_ENABLE);
1172*55107Storek 	ZS_WRITE(zc, 5, reg[5] & ~ZSWR5_TX_ENABLE);
1173*55107Storek 	ZS_WRITE(zc, 1, reg[1]);
1174*55107Storek 	ZS_WRITE(zc, 9, reg[9]);
1175*55107Storek 	ZS_WRITE(zc, 11, reg[11]);
1176*55107Storek 	ZS_WRITE(zc, 12, reg[12]);
1177*55107Storek 	ZS_WRITE(zc, 13, reg[13]);
1178*55107Storek 	ZS_WRITE(zc, 14, reg[14]);
1179*55107Storek 	ZS_WRITE(zc, 15, reg[15]);
1180*55107Storek 	ZS_WRITE(zc, 3, reg[3]);
1181*55107Storek 	ZS_WRITE(zc, 5, reg[5]);
1182*55107Storek }
1183*55107Storek 
1184*55107Storek #ifdef KGDB
1185*55107Storek /*
1186*55107Storek  * Get a character from the given kgdb channel.  Called at splhigh().
1187*55107Storek  */
1188*55107Storek static int
1189*55107Storek zs_kgdb_getc(void *arg)
1190*55107Storek {
1191*55107Storek 	register volatile struct zschan *zc = (volatile struct zschan *)arg;
1192*55107Storek 
1193*55107Storek 	while ((zc->zc_csr & ZSRR0_RX_READY) == 0)
1194*55107Storek 		continue;
1195*55107Storek 	return (zc->zc_data);
1196*55107Storek }
1197*55107Storek 
1198*55107Storek /*
1199*55107Storek  * Put a character to the given kgdb channel.  Called at splhigh().
1200*55107Storek  */
1201*55107Storek static void
1202*55107Storek zs_kgdb_putc(void *arg, int c)
1203*55107Storek {
1204*55107Storek 	register volatile struct zschan *zc = (volatile struct zschan *)arg;
1205*55107Storek 
1206*55107Storek 	while ((zc->zc_csr & ZSRR0_TX_READY) == 0)
1207*55107Storek 		continue;
1208*55107Storek 	zc->zc_data = c;
1209*55107Storek }
1210*55107Storek 
1211*55107Storek /*
1212*55107Storek  * Set up for kgdb; called at boot time before configuration.
1213*55107Storek  * KGDB interrupts will be enabled later when zs0 is configured.
1214*55107Storek  */
1215*55107Storek void
1216*55107Storek zs_kgdb_init()
1217*55107Storek {
1218*55107Storek 	volatile struct zsdevice *addr;
1219*55107Storek 	volatile struct zschan *zc;
1220*55107Storek 	int unit, zs;
1221*55107Storek 
1222*55107Storek 	if (major(kgdb_dev) != ZSMAJOR)
1223*55107Storek 		return;
1224*55107Storek 	unit = minor(kgdb_dev);
1225*55107Storek 	/*
1226*55107Storek 	 * Unit must be 0 or 1 (zs0).
1227*55107Storek 	 */
1228*55107Storek 	if ((unsigned)unit >= ZS_KBD) {
1229*55107Storek 		printf("zs_kgdb_init: bad minor dev %d\n", unit);
1230*55107Storek 		return;
1231*55107Storek 	}
1232*55107Storek 	zs = unit >> 1;
1233*55107Storek 	if ((addr = zsaddr[zs]) == NULL)
1234*55107Storek 		addr = zsaddr[zs] = findzs(zs);
1235*55107Storek 	unit &= 1;
1236*55107Storek 	zc = unit == 0 ? &addr->zs_chan[CHAN_A] : &addr->zs_chan[CHAN_B];
1237*55107Storek 	zs_kgdb_savedspeed = zs_getspeed(zc);
1238*55107Storek 	printf("zs_kgdb_init: attaching zs%d%c at %d baud\n",
1239*55107Storek 	    zs, unit + 'a', kgdb_rate);
1240*55107Storek 	zs_reset(zc, 1, kgdb_rate);
1241*55107Storek 	kgdb_attach(zs_kgdb_getc, zs_kgdb_putc, (void *)zc);
1242*55107Storek }
1243*55107Storek #endif /* KGDB */
1244