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