1/*	$OpenBSD: zs.c,v 1.33 2023/01/04 09:34:26 jsg Exp $	*/
2/*	$NetBSD: zs.c,v 1.17 2001/06/19 13:42:15 wiz Exp $	*/
3
4/*
5 * Copyright (c) 1996, 1998 Bill Studenmund
6 * Copyright (c) 1995 Gordon W. Ross
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * Zilog Z8530 Dual UART driver (machine-dependent part)
32 *
33 * Runs two serial lines per chip using slave drivers.
34 * Plain tty/async lines use the zstty slave.
35 * Sun keyboard/mouse uses the zskbd/zsms slaves.
36 * Other ports use their own mice & keyboard slaves.
37 *
38 * Credits & history:
39 *
40 * With NetBSD 1.1, port-mac68k started using a port of the port-sparc
41 * (port-sun3?) zs.c driver (which was in turn based on code in the
42 * Berkeley 4.4 Lite release). Bill Studenmund did the port, with
43 * help from Allen Briggs and Gordon Ross <gwr@netbsd.org>. Noud de
44 * Brouwer field-tested the driver at a local ISP.
45 *
46 * Bill Studenmund and Gordon Ross then ported the machine-independent
47 * z8530 driver to work with port-mac68k. NetBSD 1.2 contained an
48 * intermediate version (mac68k using a local, patched version of
49 * the m.i. drivers), with NetBSD 1.3 containing a full version.
50 */
51
52#include <sys/param.h>
53#include <sys/systm.h>
54#include <sys/proc.h>
55#include <sys/device.h>
56#include <sys/conf.h>
57#include <sys/ioctl.h>
58#include <sys/tty.h>
59#include <sys/time.h>
60#include <sys/kernel.h>
61#include <sys/syslog.h>
62
63#include <dev/cons.h>
64#include <dev/ofw/openfirm.h>
65#include <dev/ic/z8530reg.h>
66
67#include <machine/z8530var.h>
68#include <machine/autoconf.h>
69#include <machine/cpu.h>
70
71#include "zs.h"
72
73/*
74 * Some warts needed by z8530tty.c -
75 */
76int zs_def_cflag = (CREAD | CS8 | HUPCL);
77int zs_major = 7;
78
79struct zsdevice {
80	/* Yes, they are backwards. */
81	struct	zschan zs_chan_b;
82	struct	zschan zs_chan_a;
83};
84
85/* Flags from cninit() */
86static int zs_hwflags[NZS][2];
87/* Default speed for each channel */
88static int zs_defspeed[NZS][2] = {
89	{ 38400,	/* tty00 */
90	  38400 },	/* tty01 */
91};
92
93/* console stuff */
94void	*zs_conschan = 0;
95#ifdef	ZS_CONSOLE_ABORT
96int	zs_cons_canabort = 1;
97#else
98int	zs_cons_canabort = 0;
99#endif /* ZS_CONSOLE_ABORT*/
100
101/* device to which the console is attached--if serial. */
102/* Mac stuff */
103
104int zs_get_speed(struct zs_chanstate *);
105
106/*
107 * Even though zsparam will set up the clock multiples, etc., we
108 * still set them here as: 1) mice & keyboards don't use zsparam,
109 * and 2) the console stuff uses these defaults before device
110 * attach.
111 */
112
113static u_char zs_init_reg[16] = {
114	0,	/* 0: CMD (reset, etc.) */
115	ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE, 	/* 1: No interrupts yet. ??? */
116	0,	/* IVECT */
117	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
118	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
119	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
120	0,	/* 6: TXSYNC/SYNCLO */
121	0,	/* 7: RXSYNC/SYNCHI */
122	0,	/* 8: alias for data port */
123	ZSWR9_MASTER_IE,
124	0,	/*10: Misc. TX/RX control bits */
125	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
126	((PCLK/32)/38400)-2,	/*12: BAUDLO (default=38400) */
127	0,			/*13: BAUDHI (default=38400) */
128	ZSWR14_BAUD_ENA,
129	ZSWR15_BREAK_IE,
130};
131
132/****************************************************************
133 * Autoconfig
134 ****************************************************************/
135
136struct cfdriver zs_cd = {
137	NULL, "zs", DV_TTY
138};
139
140/* Definition of the driver for autoconfig. */
141int	zs_match(struct device *, void *, void *);
142void	zs_attach(struct device *, struct device *, void *);
143int	zs_print(void *, const char *name);
144
145/* Power management hooks */
146int  zs_enable (struct zs_chanstate *);
147void zs_disable (struct zs_chanstate *);
148
149const struct cfattach zs_ca = {
150	sizeof(struct zsc_softc), zs_match, zs_attach
151};
152
153int zshard(void *);
154void zssoft(void *);
155#ifdef ZS_TXDMA
156int zs_txdma_int(void *);
157#endif
158
159/*
160 * Is the zs chip present?
161 */
162int
163zs_match(struct device *parent, void *match, void *aux)
164{
165	struct confargs *ca = aux;
166	struct cfdata *cf = match;
167
168	if (strcmp(ca->ca_name, "escc") != 0)
169		return 0;
170
171	if (ca->ca_nreg < 8)
172		return 0;
173
174	if (cf->cf_unit > 1)
175		return 0;
176
177	return 1;
178}
179
180/*
181 * Attach a found zs.
182 *
183 * Match slave number to zs unit number, so that misconfiguration will
184 * not set up the keyboard as ttya, etc.
185 */
186void
187zs_attach(struct device *parent, struct device *self, void *aux)
188{
189	struct zsc_softc *zsc = (void *)self;
190	struct confargs *ca = aux;
191	struct zsc_attach_args zsc_args;
192	volatile struct zschan *zc;
193	struct xzs_chanstate *xcs;
194	struct zs_chanstate *cs;
195	struct zsdevice *zsd;
196	int zs_unit, channel;
197	int s;
198	int node, intr[3][3];
199	u_int regs[16];
200
201	zs_unit = zsc->zsc_dev.dv_unit;
202
203	zsd = mapiodev(ca->ca_baseaddr + ca->ca_reg[0], ca->ca_reg[1]);
204	node = OF_child(ca->ca_node);	/* ch-a */
205
206	for (channel = 0; channel < 2; channel++) {
207		if (OF_getprop(node, "AAPL,interrupts",
208			       intr[channel], sizeof(intr[0])) == -1 &&
209		    OF_getprop(node, "interrupts",
210			       intr[channel], sizeof(intr[0])) == -1) {
211			printf(": cannot find interrupt property\n");
212			return;
213		}
214
215		if (OF_getprop(node, "reg", regs, sizeof(regs)) < 24) {
216			printf(": cannot find reg property\n");
217			return;
218		}
219		regs[2] += ca->ca_baseaddr;
220		regs[4] += ca->ca_baseaddr;
221#ifdef ZS_TXDMA
222		zsc->zsc_txdmareg[channel] = mapiodev(regs[2], regs[3]);
223		zsc->zsc_txdmacmd[channel] =
224			dbdma_alloc(sizeof(dbdma_command_t) * 3);
225		memset(zsc->zsc_txdmacmd[channel], 0,
226			sizeof(dbdma_command_t) * 3);
227		dbdma_reset(zsc->zsc_txdmareg[channel]);
228#endif
229		node = OF_peer(node);	/* ch-b */
230	}
231
232	printf(": irq %d,%d\n", intr[0][0], intr[1][0]);
233
234	/*
235	 * Initialize software state for each channel.
236	 */
237	for (channel = 0; channel < 2; channel++) {
238		zsc_args.channel = channel;
239		zsc_args.hwflags = zs_hwflags[zs_unit][channel];
240		xcs = &zsc->xzsc_xcs_store[channel];
241		cs  = &xcs->xzs_cs;
242		zsc->zsc_cs[channel] = cs;
243
244		cs->cs_channel = channel;
245		cs->cs_private = NULL;
246		cs->cs_ops = &zsops_null;
247
248		zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b;
249
250		cs->cs_reg_csr  = &zc->zc_csr;
251		cs->cs_reg_data = &zc->zc_data;
252
253		memcpy(cs->cs_creg, zs_init_reg, 16);
254		memcpy(cs->cs_preg, zs_init_reg, 16);
255
256		/* Current BAUD rate generator clock. */
257		/* RTxC is 230400*16, so use 230400 */
258		cs->cs_brg_clk = PCLK / 16;
259		if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
260			cs->cs_defspeed = zs_get_speed(cs);
261		else
262			cs->cs_defspeed =
263			    zs_defspeed[zs_unit][channel];
264		cs->cs_defcflag = zs_def_cflag;
265
266		/* Make these correspond to cs_defcflag (-crtscts) */
267		cs->cs_rr0_dcd = ZSRR0_DCD;
268		cs->cs_rr0_cts = 0;
269		cs->cs_wr5_dtr = ZSWR5_DTR;
270		cs->cs_wr5_rts = 0;
271
272#ifdef __notyet__
273		cs->cs_slave_type = ZS_SLAVE_NONE;
274#endif
275
276		/* Define BAUD rate stuff. */
277		xcs->cs_clocks[0].clk = PCLK;
278		xcs->cs_clocks[0].flags = ZSC_RTXBRG | ZSC_RTXDIV;
279		xcs->cs_clocks[1].flags =
280			ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
281		xcs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
282		xcs->cs_clock_count = 3;
283		if (channel == 0) {
284			/*xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;*/
285			/*xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;*/
286			xcs->cs_clocks[1].clk = 0;
287			xcs->cs_clocks[2].clk = 0;
288		} else {
289			xcs->cs_clocks[1].flags = ZSC_VARIABLE;
290			/*
291			 * Yes, we aren't defining ANY clock source enables for the
292			 * printer's DCD clock in. The hardware won't let us
293			 * use it. But a clock will freak out the chip, so we
294			 * let you set it, telling us to bar interrupts on the line.
295			 */
296			/*xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;*/
297			/*xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;*/
298			xcs->cs_clocks[1].clk = 0;
299			xcs->cs_clocks[2].clk = 0;
300		}
301		if (xcs->cs_clocks[1].clk)
302			zsc_args.hwflags |= ZS_HWFLAG_NO_DCD;
303		if (xcs->cs_clocks[2].clk)
304			zsc_args.hwflags |= ZS_HWFLAG_NO_CTS;
305
306		/* Set defaults in our "extended" chanstate. */
307		xcs->cs_csource = 0;
308		xcs->cs_psource = 0;
309		xcs->cs_cclk_flag = 0;  /* Nothing fancy by default */
310		xcs->cs_pclk_flag = 0;
311
312		/*
313		 * We used to disable chip interrupts here, but we now
314		 * do that in zscnprobe, just in case MacOS left the chip on.
315		 */
316
317		xcs->cs_chip = 0;
318
319		/* Stash away a copy of the final H/W flags. */
320		xcs->cs_hwflags = zsc_args.hwflags;
321
322		/*
323		 * Look for a child driver for this channel.
324		 * The child attach will setup the hardware.
325		 */
326		if (!config_found(self, (void *)&zsc_args, zs_print)) {
327			/* No sub-driver.  Just reset it. */
328			u_char reset = (channel == 0) ?
329				ZSWR9_A_RESET : ZSWR9_B_RESET;
330			s = splzs();
331			zs_write_reg(cs, 9, reset);
332			splx(s);
333		}
334	}
335
336	/* XXX - Now safe to install interrupt handlers. */
337	mac_intr_establish(parent, intr[0][0], IST_LEVEL, IPL_TTY,
338	    zshard, NULL, "zs0");
339	mac_intr_establish(parent, intr[1][0], IST_LEVEL, IPL_TTY,
340	    zshard, NULL, "zs1");
341#ifdef ZS_TXDMA
342	mac_intr_establish(parent, intr[0][1], IST_LEVEL, IPL_TTY,
343	    zs_txdma_int, NULL, "zsdma0");
344	mac_intr_establish(parent, intr[1][1], IST_LEVEL, IPL_TTY,
345	    zs_txdma_int, (void *)1, "zsdma1");
346#endif
347	zsc->zsc_softintr = softintr_establish(IPL_SOFTTTY, zssoft, zsc);
348	if (zsc->zsc_softintr == NULL)
349		panic("zsattach: could not establish soft interrupt");
350
351	/*
352	 * Set the master interrupt enable and interrupt vector.
353	 * (common to both channels, do it on A)
354	 */
355	cs = zsc->zsc_cs[0];
356	s = splzs();
357	/* interrupt vector */
358	zs_write_reg(cs, 2, zs_init_reg[2]);
359	/* master interrupt control (enable) */
360	zs_write_reg(cs, 9, zs_init_reg[9]);
361	splx(s);
362
363	/* connect power management for port 0 */
364	cs->enable = zs_enable;
365	cs->disable = zs_disable;
366}
367
368int
369zs_print(void *aux, const char *name)
370{
371	struct zsc_attach_args *args = aux;
372
373	if (name != NULL)
374		printf("%s: ", name);
375
376	if (args->channel != -1)
377		printf(" channel %d", args->channel);
378
379	return UNCONF;
380}
381
382int
383zsmdioctl(struct zs_chanstate *cs, u_long cmd, caddr_t data)
384{
385	switch (cmd) {
386	default:
387		return (-1);
388	}
389	return (0);
390}
391
392void
393zsmd_setclock(struct zs_chanstate *cs)
394{
395#ifdef NOTYET
396	struct xzs_chanstate *xcs = (void *)cs;
397
398	if (cs->cs_channel != 0)
399		return;
400
401	/*
402	 * If the new clock has the external bit set, then select the
403	 * external source.
404	 */
405	via_set_modem((xcs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0);
406#endif
407}
408
409static int zssoftpending;
410
411/*
412 * Our ZS chips all share a common, autovectored interrupt,
413 * so we have to look at all of them on each interrupt.
414 */
415int
416zshard(void *arg)
417{
418	struct zsc_softc *zsc;
419	int unit, rval;
420
421	rval = 0;
422	for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
423		zsc = zs_cd.cd_devs[unit];
424		if (zsc == NULL)
425			continue;
426		rval |= zsc_intr_hard(zsc);
427		if (zsc->zsc_cs[0]->cs_softreq)
428		{
429			/* zs_req_softint(zsc); */
430			/* We are at splzs here, so no need to lock. */
431			if (zssoftpending == 0) {
432				zssoftpending = 1;
433				softintr_schedule(zsc->zsc_softintr);
434			}
435		}
436	}
437	return (rval);
438}
439
440/*
441 * Similar scheme as for zshard (look at all of them)
442 */
443void
444zssoft(void *arg)
445{
446	struct zsc_softc *zsc;
447	int unit;
448
449	/* This is not the only ISR on this IPL. */
450	if (zssoftpending == 0)
451		return;
452
453	/*
454	 * The soft intr. bit will be set by zshard only if
455	 * the variable zssoftpending is zero.
456	 */
457	zssoftpending = 0;
458
459	for (unit = 0; unit < zs_cd.cd_ndevs; ++unit) {
460		zsc = zs_cd.cd_devs[unit];
461		if (zsc == NULL)
462			continue;
463		(void) zsc_intr_soft(zsc);
464	}
465}
466
467#ifdef ZS_TXDMA
468int
469zs_txdma_int(void *arg)
470{
471	int ch = (int)arg;
472	struct zsc_softc *zsc;
473	struct zs_chanstate *cs;
474	int unit = 0;			/* XXX */
475	extern int zstty_txdma_int();
476
477	zsc = zs_cd.cd_devs[unit];
478	if (zsc == NULL)
479		panic("zs_txdma_int");
480
481	cs = zsc->zsc_cs[ch];
482	zstty_txdma_int(cs);
483
484	if (cs->cs_softreq) {
485		if (zssoftpending == 0) {
486			zssoftpending = 1;
487			softintr_schedule(zsc->zsc_softintr);
488		}
489	}
490	return 1;
491}
492
493void
494zs_dma_setup(struct zs_chanstate *cs, caddr_t pa, int len)
495{
496	struct zsc_softc *zsc;
497	dbdma_command_t *cmdp;
498	int ch = cs->cs_channel;
499
500	zsc = zs_cd.cd_devs[ch];
501	cmdp = zsc->zsc_txdmacmd[ch];
502
503	DBDMA_BUILD(cmdp, DBDMA_CMD_OUT_LAST, 0, len, kvtop(pa),
504		DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
505	cmdp++;
506	DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
507		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
508
509	__asm volatile("eieio");
510
511	dbdma_start(zsc->zsc_txdmareg[ch], zsc->zsc_txdmacmd[ch]);
512}
513#endif
514
515/*
516 * Compute the current baud rate given a ZS channel.
517 * XXX Assume internal BRG.
518 */
519int
520zs_get_speed(struct zs_chanstate *cs)
521{
522	int tconst;
523
524	tconst = zs_read_reg(cs, 12);
525	tconst |= zs_read_reg(cs, 13) << 8;
526	return TCONST_TO_BPS(cs->cs_brg_clk, tconst);
527}
528
529#ifndef ZS_TOLERANCE
530#define ZS_TOLERANCE 51
531/* 5% in tenths of a %, plus 1 so that exactly 5% will be ok. */
532#endif
533
534/*
535 * Search through the signal sources in the channel, and
536 * pick the best one for the baud rate requested. Return
537 * a -1 if not achievable in tolerance. Otherwise return 0
538 * and fill in the values.
539 *
540 * This routine draws inspiration from the Atari port's zs.c
541 * driver in NetBSD 1.1 which did the same type of source switching.
542 * Tolerance code inspired by comspeed routine in isa/com.c.
543 *
544 * By Bill Studenmund, 1996-05-12
545 */
546int
547zs_set_speed(struct zs_chanstate *cs, int bps)
548{
549	struct xzs_chanstate *xcs = (void *)cs;
550	int i, tc, tc0 = 0, tc1, s, sf = 0;
551	int src, rate0, rate1, err, tol;
552
553	if (bps == 0)
554		return (0);
555
556	src = -1;		/* no valid source yet */
557	tol = ZS_TOLERANCE;
558
559	/*
560	 * Step through all the sources and see which one matches
561	 * the best. A source has to match BETTER than tol to be chosen.
562	 * Thus if two sources give the same error, the first one will be
563	 * chosen. Also, allow for the possibility that one source might run
564	 * both the BRG and the direct divider (i.e. RTxC).
565	 */
566	for (i = 0; i < xcs->cs_clock_count; i++) {
567		if (xcs->cs_clocks[i].clk <= 0)
568			continue;	/* skip non-existent or bad clocks */
569		if (xcs->cs_clocks[i].flags & ZSC_BRG) {
570			/* check out BRG at /16 */
571			tc1 = BPS_TO_TCONST(xcs->cs_clocks[i].clk >> 4, bps);
572			if (tc1 >= 0) {
573				rate1 = TCONST_TO_BPS(xcs->cs_clocks[i].clk >> 4, tc1);
574				err = abs(((rate1 - bps)*1000)/bps);
575				if (err < tol) {
576					tol = err;
577					src = i;
578					sf = xcs->cs_clocks[i].flags & ~ZSC_DIV;
579					tc0 = tc1;
580					rate0 = rate1;
581				}
582			}
583		}
584		if (xcs->cs_clocks[i].flags & ZSC_DIV) {
585			/*
586			 * Check out either /1, /16, /32, or /64
587			 * Note: for /1, you'd better be using a synchronized
588			 * clock!
589			 */
590			int b0 = xcs->cs_clocks[i].clk, e0 = abs(b0-bps);
591			int b1 = b0 >> 4, e1 = abs(b1-bps);
592			int b2 = b1 >> 1, e2 = abs(b2-bps);
593			int b3 = b2 >> 1, e3 = abs(b3-bps);
594
595			if (e0 < e1 && e0 < e2 && e0 < e3) {
596				err = e0;
597				rate1 = b0;
598				tc1 = ZSWR4_CLK_X1;
599			} else if (e0 > e1 && e1 < e2  && e1 < e3) {
600				err = e1;
601				rate1 = b1;
602				tc1 = ZSWR4_CLK_X16;
603			} else if (e0 > e2 && e1 > e2 && e2 < e3) {
604				err = e2;
605				rate1 = b2;
606				tc1 = ZSWR4_CLK_X32;
607			} else {
608				err = e3;
609				rate1 = b3;
610				tc1 = ZSWR4_CLK_X64;
611			}
612
613			err = (err * 1000)/bps;
614			if (err < tol) {
615				tol = err;
616				src = i;
617				sf = xcs->cs_clocks[i].flags & ~ZSC_BRG;
618				tc0 = tc1;
619				rate0 = rate1;
620			}
621		}
622	}
623#ifdef ZSMACDEBUG
624	printf("Checking for rate %d. Found source #%d.\n",bps, src);
625#endif
626	if (src == -1)
627		return (EINVAL); /* no can do */
628
629	/*
630	 * The M.I. layer likes to keep cs_brg_clk current, even though
631	 * we are the only ones who should be touching the BRG's rate.
632	 *
633	 * Note: we are assuming that any ZSC_EXTERN signal source comes in
634	 * on the RTxC pin. Correct for the mac68k obio zsc.
635	 */
636	if (sf & ZSC_EXTERN)
637		cs->cs_brg_clk = xcs->cs_clocks[i].clk >> 4;
638	else
639		cs->cs_brg_clk = PCLK / 16;
640
641	/*
642	 * Now we have a source, so set it up.
643	 */
644	s = splzs();
645	xcs->cs_psource = src;
646	xcs->cs_pclk_flag = sf;
647	bps = rate0;
648	if (sf & ZSC_BRG) {
649		cs->cs_preg[4] = ZSWR4_CLK_X16;
650		cs->cs_preg[11]= ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD;
651		if (sf & ZSC_PCLK) {
652			cs->cs_preg[14] = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK;
653		} else {
654			cs->cs_preg[14] = ZSWR14_BAUD_ENA;
655		}
656		tc = tc0;
657	} else {
658		cs->cs_preg[4] = tc0;
659		if (sf & ZSC_RTXDIV) {
660			cs->cs_preg[11] = ZSWR11_RXCLK_RTXC | ZSWR11_TXCLK_RTXC;
661		} else {
662			cs->cs_preg[11] = ZSWR11_RXCLK_TRXC | ZSWR11_TXCLK_TRXC;
663		}
664		cs->cs_preg[14]= 0;
665		tc = 0xffff;
666	}
667	/* Set the BAUD rate divisor. */
668	cs->cs_preg[12] = tc;
669	cs->cs_preg[13] = tc >> 8;
670	splx(s);
671
672#ifdef ZSMACDEBUG
673	printf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \
674	    bps, tc, src, sf);
675	printf("Registers are: 4 %x, 11 %x, 14 %x\n\n",
676		cs->cs_preg[4], cs->cs_preg[11], cs->cs_preg[14]);
677#endif
678
679	cs->cs_preg[5] |= ZSWR5_RTS;	/* Make sure the drivers are on! */
680
681	/* Caller will stuff the pending registers. */
682	return (0);
683}
684
685int
686zs_set_modes(struct zs_chanstate *cs, int cflag)
687{
688	struct xzs_chanstate *xcs = (void*)cs;
689	int s;
690
691	/*
692	 * Make sure we don't enable hfc on a signal line we're ignoring.
693	 * As we enable CTS interrupts only if we have CRTSCTS or CDTRCTS,
694	 * this code also effectivly turns off ZSWR15_CTS_IE.
695	 *
696	 * Also, disable DCD interrupts if we've been told to ignore
697	 * the DCD pin. Happens on mac68k because the input line for
698	 * DCD can also be used as a clock input.  (Just set CLOCAL.)
699	 *
700	 * If someone tries to turn an invalid flow mode on, Just Say No
701	 * (Suggested by gwr)
702	 */
703	if (xcs->cs_hwflags & ZS_HWFLAG_NO_DCD) {
704		if (cflag & MDMBUF)
705			return (EINVAL);
706		cflag |= CLOCAL;
707	}
708#if 0
709	if ((xcs->cs_hwflags & ZS_HWFLAG_NO_CTS) && (cflag & CRTSCTS))
710		return (EINVAL);
711#endif
712
713	/*
714	 * Output hardware flow control on the chip is horrendous:
715	 * if carrier detect drops, the receiver is disabled, and if
716	 * CTS drops, the transmitter is stopped IN MID CHARACTER!
717	 * Therefore, NEVER set the HFC bit, and instead use the
718	 * status interrupt to detect CTS changes.
719	 */
720	s = splzs();
721	if ((cflag & (CLOCAL | MDMBUF)) != 0)
722		cs->cs_rr0_dcd = 0;
723	else
724		cs->cs_rr0_dcd = ZSRR0_DCD;
725	/*
726	 * The mac hardware only has one output, DTR (HSKo in Mac
727	 * parlance). In HFC mode, we use it for the functions
728	 * typically served by RTS and DTR on other ports, so we
729	 * have to fake the upper layer out some.
730	 *
731	 * CRTSCTS we use CTS as an input which tells us when to shut up.
732	 * We make no effort to shut up the other side of the connection.
733	 * DTR is used to hang up the modem.
734	 *
735	 * In CDTRCTS, we use CTS to tell us to stop, but we use DTR to
736	 * shut up the other side.
737	 */
738	if ((cflag & CRTSCTS) != 0) {
739		cs->cs_wr5_dtr = ZSWR5_DTR;
740		cs->cs_wr5_rts = 0;
741		cs->cs_rr0_cts = ZSRR0_CTS;
742#if 0
743	} else if ((cflag & CDTRCTS) != 0) {
744		cs->cs_wr5_dtr = 0;
745		cs->cs_wr5_rts = ZSWR5_DTR;
746		cs->cs_rr0_cts = ZSRR0_CTS;
747#endif
748	} else if ((cflag & MDMBUF) != 0) {
749		cs->cs_wr5_dtr = 0;
750		cs->cs_wr5_rts = ZSWR5_DTR;
751		cs->cs_rr0_cts = ZSRR0_DCD;
752	} else {
753		cs->cs_wr5_dtr = ZSWR5_DTR;
754		cs->cs_wr5_rts = 0;
755		cs->cs_rr0_cts = 0;
756	}
757	splx(s);
758
759	/* Caller will stuff the pending registers. */
760	return (0);
761}
762
763
764/*
765 * Read or write the chip with suitable delays.
766 * MacII hardware has the delay built in.
767 * No need for extra delay. :-) However, some clock-chirped
768 * macs, or zsc's on serial add-on boards might need it.
769 */
770#define	ZS_DELAY()
771
772u_char
773zs_read_reg(struct zs_chanstate *cs, u_char reg)
774{
775	u_char val;
776
777	out8(cs->cs_reg_csr, reg);
778	ZS_DELAY();
779	val = in8(cs->cs_reg_csr);
780	ZS_DELAY();
781	return val;
782}
783
784void
785zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val)
786{
787	out8(cs->cs_reg_csr, reg);
788	ZS_DELAY();
789	out8(cs->cs_reg_csr, val);
790	ZS_DELAY();
791}
792
793u_char
794zs_read_csr(struct zs_chanstate *cs)
795{
796	u_char val;
797
798	val = in8(cs->cs_reg_csr);
799	ZS_DELAY();
800	/* make up for the fact CTS is wired backwards */
801	val ^= ZSRR0_CTS;
802	return val;
803}
804
805void
806zs_write_csr(struct zs_chanstate *cs, u_char val)
807{
808	/* Note, the csr does not write CTS... */
809	out8(cs->cs_reg_csr, val);
810	ZS_DELAY();
811}
812
813u_char
814zs_read_data(struct zs_chanstate *cs)
815{
816	u_char val;
817
818	val = in8(cs->cs_reg_data);
819	ZS_DELAY();
820	return val;
821}
822
823void
824zs_write_data(struct zs_chanstate *cs, u_char val)
825{
826	out8(cs->cs_reg_data, val);
827	ZS_DELAY();
828}
829
830/*
831 * Power management hooks for zsopen() and zsclose().
832 * We use them to power on/off the ports, if necessary.
833 * This should be modified to turn on/off modem in PBG4, etc.
834 */
835void macobio_modem_power(int enable);
836
837int
838zs_enable(struct zs_chanstate *cs)
839{
840	macobio_modem_power(1); /* Whee */
841	cs->enabled = 1;
842	return(0);
843}
844
845void
846zs_disable(struct zs_chanstate *cs)
847{
848	macobio_modem_power(0); /* Whee */
849	cs->enabled = 0;
850}
851
852
853/****************************************************************
854 * Console support functions (powermac specific!)
855 * Note: this code is allowed to know about the layout of
856 * the chip registers, and uses that to keep things simple.
857 * XXX - I think I like the mvme167 code better. -gwr
858 * XXX - Well :-P  :-)  -wrs
859 ****************************************************************/
860
861cons_decl(zs);
862
863void	zs_putc(volatile struct zschan *, int);
864int	zs_getc(volatile struct zschan *);
865extern int	zsopen( dev_t dev, int flags, int mode, struct proc *p);
866
867static int stdin, stdout;
868
869/*
870 * Console functions.
871 */
872
873/*
874 * zscnprobe is the routine which gets called as the kernel is trying to
875 * figure out where the console should be. Each io driver which might
876 * be the console (as defined in mac68k/conf.c) gets probed. The probe
877 * fills in the consdev structure. Important parts are the device #,
878 * and the console priority. Values are CN_DEAD (don't touch me),
879 * CN_LOWPRI (I'm here, but elsewhere might be better), CN_MIDPRI
880 * (the video, better than CN_LOWPRI), and CN_HIGHPRI (pick me!)
881 *
882 * As the mac's a bit different, we do extra work here. We mainly check
883 * to see if we have serial echo going on. Also chould check for default
884 * speeds.
885 */
886
887/*
888 * Polled input char.
889 */
890int
891zs_getc(volatile struct zschan *zc)
892{
893	register int s, c, rr0;
894
895	s = splhigh();
896	/* Wait for a character to arrive. */
897	do {
898		rr0 = in8(&zc->zc_csr);
899		ZS_DELAY();
900	} while ((rr0 & ZSRR0_RX_READY) == 0);
901
902	c = in8(&zc->zc_data);
903	ZS_DELAY();
904	splx(s);
905
906	return (c);
907}
908
909/*
910 * Polled output char.
911 */
912void
913zs_putc(volatile struct zschan *zc, int c)
914{
915	register int s, rr0;
916	register long wait = 0;
917
918	s = splhigh();
919	/* Wait for transmitter to become ready. */
920	do {
921		rr0 = in8(&zc->zc_csr);
922		ZS_DELAY();
923	} while (((rr0 & ZSRR0_TX_READY) == 0) && (wait++ < 1000000));
924
925	if ((rr0 & ZSRR0_TX_READY) != 0) {
926		out8(&zc->zc_data, c);
927		ZS_DELAY();
928	}
929	splx(s);
930}
931
932
933/*
934 * Polled console input putchar.
935 */
936int
937zscngetc(dev_t dev)
938{
939	register volatile struct zschan *zc = zs_conschan;
940	register int c;
941
942	if (zc) {
943		c = zs_getc(zc);
944	} else {
945		char ch = 0;
946		OF_read(stdin, &ch, 1);
947		c = ch;
948	}
949	return c;
950}
951
952/*
953 * Polled console output putchar.
954 */
955void
956zscnputc(dev_t dev, int c)
957{
958	register volatile struct zschan *zc = zs_conschan;
959
960	if (zc) {
961		zs_putc(zc, c);
962	} else {
963		char ch = c;
964		OF_write(stdout, &ch, 1);
965	}
966}
967
968void
969zscnprobe(struct consdev *cp)
970{
971	int chosen, pkg;
972	int unit = 0;
973	int maj;
974	char name[16];
975
976	if ((chosen = OF_finddevice("/chosen")) == -1)
977		return;
978
979	if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1)
980		return;
981	if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1)
982		return;
983
984	if ((pkg = OF_instance_to_package(stdin)) == -1)
985		return;
986
987	bzero(name, sizeof(name));
988	if (OF_getprop(pkg, "device_type", name, sizeof(name)) == -1)
989		return;
990
991	if (strcmp(name, "serial") != 0)
992		return;
993
994	bzero(name, sizeof(name));
995	if (OF_getprop(pkg, "name", name, sizeof(name)) == -1)
996		return;
997
998	if (strcmp(name, "ch-b") == 0)
999		unit = 1;
1000
1001	/* locate the major number */
1002	for (maj = 0; maj < nchrdev; maj++)
1003		if (cdevsw[maj].d_open == zsopen)
1004			break;
1005
1006	cp->cn_dev = makedev(maj, unit);
1007	cp->cn_pri = CN_HIGHPRI;
1008}
1009
1010
1011void
1012zscninit(struct consdev *cp)
1013{
1014	int escc, escc_ch, obio;
1015	unsigned int zs_offset, zs_size;
1016	int ch = 0;
1017	u_int32_t reg[5];
1018	char name[16];
1019
1020	if ((escc_ch = OF_instance_to_package(stdin)) == -1)
1021		return;
1022
1023	bzero(name, sizeof(name));
1024	if (OF_getprop(escc_ch, "name", name, sizeof(name)) == -1)
1025		return;
1026
1027	if (strcmp(name, "ch-b") == 0)
1028		ch = 1;
1029
1030	if (OF_getprop(escc_ch, "reg", reg, sizeof(reg)) < 8)
1031		return;
1032	zs_offset = reg[0];
1033	zs_size   = reg[1];
1034
1035	escc = OF_parent(escc_ch);
1036	obio = OF_parent(escc);
1037
1038	if (OF_getprop(obio, "assigned-addresses", reg, sizeof(reg)) < 12)
1039		return;
1040	zs_conschan = mapiodev(reg[2] + zs_offset, zs_size);
1041
1042	zs_hwflags[0][ch] = ZS_HWFLAG_CONSOLE;
1043}
1044
1045void
1046zs_abort(struct zs_chanstate *channel)
1047{
1048	volatile struct zschan *zc = zs_conschan;
1049	int rr0;
1050
1051	/* Wait for end of break to avoid PROM abort. */
1052	/* XXX - Limit the wait? */
1053	do {
1054		rr0 = zc->zc_csr;
1055		ZS_DELAY();
1056	} while (rr0 & ZSRR0_BREAK);
1057
1058#if defined(DDB)
1059	if (!db_active)
1060		db_enter();
1061#endif
1062}
1063
1064/* copied from sparc - XXX? */
1065void
1066zscnpollc(dev_t dev, int on)
1067{
1068	/*
1069	 * Need to tell zs driver to acknowledge all interrupts or we get
1070	 * annoying spurious interrupt messages.  This is because mucking
1071	 * with spl() levels during polling does not prevent interrupts from
1072	 * being generated.
1073	 */
1074
1075#if 0
1076	if (on)
1077		swallow_zsintrs++;
1078	else
1079		swallow_zsintrs--;
1080#endif
1081}
1082