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