zs.c revision 1.69.2.2 1 /* $NetBSD: zs.c,v 1.69.2.2 2000/03/29 20:32:30 he 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 "opt_ddb.h"
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/conf.h>
52 #include <sys/device.h>
53 #include <sys/file.h>
54 #include <sys/ioctl.h>
55 #include <sys/kernel.h>
56 #include <sys/proc.h>
57 #include <sys/tty.h>
58 #include <sys/time.h>
59 #include <sys/syslog.h>
60
61 #include <machine/bsd_openprom.h>
62 #include <machine/autoconf.h>
63 #include <machine/conf.h>
64 #include <machine/cpu.h>
65 #include <machine/eeprom.h>
66 #include <machine/psl.h>
67 #include <machine/z8530var.h>
68
69 #include <dev/cons.h>
70 #include <dev/ic/z8530reg.h>
71
72 #include <sparc/sparc/vaddrs.h>
73 #include <sparc/sparc/auxreg.h>
74 #include <sparc/dev/cons.h>
75
76 #include "kbd.h" /* NKBD */
77 #include "zs.h" /* NZS */
78
79 /* Make life easier for the initialized arrays here. */
80 #if NZS < 3
81 #undef NZS
82 #define NZS 3
83 #endif
84
85 /*
86 * Some warts needed by z8530tty.c -
87 * The default parity REALLY needs to be the same as the PROM uses,
88 * or you can not see messages done with printf during boot-up...
89 */
90 int zs_def_cflag = (CREAD | CS8 | HUPCL);
91 int zs_major = 12;
92
93 /*
94 * The Sun provides a 4.9152 MHz clock to the ZS chips.
95 */
96 #define PCLK (9600 * 512) /* PCLK pin input clock rate */
97
98 /*
99 * Select software interrupt bit based on TTY ipl.
100 */
101 #if PIL_TTY == 1
102 # define IE_ZSSOFT IE_L1
103 #elif PIL_TTY == 4
104 # define IE_ZSSOFT IE_L4
105 #elif PIL_TTY == 6
106 # define IE_ZSSOFT IE_L6
107 #else
108 # error "no suitable software interrupt bit"
109 #endif
110
111 #define ZS_DELAY() (CPU_ISSUN4C ? (0) : delay(2))
112
113 /* The layout of this is hardware-dependent (padding, order). */
114 struct zschan {
115 volatile u_char zc_csr; /* ctrl,status, and indirect access */
116 u_char zc_xxx0;
117 volatile u_char zc_data; /* data */
118 u_char zc_xxx1;
119 };
120 struct zsdevice {
121 /* Yes, they are backwards. */
122 struct zschan zs_chan_b;
123 struct zschan zs_chan_a;
124 };
125
126 /* Saved PROM mappings */
127 static struct zsdevice *zsaddr[NZS];
128
129 /* Flags from cninit() */
130 static int zs_hwflags[NZS][2];
131
132 /* Default speed for each channel */
133 static int zs_defspeed[NZS][2] = {
134 { 9600, /* ttya */
135 9600 }, /* ttyb */
136 { 1200, /* keyboard */
137 1200 }, /* mouse */
138 { 9600, /* ttyc */
139 9600 }, /* ttyd */
140 };
141
142 static u_char zs_init_reg[16] = {
143 0, /* 0: CMD (reset, etc.) */
144 0, /* 1: No interrupts yet. */
145 0, /* 2: IVECT */
146 ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
147 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
148 ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
149 0, /* 6: TXSYNC/SYNCLO */
150 0, /* 7: RXSYNC/SYNCHI */
151 0, /* 8: alias for data port */
152 ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR,
153 0, /*10: Misc. TX/RX control bits */
154 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
155 ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */
156 0, /*13: BAUDHI (default=9600) */
157 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
158 ZSWR15_BREAK_IE,
159 };
160
161 struct zschan *
162 zs_get_chan_addr(zs_unit, channel)
163 int zs_unit, channel;
164 {
165 struct zsdevice *addr;
166 struct zschan *zc;
167
168 if (zs_unit >= NZS)
169 return (NULL);
170 addr = zsaddr[zs_unit];
171 if (addr == NULL)
172 addr = zsaddr[zs_unit] = findzs(zs_unit);
173 if (addr == NULL)
174 return (NULL);
175 if (channel == 0) {
176 zc = &addr->zs_chan_a;
177 } else {
178 zc = &addr->zs_chan_b;
179 }
180 return (zc);
181 }
182
183
184 /****************************************************************
185 * Autoconfig
186 ****************************************************************/
187
188 /* Definition of the driver for autoconfig. */
189 static int zs_match_mainbus __P((struct device *, struct cfdata *, void *));
190 static int zs_match_obio __P((struct device *, struct cfdata *, void *));
191 static void zs_attach_mainbus __P((struct device *, struct device *, void *));
192 static void zs_attach_obio __P((struct device *, struct device *, void *));
193
194 static void zs_attach __P((struct zsc_softc *, int));
195 static int zs_print __P((void *, const char *name));
196
197 struct cfattach zs_mainbus_ca = {
198 sizeof(struct zsc_softc), zs_match_mainbus, zs_attach_mainbus
199 };
200
201 struct cfattach zs_obio_ca = {
202 sizeof(struct zsc_softc), zs_match_obio, zs_attach_obio
203 };
204
205 extern struct cfdriver zs_cd;
206
207 /* Interrupt handlers. */
208 static int zshard __P((void *));
209 static int zssoft __P((void *));
210 static struct intrhand levelsoft = { zssoft };
211
212 static int zs_get_speed __P((struct zs_chanstate *));
213
214
215 /*
216 * Is the zs chip present?
217 */
218 static int
219 zs_match_mainbus(parent, cf, aux)
220 struct device *parent;
221 struct cfdata *cf;
222 void *aux;
223 {
224 struct mainbus_attach_args *ma = aux;
225
226 if (strcmp(cf->cf_driver->cd_name, ma->ma_name) != 0)
227 return (0);
228
229 return (getpropint(ma->ma_node, "slave", -2) == cf->cf_unit);
230 }
231
232 static int
233 zs_match_obio(parent, cf, aux)
234 struct device *parent;
235 struct cfdata *cf;
236 void *aux;
237 {
238 union obio_attach_args *uoba = aux;
239 struct obio4_attach_args *oba;
240
241 if (uoba->uoba_isobio4 == 0) {
242 struct sbus_attach_args *sa = &uoba->uoba_sbus;
243
244 if (strcmp(cf->cf_driver->cd_name, sa->sa_name) != 0)
245 return (0);
246
247 return (getpropint(sa->sa_node, "slave", -2) == cf->cf_unit);
248 }
249
250 oba = &uoba->uoba_oba4;
251 return (bus_space_probe(oba->oba_bustag, 0, oba->oba_paddr,
252 1, 0, 0, NULL, NULL));
253 }
254
255 static void
256 zs_attach_mainbus(parent, self, aux)
257 struct device *parent;
258 struct device *self;
259 void *aux;
260 {
261 struct zsc_softc *zsc = (void *) self;
262 struct mainbus_attach_args *ma = aux;
263 int zs_unit = zsc->zsc_dev.dv_unit;
264
265 zsc->zsc_bustag = ma->ma_bustag;
266 zsc->zsc_dmatag = ma->ma_dmatag;
267
268 /* Use the mapping setup by the Sun PROM. */
269 if (zsaddr[zs_unit] == NULL)
270 zsaddr[zs_unit] = findzs(zs_unit);
271 if ((void*)zsaddr[zs_unit] != ma->ma_promvaddr)
272 panic("zsattach_mainbus");
273
274 zs_attach(zsc, ma->ma_pri);
275 }
276
277 static void
278 zs_attach_obio(parent, self, aux)
279 struct device *parent;
280 struct device *self;
281 void *aux;
282 {
283 struct zsc_softc *zsc = (void *) self;
284 union obio_attach_args *uoba = aux;
285 int zs_unit = zsc->zsc_dev.dv_unit;
286
287 /* Use the mapping setup by the Sun PROM. */
288 if (zsaddr[zs_unit] == NULL)
289 zsaddr[zs_unit] = findzs(zs_unit);
290
291 if (uoba->uoba_isobio4 == 0) {
292 struct sbus_attach_args *sa = &uoba->uoba_sbus;
293 zsc->zsc_bustag = sa->sa_bustag;
294 zsc->zsc_dmatag = sa->sa_dmatag;
295 zs_attach(zsc, sa->sa_pri);
296 } else {
297 struct obio4_attach_args *oba = &uoba->uoba_oba4;
298 zsc->zsc_bustag = oba->oba_bustag;
299 zsc->zsc_dmatag = oba->oba_dmatag;
300 zs_attach(zsc, oba->oba_pri);
301 }
302 }
303 /*
304 * Attach a found zs.
305 *
306 * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR
307 * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE?
308 */
309 static void
310 zs_attach(zsc, pri)
311 struct zsc_softc *zsc;
312 int pri;
313 {
314 struct zsc_attach_args zsc_args;
315 volatile struct zschan *zc;
316 struct zs_chanstate *cs;
317 int s, zs_unit, channel;
318 static int didintr, prevpri;
319
320 printf(" softpri %d\n", PIL_TTY);
321
322 /*
323 * Initialize software state for each channel.
324 */
325 zs_unit = zsc->zsc_dev.dv_unit;
326 for (channel = 0; channel < 2; channel++) {
327 zsc_args.channel = channel;
328 zsc_args.hwflags = zs_hwflags[zs_unit][channel];
329 cs = &zsc->zsc_cs_store[channel];
330 zsc->zsc_cs[channel] = cs;
331
332 cs->cs_channel = channel;
333 cs->cs_private = NULL;
334 cs->cs_ops = &zsops_null;
335 cs->cs_brg_clk = PCLK / 16;
336
337 zc = zs_get_chan_addr(zs_unit, channel);
338 cs->cs_reg_csr = &zc->zc_csr;
339 cs->cs_reg_data = &zc->zc_data;
340
341 bcopy(zs_init_reg, cs->cs_creg, 16);
342 bcopy(zs_init_reg, cs->cs_preg, 16);
343
344 /* XXX: Get these from the PROM properties! */
345 /* XXX: See the mvme167 code. Better. */
346 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
347 cs->cs_defspeed = zs_get_speed(cs);
348 else
349 cs->cs_defspeed = zs_defspeed[zs_unit][channel];
350 cs->cs_defcflag = zs_def_cflag;
351
352 /* Make these correspond to cs_defcflag (-crtscts) */
353 cs->cs_rr0_dcd = ZSRR0_DCD;
354 cs->cs_rr0_cts = 0;
355 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
356 cs->cs_wr5_rts = 0;
357
358 /*
359 * Clear the master interrupt enable.
360 * The INTENA is common to both channels,
361 * so just do it on the A channel.
362 */
363 if (channel == 0) {
364 zs_write_reg(cs, 9, 0);
365 }
366
367 /*
368 * Look for a child driver for this channel.
369 * The child attach will setup the hardware.
370 */
371 if (!config_found(&zsc->zsc_dev, (void *)&zsc_args, zs_print)) {
372 /* No sub-driver. Just reset it. */
373 u_char reset = (channel == 0) ?
374 ZSWR9_A_RESET : ZSWR9_B_RESET;
375 s = splzs();
376 zs_write_reg(cs, 9, reset);
377 splx(s);
378 }
379 }
380
381 /*
382 * Now safe to install interrupt handlers. Note the arguments
383 * to the interrupt handlers aren't used. Note, we only do this
384 * once since both SCCs interrupt at the same level and vector.
385 */
386 if (!didintr) {
387 didintr = 1;
388 prevpri = pri;
389 bus_intr_establish(zsc->zsc_bustag, pri, 0, zshard, NULL);
390 intr_establish(PIL_TTY, &levelsoft);
391 } else if (pri != prevpri)
392 panic("broken zs interrupt scheme");
393
394 evcnt_attach(&zsc->zsc_dev, "intr", &zsc->zsc_intrcnt);
395
396 /*
397 * Set the master interrupt enable and interrupt vector.
398 * (common to both channels, do it on A)
399 */
400 cs = zsc->zsc_cs[0];
401 s = splhigh();
402 /* interrupt vector */
403 zs_write_reg(cs, 2, zs_init_reg[2]);
404 /* master interrupt control (enable) */
405 zs_write_reg(cs, 9, zs_init_reg[9]);
406 splx(s);
407
408 #if 0
409 /*
410 * XXX: L1A hack - We would like to be able to break into
411 * the debugger during the rest of autoconfiguration, so
412 * lower interrupts just enough to let zs interrupts in.
413 * This is done after both zs devices are attached.
414 */
415 if (zs_unit == 1) {
416 printf("zs1: enabling zs interrupts\n");
417 (void)splfd(); /* XXX: splzs - 1 */
418 }
419 #endif
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 printf("%s: ", name);
431
432 if (args->channel != -1)
433 printf(" channel %d", args->channel);
434
435 return (UNCONF);
436 }
437
438 static volatile int zssoftpending;
439
440 /*
441 * Our ZS chips all share a common, autovectored interrupt,
442 * so we have to look at all of them on each interrupt.
443 */
444 static int
445 zshard(arg)
446 void *arg;
447 {
448 register struct zsc_softc *zsc;
449 register int unit, rr3, rval, softreq;
450 struct zs_chanstate *cs;
451
452 rval = softreq = 0;
453 for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
454 zsc = zs_cd.cd_devs[unit];
455 if (zsc == NULL)
456 continue;
457 rr3 = zsc_intr_hard(zsc);
458 /* Count up the interrupts. */
459 if (rr3) {
460 rval |= rr3;
461 zsc->zsc_intrcnt.ev_count++;
462 }
463 if ((cs = zsc->zsc_cs[0]) != NULL)
464 softreq |= cs->cs_softreq;
465 if ((cs = zsc->zsc_cs[1]) != NULL)
466 softreq |= cs->cs_softreq;
467 }
468
469 /* We are at splzs here, so no need to lock. */
470 if (softreq && (zssoftpending == 0)) {
471 zssoftpending = IE_ZSSOFT;
472 #if defined(SUN4M)
473 if (CPU_ISSUN4M)
474 raise(0, PIL_TTY);
475 else
476 #endif
477 ienab_bis(IE_ZSSOFT);
478 }
479 return (rval);
480 }
481
482 /*
483 * Similar scheme as for zshard (look at all of them)
484 */
485 static int
486 zssoft(arg)
487 void *arg;
488 {
489 register struct zsc_softc *zsc;
490 register int s, unit;
491
492 /* This is not the only ISR on this IPL. */
493 if (zssoftpending == 0)
494 return (0);
495
496 /*
497 * The soft intr. bit will be set by zshard only if
498 * the variable zssoftpending is zero. The order of
499 * these next two statements prevents our clearing
500 * the soft intr bit just after zshard has set it.
501 */
502 /* ienab_bic(IE_ZSSOFT); */
503 zssoftpending = 0;
504
505 /* Make sure we call the tty layer at spltty. */
506 s = spltty();
507 for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
508 zsc = zs_cd.cd_devs[unit];
509 if (zsc == NULL)
510 continue;
511 (void)zsc_intr_soft(zsc);
512 }
513 splx(s);
514 return (1);
515 }
516
517
518 /*
519 * Compute the current baud rate given a ZS channel.
520 */
521 static int
522 zs_get_speed(cs)
523 struct zs_chanstate *cs;
524 {
525 int tconst;
526
527 tconst = zs_read_reg(cs, 12);
528 tconst |= zs_read_reg(cs, 13) << 8;
529 return (TCONST_TO_BPS(cs->cs_brg_clk, tconst));
530 }
531
532 /*
533 * MD functions for setting the baud rate and control modes.
534 */
535 int
536 zs_set_speed(cs, bps)
537 struct zs_chanstate *cs;
538 int bps; /* bits per second */
539 {
540 int tconst, real_bps;
541
542 if (bps == 0)
543 return (0);
544
545 #ifdef DIAGNOSTIC
546 if (cs->cs_brg_clk == 0)
547 panic("zs_set_speed");
548 #endif
549
550 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
551 if (tconst < 0)
552 return (EINVAL);
553
554 /* Convert back to make sure we can do it. */
555 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
556
557 /* XXX - Allow some tolerance here? */
558 if (real_bps != bps)
559 return (EINVAL);
560
561 cs->cs_preg[12] = tconst;
562 cs->cs_preg[13] = tconst >> 8;
563
564 /* Caller will stuff the pending registers. */
565 return (0);
566 }
567
568 int
569 zs_set_modes(cs, cflag)
570 struct zs_chanstate *cs;
571 int cflag; /* bits per second */
572 {
573 int s;
574
575 /*
576 * Output hardware flow control on the chip is horrendous:
577 * if carrier detect drops, the receiver is disabled, and if
578 * CTS drops, the transmitter is stoped IN MID CHARACTER!
579 * Therefore, NEVER set the HFC bit, and instead use the
580 * status interrupt to detect CTS changes.
581 */
582 s = splzs();
583 cs->cs_rr0_pps = 0;
584 if ((cflag & (CLOCAL | MDMBUF)) != 0) {
585 cs->cs_rr0_dcd = 0;
586 if ((cflag & MDMBUF) == 0)
587 cs->cs_rr0_pps = ZSRR0_DCD;
588 } else
589 cs->cs_rr0_dcd = ZSRR0_DCD;
590 if ((cflag & CRTSCTS) != 0) {
591 cs->cs_wr5_dtr = ZSWR5_DTR;
592 cs->cs_wr5_rts = ZSWR5_RTS;
593 cs->cs_rr0_cts = ZSRR0_CTS;
594 } else if ((cflag & CDTRCTS) != 0) {
595 cs->cs_wr5_dtr = 0;
596 cs->cs_wr5_rts = ZSWR5_DTR;
597 cs->cs_rr0_cts = ZSRR0_CTS;
598 } else if ((cflag & MDMBUF) != 0) {
599 cs->cs_wr5_dtr = 0;
600 cs->cs_wr5_rts = ZSWR5_DTR;
601 cs->cs_rr0_cts = ZSRR0_DCD;
602 } else {
603 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
604 cs->cs_wr5_rts = 0;
605 cs->cs_rr0_cts = 0;
606 }
607 splx(s);
608
609 /* Caller will stuff the pending registers. */
610 return (0);
611 }
612
613
614 /*
615 * Read or write the chip with suitable delays.
616 */
617
618 u_char
619 zs_read_reg(cs, reg)
620 struct zs_chanstate *cs;
621 u_char reg;
622 {
623 u_char val;
624
625 *cs->cs_reg_csr = reg;
626 ZS_DELAY();
627 val = *cs->cs_reg_csr;
628 ZS_DELAY();
629 return (val);
630 }
631
632 void
633 zs_write_reg(cs, reg, val)
634 struct zs_chanstate *cs;
635 u_char reg, val;
636 {
637 *cs->cs_reg_csr = reg;
638 ZS_DELAY();
639 *cs->cs_reg_csr = val;
640 ZS_DELAY();
641 }
642
643 u_char
644 zs_read_csr(cs)
645 struct zs_chanstate *cs;
646 {
647 register u_char val;
648
649 val = *cs->cs_reg_csr;
650 ZS_DELAY();
651 return (val);
652 }
653
654 void zs_write_csr(cs, val)
655 struct zs_chanstate *cs;
656 u_char val;
657 {
658 *cs->cs_reg_csr = val;
659 ZS_DELAY();
660 }
661
662 u_char zs_read_data(cs)
663 struct zs_chanstate *cs;
664 {
665 register u_char val;
666
667 val = *cs->cs_reg_data;
668 ZS_DELAY();
669 return (val);
670 }
671
672 void zs_write_data(cs, val)
673 struct zs_chanstate *cs;
674 u_char val;
675 {
676 *cs->cs_reg_data = val;
677 ZS_DELAY();
678 }
679
680 /****************************************************************
681 * Console support functions (Sun specific!)
682 * Note: this code is allowed to know about the layout of
683 * the chip registers, and uses that to keep things simple.
684 * XXX - I think I like the mvme167 code better. -gwr
685 ****************************************************************/
686
687 extern void Debugger __P((void));
688 void *zs_conschan;
689
690 /*
691 * Handle user request to enter kernel debugger.
692 */
693 void
694 zs_abort(cs)
695 struct zs_chanstate *cs;
696 {
697 register volatile struct zschan *zc = zs_conschan;
698 int rr0;
699
700 /* Wait for end of break to avoid PROM abort. */
701 /* XXX - Limit the wait? */
702 do {
703 rr0 = zc->zc_csr;
704 ZS_DELAY();
705 } while (rr0 & ZSRR0_BREAK);
706
707 #if defined(KGDB)
708 zskgdb(cs);
709 #elif defined(DDB)
710 Debugger();
711 #else
712 printf("stopping on keyboard abort\n");
713 callrom();
714 #endif
715 }
716
717 /*
718 * Polled input char.
719 */
720 int
721 zs_getc(arg)
722 void *arg;
723 {
724 register volatile struct zschan *zc = arg;
725 register int s, c, rr0;
726
727 s = splhigh();
728 /* Wait for a character to arrive. */
729 do {
730 rr0 = zc->zc_csr;
731 ZS_DELAY();
732 } while ((rr0 & ZSRR0_RX_READY) == 0);
733
734 c = zc->zc_data;
735 ZS_DELAY();
736 splx(s);
737
738 /*
739 * This is used by the kd driver to read scan codes,
740 * so don't translate '\r' ==> '\n' here...
741 */
742 return (c);
743 }
744
745 /*
746 * Polled output char.
747 */
748 void
749 zs_putc(arg, c)
750 void *arg;
751 int c;
752 {
753 register volatile struct zschan *zc = arg;
754 register int s, rr0;
755
756 s = splhigh();
757
758 /* Wait for transmitter to become ready. */
759 do {
760 rr0 = zc->zc_csr;
761 ZS_DELAY();
762 } while ((rr0 & ZSRR0_TX_READY) == 0);
763
764 /*
765 * Send the next character.
766 * Now you'd think that this could be followed by a ZS_DELAY()
767 * just like all the other chip accesses, but it turns out that
768 * the `transmit-ready' interrupt isn't de-asserted until
769 * some period of time after the register write completes
770 * (more than a couple instructions). So to avoid stray
771 * interrupts we put in the 2us delay regardless of cpu model.
772 */
773 zc->zc_data = c;
774 delay(2);
775
776 splx(s);
777 }
778
779 /*****************************************************************/
780
781 static void zscninit __P((struct consdev *));
782 static int zscngetc __P((dev_t));
783 static void zscnputc __P((dev_t, int));
784
785 /*
786 * Console table shared by ttya, ttyb
787 */
788 struct consdev consdev_tty = {
789 nullcnprobe,
790 zscninit,
791 zscngetc,
792 zscnputc,
793 nullcnpollc,
794 };
795
796 static void
797 zscninit(cn)
798 struct consdev *cn;
799 {
800 }
801
802 /*
803 * Polled console input putchar.
804 */
805 static int
806 zscngetc(dev)
807 dev_t dev;
808 {
809 return (zs_getc(zs_conschan));
810 }
811
812 /*
813 * Polled console output putchar.
814 */
815 static void
816 zscnputc(dev, c)
817 dev_t dev;
818 int c;
819 {
820 zs_putc(zs_conschan, c);
821 }
822
823 /*****************************************************************/
824
825 static void prom_cninit __P((struct consdev *));
826 static int prom_cngetc __P((dev_t));
827 static void prom_cnputc __P((dev_t, int));
828
829 /*
830 * The console is set to this one initially,
831 * which lets us use the PROM until consinit()
832 * is called to select a real console.
833 */
834 struct consdev consdev_prom = {
835 nullcnprobe,
836 prom_cninit,
837 prom_cngetc,
838 prom_cnputc,
839 nullcnpollc,
840 };
841
842 /*
843 * The console table pointer is statically initialized
844 * to point to the PROM (output only) table, so that
845 * early calls to printf will work.
846 */
847 struct consdev *cn_tab = &consdev_prom;
848
849 void
850 nullcnprobe(cn)
851 struct consdev *cn;
852 {
853 }
854
855 static void
856 prom_cninit(cn)
857 struct consdev *cn;
858 {
859 }
860
861 /*
862 * PROM console input putchar.
863 * (dummy - this is output only) (WHY?????!)
864 */
865 static int
866 prom_cngetc(dev)
867 dev_t dev;
868 {
869 return (prom_getchar());
870 }
871
872 /*
873 * PROM console output putchar.
874 */
875 static void
876 prom_cnputc(dev, c)
877 dev_t dev;
878 int c;
879 {
880
881 prom_putchar(c);
882 }
883
884 /*****************************************************************/
885
886 extern struct consdev consdev_kd;
887
888 static char *prom_inSrc_name[] = {
889 "keyboard/display",
890 "ttya", "ttyb",
891 "ttyc", "ttyd" };
892
893
894 static int get_serial_promdev __P((int));
895
896 int
897 get_serial_promdev(io)
898 int io;
899 {
900 char *prop, *cp, buffer[128];
901 int node;
902
903 node = findroot();
904 prop = (io == 0) ? "stdin-path" : "stdout-path";
905
906 cp = getpropstringA(node, prop, buffer, sizeof buffer);
907
908 /*
909 * At this point we assume the device path is in the form
910 * ....device@x,y:a for ttya and ...device@x,y:b for ttyb, etc.
911 */
912 if (cp[0] != '\0' && cp[1] != '\0') {
913 while (*cp != '\0')
914 cp++;
915 cp -= 2;
916 } else {
917 /*
918 * If don't have at least a 2 character string at cp, then
919 * we default to using using the string ":a" for ttya.
920 */
921 cp[0] = ':';
922 cp[1] = 'a';
923 cp[2] = '\0';
924 }
925
926 if (cp >= buffer) {
927 /* XXX: only allows tty's a->z, assumes PROMDEV_TTYx contig */
928 if (cp[0] == ':' && cp[1] >= 'a' && cp[1] <= 'z')
929 return (PROMDEV_TTYA + (cp[1] - 'a'));
930 }
931
932 printf("Warning: unparseable %s property\n", prop);
933 return (-1);
934 }
935
936 /*
937 * This function replaces sys/dev/cninit.c
938 * Determine which device is the console using
939 * the PROM "input source" and "output sink".
940 */
941 void
942 consinit()
943 {
944 struct zschan *zc;
945 struct consdev *cn;
946 int channel, zs_unit, zstty_unit;
947 int inSource, outSink;
948 int node;
949 char *devtype;
950 extern int fbnode;
951
952 switch (prom_version()) {
953 case PROM_OLDMON:
954 case PROM_OBP_V0:
955 /* The stdio handles identify the device type */
956 inSource = prom_stdin();
957 outSink = prom_stdout();
958 break;
959 case PROM_OBP_V2:
960 case PROM_OBP_V3:
961 case PROM_OPENFIRM:
962 /*
963 * We need to probe the PROM device tree.
964 *
965 * Translate the STDIO package instance (`ihandle') -- that
966 * the PROM has already opened for us -- to a device tree
967 * node (i.e. a `phandle').
968 */
969
970 if ((node = prom_instance_to_package(prom_stdin())) == 0) {
971 printf("consinit: cannot convert stdin ihandle\n");
972 inSource = -1;
973 goto setup_output;
974 }
975
976 if (prom_node_has_property(node, "keyboard")) {
977 inSource = PROMDEV_KBD;
978 } else if (strcmp(getpropstring(node, "device_type"),
979 "serial") == 0) {
980 inSource = get_serial_promdev(0);
981 } else {
982 /* not serial, not keyboard. what is it?!? */
983 inSource = -1;
984 }
985
986 setup_output:
987 if ((node = prom_instance_to_package(prom_stdout())) == 0) {
988 printf("consinit: cannot convert stdout ihandle\n");
989 outSink = -1;
990 goto setup_console;
991 }
992 devtype = getpropstring(node, "device_type");
993 if (strcmp(devtype, "display") == 0) {
994 /* frame buffer output */
995 outSink = PROMDEV_SCREEN;
996 fbnode = node;
997 } else if (strcmp(devtype, "serial") == 0) {
998 outSink = get_serial_promdev(1);
999 } else {
1000 /* not screen, not serial. Whatzit? */
1001 outSink = -1;
1002 }
1003 break;
1004
1005 default:
1006 inSource = -1;
1007 outSink = -1;
1008 }
1009
1010 setup_console:
1011 if (inSource != outSink) {
1012 printf("cninit: mismatched PROM output selector\n");
1013 printf("inSource=%x; Sink=%x\n", inSource, outSink);
1014 }
1015
1016 switch (inSource) {
1017 default:
1018 printf("cninit: invalid inSource=0x%x\n", inSource);
1019 prom_abort();
1020 inSource = PROMDEV_KBD;
1021 /* fall through */
1022
1023 case 0: /* keyboard/display */
1024 #if NKBD > 0
1025 zs_unit = 1; /* XXX - config info! */
1026 channel = 0;
1027 cn = &consdev_kd;
1028 /* Set cn_dev, cn_pri in kd.c */
1029 break;
1030 #else /* NKBD */
1031 printf("cninit: kdb/display not configured\n");
1032 callrom();
1033 inSource = PROMDEV_TTYA;
1034 /* fall through */
1035 #endif /* NKBD */
1036
1037 case PROMDEV_TTYA:
1038 case PROMDEV_TTYB:
1039 zstty_unit = inSource - PROMDEV_TTYA;
1040 zs_unit = 0; /* XXX - config info! */
1041 channel = zstty_unit & 1;
1042 cn = &consdev_tty;
1043 cn->cn_dev = makedev(zs_major, zstty_unit);
1044 cn->cn_pri = CN_REMOTE;
1045 break;
1046
1047 }
1048 /* Now that inSource has been validated, print it. */
1049 printf("console is %s\n", prom_inSrc_name[inSource]);
1050
1051 zc = zs_get_chan_addr(zs_unit, channel);
1052 if (zc == NULL) {
1053 printf("cninit: zs not mapped.\n");
1054 return;
1055 }
1056 zs_conschan = zc;
1057 zs_hwflags[zs_unit][channel] = ZS_HWFLAG_CONSOLE;
1058 cn_tab = cn;
1059 (*cn->cn_init)(cn);
1060 #ifdef KGDB
1061 zs_kgdb_init();
1062 #endif
1063 }
1064