zs.c revision 1.73
1/*	$NetBSD: zs.c,v 1.73 2011/04/24 16:26:55 rmind Exp $	*/
2
3/*
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 *
12 * All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 *	This product includes software developed by the University of
15 *	California, Lawrence Berkeley Laboratory.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors
26 *    may be used to endorse or promote products derived from this software
27 *    without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 *	@(#)zs.c	8.1 (Berkeley) 7/19/93
42 */
43
44/*-
45 * Copyright (c) 1995 The NetBSD Foundation, Inc. (Atari modifications)
46 * All rights reserved.
47 *
48 * This code is derived from software contributed to The NetBSD Foundation
49 * by Leo Weppelman.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 *    notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 *    notice, this list of conditions and the following disclaimer in the
58 *    documentation and/or other materials provided with the distribution.
59 *
60 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
61 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
62 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
63 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
64 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
65 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
66 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
67 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
68 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
69 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
70 * POSSIBILITY OF SUCH DAMAGE.
71 */
72
73/*
74 * Zilog Z8530 (ZSCC) driver.
75 *
76 * Runs two tty ports (modem2 and serial2) on zs0.
77 *
78 * This driver knows far too much about chip to usage mappings.
79 */
80
81#include <sys/cdefs.h>
82__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.73 2011/04/24 16:26:55 rmind Exp $");
83
84#include <sys/param.h>
85#include <sys/systm.h>
86#include <sys/proc.h>
87#include <sys/device.h>
88#include <sys/conf.h>
89#include <sys/file.h>
90#include <sys/ioctl.h>
91#include <sys/malloc.h>
92#include <sys/tty.h>
93#include <sys/time.h>
94#include <sys/kernel.h>
95#include <sys/syslog.h>
96#include <sys/kauth.h>
97
98#include <machine/cpu.h>
99#include <machine/iomap.h>
100#include <machine/scu.h>
101#include <machine/mfp.h>
102#include <atari/dev/ym2149reg.h>
103
104#include <dev/ic/z8530reg.h>
105#include <atari/dev/zsvar.h>
106
107#include "ioconf.h"
108
109#include "zs.h"
110#if NZS > 1
111#error "This driver supports only 1 85C30!"
112#endif
113
114#if NZS > 0
115
116#define PCLK	(8053976)	/* PCLK pin input clock rate */
117#define PCLK_HD	(9600 * 1536)	/* PCLK on Hades pin input clock rate */
118
119#define splzs	spl5
120
121/*
122 * Software state per found chip.
123 */
124struct zs_softc {
125	device_t sc_dev;		/* base device */
126	struct zs_chanstate *sc_cs[2];	/* chan A and B software state */
127
128	struct zs_chanstate sc_cs_store[2];
129	void *sc_sicookie;		/* for callback */
130};
131
132/*
133 * Define the registers for a closed port
134 */
135static uint8_t zs_init_regs[16] = {
136/*  0 */	0,
137/*  1 */	0,
138/*  2 */	0x60,
139/*  3 */	0,
140/*  4 */	0,
141/*  5 */	0,
142/*  6 */	0,
143/*  7 */	0,
144/*  8 */	0,
145/*  9 */	ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT,
146/* 10 */	ZSWR10_NRZ,
147/* 11 */	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
148/* 12 */	0,
149/* 13 */	0,
150/* 14 */	ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
151/* 15 */	0
152};
153
154/*
155 * Define the machine dependant clock frequencies
156 * If BRgen feeds sender/receiver we always use a
157 * divisor 16, therefor the division by 16 can as
158 * well be done here.
159 */
160static const u_long zs_freqs_tt[] = {
161	/*
162	 * Atari TT, RTxCB is generated by TT-MFP timer C,
163	 * which is set to 307.2 kHz during initialisation
164	 * and never changed afterwards.
165	 */
166	PCLK/16,	/* BRgen, PCLK,  divisor 16	*/
167	 229500,	/* BRgen, RTxCA, divisor 16	*/
168	3672000,	/* RTxCA, from PCLK4		*/
169	      0,	/* TRxCA, external		*/
170
171	PCLK/16,	/* BRgen, PCLK,  divisor 16	*/
172	  19200,	/* BRgen, RTxCB, divisor 16	*/
173	 307200,	/* RTxCB, from TT-MFP TCO	*/
174	2457600		/* TRxCB, from BCLK		*/
175};
176
177static const u_long zs_freqs_falcon[] = {
178	/*
179	 * Atari Falcon, XXX no specs available, this might be wrong
180	 */
181	PCLK/16,	/* BRgen, PCLK,  divisor 16	*/
182	 229500,	/* BRgen, RTxCA, divisor 16	*/
183	3672000,	/* RTxCA, ???			*/
184	      0,	/* TRxCA, external		*/
185
186	PCLK/16,	/* BRgen, PCLK,  divisor 16	*/
187	 229500,	/* BRgen, RTxCB, divisor 16	*/
188	3672000,	/* RTxCB, ???			*/
189	2457600		/* TRxCB, ???			*/
190};
191
192static const u_long zs_freqs_hades[] = {
193	/*
194	 * XXX: Channel-A unchecked!!!!!
195	 */
196     PCLK_HD/16,	/* BRgen, PCLK,  divisor 16	*/
197	 229500,	/* BRgen, RTxCA, divisor 16	*/
198	3672000,	/* RTxCA, from PCLK4		*/
199	      0,	/* TRxCA, external		*/
200
201     PCLK_HD/16,	/* BRgen, PCLK,  divisor 16	*/
202	 235550,	/* BRgen, RTxCB, divisor 16	*/
203	3768800,	/* RTxCB, 3.7688MHz		*/
204	3768800		/* TRxCB, 3.7688MHz		*/
205};
206
207static const u_long zs_freqs_generic[] = {
208	/*
209	 * other machines, assume only PCLK is available
210	 */
211	PCLK/16,	/* BRgen, PCLK,  divisor 16	*/
212	      0,	/* BRgen, RTxCA, divisor 16	*/
213	      0,	/* RTxCA, unknown		*/
214	      0,	/* TRxCA, unknown		*/
215
216	PCLK/16,	/* BRgen, PCLK,  divisor 16	*/
217	      0,	/* BRgen, RTxCB, divisor 16	*/
218	      0,	/* RTxCB, unknown		*/
219	      0		/* TRxCB, unknown		*/
220};
221static const u_long *zs_frequencies;
222
223/* Definition of the driver for autoconfig. */
224static int	zsmatch(device_t, cfdata_t, void *);
225static void	zsattach(device_t, device_t, void *);
226
227CFATTACH_DECL_NEW(zs, sizeof(struct zs_softc),
228    zsmatch, zsattach, NULL, NULL);
229
230/* {b,c}devsw[] function prototypes */
231dev_type_open(zsopen);
232dev_type_close(zsclose);
233dev_type_read(zsread);
234dev_type_write(zswrite);
235dev_type_ioctl(zsioctl);
236dev_type_stop(zsstop);
237dev_type_tty(zstty);
238dev_type_poll(zspoll);
239
240const struct cdevsw zs_cdevsw = {
241	zsopen, zsclose, zsread, zswrite, zsioctl,
242	zsstop, zstty, zspoll, nommap, ttykqfilter, D_TTY
243};
244
245/* Interrupt handlers. */
246static int	zshard(void *);
247static int	zssoft(void *);
248static int	zsrint(struct zs_chanstate *, struct zschan *);
249static int	zsxint(struct zs_chanstate *, struct zschan *);
250static int	zssint(struct zs_chanstate *, struct zschan *);
251
252/* Routines called from other code. */
253static void	zsstart(struct tty *);
254
255/* Routines purely local to this driver. */
256static void	zsoverrun(int, long *, const char *);
257static int	zsparam(struct tty *, struct termios *);
258static int	zsbaudrate(int, int, int *, int *, int *, int *);
259static int	zs_modem(struct zs_chanstate *, int, int);
260static void	zs_loadchannelregs(struct zschan *, uint8_t *);
261static void	zs_shutdown(struct zs_chanstate *);
262
263static int
264zsmatch(device_t parent, cfdata_t cf, void *aux)
265{
266	static int zs_matched = 0;
267
268	if (strcmp("zs", aux) || zs_matched)
269		return 0;
270	zs_matched = 1;
271	return 1;
272}
273
274/*
275 * Attach a found zs.
276 */
277static void
278zsattach(device_t parent, device_t self, void *aux)
279{
280	struct zs_softc *sc;
281	struct zsdevice *zs;
282	struct zschan *zc;
283	struct zs_chanstate *cs;
284	int channel;
285
286	sc = device_private(self);
287	sc->sc_dev = self;
288
289	printf(": serial2 on channel a and modem2 on channel b\n");
290
291	zs = (struct zsdevice *)AD_SCC;
292
293	for (channel = 0; channel < 2; channel++) {
294		cs = &sc->sc_cs_store[channel];
295		sc->sc_cs[channel] = cs;
296
297		cs->cs_unit = channel;
298		cs->cs_zc = zc =
299		    (channel == 0) ?  &zs->zs_chan_a : &zs->zs_chan_b;
300		/*
301		 * Get the command register into a known state.
302		 */
303		(void)zc->zc_csr;
304		(void)zc->zc_csr;
305
306		/*
307		 * Do a hardware reset.
308		 */
309		if (channel == 0) {
310			ZS_WRITE(zc, 9, ZSWR9_HARD_RESET);
311			delay(50000);	/* enough ? */
312			ZS_WRITE(zc, 9, 0);
313		}
314
315		/*
316		 * Initialize channel
317		 */
318		zs_loadchannelregs(zc, zs_init_regs);
319	}
320
321	if (machineid & ATARI_TT) {
322		/*
323		 * ininitialise TT-MFP timer C: 307200Hz
324		 * timer C and D share one control register:
325		 *	bits 0-2 control timer D
326		 *	bits 4-6 control timer C
327		 */
328		int cr = MFP2->mf_tcdcr & 7;
329		MFP2->mf_tcdcr = cr;		/* stop timer C  */
330		MFP2->mf_tcdr  = 1;		/* counter 1     */
331		cr |= T_Q004 << 4;		/* divisor 4     */
332		MFP2->mf_tcdcr = cr;		/* start timer C */
333		/*
334		 * enable scc related interrupts
335		 */
336		SCU->vme_mask |= SCU_SCC;
337
338		zs_frequencies = zs_freqs_tt;
339	} else if (machineid & ATARI_FALCON) {
340		zs_frequencies = zs_freqs_falcon;
341	} else if (machineid & ATARI_HADES) {
342		zs_frequencies = zs_freqs_hades;
343	} else {
344		zs_frequencies = zs_freqs_generic;
345	}
346
347	if (intr_establish(36, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
348		aprint_error_dev(self,
349		    "Can't establish interrupt (Rx chan B)\n");
350	if (intr_establish(32, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
351		aprint_error_dev(self,
352		    "Can't establish interrupt (Tx empty chan B)\n");
353	if (intr_establish(34, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
354		aprint_error_dev(self,
355		    "Can't establish interrupt (Ext./Status chan B)\n");
356	if (intr_establish(38, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
357		aprint_error_dev(self,
358		    "Can't establish interrupt (Special Rx cond. chan B)\n");
359	if (intr_establish(44, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
360		aprint_error_dev(self,
361		    "Can't establish interrupt (Rx chan A)\n");
362	if (intr_establish(40, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
363		aprint_error_dev(self,
364		    "Can't establish interrupt (Tx empty chan A)\n");
365	if (intr_establish(42, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
366		aprint_error_dev(self,
367		    "Can't establish interrupt (Ext./Status chan A)\n");
368	if (intr_establish(46, USER_VEC, 0, (hw_ifun_t)zshard, sc) == NULL)
369		aprint_error_dev(self,
370		    "Can't establish interrupt (Special Rx cond. chan A)\n");
371
372	sc->sc_sicookie = softint_establish(SOFTINT_SERIAL,
373	    (void (*)(void *))zssoft, sc);
374}
375
376/*
377 * Open a zs serial port.
378 */
379int
380zsopen(dev_t dev, int flags, int mode, struct lwp *l)
381{
382	struct tty *tp;
383	struct zs_chanstate *cs;
384	struct zs_softc *sc;
385	int unit = ZS_UNIT(dev);
386	int zs = unit >> 1;
387	int error, s;
388
389	sc = device_lookup_private(&zs_cd, zs);
390	if (sc == NULL)
391		return ENXIO;
392	cs = sc->sc_cs[unit & 1];
393
394	/*
395	 * When port A (ser02) is selected on the TT, make sure
396	 * the port is enabled.
397	 */
398	if ((machineid & ATARI_TT) && !(unit & 1))
399		ym2149_ser2(1);
400
401	if (cs->cs_rbuf == NULL) {
402		cs->cs_rbuf = malloc(ZLRB_RING_SIZE * sizeof(int), M_DEVBUF,
403		    M_WAITOK);
404	}
405
406	tp = cs->cs_ttyp;
407	if (tp == NULL) {
408		cs->cs_ttyp = tp = tty_alloc();
409		tty_attach(tp);
410		tp->t_dev   = dev;
411		tp->t_oproc = zsstart;
412		tp->t_param = zsparam;
413	}
414
415	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
416		return EBUSY;
417
418	s  = spltty();
419
420	/*
421	 * Do the following iff this is a first open.
422	 */
423	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
424		if (tp->t_ispeed == 0) {
425			tp->t_iflag = TTYDEF_IFLAG;
426			tp->t_oflag = TTYDEF_OFLAG;
427			tp->t_cflag = TTYDEF_CFLAG;
428			tp->t_lflag = TTYDEF_LFLAG;
429			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
430		}
431		ttychars(tp);
432		ttsetwater(tp);
433
434		(void)zsparam(tp, &tp->t_termios);
435
436		/*
437		 * Turn on DTR.  We must always do this, even if carrier is not
438		 * present, because otherwise we'd have to use TIOCSDTR
439		 * immediately after setting CLOCAL, which applications do not
440		 * expect.  We always assert DTR while the device is open
441		 * unless explicitly requested to deassert it.
442		 */
443		zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, DMSET);
444		/* May never get a status intr. if DCD already on. -gwr */
445		if (((cs->cs_rr0 = cs->cs_zc->zc_csr) & ZSRR0_DCD) != 0)
446			tp->t_state |= TS_CARR_ON;
447		if (cs->cs_softcar)
448			tp->t_state |= TS_CARR_ON;
449	}
450
451	splx(s);
452
453	error = ttyopen(tp, ZS_DIALOUT(dev), (flags & O_NONBLOCK));
454	if (error)
455		goto bad;
456
457	error = tp->t_linesw->l_open(dev, tp);
458	if (error)
459		goto bad;
460	return 0;
461
462bad:
463	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
464		/*
465		 * We failed to open the device, and nobody else had it opened.
466		 * Clean up the state as appropriate.
467		 */
468		zs_shutdown(cs);
469	}
470	return error;
471}
472
473/*
474 * Close a zs serial port.
475 */
476int
477zsclose(dev_t dev, int flags, int mode, struct lwp *l)
478{
479	struct zs_chanstate *cs;
480	struct tty *tp;
481	struct zs_softc *sc;
482	int unit = ZS_UNIT(dev);
483
484	sc = device_lookup_private(&zs_cd, unit >> 1);
485	cs = sc->sc_cs[unit & 1];
486	tp = cs->cs_ttyp;
487
488	tp->t_linesw->l_close(tp, flags);
489	ttyclose(tp);
490
491	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
492		/*
493		 * Although we got a last close, the device may still be in
494		 * use; e.g. if this was the dialout node, and there are still
495		 * processes waiting for carrier on the non-dialout node.
496		 */
497		zs_shutdown(cs);
498	}
499	return 0;
500}
501
502/*
503 * Read/write zs serial port.
504 */
505int
506zsread(dev_t dev, struct uio *uio, int flags)
507{
508	struct zs_chanstate *cs;
509	struct zs_softc *sc;
510	struct tty *tp;
511	int unit;
512
513	unit = ZS_UNIT(dev);
514	sc   = device_lookup_private(&zs_cd, unit >> 1);
515	cs   = sc->sc_cs[unit & 1];
516	tp   = cs->cs_ttyp;
517
518	return (*tp->t_linesw->l_read)(tp, uio, flags);
519}
520
521int
522zswrite(dev_t dev, struct uio *uio, int flags)
523{
524	struct zs_chanstate *cs;
525	struct zs_softc *sc;
526	struct tty *tp;
527	int unit;
528
529	unit = ZS_UNIT(dev);
530	sc   = device_lookup_private(&zs_cd, unit >> 1);
531	cs   = sc->sc_cs[unit & 1];
532	tp   = cs->cs_ttyp;
533
534	return (*tp->t_linesw->l_write)(tp, uio, flags);
535}
536
537int
538zspoll(dev_t dev, int events, struct lwp *l)
539{
540	struct zs_chanstate *cs;
541	struct zs_softc *sc;
542	struct tty *tp;
543	int unit;
544
545	unit = ZS_UNIT(dev);
546	sc   = device_lookup_private(&zs_cd, unit >> 1);
547	cs   = sc->sc_cs[unit & 1];
548	tp   = cs->cs_ttyp;
549
550	return (*tp->t_linesw->l_poll)(tp, events, l);
551}
552
553struct tty *
554zstty(dev_t dev)
555{
556	struct zs_chanstate *cs;
557	struct zs_softc *sc;
558	int unit;
559
560	unit = ZS_UNIT(dev);
561	sc   = device_lookup_private(&zs_cd, unit >> 1);
562	cs   = sc->sc_cs[unit & 1];
563	return cs->cs_ttyp;
564}
565
566/*
567 * ZS hardware interrupt.  Scan all ZS channels.  NB: we know here that
568 * channels are kept in (A,B) pairs.
569 *
570 * Do just a little, then get out; set a software interrupt if more
571 * work is needed.
572 *
573 * We deliberately ignore the vectoring Zilog gives us, and match up
574 * only the number of `reset interrupt under service' operations, not
575 * the order.
576 */
577
578int
579zshard(void *arg)
580{
581	struct zs_softc *sc;
582	struct zs_chanstate *cs0, *cs1;
583	struct zschan *zc;
584	int intflags, v, i;
585	uint8_t rr3;
586
587	sc = arg;
588	intflags = 0;
589	cs0 = sc->sc_cs[0];
590	cs1 = sc->sc_cs[1];
591
592	do {
593		intflags &= ~4;
594		rr3 = ZS_READ(cs0->cs_zc, 3);
595		if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
596			intflags |= 4 | 2;
597			zc = cs0->cs_zc;
598			i  = cs0->cs_rbput;
599			if ((rr3 & ZSRR3_IP_A_RX) != 0 &&
600			    (v = zsrint(cs0, zc)) != 0) {
601				cs0->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
602				intflags |= 1;
603			}
604			if ((rr3 & ZSRR3_IP_A_TX) != 0 &&
605			    (v = zsxint(cs0, zc)) != 0) {
606				cs0->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
607				intflags |= 1;
608			}
609			if ((rr3 & ZSRR3_IP_A_STAT) != 0 &&
610			    (v = zssint(cs0, zc)) != 0) {
611				cs0->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
612				intflags |= 1;
613			}
614			cs0->cs_rbput = i;
615		}
616		if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
617			intflags |= 4 | 2;
618			zc = cs1->cs_zc;
619			i  = cs1->cs_rbput;
620			if ((rr3 & ZSRR3_IP_B_RX) != 0 &&
621			    (v = zsrint(cs1, zc)) != 0) {
622				cs1->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
623				intflags |= 1;
624			}
625			if ((rr3 & ZSRR3_IP_B_TX) != 0 &&
626			    (v = zsxint(cs1, zc)) != 0) {
627				cs1->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
628				intflags |= 1;
629			}
630			if ((rr3 & ZSRR3_IP_B_STAT) != 0 &&
631			    (v = zssint(cs1, zc)) != 0) {
632				cs1->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
633				intflags |= 1;
634			}
635			cs1->cs_rbput = i;
636		}
637	} while (intflags & 4);
638
639	if (intflags & 1)
640		softint_schedule(sc->sc_sicookie);
641
642	return intflags & 2;
643}
644
645static int
646zsrint(struct zs_chanstate *cs, struct zschan *zc)
647{
648	int c;
649
650	/*
651	 * First read the status, because read of the received char
652	 * destroy the status of this char.
653	 */
654	c = ZS_READ(zc, 1);
655	c |= (zc->zc_data << 8);
656
657	/* clear receive error & interrupt condition */
658	zc->zc_csr = ZSWR0_RESET_ERRORS;
659	zc->zc_csr = ZSWR0_CLR_INTR;
660
661	return ZRING_MAKE(ZRING_RINT, c);
662}
663
664static int
665zsxint(struct zs_chanstate *cs, struct zschan *zc)
666{
667	int i = cs->cs_tbc;
668
669	if (i == 0) {
670		zc->zc_csr = ZSWR0_RESET_TXINT;
671		zc->zc_csr = ZSWR0_CLR_INTR;
672		return ZRING_MAKE(ZRING_XINT, 0);
673	}
674	cs->cs_tbc = i - 1;
675	zc->zc_data = *cs->cs_tba++;
676	zc->zc_csr = ZSWR0_CLR_INTR;
677	return 0;
678}
679
680static int
681zssint(struct zs_chanstate *cs, struct zschan *zc)
682{
683	int rr0;
684
685	rr0 = zc->zc_csr;
686	zc->zc_csr = ZSWR0_RESET_STATUS;
687	zc->zc_csr = ZSWR0_CLR_INTR;
688	/*
689	 * The chip's hardware flow control is, as noted in zsreg.h,
690	 * busted---if the DCD line goes low the chip shuts off the
691	 * receiver (!).  If we want hardware CTS flow control but do
692	 * not have it, and carrier is now on, turn HFC on; if we have
693	 * HFC now but carrier has gone low, turn it off.
694	 */
695	if (rr0 & ZSRR0_DCD) {
696		if (cs->cs_ttyp->t_cflag & CCTS_OFLOW &&
697		    (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
698			cs->cs_creg[3] |= ZSWR3_HFC;
699			ZS_WRITE(zc, 3, cs->cs_creg[3]);
700		}
701	} else {
702		if (cs->cs_creg[3] & ZSWR3_HFC) {
703			cs->cs_creg[3] &= ~ZSWR3_HFC;
704			ZS_WRITE(zc, 3, cs->cs_creg[3]);
705		}
706	}
707	return ZRING_MAKE(ZRING_SINT, rr0);
708}
709
710/*
711 * Print out a ring or fifo overrun error message.
712 */
713static void
714zsoverrun(int unit, long *ptime, const char *what)
715{
716	time_t cur_sec = time_second;
717
718	if (*ptime != cur_sec) {
719		*ptime = cur_sec;
720		log(LOG_WARNING, "zs%d%c: %s overrun\n", unit >> 1,
721		    (unit & 1) + 'a', what);
722	}
723}
724
725/*
726 * ZS software interrupt.  Scan all channels for deferred interrupts.
727 */
728int
729zssoft(void *arg)
730{
731	struct zs_softc *sc;
732	struct zs_chanstate *cs;
733	struct zschan *zc;
734	struct linesw *line;
735	struct tty *tp;
736	int chan, get, n, c, cc, s;
737	int retval = 0;
738
739	sc = arg;
740	s = spltty();
741	for (chan = 0; chan < 2; chan++) {
742		cs = sc->sc_cs[chan];
743		get = cs->cs_rbget;
744again:
745		n = cs->cs_rbput;	/* atomic			*/
746		if (get == n)		/* nothing more on this line	*/
747			continue;
748		retval = 1;
749		zc     = cs->cs_zc;
750		tp     = cs->cs_ttyp;
751		line   = tp->t_linesw;
752		/*
753		 * Compute the number of interrupts in the receive ring.
754		 * If the count is overlarge, we lost some events, and
755		 * must advance to the first valid one.  It may get
756		 * overwritten if more data are arriving, but this is
757		 * too expensive to check and gains nothing (we already
758		 * lost out; all we can do at this point is trade one
759		 * kind of loss for another).
760		 */
761		n -= get;
762		if (n > ZLRB_RING_SIZE) {
763			zsoverrun(chan, &cs->cs_rotime, "ring");
764			get += n - ZLRB_RING_SIZE;
765			n    = ZLRB_RING_SIZE;
766		}
767		while (--n >= 0) {
768			/* race to keep ahead of incoming interrupts */
769			c = cs->cs_rbuf[get++ & ZLRB_RING_MASK];
770			switch (ZRING_TYPE(c)) {
771
772			case ZRING_RINT:
773				c = ZRING_VALUE(c);
774				if ((c & ZSRR1_DO) != 0)
775					zsoverrun(chan, &cs->cs_fotime, "fifo");
776				cc = c >> 8;
777				if ((c & ZSRR1_FE) != 0)
778					cc |= TTY_FE;
779				if ((c & ZSRR1_PE) != 0)
780					cc |= TTY_PE;
781				line->l_rint(cc, tp);
782				break;
783
784			case ZRING_XINT:
785				/*
786				 * Transmit done: change registers and resume,
787				 * or clear BUSY.
788				 */
789				if (cs->cs_heldchange) {
790					int sps;
791
792					sps = splzs();
793					c = zc->zc_csr;
794					if ((c & ZSRR0_DCD) == 0)
795						cs->cs_preg[3] &= ~ZSWR3_HFC;
796					memcpy((void *)cs->cs_creg,
797					    (void *)cs->cs_preg, 16);
798					zs_loadchannelregs(zc, cs->cs_creg);
799					splx(sps);
800					cs->cs_heldchange = 0;
801					if (cs->cs_heldtbc &&
802					    (tp->t_state & TS_TTSTOP) == 0) {
803						cs->cs_tbc = cs->cs_heldtbc - 1;
804						zc->zc_data = *cs->cs_tba++;
805						goto again;
806					}
807				}
808				tp->t_state &= ~TS_BUSY;
809				if ((tp->t_state & TS_FLUSH) != 0)
810					tp->t_state &= ~TS_FLUSH;
811				else
812					ndflush(&tp->t_outq,
813					    cs->cs_tba - tp->t_outq.c_cf);
814				line->l_start(tp);
815				break;
816
817			case ZRING_SINT:
818				/*
819				 * Status line change.  HFC bit is run in
820				 * hardware interrupt, to avoid locking
821				 * at splzs here.
822				 */
823				c = ZRING_VALUE(c);
824				if (((c ^ cs->cs_rr0) & ZSRR0_DCD) != 0) {
825					cc = (c & ZSRR0_DCD) != 0;
826					if (line->l_modem(tp, cc) == 0)
827						zs_modem(cs,
828						    ZSWR5_RTS | ZSWR5_DTR,
829						    cc ? DMBIS : DMBIC);
830				}
831				cs->cs_rr0 = c;
832				break;
833
834			default:
835				log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (%x)\n",
836				    chan >> 1, (chan & 1) + 'a', c);
837				break;
838			}
839		}
840		cs->cs_rbget = get;
841		goto again;
842	}
843	splx(s);
844	return retval;
845}
846
847int
848zsioctl(dev_t dev, u_long cmd, void * data, int flag, struct lwp *l)
849{
850	int unit = ZS_UNIT(dev);
851	struct zs_softc *sc = device_lookup_private(&zs_cd, unit >> 1);
852	struct zs_chanstate *cs = sc->sc_cs[unit & 1];
853	struct tty *tp = cs->cs_ttyp;
854	int error, s;
855
856	error = tp->t_linesw->l_ioctl(tp, cmd, data, flag, l);
857	if (error != EPASSTHROUGH)
858		return error;
859
860	error = ttioctl(tp, cmd, data, flag, l);
861	if (error !=EPASSTHROUGH)
862		return error;
863
864	switch (cmd) {
865	case TIOCSBRK:
866		s = splzs();
867		cs->cs_preg[5] |= ZSWR5_BREAK;
868		cs->cs_creg[5] |= ZSWR5_BREAK;
869		ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
870		splx(s);
871		break;
872	case TIOCCBRK:
873		s = splzs();
874		cs->cs_preg[5] &= ~ZSWR5_BREAK;
875		cs->cs_creg[5] &= ~ZSWR5_BREAK;
876		ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
877		splx(s);
878		break;
879	case TIOCGFLAGS: {
880		int bits = 0;
881
882		if (cs->cs_softcar)
883			bits |= TIOCFLAG_SOFTCAR;
884		if ((cs->cs_creg[15] & ZSWR15_DCD_IE) != 0)
885			bits |= TIOCFLAG_CLOCAL;
886		if ((cs->cs_creg[3] & ZSWR3_HFC) != 0)
887			bits |= TIOCFLAG_CRTSCTS;
888		*(int *)data = bits;
889		break;
890	}
891	case TIOCSFLAGS: {
892		int userbits = 0;
893
894		error = kauth_authorize_device_tty(l->l_cred,
895		    KAUTH_DEVICE_TTY_PRIVSET, tp);
896		if (error != 0)
897			return EPERM;
898
899		userbits = *(int *)data;
900
901		/*
902		 * can have `local' or `softcar', and `rtscts' or `mdmbuf'
903		 # defaulting to software flow control.
904		 */
905		if ((userbits & TIOCFLAG_SOFTCAR) != 0 &&
906		    (userbits & TIOCFLAG_CLOCAL) != 0)
907			return EINVAL;
908		if ((userbits & TIOCFLAG_MDMBUF) != 0)
909			/* don't support this (yet?) */
910			return ENODEV;
911
912		s = splzs();
913		if ((userbits & TIOCFLAG_SOFTCAR) != 0) {
914			cs->cs_softcar = 1;	/* turn on softcar */
915			cs->cs_preg[15] &= ~ZSWR15_DCD_IE; /* turn off dcd */
916			cs->cs_creg[15] &= ~ZSWR15_DCD_IE;
917			ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
918		} else if ((userbits & TIOCFLAG_CLOCAL) != 0) {
919			cs->cs_softcar = 0; 	/* turn off softcar */
920			cs->cs_preg[15] |= ZSWR15_DCD_IE; /* turn on dcd */
921			cs->cs_creg[15] |= ZSWR15_DCD_IE;
922			ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
923			tp->t_termios.c_cflag |= CLOCAL;
924		}
925		if ((userbits & TIOCFLAG_CRTSCTS) != 0) {
926			cs->cs_preg[15] |= ZSWR15_CTS_IE;
927			cs->cs_creg[15] |= ZSWR15_CTS_IE;
928			ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
929			cs->cs_preg[3] |= ZSWR3_HFC;
930			cs->cs_creg[3] |= ZSWR3_HFC;
931			ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]);
932			tp->t_termios.c_cflag |= CRTSCTS;
933		} else {
934			/* no mdmbuf, so we must want software flow control */
935			cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
936			cs->cs_creg[15] &= ~ZSWR15_CTS_IE;
937			ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
938			cs->cs_preg[3] &= ~ZSWR3_HFC;
939			cs->cs_creg[3] &= ~ZSWR3_HFC;
940			ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]);
941			tp->t_termios.c_cflag &= ~CRTSCTS;
942		}
943		splx(s);
944		break;
945	}
946	case TIOCSDTR:
947		zs_modem(cs, ZSWR5_DTR, DMBIS);
948		break;
949	case TIOCCDTR:
950		zs_modem(cs, ZSWR5_DTR, DMBIC);
951		break;
952	case TIOCMGET:
953		zs_modem(cs, 0, DMGET);
954		break;
955	case TIOCMSET:
956	case TIOCMBIS:
957	case TIOCMBIC:
958	default:
959		return EPASSTHROUGH;
960	}
961	return 0;
962}
963
964/*
965 * Start or restart transmission.
966 */
967static void
968zsstart(struct tty *tp)
969{
970	struct zs_chanstate *cs;
971	int s, nch;
972	int unit = ZS_UNIT(tp->t_dev);
973	struct zs_softc *sc = device_lookup_private(&zs_cd, unit >> 1);
974
975	cs = sc->sc_cs[unit & 1];
976	s  = spltty();
977
978	/*
979	 * If currently active or delaying, no need to do anything.
980	 */
981	if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) != 0)
982		goto out;
983
984	/*
985	 * If there are sleepers, and output has drained below low
986	 * water mark, awaken.
987	 */
988	ttypull(tp);
989
990	nch = ndqb(&tp->t_outq, 0);	/* XXX */
991	if (nch) {
992		char *p = tp->t_outq.c_cf;
993
994		/* mark busy, enable tx done interrupts, & send first byte */
995		tp->t_state |= TS_BUSY;
996		(void)splzs();
997		cs->cs_preg[1] |= ZSWR1_TIE;
998		cs->cs_creg[1] |= ZSWR1_TIE;
999		ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
1000		cs->cs_zc->zc_data = *p;
1001		cs->cs_tba = p + 1;
1002		cs->cs_tbc = nch - 1;
1003	} else {
1004		/*
1005		 * Nothing to send, turn off transmit done interrupts.
1006		 * This is useful if something is doing polled output.
1007		 */
1008		(void)splzs();
1009		cs->cs_preg[1] &= ~ZSWR1_TIE;
1010		cs->cs_creg[1] &= ~ZSWR1_TIE;
1011		ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
1012	}
1013out:
1014	splx(s);
1015}
1016
1017/*
1018 * Stop output, e.g., for ^S or output flush.
1019 */
1020void
1021zsstop(struct tty *tp, int flag)
1022{
1023	struct zs_chanstate *cs;
1024	int s, unit = ZS_UNIT(tp->t_dev);
1025	struct zs_softc *sc = device_lookup_private(&zs_cd, unit >> 1);
1026
1027	cs = sc->sc_cs[unit & 1];
1028	s  = splzs();
1029	if ((tp->t_state & TS_BUSY) != 0) {
1030		/*
1031		 * Device is transmitting; must stop it.
1032		 */
1033		cs->cs_tbc = 0;
1034		if ((tp->t_state & TS_TTSTOP) == 0)
1035			tp->t_state |= TS_FLUSH;
1036	}
1037	splx(s);
1038}
1039
1040static void
1041zs_shutdown(struct zs_chanstate *cs)
1042{
1043	struct tty *tp = cs->cs_ttyp;
1044	int s;
1045
1046	s = splzs();
1047
1048	/*
1049	 * Hang up if necessary.  Wait a bit, so the other side has time to
1050	 * notice even if we immediately open the port again.
1051	 */
1052	if ((tp->t_cflag & HUPCL) != 0) {
1053		zs_modem(cs, 0, DMSET);
1054		(void)tsleep((void *)cs, TTIPRI, ttclos, hz);
1055	}
1056
1057	/* Clear any break condition set with TIOCSBRK. */
1058	if ((cs->cs_creg[5] & ZSWR5_BREAK) != 0) {
1059		cs->cs_preg[5] &= ~ZSWR5_BREAK;
1060		cs->cs_creg[5] &= ~ZSWR5_BREAK;
1061		ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
1062	}
1063
1064	/*
1065	 * Drop all lines and cancel interrupts
1066	 */
1067	zs_loadchannelregs(cs->cs_zc, zs_init_regs);
1068	splx(s);
1069}
1070
1071/*
1072 * Set ZS tty parameters from termios.
1073 *
1074 * This routine makes use of the fact that only registers
1075 * 1, 3, 4, 5, 9, 10, 11, 12, 13, 14, and 15 are written.
1076 */
1077static int
1078zsparam(struct tty *tp, struct termios *t)
1079{
1080	int unit = ZS_UNIT(tp->t_dev);
1081	struct zs_softc *sc = device_lookup_private(&zs_cd, unit >> 1);
1082	struct zs_chanstate *cs = sc->sc_cs[unit & 1];
1083	int cdiv = 0;	/* XXX gcc4 -Wuninitialized */
1084	int clkm = 0;	/* XXX gcc4 -Wuninitialized */
1085	int brgm = 0;	/* XXX gcc4 -Wuninitialized */
1086	int tcon = 0;	/* XXX gcc4 -Wuninitialized */
1087	int tmp, tmp5, cflag, s;
1088
1089	tmp  = t->c_ospeed;
1090	tmp5 = t->c_ispeed;
1091	if (tmp < 0 || (tmp5 && tmp5 != tmp))
1092		return EINVAL;
1093	if (tmp == 0) {
1094		/* stty 0 => drop DTR and RTS */
1095		zs_modem(cs, 0, DMSET);
1096		return 0;
1097	}
1098	tmp = zsbaudrate(unit, tmp, &cdiv, &clkm, &brgm, &tcon);
1099	if (tmp < 0)
1100		return EINVAL;
1101	tp->t_ispeed = tp->t_ospeed = tmp;
1102
1103	cflag = tp->t_cflag = t->c_cflag;
1104	if ((cflag & CSTOPB) != 0)
1105		cdiv |= ZSWR4_TWOSB;
1106	else
1107		cdiv |= ZSWR4_ONESB;
1108	if ((cflag & PARODD) == 0)
1109		cdiv |= ZSWR4_EVENP;
1110	if ((cflag & PARENB) != 0)
1111		cdiv |= ZSWR4_PARENB;
1112
1113	switch (cflag & CSIZE) {
1114	case CS5:
1115		tmp  = ZSWR3_RX_5;
1116		tmp5 = ZSWR5_TX_5;
1117		break;
1118	case CS6:
1119		tmp  = ZSWR3_RX_6;
1120		tmp5 = ZSWR5_TX_6;
1121		break;
1122	case CS7:
1123		tmp  = ZSWR3_RX_7;
1124		tmp5 = ZSWR5_TX_7;
1125		break;
1126	case CS8:
1127	default:
1128		tmp  = ZSWR3_RX_8;
1129		tmp5 = ZSWR5_TX_8;
1130		break;
1131	}
1132	tmp  |= ZSWR3_RX_ENABLE;
1133	tmp5 |= ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
1134
1135	/*
1136	 * Block interrupts so that state will not
1137	 * be altered until we are done setting it up.
1138	 */
1139	s = splzs();
1140	cs->cs_preg[4]  = cdiv;
1141	cs->cs_preg[11] = clkm;
1142	cs->cs_preg[12] = tcon;
1143	cs->cs_preg[13] = tcon >> 8;
1144	cs->cs_preg[14] = brgm;
1145	cs->cs_preg[1]  = ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE;
1146	cs->cs_preg[9]  = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT;
1147	cs->cs_preg[10] = ZSWR10_NRZ;
1148	cs->cs_preg[15] = ZSWR15_BREAK_IE | ZSWR15_DCD_IE;
1149
1150	/*
1151	 * Output hardware flow control on the chip is horrendous: if
1152	 * carrier detect drops, the receiver is disabled.  Hence we
1153	 * can only do this when the carrier is on.
1154	 */
1155	if ((cflag & CCTS_OFLOW) != 0 &&
1156	    (cs->cs_zc->zc_csr & ZSRR0_DCD) != 0)
1157		tmp |= ZSWR3_HFC;
1158	cs->cs_preg[3] = tmp;
1159	cs->cs_preg[5] = tmp5;
1160
1161	/*
1162	 * If nothing is being transmitted, set up new current values,
1163	 * else mark them as pending.
1164	 */
1165	if (cs->cs_heldchange == 0) {
1166		if ((cs->cs_ttyp->t_state & TS_BUSY) != 0) {
1167			cs->cs_heldtbc = cs->cs_tbc;
1168			cs->cs_tbc = 0;
1169			cs->cs_heldchange = 1;
1170		} else {
1171			memcpy((void *)cs->cs_creg, (void *)cs->cs_preg, 16);
1172			zs_loadchannelregs(cs->cs_zc, cs->cs_creg);
1173		}
1174	}
1175	splx(s);
1176	return 0;
1177}
1178
1179/*
1180 * search for the best matching baudrate
1181 */
1182static int
1183zsbaudrate(int unit, int wanted, int *divisor, int *clockmode, int *brgenmode,
1184    int *timeconst)
1185{
1186	int bestdiff, bestbps, source;
1187
1188	bestdiff = bestbps = 0;
1189	unit = (unit & 1) << 2;
1190	for (source = 0; source < 4; ++source) {
1191		u_long freq = zs_frequencies[unit + source];
1192		int diff, bps, div, clkm, brgm, tcon;
1193
1194		bps = div = clkm = brgm = tcon = 0;
1195		switch (source) {
1196		case 0:	/* BRgen, PCLK */
1197			brgm = ZSWR14_BAUD_ENA|ZSWR14_BAUD_FROM_PCLK;
1198			break;
1199		case 1:	/* BRgen, RTxC */
1200			brgm = ZSWR14_BAUD_ENA;
1201			break;
1202		case 2: /* RTxC */
1203			clkm = ZSWR11_RXCLK_RTXC|ZSWR11_TXCLK_RTXC;
1204			break;
1205		case 3: /* TRxC */
1206			clkm = ZSWR11_RXCLK_TRXC|ZSWR11_TXCLK_TRXC;
1207			break;
1208		}
1209		switch (source) {
1210		case 0:
1211		case 1:
1212			div  = ZSWR4_CLK_X16;
1213			clkm = ZSWR11_RXCLK_BAUD|ZSWR11_TXCLK_BAUD;
1214			tcon = BPS_TO_TCONST(freq, wanted);
1215			if (tcon < 0)
1216				tcon = 0;
1217			bps  = TCONST_TO_BPS(freq, tcon);
1218			break;
1219		case 2:
1220		case 3:
1221		    {
1222			int b1 = freq / 16, d1 = abs(b1 - wanted);
1223			int b2 = freq / 32, d2 = abs(b2 - wanted);
1224			int b3 = freq / 64, d3 = abs(b3 - wanted);
1225
1226			if (d1 < d2 && d1 < d3) {
1227				div = ZSWR4_CLK_X16;
1228				bps = b1;
1229			} else if (d2 < d3 && d2 < d1) {
1230				div = ZSWR4_CLK_X32;
1231				bps = b2;
1232			} else {
1233				div = ZSWR4_CLK_X64;
1234				bps = b3;
1235			}
1236			brgm = tcon = 0;
1237			break;
1238		    }
1239		}
1240		diff = abs(bps - wanted);
1241		if (!source || diff < bestdiff) {
1242			*divisor   = div;
1243			*clockmode = clkm;
1244			*brgenmode = brgm;
1245			*timeconst = tcon;
1246			bestbps    = bps;
1247			bestdiff   = diff;
1248			if (diff == 0)
1249				break;
1250		}
1251	}
1252	/* Allow deviations upto 5% */
1253	if (20 * bestdiff > wanted)
1254		return -1;
1255	return bestbps;
1256}
1257
1258/*
1259 * Raise or lower modem control (DTR/RTS) signals.  If a character is
1260 * in transmission, the change is deferred.
1261 */
1262static int
1263zs_modem(struct zs_chanstate *cs, int bits, int how)
1264{
1265	int s, mbits;
1266
1267	bits  &= ZSWR5_DTR | ZSWR5_RTS;
1268
1269	s = splzs();
1270	mbits  = cs->cs_preg[5] &  (ZSWR5_DTR | ZSWR5_RTS);
1271
1272	switch (how) {
1273	case DMSET:
1274		mbits  = bits;
1275		break;
1276	case DMBIS:
1277		mbits |= bits;
1278		break;
1279	case DMBIC:
1280		mbits &= ~bits;
1281		break;
1282	case DMGET:
1283		splx(s);
1284		return mbits;
1285	}
1286
1287	cs->cs_preg[5] = (cs->cs_preg[5] & ~(ZSWR5_DTR | ZSWR5_RTS)) | mbits;
1288	if (cs->cs_heldchange == 0) {
1289		if ((cs->cs_ttyp->t_state & TS_BUSY) != 0) {
1290			cs->cs_heldtbc = cs->cs_tbc;
1291			cs->cs_tbc = 0;
1292			cs->cs_heldchange = 1;
1293		} else {
1294			ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
1295		}
1296	}
1297	splx(s);
1298	return 0;
1299}
1300
1301/*
1302 * Write the given register set to the given zs channel in the proper order.
1303 * The channel must not be transmitting at the time.  The receiver will
1304 * be disabled for the time it takes to write all the registers.
1305 */
1306static void
1307zs_loadchannelregs(struct zschan *zc, uint8_t *reg)
1308{
1309	int i;
1310
1311	zc->zc_csr = ZSM_RESET_ERR;	/* reset error condition */
1312	i = zc->zc_data;		/* drain fifo */
1313	i = zc->zc_data;
1314	i = zc->zc_data;
1315	ZS_WRITE(zc,  4, reg[4]);
1316	ZS_WRITE(zc, 10, reg[10]);
1317	ZS_WRITE(zc,  3, reg[3] & ~ZSWR3_RX_ENABLE);
1318	ZS_WRITE(zc,  5, reg[5] & ~ZSWR5_TX_ENABLE);
1319	ZS_WRITE(zc,  1, reg[1]);
1320	ZS_WRITE(zc,  9, reg[9]);
1321	ZS_WRITE(zc, 11, reg[11]);
1322	ZS_WRITE(zc, 12, reg[12]);
1323	ZS_WRITE(zc, 13, reg[13]);
1324	ZS_WRITE(zc, 14, reg[14]);
1325	ZS_WRITE(zc, 15, reg[15]);
1326	ZS_WRITE(zc,  3, reg[3]);
1327	ZS_WRITE(zc,  5, reg[5]);
1328}
1329#endif /* NZS > 1 */
1330