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