zs.c revision 1.8 1 /* $NetBSD: zs.c,v 1.8 1996/09/16 05:24:21 scottr Exp $ */
2
3 /*
4 * Copyright (c) 1995 Gordon W. Ross
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 * 4. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Gordon Ross
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Zilog Z8530 Dual UART driver (machine-dependent part)
35 *
36 * Runs two serial lines per chip using slave drivers.
37 * Plain tty/async lines use the zs_async slave.
38 * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
39 */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/proc.h>
44 #include <sys/device.h>
45 #include <sys/conf.h>
46 #include <sys/file.h>
47 #include <sys/ioctl.h>
48 #include <sys/tty.h>
49 #include <sys/time.h>
50 #include <sys/kernel.h>
51 #include <sys/syslog.h>
52
53 #include <dev/cons.h>
54 #include "z8530reg.h"
55 #include <machine/z8530var.h>
56
57 #include <machine/autoconf.h>
58 #include <machine/cpu.h>
59 #include <machine/viareg.h>
60
61 /*
62 * XXX: Hard code this to make console init easier...
63 */
64 #define NZSC 1 /* XXX */
65
66 /*
67 * Define interrupt levels.
68 */
69 #define ZSHARD_PRI 6 /* Wired on the CPU board... */
70 #define ZSSOFT_PRI 3 /* Want tty pri (4) but this is OK. */
71
72 /* The layout of this is hardware-dependent (padding, order). */
73 struct zschan {
74 volatile u_char zc_csr; /* ctrl,status, and indirect access */
75 u_char zc_xxx0;
76 u_char zc_xxx1;
77 u_char zc_xxx2;
78 volatile u_char zc_data; /* data */
79 u_char zc_xxx3;
80 u_char zc_xxx4;
81 u_char zc_xxx5;
82 };
83 /*
84 * The zsdevice structure is not used on the mac68k port as the
85 * chip is wired up weird. Channel B & A are interspursed with
86 * the data & control bytes
87 struct zsdevice {
88 /! Yes, they are backwards. !/
89 struct zschan zs_chan_b;
90 struct zschan zs_chan_a;
91 };
92 */
93
94 /* Saved PROM mappings */
95 static char *zsaddr[NZSC]; /* See zs_init() */
96 /* Flags from cninit() */
97 static int zs_hwflags[NZSC][2];
98 /* Default speed for each channel */
99 static int zs_defspeed[NZSC][2] = {
100 { 9600, /* tty00 */
101 9600 }, /* tty01 */
102 };
103 /* console stuff */
104 void *zs_conschan = 0;
105 int zs_consunit;
106 /* device that the console is attached to--if serial. */
107 dev_t mac68k_zsdev;
108 /* Mac stuff, some vestages of old mac serial driver here */
109 volatile unsigned char *sccA = 0;
110
111 static struct zschan *zs_get_chan_addr __P((int zsc_unit, int channel));
112 void zs_init __P((void));
113
114 static struct zschan *
115 zs_get_chan_addr(zsc_unit, channel)
116 int zsc_unit, channel;
117 {
118 char *addr;
119 struct zschan *zc;
120
121 if (zsc_unit >= NZSC)
122 return NULL;
123 addr = zsaddr[zsc_unit];
124 if (addr == NULL)
125 return NULL;
126 if (channel == 0) {
127 zc = (struct zschan *)(addr +2);
128 /* handle the fact the ports are intertwined. */
129 } else {
130 zc = (struct zschan *)(addr);
131 }
132 return (zc);
133 }
134
135
136 /* Find PROM mappings (for console support). */
137 static int zsinited = 0; /* 0 = not, 1 = inited, not attached, 2= attached */
138
139 void
140 zs_init()
141 {
142 if ((zsinited == 2)&&(zsaddr[0] != (char *) sccA))
143 panic("Moved zs0 address after attached!");
144 zsaddr[0] = (char *) sccA;
145 zsinited = 1;
146 if (zs_conschan != 0){ /* we might have moved io under the console */
147 zs_conschan = zs_get_chan_addr(0, zs_consunit);
148 /* so recalc the console port */
149 }
150 }
151
152
153 /*
154 * Even though zsparam will set up the clock multiples, etc., we
155 * still set them here as: 1) mice & keyboards don't use zsparam,
156 * and 2) the console stuff uses these defaults before device
157 * attach.
158 */
159
160 static u_char zs_init_reg[16] = {
161 0, /* 0: CMD (reset, etc.) */
162 ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE,
163 0x18 + ZSHARD_PRI, /* IVECT */
164 ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
165 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
166 ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
167 0, /* 6: TXSYNC/SYNCLO */
168 0, /* 7: RXSYNC/SYNCHI */
169 0, /* 8: alias for data port */
170 ZSWR9_MASTER_IE,
171 0, /*10: Misc. TX/RX control bits */
172 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
173 14, /*12: BAUDLO (default=9600) */
174 0, /*13: BAUDHI (default=9600) */
175 ZSWR14_BAUD_ENA,
176 ZSWR15_BREAK_IE | ZSWR15_DCD_IE | ZSWR15_CTS_IE,
177 };
178
179
180 /****************************************************************
181 * Autoconfig
182 ****************************************************************/
183
184 /* Definition of the driver for autoconfig. */
185 static int zsc_match __P((struct device *, void *, void *));
186 static void zsc_attach __P((struct device *, struct device *, void *));
187 static int zsc_print __P((void *aux, const char *name));
188
189 struct cfattach zsc_ca = {
190 sizeof(struct zsc_softc), zsc_match, zsc_attach
191 };
192
193 struct cfdriver zsc_cd = {
194 NULL, "zsc", DV_DULL
195 };
196
197 int zshard __P((void *));
198 int zssoft __P((void *));
199
200
201 /*
202 * Is the zs chip present?
203 */
204 static int
205 zsc_match(parent, vcf, aux)
206 struct device *parent;
207 void *vcf;
208 void *aux;
209 {
210 return 1;
211 }
212
213 static int
214 zsc_print(aux, name)
215 void *aux;
216 const char *name;
217 {
218 struct zsc_attach_args *args = aux;
219
220 if (name != NULL)
221 printf("%s: ", name);
222
223 if (args->channel != -1)
224 printf(" channel %d", args->channel);
225
226 return UNCONF;
227 }
228
229 /*
230 * Attach a found zs.
231 *
232 * Match slave number to zs unit number, so that misconfiguration will
233 * not set up the keyboard as ttya, etc.
234 */
235 static void
236 zsc_attach(parent, self, aux)
237 struct device *parent;
238 struct device *self;
239 void *aux;
240 {
241 struct zsc_softc *zsc = (void *) self;
242 struct zsc_attach_args zsc_args;
243 volatile struct zschan *zc;
244 struct zs_chanstate *cs;
245 int zsc_unit, channel;
246 int reset, s, chip;
247
248 if (!zsinited) zs_init();
249 zsinited = 2;
250
251 zsc_unit = zsc->zsc_dev.dv_unit;
252
253 /* Make sure everything's inited ok. */
254 if (zsaddr[zsc_unit] == NULL)
255 panic("zs_attach: zs%d not mapped\n", zsc_unit);
256
257 /*
258 * Initialize software state for each channel.
259 */
260 for (channel = 0; channel < 2; channel++) {
261 cs = &zsc->zsc_cs[channel];
262
263 zc = zs_get_chan_addr(zsc_unit, channel);
264 cs->cs_reg_csr = &zc->zc_csr;
265 cs->cs_reg_data = &zc->zc_data;
266
267 cs->cs_channel = channel;
268 cs->cs_private = NULL;
269 cs->cs_ops = &zsops_null;
270
271 /* Define BAUD rate clock for the MI code. */
272 cs->cs_pclk_div16 = mac68k_machine.sccClkConst*2;
273 cs->cs_csource = 0;
274 cs->cs_psource = 0;
275
276 cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
277
278 bcopy(zs_init_reg, cs->cs_creg, 16);
279 bcopy(zs_init_reg, cs->cs_preg, 16);
280
281 /*
282 * Clear the master interrupt enable.
283 * The INTENA is common to both channels,
284 * so just do it on the A channel.
285 */
286 if (channel == 0) {
287 zs_write_reg(cs, 9, 0);
288
289 chip = 0; /* We'll turn chip checking on post 1.2 */
290 printf(" chip type %d \n",chip);
291 }
292 cs->cs_chip = chip;
293
294 /*
295 * Look for a child driver for this channel.
296 * The child attach will setup the hardware.
297 */
298 zsc_args.channel = channel;
299 zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
300 if (!config_found(self, (void *) &zsc_args, zsc_print)) {
301 /* No sub-driver. Just reset it. */
302 reset = (channel == 0) ?
303 ZSWR9_A_RESET : ZSWR9_B_RESET;
304 s = splzs();
305 zs_write_reg(cs, 9, reset);
306 splx(s);
307 }
308 }
309
310 /*
311 * Set the master interrupt enable and interrupt vector.
312 * (common to both channels, do it on A)
313 */
314 cs = &zsc->zsc_cs[0];
315 s = splzs();
316 /* interrupt vector */
317 zs_write_reg(cs, 2, zs_init_reg[2]);
318 /* master interrupt control (enable) */
319 zs_write_reg(cs, 9, zs_init_reg[9]);
320 splx(s);
321 }
322
323 void
324 zstty_mdattach(zsc, zst, cs, tp)
325 struct zsc_softc *zsc;
326 struct zstty_softc *zst;
327 struct zs_chanstate *cs;
328 struct tty *tp;
329 {
330 int theflags;
331
332 zst->zst_resetdef = 0;
333 cs->cs_clock_count = 3; /* internal + externals */
334 cs->cs_cclk_flag = 0; /* Not doing anything fancy by default */
335 cs->cs_pclk_flag = 0;
336 cs->cs_clocks[0].clk = mac68k_machine.sccClkConst*32;
337 cs->cs_clocks[0].flags = ZSC_RTXBRG; /* allowing divide by 16 will
338 melt the driver! */
339
340 cs->cs_clocks[1].flags = ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
341 cs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
342 if (zst->zst_dev.dv_unit == 0) {
343 theflags = mac68k_machine.modem_flags;
344 cs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;
345 cs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;
346 } else if (zst->zst_dev.dv_unit == 1) {
347 theflags = mac68k_machine.print_flags;
348 cs->cs_clocks[1].flags = ZSC_VARIABLE;
349 /*
350 * Yes, we aren't defining ANY clock source enables for the
351 * printer's DCD clock in. The hardware won't let us
352 * use it. But a clock will freak out the chip, so we
353 * let you set it, telling us to bar interrupts on the line.
354 */
355 cs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;
356 cs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;
357 }
358
359 if (cs->cs_clocks[1].clk)
360 zst->zst_hwflags |= ZS_HWFLAG_IGDCD;
361 if (cs->cs_clocks[2].clk)
362 zst->zst_hwflags |= ZS_HWFLAG_IGCTS;
363
364 if (theflags & ZSMAC_RAW) {
365 zst->zst_cflag = ZSTTY_RAW_CFLAG;
366 zst->zst_iflag = ZSTTY_RAW_IFLAG;
367 zst->zst_lflag = ZSTTY_RAW_LFLAG;
368 zst->zst_oflag = ZSTTY_RAW_OFLAG;
369 printf(" (raw defaults)");
370 }
371 if (theflags & ZSMAC_LOCALTALK) {
372 printf(" shielding from LocalTalk");
373 zst->zst_ospeed = tp->t_ospeed = 1;
374 zst->zst_ispeed = tp->t_ispeed = 1;
375 cs->cs_defspeed = 1;
376 cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff;
377 cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff;
378 zs_write_reg(cs, ZSRR_BAUDLO, 0xff);
379 zs_write_reg(cs, ZSRR_BAUDHI, 0xff);
380 /*
381 * If we might have LocalTalk, then make sure we have the
382 * Baud rate low-enough to not do any damage.
383 */
384 }
385
386 /* For the mac, we have rtscts = check CTS for output control, no
387 * input control. mdmbuf means check DCD for output, and use DTR
388 * for input control. mdmbuf & rtscts means use CTS for output
389 * control, and DTR for input control. */
390
391 zst->zst_hwimasks[1] = 0;
392 zst->zst_hwimasks[2] = ZSWR5_DTR;
393 zst->zst_hwimasks[3] = ZSWR5_DTR;
394 }
395
396 int
397 zsmdioctl(tp, com, data, flag, p)
398 struct tty *tp;
399 u_long com;
400 caddr_t data;
401 int flag;
402 struct proc *p;
403 {
404 return (-1);
405 }
406
407 void
408 zsmd_setclock(cs)
409 struct zs_chanstate *cs;
410 {
411 if (cs->cs_channel != 0)
412 return;
413 /*
414 * If the new clock has the external bit set, then select the
415 * external source.
416 */
417 via_set_modem((cs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0);
418 }
419
420 int
421 zshard(arg)
422 void *arg;
423 {
424 struct zsc_softc *zsc;
425 int unit, rval;
426 #ifdef ZSMACDEBUG
427 itecnputc(mac68k_zsdev, 'Z');
428 #endif
429
430 rval = 0;
431 unit = zsc_cd.cd_ndevs;
432 while (--unit >= 0) {
433 zsc = zsc_cd.cd_devs[unit];
434 if (zsc != NULL) {
435 rval |= zsc_intr_hard(zsc);
436 }
437 }
438 #ifdef ZSMACDEBUG
439 itecnputc(mac68k_zsdev, '\n');
440 #endif
441 return (rval);
442 }
443
444 int zssoftpending;
445
446 void
447 zsc_req_softint(zsc)
448 struct zsc_softc *zsc;
449 {
450 if (zssoftpending == 0) {
451 /* We are at splzs here, so no need to lock. */
452 zssoftpending = ZSSOFT_PRI;
453 /* isr_soft_request(ZSSOFT_PRI); */
454 setsoftserial();
455 }
456 }
457
458 int
459 zssoft(arg)
460 void *arg;
461 {
462 struct zsc_softc *zsc;
463 int unit;
464
465 /* This is not the only ISR on this IPL. */
466 if (zssoftpending == 0)
467 return (0);
468
469 /*
470 * The soft intr. bit will be set by zshard only if
471 * the variable zssoftpending is zero. The order of
472 * these next two statements prevents our clearing
473 * the soft intr bit just after zshard has set it.
474 */
475 /* isr_soft_clear(ZSSOFT_PRI); */
476 zssoftpending = 0;
477
478 /* Do ttya/ttyb first, because they go faster. */
479 unit = zsc_cd.cd_ndevs;
480 while (--unit >= 0) {
481 zsc = zsc_cd.cd_devs[unit];
482 if (zsc != NULL) {
483 (void) zsc_intr_soft(zsc);
484 }
485 }
486 return (1);
487 }
488
489
490 /*
491 * Read or write the chip with suitable delays.
492 */
493 #define ZS_DELAY()
494 /*
495 * MacII hardware has the delay built in. No need for extra delay. :-)
496 */
497
498 u_char
499 zs_read_reg(cs, reg)
500 struct zs_chanstate *cs;
501 u_char reg;
502 {
503 u_char val;
504
505 *cs->cs_reg_csr = reg;
506 ZS_DELAY();
507 val = *cs->cs_reg_csr;
508 ZS_DELAY();
509 return val;
510 }
511
512 void
513 zs_write_reg(cs, reg, val)
514 struct zs_chanstate *cs;
515 u_char reg, val;
516 {
517 *cs->cs_reg_csr = reg;
518 ZS_DELAY();
519 *cs->cs_reg_csr = val;
520 ZS_DELAY();
521 }
522
523 u_char zs_read_csr(cs)
524 struct zs_chanstate *cs;
525 {
526 register u_char v;
527
528 v = (*cs->cs_reg_csr) ^ ZSRR0_CTS;
529 /* make up for the fact CTS is wired backwards */
530 ZS_DELAY();
531 return v;
532 }
533
534 u_char zs_read_data(cs)
535 struct zs_chanstate *cs;
536 {
537 register u_char v;
538
539 v = *cs->cs_reg_data;
540 ZS_DELAY();
541 return v;
542 }
543
544 void zs_write_csr(cs, val)
545 struct zs_chanstate *cs;
546 u_char val;
547 {
548 *cs->cs_reg_csr = val;
549 ZS_DELAY();
550 }
551
552 void zs_write_data(cs, val)
553 struct zs_chanstate *cs;
554 u_char val;
555 {
556 *cs->cs_reg_data = val;
557 ZS_DELAY();
558 }
559
560 /****************************************************************
561 * Console support functions (Originally Sun3 specific!)
562 * Now works w/ just mac68k port!
563 ****************************************************************/
564
565 #define zscnpollc nullcnpollc
566 cons_decl(zs);
567
568 static void zs_putc __P((register volatile struct zschan *, int));
569 static int zs_getc __P((register volatile struct zschan *));
570 static void zscnsetup __P((void));
571 extern int zsopen __P(( dev_t dev, int flags, int mode, struct proc *p));
572
573 /*
574 * Console functions.
575 */
576
577 /*
578 * This code modled after the zs_setparam routine in zskgdb
579 * It sets the console unit to a known state so we can output
580 * correctly.
581 */
582 static void
583 zscnsetup()
584 {
585 struct zs_chanstate cs;
586 struct zschan *zc;
587 int tconst, s;
588
589 /* Setup temporary chanstate. */
590 bzero((caddr_t)&cs, sizeof(cs));
591 zc = zs_conschan;
592 cs.cs_reg_csr = &zc->zc_csr;
593 cs.cs_reg_data = &zc->zc_data;
594 cs.cs_channel = zs_consunit;
595
596 bcopy(zs_init_reg, cs.cs_preg, 16);
597 tconst = BPS_TO_TCONST(mac68k_machine.sccClkConst*2, zs_defspeed[0][zs_consunit]);
598 cs.cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
599 cs.cs_preg[1] = 0; /* don't enable interrupts */
600 cs.cs_preg[12] = tconst;
601 cs.cs_preg[13] = tconst >> 8;
602
603 s = splhigh();
604 zs_loadchannelregs(&cs);
605 splx(s);
606 }
607
608 /*
609 * zscnprobe is the routine which gets called as the kernel is trying to
610 * figure out where the console should be. Each io driver which might
611 * be the console (as defined in mac68k/conf.c) gets probed. The probe
612 * fills in the consdev structure. Important parts are the device #,
613 * and the console priority. Values are CN_DEAD (don't touch me),
614 * CN_NORMAL (I'm here, but elsewhere might be better), CN_INTERNAL
615 * (the video, better than CN_NORMAL), and CN_REMOTE (pick me!)
616 *
617 * As the mac's a bit different, we do extra work here. We mainly check
618 * to see if we have serial echo going on, and if the tty's are supposed
619 * to default to raw or not.
620 */
621 void
622 zscnprobe(struct consdev * cp)
623 {
624 extern u_long IOBase;
625 int maj, unit;
626
627 for (maj = 0; maj < nchrdev; maj++) {
628 if (cdevsw[maj].d_open == zsopen) {
629 break;
630 }
631 }
632 if (maj == nchrdev) {
633 /* no console entry for us */
634 if (mac68k_machine.serial_boot_echo) {
635 mac68k_set_io_offsets(IOBase);
636 zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
637 zs_consunit = 1;
638 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
639 zs_init();
640 zscnsetup();
641 }
642 return;
643 }
644
645 cp->cn_pri = CN_NORMAL; /* Lower than CN_INTERNAL */
646 if (mac68k_machine.serial_console != 0) {
647 cp->cn_pri = CN_REMOTE; /* Higher than CN_INTERNAL */
648 mac68k_machine.serial_boot_echo =0;
649 }
650
651 unit = (mac68k_machine.serial_console == 1) ? 0 : 1;
652 zs_consunit = unit;
653
654 mac68k_zsdev = cp->cn_dev = makedev(maj, unit);
655
656 if (mac68k_machine.serial_boot_echo) {
657 /*
658 * at this point, we know that we don't have a serial
659 * console, but are doing echo
660 */
661 mac68k_set_io_offsets(IOBase);
662 zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
663 zs_consunit = 1;
664 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
665 zs_init();
666 zscnsetup();
667 }
668 return;
669 }
670
671 void
672 zscninit(struct consdev * cp)
673 {
674 extern u_long IOBase;
675 int chan = minor(cp->cn_dev & 1);
676
677 mac68k_set_io_offsets(IOBase);
678 zs_conschan = (struct zschan *) -1;
679 zs_consunit = chan;
680 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
681 #ifdef ZS_CONSOLE_ABORT
682 zs_hwflags[0][zs_consunit] |= ZS_HWFLAG_CONABRT;
683 #endif
684 zs_init();
685 /*
686 * zsinit will set up the addresses of the scc. It will also, if
687 * zs_conschan != 0, calculate the new address of the conschan for
688 * unit zs_consunit. So zs_init implicitly sets zs_conschan to the right
689 * number. :-)
690 */
691 zscnsetup();
692 printf("\nNetBSD/mac68k console\n");
693 }
694
695
696 /*
697 * Polled input char.
698 */
699 static int
700 zs_getc(zc)
701 register volatile struct zschan *zc;
702 {
703 register int s, c, rr0;
704
705 s = splhigh();
706 /* Wait for a character to arrive. */
707 do {
708 rr0 = zc->zc_csr;
709 ZS_DELAY();
710 } while ((rr0 & ZSRR0_RX_READY) == 0);
711
712 c = zc->zc_data;
713 ZS_DELAY();
714 splx(s);
715
716 /*
717 * This is used by the kd driver to read scan codes,
718 * so don't translate '\r' ==> '\n' here...
719 */
720 return (c);
721 }
722
723 /*
724 * Polled output char.
725 */
726 static void
727 zs_putc(zc, c)
728 register volatile struct zschan *zc;
729 int c;
730 {
731 register int s, rr0;
732 register long wait = 0;
733
734 s = splhigh();
735 /* Wait for transmitter to become ready. */
736 do {
737 rr0 = zc->zc_csr;
738 ZS_DELAY();
739 } while (((rr0 & ZSRR0_TX_READY) == 0) && (wait++ < 1000000));
740
741 if ((rr0 & ZSRR0_TX_READY) != 0) {
742 zc->zc_data = c;
743 ZS_DELAY();
744 }
745 splx(s);
746 }
747
748
749 /*
750 * Polled console input putchar.
751 */
752 int
753 zscngetc(dev)
754 dev_t dev;
755 {
756 register volatile struct zschan *zc = zs_conschan;
757 register int c;
758
759 c = zs_getc(zc);
760 return (c);
761 }
762
763 /*
764 * Polled console output putchar.
765 */
766 void
767 zscnputc(dev, c)
768 dev_t dev;
769 int c;
770 {
771 register volatile struct zschan *zc = zs_conschan;
772
773 zs_putc(zc, c);
774 }
775
776
777
778 /*
779 * Handle user request to enter kernel debugger.
780 */
781 void
782 zs_abort(zst)
783 register struct zstty_softc *zst;
784 {
785 register volatile struct zschan *zc = zs_conschan;
786 int rr0;
787 register long wait = 0;
788
789 if ((zst->zst_hwflags & ZS_HWFLAG_CONABRT) == 0)
790 return;
791
792 /* Wait for end of break to avoid PROM abort. */
793 /* XXX - Limit the wait? */
794 do {
795 rr0 = zc->zc_csr;
796 ZS_DELAY();
797 } while ((rr0 & ZSRR0_BREAK) && (wait++ < ZSABORT_DELAY));
798
799 if (wait > ZSABORT_DELAY) {
800 if (zst != NULL) zst->zst_hwflags &= ~ZS_HWFLAG_CONABRT;
801 /* If we time out, turn off the abort ability! */
802 }
803
804 /* XXX - Always available, but may be the PROM monitor. */
805 Debugger();
806 }
807