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