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