zs.c revision 1.13.4.1 1 /* $NetBSD: zs.c,v 1.13.4.1 1997/08/23 07:10:34 thorpej 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 <mac68k/dev/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 *, struct cfdata *, 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, cf, aux)
206 struct device *parent;
207 struct cfdata *cf;
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;
247 int chip = 0; /* XXX quiet bogus gcc warning */
248
249 if (!zsinited) zs_init();
250 zsinited = 2;
251
252 zsc_unit = zsc->zsc_dev.dv_unit;
253
254 /* Make sure everything's inited ok. */
255 if (zsaddr[zsc_unit] == NULL)
256 panic("zs_attach: zs%d not mapped\n", zsc_unit);
257
258 /*
259 * Initialize software state for each channel.
260 */
261 for (channel = 0; channel < 2; channel++) {
262 cs = &zsc->zsc_cs[channel];
263
264 zc = zs_get_chan_addr(zsc_unit, channel);
265 cs->cs_reg_csr = &zc->zc_csr;
266 cs->cs_reg_data = &zc->zc_data;
267
268 cs->cs_channel = channel;
269 cs->cs_private = NULL;
270 cs->cs_ops = &zsops_null;
271
272 /* Define BAUD rate clock for the MI code. */
273 cs->cs_pclk_div16 = mac68k_machine.sccClkConst*2;
274 cs->cs_csource = 0;
275 cs->cs_psource = 0;
276
277 cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
278
279 bcopy(zs_init_reg, cs->cs_creg, 16);
280 bcopy(zs_init_reg, cs->cs_preg, 16);
281
282 /*
283 * Clear the master interrupt enable.
284 * The INTENA is common to both channels,
285 * so just do it on the A channel.
286 */
287 if (channel == 0) {
288 zs_write_reg(cs, 9, 0);
289
290 chip = 0; /* We'll turn chip checking on post 1.2 */
291 printf(" chip type %d \n",chip);
292 }
293 cs->cs_chip = chip;
294
295 /*
296 * Look for a child driver for this channel.
297 * The child attach will setup the hardware.
298 */
299 zsc_args.channel = channel;
300 zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
301 if (!config_found(self, (void *) &zsc_args, zsc_print)) {
302 /* No sub-driver. Just reset it. */
303 reset = (channel == 0) ?
304 ZSWR9_A_RESET : ZSWR9_B_RESET;
305 s = splzs();
306 zs_write_reg(cs, 9, reset);
307 splx(s);
308 }
309 }
310
311 /*
312 * Set the master interrupt enable and interrupt vector.
313 * (common to both channels, do it on A)
314 */
315 cs = &zsc->zsc_cs[0];
316 s = splzs();
317 /* interrupt vector */
318 zs_write_reg(cs, 2, zs_init_reg[2]);
319 /* master interrupt control (enable) */
320 zs_write_reg(cs, 9, zs_init_reg[9]);
321 splx(s);
322 }
323
324 void
325 zstty_mdattach(zsc, zst, cs, tp)
326 struct zsc_softc *zsc;
327 struct zstty_softc *zst;
328 struct zs_chanstate *cs;
329 struct tty *tp;
330 {
331 int theflags;
332
333 zst->zst_resetdef = 0;
334 cs->cs_clock_count = 3; /* internal + externals */
335 cs->cs_cclk_flag = 0; /* Not doing anything fancy by default */
336 cs->cs_pclk_flag = 0;
337 cs->cs_clocks[0].clk = mac68k_machine.sccClkConst*32;
338 cs->cs_clocks[0].flags = ZSC_RTXBRG; /* allowing divide by 16 will
339 melt the driver! */
340
341 cs->cs_clocks[1].flags = ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
342 cs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
343 if (zst->zst_dev.dv_unit == 0) {
344 theflags = mac68k_machine.modem_flags;
345 cs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;
346 cs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;
347 } else if (zst->zst_dev.dv_unit == 1) {
348 theflags = mac68k_machine.print_flags;
349 cs->cs_clocks[1].flags = ZSC_VARIABLE;
350 /*
351 * Yes, we aren't defining ANY clock source enables for the
352 * printer's DCD clock in. The hardware won't let us
353 * use it. But a clock will freak out the chip, so we
354 * let you set it, telling us to bar interrupts on the line.
355 */
356 cs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;
357 cs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;
358 } else
359 theflags = 0;
360
361 if (cs->cs_clocks[1].clk)
362 zst->zst_hwflags |= ZS_HWFLAG_IGDCD;
363 if (cs->cs_clocks[2].clk)
364 zst->zst_hwflags |= ZS_HWFLAG_IGCTS;
365
366 if (theflags & ZSMAC_RAW) {
367 zst->zst_cflag = ZSTTY_RAW_CFLAG;
368 zst->zst_iflag = ZSTTY_RAW_IFLAG;
369 zst->zst_lflag = ZSTTY_RAW_LFLAG;
370 zst->zst_oflag = ZSTTY_RAW_OFLAG;
371 printf(" (raw defaults)");
372 }
373 if (theflags & ZSMAC_LOCALTALK) {
374 printf(" shielding from LocalTalk");
375 zst->zst_ospeed = tp->t_ospeed = 1;
376 zst->zst_ispeed = tp->t_ispeed = 1;
377 cs->cs_defspeed = 1;
378 cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff;
379 cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff;
380 zs_write_reg(cs, ZSRR_BAUDLO, 0xff);
381 zs_write_reg(cs, ZSRR_BAUDHI, 0xff);
382 /*
383 * If we might have LocalTalk, then make sure we have the
384 * Baud rate low-enough to not do any damage.
385 */
386 }
387
388 /* For the mac, we have rtscts = check CTS for output control, no
389 * input control. mdmbuf means check DCD for output, and use DTR
390 * for input control. mdmbuf & rtscts means use CTS for output
391 * control, and DTR for input control. */
392
393 zst->zst_hwimasks[1] = 0;
394 zst->zst_hwimasks[2] = ZSWR5_DTR;
395 zst->zst_hwimasks[3] = ZSWR5_DTR;
396 }
397
398 int
399 zsmdioctl(tp, com, data, flag, p)
400 struct tty *tp;
401 u_long com;
402 caddr_t data;
403 int flag;
404 struct proc *p;
405 {
406 return (-1);
407 }
408
409 void
410 zsmd_setclock(cs)
411 struct zs_chanstate *cs;
412 {
413 if (cs->cs_channel != 0)
414 return;
415 /*
416 * If the new clock has the external bit set, then select the
417 * external source.
418 */
419 via_set_modem((cs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0);
420 }
421
422 int
423 zshard(arg)
424 void *arg;
425 {
426 struct zsc_softc *zsc;
427 int unit, rval;
428 #ifdef ZSMACDEBUG
429 itecnputc(mac68k_zsdev, 'Z');
430 #endif
431
432 rval = 0;
433 unit = zsc_cd.cd_ndevs;
434 while (--unit >= 0) {
435 zsc = zsc_cd.cd_devs[unit];
436 if (zsc != NULL) {
437 rval |= zsc_intr_hard(zsc);
438 }
439 }
440 #ifdef ZSMACDEBUG
441 itecnputc(mac68k_zsdev, '\n');
442 #endif
443 return (rval);
444 }
445
446 int zssoftpending;
447
448 void
449 zsc_req_softint(zsc)
450 struct zsc_softc *zsc;
451 {
452 if (zssoftpending == 0) {
453 /* We are at splzs here, so no need to lock. */
454 zssoftpending = ZSSOFT_PRI;
455 /* isr_soft_request(ZSSOFT_PRI); */
456 setsoftserial();
457 }
458 }
459
460 int
461 zssoft(arg)
462 void *arg;
463 {
464 struct zsc_softc *zsc;
465 int unit;
466
467 /* This is not the only ISR on this IPL. */
468 if (zssoftpending == 0)
469 return (0);
470
471 /*
472 * The soft intr. bit will be set by zshard only if
473 * the variable zssoftpending is zero. The order of
474 * these next two statements prevents our clearing
475 * the soft intr bit just after zshard has set it.
476 */
477 /* isr_soft_clear(ZSSOFT_PRI); */
478 zssoftpending = 0;
479
480 /* Do ttya/ttyb first, because they go faster. */
481 unit = zsc_cd.cd_ndevs;
482 while (--unit >= 0) {
483 zsc = zsc_cd.cd_devs[unit];
484 if (zsc != NULL) {
485 (void) zsc_intr_soft(zsc);
486 }
487 }
488 return (1);
489 }
490
491
492 /*
493 * Read or write the chip with suitable delays.
494 */
495 #define ZS_DELAY()
496 /*
497 * MacII hardware has the delay built in. No need for extra delay. :-)
498 */
499
500 u_char
501 zs_read_reg(cs, reg)
502 struct zs_chanstate *cs;
503 u_char reg;
504 {
505 u_char val;
506
507 *cs->cs_reg_csr = reg;
508 ZS_DELAY();
509 val = *cs->cs_reg_csr;
510 ZS_DELAY();
511 return val;
512 }
513
514 void
515 zs_write_reg(cs, reg, val)
516 struct zs_chanstate *cs;
517 u_char reg, val;
518 {
519 *cs->cs_reg_csr = reg;
520 ZS_DELAY();
521 *cs->cs_reg_csr = val;
522 ZS_DELAY();
523 }
524
525 u_char zs_read_csr(cs)
526 struct zs_chanstate *cs;
527 {
528 register u_char v;
529
530 v = (*cs->cs_reg_csr) ^ ZSRR0_CTS;
531 /* make up for the fact CTS is wired backwards */
532 ZS_DELAY();
533 return v;
534 }
535
536 u_char zs_read_data(cs)
537 struct zs_chanstate *cs;
538 {
539 register u_char v;
540
541 v = *cs->cs_reg_data;
542 ZS_DELAY();
543 return v;
544 }
545
546 void zs_write_csr(cs, val)
547 struct zs_chanstate *cs;
548 u_char val;
549 {
550 *cs->cs_reg_csr = val;
551 ZS_DELAY();
552 }
553
554 void zs_write_data(cs, val)
555 struct zs_chanstate *cs;
556 u_char val;
557 {
558 *cs->cs_reg_data = val;
559 ZS_DELAY();
560 }
561
562 /****************************************************************
563 * Console support functions (Originally Sun3 specific!)
564 * Now works w/ just mac68k port!
565 ****************************************************************/
566
567 #define zscnpollc nullcnpollc
568 cons_decl(zs);
569
570 static void zs_putc __P((register volatile struct zschan *, int));
571 static int zs_getc __P((register volatile struct zschan *));
572 static void zscnsetup __P((void));
573 extern int zsopen __P(( dev_t dev, int flags, int mode, struct proc *p));
574
575 /*
576 * Console functions.
577 */
578
579 /*
580 * This code modled after the zs_setparam routine in zskgdb
581 * It sets the console unit to a known state so we can output
582 * correctly.
583 */
584 static void
585 zscnsetup()
586 {
587 struct zs_chanstate cs;
588 struct zschan *zc;
589 int tconst, s;
590
591 /* Setup temporary chanstate. */
592 bzero((caddr_t)&cs, sizeof(cs));
593 zc = zs_conschan;
594 cs.cs_reg_csr = &zc->zc_csr;
595 cs.cs_reg_data = &zc->zc_data;
596 cs.cs_channel = zs_consunit;
597
598 bcopy(zs_init_reg, cs.cs_preg, 16);
599 tconst = BPS_TO_TCONST(mac68k_machine.sccClkConst*2, zs_defspeed[0][zs_consunit]);
600 cs.cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
601 cs.cs_preg[1] = 0; /* don't enable interrupts */
602 cs.cs_preg[12] = tconst;
603 cs.cs_preg[13] = tconst >> 8;
604
605 s = splhigh();
606 zs_loadchannelregs(&cs);
607 splx(s);
608 }
609
610 /*
611 * zscnprobe is the routine which gets called as the kernel is trying to
612 * figure out where the console should be. Each io driver which might
613 * be the console (as defined in mac68k/conf.c) gets probed. The probe
614 * fills in the consdev structure. Important parts are the device #,
615 * and the console priority. Values are CN_DEAD (don't touch me),
616 * CN_NORMAL (I'm here, but elsewhere might be better), CN_INTERNAL
617 * (the video, better than CN_NORMAL), and CN_REMOTE (pick me!)
618 *
619 * As the mac's a bit different, we do extra work here. We mainly check
620 * to see if we have serial echo going on, and if the tty's are supposed
621 * to default to raw or not.
622 */
623 void
624 zscnprobe(struct consdev * cp)
625 {
626 extern u_long IOBase;
627 int maj, unit;
628
629 for (maj = 0; maj < nchrdev; maj++) {
630 if (cdevsw[maj].d_open == zsopen) {
631 break;
632 }
633 }
634 if (maj == nchrdev) {
635 /* no console entry for us */
636 if (mac68k_machine.serial_boot_echo) {
637 mac68k_set_io_offsets(IOBase);
638 zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
639 zs_consunit = 1;
640 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
641 zs_init();
642 zscnsetup();
643 }
644 return;
645 }
646
647 cp->cn_pri = CN_NORMAL; /* Lower than CN_INTERNAL */
648 if (mac68k_machine.serial_console != 0) {
649 cp->cn_pri = CN_REMOTE; /* Higher than CN_INTERNAL */
650 mac68k_machine.serial_boot_echo =0;
651 }
652
653 unit = (mac68k_machine.serial_console == 1) ? 0 : 1;
654 zs_consunit = unit;
655
656 mac68k_zsdev = cp->cn_dev = makedev(maj, unit);
657
658 if (mac68k_machine.serial_boot_echo) {
659 /*
660 * at this point, we know that we don't have a serial
661 * console, but are doing echo
662 */
663 mac68k_set_io_offsets(IOBase);
664 zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
665 zs_consunit = 1;
666 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
667 zs_init();
668 zscnsetup();
669 }
670 return;
671 }
672
673 void
674 zscninit(struct consdev * cp)
675 {
676 extern u_long IOBase;
677 int chan = minor(cp->cn_dev & 1);
678
679 mac68k_set_io_offsets(IOBase);
680 zs_conschan = (struct zschan *) -1;
681 zs_consunit = chan;
682 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
683 #ifdef ZS_CONSOLE_ABORT
684 zs_hwflags[0][zs_consunit] |= ZS_HWFLAG_CONABRT;
685 #endif
686 zs_init();
687 /*
688 * zsinit will set up the addresses of the scc. It will also, if
689 * zs_conschan != 0, calculate the new address of the conschan for
690 * unit zs_consunit. So zs_init implicitly sets zs_conschan to the right
691 * number. :-)
692 */
693 zscnsetup();
694 printf("\nNetBSD/mac68k console\n");
695 }
696
697
698 /*
699 * Polled input char.
700 */
701 static int
702 zs_getc(zc)
703 register volatile struct zschan *zc;
704 {
705 register int s, c, rr0;
706
707 s = splhigh();
708 /* Wait for a character to arrive. */
709 do {
710 rr0 = zc->zc_csr;
711 ZS_DELAY();
712 } while ((rr0 & ZSRR0_RX_READY) == 0);
713
714 c = zc->zc_data;
715 ZS_DELAY();
716 splx(s);
717
718 /*
719 * This is used by the kd driver to read scan codes,
720 * so don't translate '\r' ==> '\n' here...
721 */
722 return (c);
723 }
724
725 /*
726 * Polled output char.
727 */
728 static void
729 zs_putc(zc, c)
730 register volatile struct zschan *zc;
731 int c;
732 {
733 register int s, rr0;
734 register long wait = 0;
735
736 s = splhigh();
737 /* Wait for transmitter to become ready. */
738 do {
739 rr0 = zc->zc_csr;
740 ZS_DELAY();
741 } while (((rr0 & ZSRR0_TX_READY) == 0) && (wait++ < 1000000));
742
743 if ((rr0 & ZSRR0_TX_READY) != 0) {
744 zc->zc_data = c;
745 ZS_DELAY();
746 }
747 splx(s);
748 }
749
750
751 /*
752 * Polled console input putchar.
753 */
754 int
755 zscngetc(dev)
756 dev_t dev;
757 {
758 register volatile struct zschan *zc = zs_conschan;
759 register int c;
760
761 c = zs_getc(zc);
762 return (c);
763 }
764
765 /*
766 * Polled console output putchar.
767 */
768 void
769 zscnputc(dev, c)
770 dev_t dev;
771 int c;
772 {
773 register volatile struct zschan *zc = zs_conschan;
774
775 zs_putc(zc, c);
776 }
777
778
779
780 /*
781 * Handle user request to enter kernel debugger.
782 */
783 void
784 zs_abort(zst)
785 register struct zstty_softc *zst;
786 {
787 register volatile struct zschan *zc = zs_conschan;
788 int rr0;
789 register long wait = 0;
790
791 if ((zst->zst_hwflags & ZS_HWFLAG_CONABRT) == 0)
792 return;
793
794 /* Wait for end of break to avoid PROM abort. */
795 /* XXX - Limit the wait? */
796 do {
797 rr0 = zc->zc_csr;
798 ZS_DELAY();
799 } while ((rr0 & ZSRR0_BREAK) && (wait++ < ZSABORT_DELAY));
800
801 if (wait > ZSABORT_DELAY) {
802 if (zst != NULL) zst->zst_hwflags &= ~ZS_HWFLAG_CONABRT;
803 /* If we time out, turn off the abort ability! */
804 }
805
806 #ifdef DDB
807 Debugger();
808 #endif
809 }
810