zs.c revision 1.15 1 /* $NetBSD: zs.c,v 1.15 1997/10/20 08:13:53 scottr Exp $ */
2
3 /*
4 * Copyright (c) 1996 Bill Studenmund
5 * Copyright (c) 1995 Gordon W. Ross
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 * 4. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Gordon Ross
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Zilog Z8530 Dual UART driver (machine-dependent part)
36 *
37 * Runs two serial lines per chip using slave drivers.
38 * Plain tty/async lines use the zs_async slave.
39 * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
40 * Other ports use their own mice & keyboard slaves.
41 *
42 * Credits & history:
43 *
44 * With NetBSD 1.1, port-mac68k started using a port of the port-sparc
45 * (port-sun3?) zs.c driver (which was in turn based on code in the
46 * Berkeley 4.4 Lite release). Bill Studenmund did the port, with
47 * help from Allen Briggs and Gordon Ross <gwr (at) netbsd.org>. Noud de
48 * Brouwer field-tested the driver at a local ISP.
49 *
50 * Bill Studenmund and Gordon Ross then ported the machine-independant
51 * z8530 driver to work with port-mac68k. NetBSD 1.2 contained an
52 * intermediate version (mac68k using a local, patched version of
53 * the m.i. drivers), with NetBSD 1.3 containing a full version.
54 */
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/proc.h>
59 #include <sys/device.h>
60 #include <sys/conf.h>
61 #include <sys/file.h>
62 #include <sys/ioctl.h>
63 #include <sys/tty.h>
64 #include <sys/time.h>
65 #include <sys/kernel.h>
66 #include <sys/syslog.h>
67
68 #include <dev/cons.h>
69
70 #include <dev/ic/z8530reg.h>
71 #include <machine/z8530var.h>
72
73 #include <machine/autoconf.h>
74 #include <machine/cpu.h>
75 #include <machine/viareg.h>
76
77 /* Are these in a header file anywhere? */
78 /* Booter flags interface */
79 #define ZSMAC_RAW 0x01
80 #define ZSMAC_LOCALTALK 0x02
81 #define ZS_STD_BRG (57600*4)
82
83 #include "zsc.h" /* get the # of zs chips defined */
84
85 /*
86 * Some warts needed by z8530tty.c -
87 */
88 int zs_def_cflag = (CREAD | CS8 | HUPCL);
89 int zs_major = 12;
90
91 /*
92 * abort detection on console will now timeout after iterating on a loop
93 * the following # of times. Cheep hack. Also, abort detection is turned
94 * off after a timeout (i.e. maybe there's not a terminal hooked up).
95 */
96 #define ZSABORT_DELAY 3000000
97
98 /*
99 * Define interrupt levels.
100 */
101 #define ZSHARD_PRI 4 /* Wired on the CPU board... */
102 /*
103 * Serial port cards with zs chips on them are actually at the
104 * NuBus interrupt level, which is lower than 4. But blocking
105 * level 4 interrupts will block those interrupts too, so level
106 * 4 is fine.
107 */
108
109 /* The layout of this is hardware-dependent (padding, order). */
110 struct zschan {
111 volatile u_char zc_csr; /* ctrl,status, and indirect access */
112 u_char zc_xxx0;
113 u_char zc_xxx1; /* part of the other channel lives here! */
114 u_char zc_xxx2; /* Yea Apple! */
115 volatile u_char zc_data; /* data */
116 u_char zc_xxx3;
117 u_char zc_xxx4;
118 u_char zc_xxx5;
119 };
120
121 /* Saved PROM mappings */
122 static char *zsaddr[NZSC]; /* See zs_init() */
123 /* Flags from cninit() */
124 static int zs_hwflags[NZSC][2];
125 /* Default speed for each channel */
126 static int zs_defspeed[NZSC][2] = {
127 { 9600, /* tty00 */
128 9600 }, /* tty01 */
129 };
130 /* console stuff */
131 void *zs_conschan = 0;
132 int zs_consunit;
133 #ifdef ZS_CONSOLE_ABORT
134 int zs_cons_canabort = 1;
135 #else
136 int zs_cons_canabort = 0;
137 #endif /* ZS_CONSOLE_ABORT*/
138 /* device to which the console is attached--if serial. */
139 dev_t mac68k_zsdev;
140 /* Mac stuff */
141 volatile unsigned char *sccA = 0;
142
143 static struct zschan *zs_get_chan_addr __P((int zsc_unit, int channel));
144 void zs_init __P((void));
145 int zs_cn_check_speed __P((int bps));
146
147 /*
148 * Even though zsparam will set up the clock multiples, etc., we
149 * still set them here as: 1) mice & keyboards don't use zsparam,
150 * and 2) the console stuff uses these defaults before device
151 * attach.
152 */
153
154 static u_char zs_init_reg[16] = {
155 0, /* 0: CMD (reset, etc.) */
156 0, /* 1: No interrupts yet. */
157 0x18 + ZSHARD_PRI, /* IVECT */
158 ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
159 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
160 ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
161 0, /* 6: TXSYNC/SYNCLO */
162 0, /* 7: RXSYNC/SYNCHI */
163 0, /* 8: alias for data port */
164 ZSWR9_MASTER_IE,
165 0, /*10: Misc. TX/RX control bits */
166 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
167 14, /*12: BAUDLO (default=9600) */
168 0, /*13: BAUDHI (default=9600) */
169 ZSWR14_BAUD_ENA,
170 ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
171 };
172
173 static struct zschan *
174 zs_get_chan_addr(zsc_unit, channel)
175 int zsc_unit, channel;
176 {
177 char *addr;
178 struct zschan *zc;
179
180 if (zsc_unit >= NZSC)
181 return NULL;
182 addr = zsaddr[zsc_unit];
183 if (addr == NULL)
184 return NULL;
185 if (channel == 0) {
186 zc = (struct zschan *)(addr +2);
187 /* handle the fact the ports are intertwined. */
188 } else {
189 zc = (struct zschan *)(addr);
190 }
191 return (zc);
192 }
193
194
195 /* Find PROM mappings (for console support). */
196 int zsinited = 0; /* 0 = not, 1 = inited, not attached, 2= attached */
197
198 void
199 zs_init()
200 {
201 if ((zsinited == 2)&&(zsaddr[0] != (char *) sccA))
202 panic("Moved zs0 address after attached!");
203 zsaddr[0] = (char *) sccA;
204 zsinited = 1;
205 if (zs_conschan != 0){ /* we might have moved io under the console */
206 zs_conschan = zs_get_chan_addr(0, zs_consunit);
207 /* so recalc the console port */
208 }
209 }
210
211
212 /****************************************************************
213 * Autoconfig
214 ****************************************************************/
215
216 /* Definition of the driver for autoconfig. */
217 static int zsc_match __P((struct device *, struct cfdata *, void *));
218 static void zsc_attach __P((struct device *, struct device *, void *));
219 static int zsc_print __P((void *, const char *name));
220
221 struct cfattach zsc_ca = {
222 sizeof(struct zsc_softc), zsc_match, zsc_attach
223 };
224
225 struct cfdriver zsc_cd = {
226 NULL, "zsc", DV_DULL
227 };
228
229 int zshard __P((void *));
230 int zssoft __P((void *));
231
232
233 /*
234 * Is the zs chip present?
235 */
236 static int
237 zsc_match(parent, cf, aux)
238 struct device *parent;
239 struct cfdata *cf;
240 void *aux;
241 {
242 return 1;
243 }
244
245 /*
246 * Attach a found zs.
247 *
248 * Match slave number to zs unit number, so that misconfiguration will
249 * not set up the keyboard as ttya, etc.
250 */
251 static void
252 zsc_attach(parent, self, aux)
253 struct device *parent;
254 struct device *self;
255 void *aux;
256 {
257 struct zsc_softc *zsc = (void *) self;
258 struct zsc_attach_args zsc_args;
259 volatile struct zschan *zc;
260 struct xzs_chanstate *xcs;
261 struct zs_chanstate *cs;
262 int zsc_unit, channel;
263 int s, chip, theflags;
264
265 if (!zsinited)
266 zs_init();
267 zsinited = 2;
268
269 zsc_unit = zsc->zsc_dev.dv_unit;
270
271 /* Make sure everything's inited ok. */
272 if (zsaddr[zsc_unit] == NULL)
273 panic("zs_attach: zs%d not mapped\n", zsc_unit);
274
275 chip = 0; /* We'll deal with chip types post 1.2 */
276 printf(" chip type %d \n",chip);
277
278 /*
279 * Initialize software state for each channel.
280 */
281 for (channel = 0; channel < 2; channel++) {
282 zsc_args.channel = channel;
283 zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
284 xcs = &zsc->xzsc_xcs_store[channel];
285 cs = &xcs->xzs_cs;
286 zsc->zsc_cs[channel] = cs;
287
288 cs->cs_channel = channel;
289 cs->cs_private = NULL;
290 cs->cs_ops = &zsops_null;
291
292 zc = zs_get_chan_addr(zsc_unit, channel);
293 cs->cs_reg_csr = &zc->zc_csr;
294 cs->cs_reg_data = &zc->zc_data;
295
296 bcopy(zs_init_reg, cs->cs_creg, 16);
297 bcopy(zs_init_reg, cs->cs_preg, 16);
298
299 /* Current BAUD rate generator clock. */
300 cs->cs_brg_clk = ZS_STD_BRG; /* RTxC is 230400*16, so use 230400 */
301 cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
302 cs->cs_defcflag = zs_def_cflag;
303 #ifdef __notyet__
304 cs->cs_slave_type = ZS_SLAVE_NONE;
305 #endif
306
307 /* Define BAUD rate stuff. */
308 xcs->cs_clocks[0].clk = ZS_STD_BRG * 16;
309 xcs->cs_clocks[0].flags = ZSC_RTXBRG;
310 xcs->cs_clocks[1].flags =
311 ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
312 xcs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
313 xcs->cs_clock_count = 3;
314 if (channel == 0) {
315 theflags = mac68k_machine.modem_flags;
316 xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;
317 xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;
318 } else {
319 theflags = mac68k_machine.print_flags;
320 xcs->cs_clocks[1].flags = ZSC_VARIABLE;
321 /*
322 * Yes, we aren't defining ANY clock source enables for the
323 * printer's DCD clock in. The hardware won't let us
324 * use it. But a clock will freak out the chip, so we
325 * let you set it, telling us to bar interrupts on the line.
326 */
327 xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;
328 xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;
329 }
330 if (xcs->cs_clocks[1].clk)
331 zsc_args.hwflags |= ZS_HWFLAG_NO_DCD;
332 if (xcs->cs_clocks[2].clk)
333 zsc_args.hwflags |= ZS_HWFLAG_NO_CTS;
334
335 printf("zsc%d channel %d: d_speed %6d DCD clk %ld CTS clk %ld",
336 zsc_unit, channel, cs->cs_defspeed,
337 xcs->cs_clocks[1].clk, xcs->cs_clocks[2].clk);
338
339 /* Set defaults in our "extended" chanstate. */
340 xcs->cs_csource = 0;
341 xcs->cs_psource = 0;
342 xcs->cs_cclk_flag = 0; /* Nothing fancy by default */
343 xcs->cs_pclk_flag = 0;
344
345 if (theflags & ZSMAC_RAW) {
346 zsc_args.hwflags |= ZS_HWFLAG_RAW;
347 printf(" (raw defaults)");
348 }
349
350 /*
351 * XXX - This might be better done with a "stub" driver
352 * (to replace zstty) that ignores LocalTalk for now.
353 */
354 if (theflags & ZSMAC_LOCALTALK) {
355 printf(" shielding from LocalTalk");
356 cs->cs_defspeed = 1;
357 cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff;
358 cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff;
359 zs_write_reg(cs, ZSRR_BAUDLO, 0xff);
360 zs_write_reg(cs, ZSRR_BAUDHI, 0xff);
361 /*
362 * If we might have LocalTalk, then make sure we have the
363 * Baud rate low-enough to not do any damage.
364 */
365 }
366
367 /*
368 * We used to disable chip interrupts here, but we now
369 * do that in zscnprobe, just in case MacOS left the chip on.
370 */
371
372 xcs->cs_chip = chip;
373
374 /* Stash away a copy of the final H/W flags. */
375 xcs->cs_hwflags = zsc_args.hwflags;
376
377 printf("\n");
378
379 /*
380 * Look for a child driver for this channel.
381 * The child attach will setup the hardware.
382 */
383 if (!config_found(self, (void *)&zsc_args, zsc_print)) {
384 /* No sub-driver. Just reset it. */
385 u_char reset = (channel == 0) ?
386 ZSWR9_A_RESET : ZSWR9_B_RESET;
387 s = splzs();
388 zs_write_reg(cs, 9, reset);
389 splx(s);
390 }
391 }
392
393 /* XXX - Now safe to install interrupt handlers. */
394
395 /*
396 * Set the master interrupt enable and interrupt vector.
397 * (common to both channels, do it on A)
398 */
399 cs = zsc->zsc_cs[0];
400 s = splzs();
401 /* interrupt vector */
402 zs_write_reg(cs, 2, zs_init_reg[2]);
403 /* master interrupt control (enable) */
404 zs_write_reg(cs, 9, zs_init_reg[9]);
405 splx(s);
406 }
407
408 static int
409 zsc_print(aux, name)
410 void *aux;
411 const char *name;
412 {
413 struct zsc_attach_args *args = aux;
414
415 if (name != NULL)
416 printf("%s: ", name);
417
418 if (args->channel != -1)
419 printf(" channel %d", args->channel);
420
421 return UNCONF;
422 }
423
424 int
425 zsmdioctl(cs, cmd, data)
426 struct zs_chanstate *cs;
427 u_long cmd;
428 caddr_t data;
429 {
430 switch (cmd) {
431 default:
432 return (-1);
433 }
434 return (0);
435 }
436
437 void
438 zsmd_setclock(cs)
439 struct zs_chanstate *cs;
440 {
441 struct xzs_chanstate *xcs = (void *)cs;
442
443 if (cs->cs_channel != 0)
444 return;
445
446 /*
447 * If the new clock has the external bit set, then select the
448 * external source.
449 */
450 via_set_modem((xcs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0);
451 }
452
453 static int zssoftpending;
454
455 /*
456 * Our ZS chips all share a common, autovectored interrupt,
457 * so we have to look at all of them on each interrupt.
458 */
459 int
460 zshard(arg)
461 void *arg;
462 {
463 register struct zsc_softc *zsc;
464 register int unit, rval;
465
466 rval = 0;
467 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
468 zsc = zsc_cd.cd_devs[unit];
469 if (zsc == NULL)
470 continue;
471 rval |= zsc_intr_hard(zsc);
472 if ((zsc->zsc_cs[0]->cs_softreq) ||
473 (zsc->zsc_cs[1]->cs_softreq))
474 {
475 /* zsc_req_softint(zsc); */
476 /* We are at splzs here, so no need to lock. */
477 if (zssoftpending == 0) {
478 zssoftpending = 1;
479 setsoftserial();
480 }
481 }
482 }
483 return (rval);
484 }
485
486 /*
487 * Similar scheme as for zshard (look at all of them)
488 */
489 int
490 zssoft(arg)
491 void *arg;
492 {
493 register struct zsc_softc *zsc;
494 register int unit;
495
496 /* This is not the only ISR on this IPL. */
497 if (zssoftpending == 0)
498 return (0);
499
500 /*
501 * The soft intr. bit will be set by zshard only if
502 * the variable zssoftpending is zero.
503 */
504 zssoftpending = 0;
505
506 for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) {
507 zsc = zsc_cd.cd_devs[unit];
508 if (zsc == NULL)
509 continue;
510 (void) zsc_intr_soft(zsc);
511 }
512 return (1);
513 }
514
515
516 #ifndef ZS_TOLERANCE
517 #define ZS_TOLERANCE 51
518 /* 5% in tenths of a %, plus 1 so that exactly 5% will be ok. */
519 #endif
520
521 /*
522 * check out a rate for acceptability from the internal clock
523 * source. Used in console config to validate a requested
524 * default speed. Placed here so that all the speed checking code is
525 * in one place.
526 *
527 * != 0 means ok.
528 */
529 int
530 zs_cn_check_speed(bps)
531 int bps; /* target rate */
532 {
533 int tc, rate;
534
535 tc = BPS_TO_TCONST(ZS_STD_BRG, bps);
536 if (tc < 0)
537 return 0;
538 rate = TCONST_TO_BPS(ZS_STD_BRG, tc);
539 if (ZS_TOLERANCE > abs(((rate - bps)*1000)/bps))
540 return 1;
541 else
542 return 0;
543 }
544
545 /*
546 * Search through the signal sources in the channel, and
547 * pick the best one for the baud rate requested. Return
548 * a -1 if not achievable in tolerance. Otherwise return 0
549 * and fill in the values.
550 *
551 * This routine draws inspiration from the Atari port's zs.c
552 * driver in NetBSD 1.1 which did the same type of source switching.
553 * Tolerance code inspired by comspeed routine in isa/com.c.
554 *
555 * By Bill Studenmund, 1996-05-12
556 */
557 int
558 zs_set_speed(cs, bps)
559 struct zs_chanstate *cs;
560 int bps; /* bits per second */
561 {
562 struct xzs_chanstate *xcs = (void *) cs;
563 int i, tc, tc0 = 0, tc1, s, sf = 0;
564 int src, rate0, rate1, err, tol;
565
566 if (bps == 0)
567 return (0);
568
569 src = -1; /* no valid source yet */
570 tol = ZS_TOLERANCE;
571
572 /*
573 * Step through all the sources and see which one matches
574 * the best. A source has to match BETTER than tol to be chosen.
575 * Thus if two sources give the same error, the first one will be
576 * chosen. Also, allow for the possability that one source might run
577 * both the BRG and the direct divider (i.e. RTxC).
578 */
579 for (i=0; i < xcs->cs_clock_count; i++) {
580 if (xcs->cs_clocks[i].clk <= 0)
581 continue; /* skip non-existant or bad clocks */
582 if (xcs->cs_clocks[i].flags & ZSC_BRG) {
583 /* check out BRG at /16 */
584 tc1 = BPS_TO_TCONST(xcs->cs_clocks[i].clk >> 4, bps);
585 if (tc1 >= 0) {
586 rate1 = TCONST_TO_BPS(xcs->cs_clocks[i].clk >> 4, tc1);
587 err = abs(((rate1 - bps)*1000)/bps);
588 if (err < tol) {
589 tol = err;
590 src = i;
591 sf = xcs->cs_clocks[i].flags & ~ZSC_DIV;
592 tc0 = tc1;
593 rate0 = rate1;
594 }
595 }
596 }
597 if (xcs->cs_clocks[i].flags & ZSC_DIV) {
598 /*
599 * Check out either /1, /16, /32, or /64
600 * Note: for /1, you'd better be using a synchronized
601 * clock!
602 */
603 int b0 = xcs->cs_clocks[i].clk, e0 = abs(b0-bps);
604 int b1 = b0 >> 4, e1 = abs(b1-bps);
605 int b2 = b1 >> 1, e2 = abs(b2-bps);
606 int b3 = b2 >> 1, e3 = abs(b3-bps);
607
608 if (e0 < e1 && e0 < e2 && e0 < e3) {
609 err = e0;
610 rate1 = b0;
611 tc1 = ZSWR4_CLK_X1;
612 } else if (e0 > e1 && e1 < e2 && e1 < e3) {
613 err = e1;
614 rate1 = b1;
615 tc1 = ZSWR4_CLK_X16;
616 } else if (e0 > e2 && e1 > e2 && e2 < e3) {
617 err = e2;
618 rate1 = b2;
619 tc1 = ZSWR4_CLK_X32;
620 } else {
621 err = e3;
622 rate1 = b3;
623 tc1 = ZSWR4_CLK_X64;
624 }
625
626 err = (err * 1000)/bps;
627 if (err < tol) {
628 tol = err;
629 src = i;
630 sf = xcs->cs_clocks[i].flags & ~ZSC_BRG;
631 tc0 = tc1;
632 rate0 = rate1;
633 }
634 }
635 }
636 #ifdef ZSMACDEBUG
637 zsprintf("Checking for rate %d. Found source #%d.\n",bps, src);
638 #endif
639 if (src == -1)
640 return (EINVAL); /* no can do */
641
642 /*
643 * The M.I. layer likes to keep cs_brg_clk current, even though
644 * we are the only ones who should be touching the BRG's rate.
645 *
646 * Note: we are assuming that any ZSC_EXTERN signal source comes in
647 * on the RTxC pin. Correct for the mac68k obio zsc.
648 */
649 if (sf & ZSC_EXTERN)
650 cs->cs_brg_clk = xcs->cs_clocks[i].clk >> 4;
651 else
652 cs->cs_brg_clk = ZS_STD_BRG;
653
654 /*
655 * Now we have a source, so set it up.
656 */
657 s = splzs();
658 xcs->cs_psource = src;
659 xcs->cs_pclk_flag = sf;
660 bps = rate0;
661 if (sf & ZSC_BRG) {
662 cs->cs_preg[4] = ZSWR4_CLK_X16;
663 cs->cs_preg[11]= ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD;
664 if (sf & ZSC_PCLK) {
665 cs->cs_preg[14] = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK;
666 } else {
667 cs->cs_preg[14] = ZSWR14_BAUD_ENA;
668 }
669 tc = tc0;
670 } else {
671 cs->cs_preg[4] = tc0;
672 if (sf & ZSC_RTXDIV) {
673 cs->cs_preg[11] = ZSWR11_RXCLK_RTXC | ZSWR11_TXCLK_RTXC;
674 } else {
675 cs->cs_preg[11] = ZSWR11_RXCLK_TRXC | ZSWR11_TXCLK_TRXC;
676 }
677 cs->cs_preg[14]= 0;
678 tc = 0xffff;
679 }
680 /* Set the BAUD rate divisor. */
681 cs->cs_preg[12] = tc;
682 cs->cs_preg[13] = tc >> 8;
683 splx(s);
684
685 #ifdef ZSMACDEBUG
686 zsprintf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \
687 bps, tc, src, sf);
688 zsprintf("Registers are: 4 %x, 11 %x, 14 %x\n\n",
689 cs->cs_preg[4], cs->cs_preg[11], cs->cs_preg[14]);
690 #endif
691
692 cs->cs_preg[5] |= ZSWR5_RTS; /* Make sure the drivers are on! */
693
694 /* Caller will stuff the pending registers. */
695 return (0);
696 }
697
698 int
699 zs_set_modes(cs, cflag)
700 struct zs_chanstate *cs;
701 int cflag; /* bits per second */
702 {
703 struct xzs_chanstate *xcs = (void*)cs;
704 int s;
705
706 /*
707 * Make sure we don't enable hfc on a signal line we're ignoring.
708 * As we enable CTS interrupts only if we have CRTSCTS or CDTRCTS,
709 * this code also effectivly turns off ZSWR15_CTS_IE.
710 *
711 * Also, disable DCD interrupts if we've been told to ignore
712 * the DCD pin. Happens on mac68k because the input line for
713 * DCD can also be used as a clock input. (Just set CLOCAL.)
714 *
715 * If someone tries to turn an invalid flow mode on, Just Say No
716 * (Suggested by gwr)
717 */
718 if ((cflag & CDTRCTS) && (cflag & (CRTSCTS | MDMBUF)))
719 return (EINVAL);
720 if (xcs->cs_hwflags & ZS_HWFLAG_NO_DCD) {
721 if (cflag & MDMBUF)
722 return (EINVAL);
723 cflag |= CLOCAL;
724 cs->cs_rr0_dcd = 0; /* don't look at the dcd input! */
725 } else
726 cs->cs_rr0_dcd = ZSRR0_DCD; /* can look at pin */
727 if ((xcs->cs_hwflags & ZS_HWFLAG_NO_CTS) && (cflag & (CRTSCTS | CDTRCTS)))
728 return (EINVAL);
729
730 /*
731 * Output hardware flow control on the chip is horrendous:
732 * if carrier detect drops, the receiver is disabled, and if
733 * CTS drops, the transmitter is stoped IN MID CHARACTER!
734 * Therefore, NEVER set the HFC bit, and instead use the
735 * status interrupt to detect CTS changes.
736 */
737 s = splzs();
738 #if 0
739 if (cflag & CLOCAL) {
740 /* cs->cs_rr0_dcd = 0; */
741 cs->cs_preg[15] &= ~ZSWR15_DCD_IE;
742 } else {
743 /* cs->cs_rr0_dcd = ZSRR0_DCD; */
744 cs->cs_preg[15] |= ZSWR15_DCD_IE;
745 }
746 #endif
747 /*
748 * The mac hardware only has one output, DTR (HSKo in Mac
749 * parlance). In HFC mode, we use it for the functions
750 * typically served by RTS and DTR on other ports, so we
751 * have to fake the upper layer out some.
752 *
753 * CRTSCTS we use CTS as an input which tells us when to shut up.
754 * We make no effort to shut up the other side of the connection.
755 * DTR is used to hang up the modem.
756 *
757 * In CDTRCTS, we use CTS to tell us to stop, but we use DTR to
758 * shut up the other side.
759 */
760 if (cflag & CRTSCTS) {
761 cs->cs_wr5_dtr = ZSWR5_DTR;
762 cs->cs_wr5_rts = 0;
763 cs->cs_rr0_cts = ZSRR0_CTS;
764 cs->cs_preg[15] |= ZSWR15_CTS_IE;
765 } else if (cflag & CDTRCTS) {
766 cs->cs_wr5_dtr = 0;
767 cs->cs_wr5_rts = ZSWR5_DTR;
768 cs->cs_rr0_cts = ZSRR0_CTS;
769 cs->cs_preg[15] |= ZSWR15_CTS_IE;
770 } else {
771 cs->cs_wr5_dtr = ZSWR5_DTR;
772 cs->cs_wr5_rts = 0;
773 cs->cs_rr0_cts = 0;
774 cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
775 }
776 splx(s);
777
778 /* Caller will stuff the pending registers. */
779 return (0);
780 }
781
782
783 /*
784 * Read or write the chip with suitable delays.
785 * MacII hardware has the delay built in.
786 * No need for extra delay. :-) However, some clock-chirped
787 * macs, or zsc's on serial add-on boards might need it.
788 */
789 #define ZS_DELAY()
790
791 u_char
792 zs_read_reg(cs, reg)
793 struct zs_chanstate *cs;
794 u_char reg;
795 {
796 u_char val;
797
798 *cs->cs_reg_csr = reg;
799 ZS_DELAY();
800 val = *cs->cs_reg_csr;
801 ZS_DELAY();
802 return val;
803 }
804
805 void
806 zs_write_reg(cs, reg, val)
807 struct zs_chanstate *cs;
808 u_char reg, val;
809 {
810 *cs->cs_reg_csr = reg;
811 ZS_DELAY();
812 *cs->cs_reg_csr = val;
813 ZS_DELAY();
814 }
815
816 u_char zs_read_csr(cs)
817 struct zs_chanstate *cs;
818 {
819 register u_char val;
820
821 val = *cs->cs_reg_csr;
822 ZS_DELAY();
823 /* make up for the fact CTS is wired backwards */
824 val ^= ZSRR0_CTS;
825 return val;
826 }
827
828 void zs_write_csr(cs, val)
829 struct zs_chanstate *cs;
830 u_char val;
831 {
832 /* Note, the csr does not write CTS... */
833 *cs->cs_reg_csr = val;
834 ZS_DELAY();
835 }
836
837 u_char zs_read_data(cs)
838 struct zs_chanstate *cs;
839 {
840 register u_char val;
841
842 val = *cs->cs_reg_data;
843 ZS_DELAY();
844 return val;
845 }
846
847 void zs_write_data(cs, val)
848 struct zs_chanstate *cs;
849 u_char val;
850 {
851 *cs->cs_reg_data = val;
852 ZS_DELAY();
853 }
854
855 /****************************************************************
856 * Console support functions (mac68k specific!)
857 * Note: this code is allowed to know about the layout of
858 * the chip registers, and uses that to keep things simple.
859 * XXX - I think I like the mvme167 code better. -gwr
860 * XXX - Well :-P :-) -wrs
861 ****************************************************************/
862
863 #define zscnpollc nullcnpollc
864 cons_decl(zs);
865
866 static void zs_putc __P((register volatile struct zschan *, int));
867 static int zs_getc __P((register volatile struct zschan *));
868 static void zscnsetup __P((void));
869 extern int zsopen __P(( dev_t dev, int flags, int mode, struct proc *p));
870
871 /*
872 * Console functions.
873 */
874
875 /*
876 * This code modled after the zs_setparam routine in zskgdb
877 * It sets the console unit to a known state so we can output
878 * correctly.
879 */
880 static void
881 zscnsetup()
882 {
883 struct xzs_chanstate xcs;
884 struct zs_chanstate *cs;
885 struct zschan *zc;
886 int tconst, s;
887
888 /* Setup temporary chanstate. */
889 bzero((caddr_t)&xcs, sizeof(xcs));
890 cs = &xcs.xzs_cs;
891 zc = zs_conschan;
892 cs->cs_reg_csr = &zc->zc_csr;
893 cs->cs_reg_data = &zc->zc_data;
894 cs->cs_channel = zs_consunit;
895 cs->cs_brg_clk = ZS_STD_BRG;
896
897 bcopy(zs_init_reg, cs->cs_preg, 16);
898 cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
899 cs->cs_preg[15] = ZSWR15_BREAK_IE;
900 tconst = BPS_TO_TCONST(cs->cs_brg_clk,
901 zs_defspeed[0][zs_consunit]);
902 cs->cs_preg[12] = tconst;
903 cs->cs_preg[13] = tconst >> 8;
904 /* can't use zs_set_speed as we haven't set up the
905 * signal sources, and it's not worth it for now
906 */
907
908 cs->cs_preg[9] &= ~ZSWR9_MASTER_IE;
909 /* no interrupts until later, after attach. */
910 s = splhigh();
911 zs_loadchannelregs(cs);
912 splx(s);
913 }
914
915 /*
916 * zscnprobe is the routine which gets called as the kernel is trying to
917 * figure out where the console should be. Each io driver which might
918 * be the console (as defined in mac68k/conf.c) gets probed. The probe
919 * fills in the consdev structure. Important parts are the device #,
920 * and the console priority. Values are CN_DEAD (don't touch me),
921 * CN_NORMAL (I'm here, but elsewhere might be better), CN_INTERNAL
922 * (the video, better than CN_NORMAL), and CN_REMOTE (pick me!)
923 *
924 * As the mac's a bit different, we do extra work here. We mainly check
925 * to see if we have serial echo going on. Also chould check for default
926 * speeds.
927 */
928 void
929 zscnprobe(struct consdev * cp)
930 {
931 extern u_long IOBase;
932 int maj, unit, i;
933
934 for (maj = 0; maj < nchrdev; maj++) {
935 if (cdevsw[maj].d_open == zsopen) {
936 break;
937 }
938 }
939 if (maj != nchrdev) {
940 cp->cn_pri = CN_NORMAL; /* Lower than CN_INTERNAL */
941 if (mac68k_machine.serial_console != 0) {
942 cp->cn_pri = CN_REMOTE; /* Higher than CN_INTERNAL */
943 mac68k_machine.serial_boot_echo =0;
944 }
945
946 unit = (mac68k_machine.serial_console == 1) ? 0 : 1;
947 zs_consunit = unit;
948 zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
949
950 mac68k_zsdev = cp->cn_dev = makedev(maj, unit);
951 }
952 if (mac68k_machine.serial_boot_echo) {
953 /*
954 * at this point, we know that we don't have a serial
955 * console, but are doing echo
956 */
957 zs_conschan = (struct zschan *) -1; /* dummy flag for zs_init() */
958 zs_consunit = 1;
959 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
960 }
961
962 if ((i = mac68k_machine.modem_d_speed) > 0) {
963 if (zs_cn_check_speed(i))
964 zs_defspeed[0][0] = i;
965 }
966 if ((i = mac68k_machine.print_d_speed) > 0) {
967 if (zs_cn_check_speed(i))
968 zs_defspeed[0][1] = i;
969 }
970 mac68k_set_io_offsets(IOBase);
971 zs_init();
972 /*
973 * zsinit will set up the addresses of the scc. It will also, if
974 * zs_conschan != 0, calculate the new address of the conschan for
975 * unit zs_consunit. So if we are (or think we are) going to use the
976 * chip for console I/O, we just set up the internal addresses for it.
977 *
978 * Now turn off interrupts for the chip. Note: this code piece is the
979 * only vestage of the NetBSD 1.0 ser driver. :-)
980 */
981 sccA[2] = 9; sccA[2] = 0; /* write 0 to register 9, clearing MIE */
982
983 if (mac68k_machine.serial_boot_echo)
984 zscnsetup();
985 return;
986 }
987
988 void
989 zscninit(struct consdev * cp)
990 {
991
992 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE;
993 /*
994 * zsinit will set up the addresses of the scc. It will also, if
995 * zs_conschan != 0, calculate the new address of the conschan for
996 * unit zs_consunit. So zs_init implicitly sets zs_conschan to the right
997 * number. :-)
998 */
999 zscnsetup();
1000 printf("\nNetBSD/mac68k console\n");
1001 }
1002
1003
1004 /*
1005 * Polled input char.
1006 */
1007 static int
1008 zs_getc(zc)
1009 register volatile struct zschan *zc;
1010 {
1011 register int s, c, rr0;
1012
1013 s = splhigh();
1014 /* Wait for a character to arrive. */
1015 do {
1016 rr0 = zc->zc_csr;
1017 ZS_DELAY();
1018 } while ((rr0 & ZSRR0_RX_READY) == 0);
1019
1020 c = zc->zc_data;
1021 ZS_DELAY();
1022 splx(s);
1023
1024 /*
1025 * This is used by the kd driver to read scan codes,
1026 * so don't translate '\r' ==> '\n' here...
1027 */
1028 return (c);
1029 }
1030
1031 /*
1032 * Polled output char.
1033 */
1034 static void
1035 zs_putc(zc, c)
1036 register volatile struct zschan *zc;
1037 int c;
1038 {
1039 register int s, rr0;
1040 register long wait = 0;
1041
1042 s = splhigh();
1043 /* Wait for transmitter to become ready. */
1044 do {
1045 rr0 = zc->zc_csr;
1046 ZS_DELAY();
1047 } while (((rr0 & ZSRR0_TX_READY) == 0) && (wait++ < 1000000));
1048
1049 if ((rr0 & ZSRR0_TX_READY) != 0) {
1050 zc->zc_data = c;
1051 ZS_DELAY();
1052 }
1053 splx(s);
1054 }
1055
1056
1057 /*
1058 * Polled console input putchar.
1059 */
1060 int
1061 zscngetc(dev)
1062 dev_t dev;
1063 {
1064 register volatile struct zschan *zc = zs_conschan;
1065 register int c;
1066
1067 c = zs_getc(zc);
1068 return (c);
1069 }
1070
1071 /*
1072 * Polled console output putchar.
1073 */
1074 void
1075 zscnputc(dev, c)
1076 dev_t dev;
1077 int c;
1078 {
1079 register volatile struct zschan *zc = zs_conschan;
1080
1081 zs_putc(zc, c);
1082 }
1083
1084
1085
1086 /*
1087 * Handle user request to enter kernel debugger.
1088 */
1089 void
1090 zs_abort(cs)
1091 struct zs_chanstate *cs;
1092 {
1093 volatile struct zschan *zc = zs_conschan;
1094 int rr0;
1095 register long wait = 0;
1096
1097 if (zs_cons_canabort == 0)
1098 return;
1099
1100 /* Wait for end of break to avoid PROM abort. */
1101 do {
1102 rr0 = zc->zc_csr;
1103 ZS_DELAY();
1104 } while ((rr0 & ZSRR0_BREAK) && (wait++ < ZSABORT_DELAY));
1105
1106 if (wait > ZSABORT_DELAY) {
1107 zs_cons_canabort = 0;
1108 /* If we time out, turn off the abort ability! */
1109 }
1110
1111 Debugger();
1112 }
1113
1114