xref: /netbsd-src/sys/arch/sparc64/dev/zs.c (revision de1dfb1250df962f1ff3a011772cf58e605aed11)
1 /*	$NetBSD: zs.c,v 1.54 2004/03/21 15:08:24 pk Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Gordon W. Ross.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Zilog Z8530 Dual UART driver (machine-dependent part)
41  *
42  * Runs two serial lines per chip using slave drivers.
43  * Plain tty/async lines use the zs_async slave.
44  * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
45  */
46 
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.54 2004/03/21 15:08:24 pk Exp $");
49 
50 #include "opt_ddb.h"
51 #include "opt_kgdb.h"
52 
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/conf.h>
56 #include <sys/device.h>
57 #include <sys/file.h>
58 #include <sys/ioctl.h>
59 #include <sys/kernel.h>
60 #include <sys/proc.h>
61 #include <sys/tty.h>
62 #include <sys/time.h>
63 #include <sys/syslog.h>
64 
65 #include <machine/autoconf.h>
66 #include <machine/openfirm.h>
67 #include <machine/cpu.h>
68 #include <machine/eeprom.h>
69 #include <machine/psl.h>
70 #include <machine/z8530var.h>
71 
72 #include <dev/cons.h>
73 #include <dev/ic/z8530reg.h>
74 #include <dev/sun/kbd_ms_ttyvar.h>
75 #include <ddb/db_output.h>
76 
77 #include <sparc64/dev/cons.h>
78 
79 #include "kbd.h"	/* NKBD */
80 #include "ms.h"		/* NMS */
81 #include "zs.h" 	/* NZS */
82 
83 /* Make life easier for the initialized arrays here. */
84 #if NZS < 3
85 #undef  NZS
86 #define NZS 3
87 #endif
88 
89 /*
90  * Some warts needed by z8530tty.c -
91  * The default parity REALLY needs to be the same as the PROM uses,
92  * or you can not see messages done with printf during boot-up...
93  */
94 int zs_def_cflag = (CREAD | CS8 | HUPCL);
95 
96 /*
97  * The Sun provides a 4.9152 MHz clock to the ZS chips.
98  */
99 #define PCLK	(9600 * 512)	/* PCLK pin input clock rate */
100 
101 #define	ZS_DELAY()
102 
103 /* The layout of this is hardware-dependent (padding, order). */
104 struct zschan {
105 	volatile u_char	zc_csr;		/* ctrl,status, and indirect access */
106 	u_char		zc_xxx0;
107 	volatile u_char	zc_data;	/* data */
108 	u_char		zc_xxx1;
109 };
110 struct zsdevice {
111 	/* Yes, they are backwards. */
112 	struct	zschan zs_chan_b;
113 	struct	zschan zs_chan_a;
114 };
115 
116 /* ZS channel used as the console device (if any) */
117 void *zs_conschan_get, *zs_conschan_put;
118 
119 /* Saved PROM mappings */
120 static struct zsdevice *zsaddr[NZS];
121 
122 static u_char zs_init_reg[16] = {
123 	0,	/* 0: CMD (reset, etc.) */
124 	0,	/* 1: No interrupts yet. */
125 	0,	/* 2: IVECT */
126 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
127 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
128 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
129 	0,	/* 6: TXSYNC/SYNCLO */
130 	0,	/* 7: RXSYNC/SYNCHI */
131 	0,	/* 8: alias for data port */
132 	ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR,
133 	0,	/*10: Misc. TX/RX control bits */
134 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
135 	((PCLK/32)/9600)-2,	/*12: BAUDLO (default=9600) */
136 	0,			/*13: BAUDHI (default=9600) */
137 	ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
138 	ZSWR15_BREAK_IE,
139 };
140 
141 /* Console ops */
142 static int  zscngetc __P((dev_t));
143 static void zscnputc __P((dev_t, int));
144 static void zscnpollc __P((dev_t, int));
145 
146 struct consdev zs_consdev = {
147 	NULL,
148 	NULL,
149 	zscngetc,
150 	zscnputc,
151 	zscnpollc,
152 	NULL,
153 };
154 
155 
156 /****************************************************************
157  * Autoconfig
158  ****************************************************************/
159 
160 /* Definition of the driver for autoconfig. */
161 static int  zs_match_sbus __P((struct device *, struct cfdata *, void *));
162 static void zs_attach_sbus __P((struct device *, struct device *, void *));
163 
164 static void zs_attach __P((struct zsc_softc *, struct zsdevice *, int));
165 static int  zs_print __P((void *, const char *name));
166 
167 CFATTACH_DECL(zs, sizeof(struct zsc_softc),
168     zs_match_sbus, zs_attach_sbus, NULL, NULL);
169 
170 extern struct cfdriver zs_cd;
171 
172 /* Interrupt handlers. */
173 int zscheckintr __P((void *));
174 static int zshard __P((void *));
175 static void zssoft __P((void *));
176 
177 static int zs_get_speed __P((struct zs_chanstate *));
178 
179 /* Console device support */
180 static int zs_console_flags __P((int, int, int));
181 
182 /* Power management hooks */
183 int  zs_enable __P((struct zs_chanstate *));
184 void zs_disable __P((struct zs_chanstate *));
185 
186 /*
187  * Is the zs chip present?
188  */
189 static int
190 zs_match_sbus(parent, cf, aux)
191 	struct device *parent;
192 	struct cfdata *cf;
193 	void *aux;
194 {
195 	struct sbus_attach_args *sa = aux;
196 
197 	if (strcmp(cf->cf_name, sa->sa_name) != 0)
198 		return (0);
199 
200 	return (1);
201 }
202 
203 static void
204 zs_attach_sbus(parent, self, aux)
205 	struct device *parent;
206 	struct device *self;
207 	void *aux;
208 {
209 	struct zsc_softc *zsc = (void *) self;
210 	struct sbus_attach_args *sa = aux;
211 	bus_space_handle_t bh;
212 	int zs_unit = zsc->zsc_dev.dv_unit;
213 
214 	if (sa->sa_nintr == 0) {
215 		printf(" no interrupt lines\n");
216 		return;
217 	}
218 
219 	/* Use the mapping setup by the Sun PROM if possible. */
220 	if (zsaddr[zs_unit] == NULL) {
221 		/* Only map registers once. */
222 		if (sa->sa_npromvaddrs) {
223 			/*
224 			 * We're converting from a 32-bit pointer to a 64-bit
225 			 * pointer.  Since the 32-bit entity is negative, but
226 			 * the kernel is still mapped into the lower 4GB
227 			 * range, this needs to be zero-extended.
228 			 *
229 			 * XXXXX If we map the kernel and devices into the
230 			 * high 4GB range, this needs to be changed to
231 			 * sign-extend the address.
232 			 */
233 			sparc_promaddr_to_handle(sa->sa_bustag,
234 				sa->sa_promvaddrs[0], &bh);
235 
236 		} else {
237 
238 			if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
239 					 sa->sa_offset,
240 					 sa->sa_size,
241 					 BUS_SPACE_MAP_LINEAR,
242 					 &bh) != 0) {
243 				printf("%s @ sbus: cannot map registers\n",
244 				       self->dv_xname);
245 				return;
246 			}
247 		}
248 		zsaddr[zs_unit] = (struct zsdevice *)
249 			bus_space_vaddr(sa->sa_bustag, bh);
250 	}
251 	zsc->zsc_bustag = sa->sa_bustag;
252 	zsc->zsc_dmatag = sa->sa_dmatag;
253 	zsc->zsc_promunit = prom_getpropint(sa->sa_node, "slave", -2);
254 	zsc->zsc_node = sa->sa_node;
255 	zs_attach(zsc, zsaddr[zs_unit], sa->sa_pri);
256 }
257 
258 /*
259  * Attach a found zs.
260  *
261  * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR
262  * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE?
263  */
264 static void
265 zs_attach(zsc, zsd, pri)
266 	struct zsc_softc *zsc;
267 	struct zsdevice *zsd;
268 	int pri;
269 {
270 	struct zsc_attach_args zsc_args;
271 	struct zs_chanstate *cs;
272 	int s, channel, softpri = PIL_TTY;
273 
274 	if (zsd == NULL) {
275 		printf("configuration incomplete\n");
276 		return;
277 	}
278 
279 	printf(" softpri %d\n", softpri);
280 
281 	/*
282 	 * Initialize software state for each channel.
283 	 */
284 	for (channel = 0; channel < 2; channel++) {
285 		struct zschan *zc;
286 		struct device *child;
287 
288 		zsc_args.channel = channel;
289 		cs = &zsc->zsc_cs_store[channel];
290 		zsc->zsc_cs[channel] = cs;
291 
292 		simple_lock_init(&cs->cs_lock);
293 		cs->cs_channel = channel;
294 		cs->cs_private = NULL;
295 		cs->cs_ops = &zsops_null;
296 		cs->cs_brg_clk = PCLK / 16;
297 
298 		zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b;
299 
300 		zsc_args.consdev = NULL;
301 		zsc_args.hwflags = zs_console_flags(zsc->zsc_promunit,
302 						    zsc->zsc_node,
303 						    channel);
304 
305 		if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) {
306 			zsc_args.hwflags |= ZS_HWFLAG_USE_CONSDEV;
307 			zsc_args.consdev = &zs_consdev;
308 		}
309 
310 		if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) {
311 			zs_conschan_get = zc;
312 		}
313 		if ((zsc_args.hwflags & ZS_HWFLAG_CONSOLE_OUTPUT) != 0) {
314 			zs_conschan_put = zc;
315 		}
316 
317 		/* Children need to set cn_dev, etc */
318 		cs->cs_reg_csr  = &zc->zc_csr;
319 		cs->cs_reg_data = &zc->zc_data;
320 
321 		memcpy(cs->cs_creg, zs_init_reg, 16);
322 		memcpy(cs->cs_preg, zs_init_reg, 16);
323 
324 		/* XXX: Consult PROM properties for this?! */
325 		cs->cs_defspeed = zs_get_speed(cs);
326 		cs->cs_defcflag = zs_def_cflag;
327 
328 		/* Make these correspond to cs_defcflag (-crtscts) */
329 		cs->cs_rr0_dcd = ZSRR0_DCD;
330 		cs->cs_rr0_cts = 0;
331 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
332 		cs->cs_wr5_rts = 0;
333 
334 		/*
335 		 * Clear the master interrupt enable.
336 		 * The INTENA is common to both channels,
337 		 * so just do it on the A channel.
338 		 */
339 		if (channel == 0) {
340 			zs_write_reg(cs, 9, 0);
341 		}
342 
343 		/*
344 		 * Look for a child driver for this channel.
345 		 * The child attach will setup the hardware.
346 		 */
347 		if (!(child =
348 		      config_found(&zsc->zsc_dev, (void *)&zsc_args, zs_print))) {
349 			/* No sub-driver.  Just reset it. */
350 			u_char reset = (channel == 0) ?
351 				ZSWR9_A_RESET : ZSWR9_B_RESET;
352 			s = splzs();
353 			zs_write_reg(cs,  9, reset);
354 			splx(s);
355 		}
356 #if (NKBD > 0) || (NMS > 0)
357 		/*
358 		 * If this was a zstty it has a keyboard
359 		 * property on it we need to attach the
360 		 * sunkbd and sunms line disciplines.
361 		 */
362 		if (child
363 		    && (!strcmp(child->dv_cfdata->cf_name, "zstty"))
364 		    && (prom_getproplen(zsc->zsc_node, "keyboard") == 0)) {
365 			struct kbd_ms_tty_attach_args kma;
366 			struct zstty_softc {
367 				/* The following are the only fields we need here */
368 				struct	device zst_dev;
369 				struct  tty *zst_tty;
370 				struct	zs_chanstate *zst_cs;
371 			} *zst = (struct zstty_softc *)child;
372 			struct tty *tp;
373 
374 			kma.kmta_tp = tp = zst->zst_tty;
375 			kma.kmta_dev = tp->t_dev;
376 			kma.kmta_consdev = zsc_args.consdev;
377 
378 			/* Attach 'em if we got 'em. */
379 #if (NKBD > 0)
380 			if (channel == 0) {
381 				kma.kmta_name = "keyboard";
382 				config_found(child, (void *)&kma, NULL);
383 			}
384 #endif
385 #if (NMS > 0)
386 			if (channel == 1) {
387 				kma.kmta_name = "mouse";
388 				config_found(child, (void *)&kma, NULL);
389 			}
390 #endif
391 		}
392 #endif
393 	}
394 
395 	/*
396 	 * Now safe to install interrupt handlers.  Note the arguments
397 	 * to the interrupt handlers aren't used.  Note, we only do this
398 	 * once since both SCCs interrupt at the same level and vector.
399 	 */
400 	bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, zshard, zsc);
401 	if (!(zsc->zsc_softintr = softintr_establish(softpri, zssoft, zsc)))
402 		panic("zsattach: could not establish soft interrupt");
403 
404 	evcnt_attach_dynamic(&zsc->zsc_intrcnt, EVCNT_TYPE_INTR, NULL,
405 	    zsc->zsc_dev.dv_xname, "intr");
406 
407 
408 	/*
409 	 * Set the master interrupt enable and interrupt vector.
410 	 * (common to both channels, do it on A)
411 	 */
412 	cs = zsc->zsc_cs[0];
413 	s = splhigh();
414 	/* interrupt vector */
415 	zs_write_reg(cs, 2, zs_init_reg[2]);
416 	/* master interrupt control (enable) */
417 	zs_write_reg(cs, 9, zs_init_reg[9]);
418 	splx(s);
419 
420 }
421 
422 static int
423 zs_print(aux, name)
424 	void *aux;
425 	const char *name;
426 {
427 	struct zsc_attach_args *args = aux;
428 
429 	if (name != NULL)
430 		aprint_normal("%s: ", name);
431 
432 	if (args->channel != -1)
433 		aprint_normal(" channel %d", args->channel);
434 
435 	return (UNCONF);
436 }
437 
438 /* Deprecate this? */
439 static volatile int zssoftpending;
440 
441 static int
442 zshard(arg)
443 	void *arg;
444 {
445 	struct zsc_softc *zsc = (struct zsc_softc *)arg;
446 	int rr3, rval;
447 
448 	rval = 0;
449 	while ((rr3 = zsc_intr_hard(zsc))) {
450 		/* Count up the interrupts. */
451 		rval |= rr3;
452 		zsc->zsc_intrcnt.ev_count++;
453 	}
454 	if (((zsc->zsc_cs[0] && zsc->zsc_cs[0]->cs_softreq) ||
455 	     (zsc->zsc_cs[1] && zsc->zsc_cs[1]->cs_softreq)) &&
456 	    zsc->zsc_softintr) {
457 		zssoftpending = PIL_TTY;
458 		softintr_schedule(zsc->zsc_softintr);
459 	}
460 	return (rval);
461 }
462 
463 int
464 zscheckintr(arg)
465 	void *arg;
466 {
467 	struct zsc_softc *zsc;
468 	int unit, rval;
469 
470 	rval = 0;
471 	for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
472 
473 		zsc = zs_cd.cd_devs[unit];
474 		if (zsc == NULL)
475 			continue;
476 		rval = (zshard((void *)zsc) || rval);
477 	}
478 	return (rval);
479 }
480 
481 
482 /*
483  * We need this only for TTY_DEBUG purposes.
484  */
485 static void
486 zssoft(arg)
487 	void *arg;
488 {
489 	struct zsc_softc *zsc = (struct zsc_softc *)arg;
490 	int s;
491 
492 	/* Make sure we call the tty layer at spltty. */
493 	s = spltty();
494 	zssoftpending = 0;
495 	(void)zsc_intr_soft(zsc);
496 #ifdef TTY_DEBUG
497 	{
498 		struct zstty_softc *zst0 = zsc->zsc_cs[0]->cs_private;
499 		struct zstty_softc *zst1 = zsc->zsc_cs[1]->cs_private;
500 		if (zst0->zst_overflows || zst1->zst_overflows ) {
501 			struct trapframe *frame = (struct trapframe *)arg;
502 
503 			printf("zs silo overflow from %p\n",
504 			       (long)frame->tf_pc);
505 		}
506 	}
507 #endif
508 	splx(s);
509 }
510 
511 
512 /*
513  * Compute the current baud rate given a ZS channel.
514  */
515 static int
516 zs_get_speed(cs)
517 	struct zs_chanstate *cs;
518 {
519 	int tconst;
520 
521 	tconst = zs_read_reg(cs, 12);
522 	tconst |= zs_read_reg(cs, 13) << 8;
523 	return (TCONST_TO_BPS(cs->cs_brg_clk, tconst));
524 }
525 
526 /*
527  * MD functions for setting the baud rate and control modes.
528  */
529 int
530 zs_set_speed(cs, bps)
531 	struct zs_chanstate *cs;
532 	int bps;	/* bits per second */
533 {
534 	int tconst, real_bps;
535 
536 	if (bps == 0)
537 		return (0);
538 
539 #ifdef	DIAGNOSTIC
540 	if (cs->cs_brg_clk == 0)
541 		panic("zs_set_speed");
542 #endif
543 
544 	tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
545 	if (tconst < 0)
546 		return (EINVAL);
547 
548 	/* Convert back to make sure we can do it. */
549 	real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
550 
551 	/* XXX - Allow some tolerance here? */
552 	if (real_bps != bps)
553 		return (EINVAL);
554 
555 	cs->cs_preg[12] = tconst;
556 	cs->cs_preg[13] = tconst >> 8;
557 
558 	/* Caller will stuff the pending registers. */
559 	return (0);
560 }
561 
562 int
563 zs_set_modes(cs, cflag)
564 	struct zs_chanstate *cs;
565 	int cflag;	/* bits per second */
566 {
567 	int s;
568 
569 	/*
570 	 * Output hardware flow control on the chip is horrendous:
571 	 * if carrier detect drops, the receiver is disabled, and if
572 	 * CTS drops, the transmitter is stoped IN MID CHARACTER!
573 	 * Therefore, NEVER set the HFC bit, and instead use the
574 	 * status interrupt to detect CTS changes.
575 	 */
576 	s = splzs();
577 	cs->cs_rr0_pps = 0;
578 	if ((cflag & (CLOCAL | MDMBUF)) != 0) {
579 		cs->cs_rr0_dcd = 0;
580 		if ((cflag & MDMBUF) == 0)
581 			cs->cs_rr0_pps = ZSRR0_DCD;
582 	} else
583 		cs->cs_rr0_dcd = ZSRR0_DCD;
584 	if ((cflag & CRTSCTS) != 0) {
585 		cs->cs_wr5_dtr = ZSWR5_DTR;
586 		cs->cs_wr5_rts = ZSWR5_RTS;
587 		cs->cs_rr0_cts = ZSRR0_CTS;
588 	} else if ((cflag & CDTRCTS) != 0) {
589 		cs->cs_wr5_dtr = 0;
590 		cs->cs_wr5_rts = ZSWR5_DTR;
591 		cs->cs_rr0_cts = ZSRR0_CTS;
592 	} else if ((cflag & MDMBUF) != 0) {
593 		cs->cs_wr5_dtr = 0;
594 		cs->cs_wr5_rts = ZSWR5_DTR;
595 		cs->cs_rr0_cts = ZSRR0_DCD;
596 	} else {
597 		cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
598 		cs->cs_wr5_rts = 0;
599 		cs->cs_rr0_cts = 0;
600 	}
601 	splx(s);
602 
603 	/* Caller will stuff the pending registers. */
604 	return (0);
605 }
606 
607 
608 /*
609  * Read or write the chip with suitable delays.
610  */
611 
612 u_char
613 zs_read_reg(cs, reg)
614 	struct zs_chanstate *cs;
615 	u_char reg;
616 {
617 	u_char val;
618 
619 	*cs->cs_reg_csr = reg;
620 	ZS_DELAY();
621 	val = *cs->cs_reg_csr;
622 	ZS_DELAY();
623 	return (val);
624 }
625 
626 void
627 zs_write_reg(cs, reg, val)
628 	struct zs_chanstate *cs;
629 	u_char reg, val;
630 {
631 	*cs->cs_reg_csr = reg;
632 	ZS_DELAY();
633 	*cs->cs_reg_csr = val;
634 	ZS_DELAY();
635 }
636 
637 u_char
638 zs_read_csr(cs)
639 	struct zs_chanstate *cs;
640 {
641 	u_char val;
642 
643 	val = *cs->cs_reg_csr;
644 	ZS_DELAY();
645 	return (val);
646 }
647 
648 void  zs_write_csr(cs, val)
649 	struct zs_chanstate *cs;
650 	u_char val;
651 {
652 	*cs->cs_reg_csr = val;
653 	ZS_DELAY();
654 }
655 
656 u_char zs_read_data(cs)
657 	struct zs_chanstate *cs;
658 {
659 	u_char val;
660 
661 	val = *cs->cs_reg_data;
662 	ZS_DELAY();
663 	return (val);
664 }
665 
666 void  zs_write_data(cs, val)
667 	struct zs_chanstate *cs;
668 	u_char val;
669 {
670 	*cs->cs_reg_data = val;
671 	ZS_DELAY();
672 }
673 
674 /****************************************************************
675  * Console support functions (Sun specific!)
676  * Note: this code is allowed to know about the layout of
677  * the chip registers, and uses that to keep things simple.
678  * XXX - I think I like the mvme167 code better. -gwr
679  ****************************************************************/
680 
681 extern void Debugger __P((void));
682 
683 /*
684  * Handle user request to enter kernel debugger.
685  */
686 void
687 zs_abort(cs)
688 	struct zs_chanstate *cs;
689 {
690 	volatile struct zschan *zc = zs_conschan_get;
691 	int rr0;
692 
693 	/* Wait for end of break to avoid PROM abort. */
694 	/* XXX - Limit the wait? */
695 	do {
696 		rr0 = zc->zc_csr;
697 		ZS_DELAY();
698 	} while (rr0 & ZSRR0_BREAK);
699 
700 #if defined(KGDB)
701 	zskgdb(cs);
702 #elif defined(DDB)
703 	{
704 		extern int db_active;
705 
706 		if (!db_active)
707 			Debugger();
708 		else
709 			/* Debugger is probably hozed */
710 			callrom();
711 	}
712 #else
713 	printf("stopping on keyboard abort\n");
714 	callrom();
715 #endif
716 }
717 
718 
719 /*
720  * Polled input char.
721  */
722 int
723 zs_getc(arg)
724 	void *arg;
725 {
726 	volatile struct zschan *zc = arg;
727 	int s, c, rr0;
728 
729 	s = splhigh();
730 	/* Wait for a character to arrive. */
731 	do {
732 		rr0 = zc->zc_csr;
733 		ZS_DELAY();
734 	} while ((rr0 & ZSRR0_RX_READY) == 0);
735 
736 	c = zc->zc_data;
737 	ZS_DELAY();
738 	splx(s);
739 
740 	/*
741 	 * This is used by the kd driver to read scan codes,
742 	 * so don't translate '\r' ==> '\n' here...
743 	 */
744 	return (c);
745 }
746 
747 /*
748  * Polled output char.
749  */
750 void
751 zs_putc(arg, c)
752 	void *arg;
753 	int c;
754 {
755 	volatile struct zschan *zc = arg;
756 	int s, rr0;
757 
758 	s = splhigh();
759 
760 	/* Wait for transmitter to become ready. */
761 	do {
762 		rr0 = zc->zc_csr;
763 		ZS_DELAY();
764 	} while ((rr0 & ZSRR0_TX_READY) == 0);
765 
766 	/*
767 	 * Send the next character.
768 	 * Now you'd think that this could be followed by a ZS_DELAY()
769 	 * just like all the other chip accesses, but it turns out that
770 	 * the `transmit-ready' interrupt isn't de-asserted until
771 	 * some period of time after the register write completes
772 	 * (more than a couple instructions).  So to avoid stray
773 	 * interrupts we put in the 2us delay regardless of CPU model.
774 	 */
775 	zc->zc_data = c;
776 	delay(2);
777 
778 	splx(s);
779 }
780 
781 /*****************************************************************/
782 
783 
784 
785 
786 /*
787  * Polled console input putchar.
788  */
789 static int
790 zscngetc(dev)
791 	dev_t dev;
792 {
793 	return (zs_getc(zs_conschan_get));
794 }
795 
796 /*
797  * Polled console output putchar.
798  */
799 static void
800 zscnputc(dev, c)
801 	dev_t dev;
802 	int c;
803 {
804 	zs_putc(zs_conschan_put, c);
805 }
806 
807 int swallow_zsintrs;
808 
809 static void
810 zscnpollc(dev, on)
811 	dev_t dev;
812 	int on;
813 {
814 	/*
815 	 * Need to tell zs driver to acknowledge all interrupts or we get
816 	 * annoying spurious interrupt messages.  This is because mucking
817 	 * with spl() levels during polling does not prevent interrupts from
818 	 * being generated.
819 	 */
820 
821 	if (on) swallow_zsintrs++;
822 	else swallow_zsintrs--;
823 }
824 
825 int
826 zs_console_flags(promunit, node, channel)
827 	int promunit;
828 	int node;
829 	int channel;
830 {
831 	int cookie, flags = 0;
832 	char buf[255];
833 
834 	/*
835 	 * We'll just do the OBP grovelling down here since that's
836 	 * the only type of firmware we support.
837 	 */
838 
839 	/* Default to channel 0 if there are no explicit prom args */
840 	cookie = 0;
841 	if (node == prom_instance_to_package(prom_stdin())) {
842 		if (prom_getoption("input-device", buf, sizeof buf) != 0 &&
843 		    strcmp("ttyb", buf) == 0)
844 			cookie = 1;
845 
846 		if (channel == cookie)
847 			flags |= ZS_HWFLAG_CONSOLE_INPUT;
848 	}
849 
850 	if (node == prom_instance_to_package(prom_stdout())) {
851 		if (prom_getoption("output-device", buf, sizeof buf) != 0 &&
852 		    strcmp("ttyb", buf) == 0)
853 			cookie = 1;
854 
855 		if (channel == cookie)
856 			flags |= ZS_HWFLAG_CONSOLE_OUTPUT;
857 	}
858 
859 	return (flags);
860 }
861 
862