1 /* $NetBSD: zs.c,v 1.48 2008/12/07 08:24:26 tsutsui Exp $ */
4 * Copyright (c) 1996, 1998 Bill Studenmund
5 * Copyright (c) 1995 Gordon W. Ross
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Zilog Z8530 Dual UART driver (machine-dependent part)
32 * Runs two serial lines per chip using slave drivers.
33 * Plain tty/async lines use the zs_async slave.
34 * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
35 * Other ports use their own mice & keyboard slaves.
39 * With NetBSD 1.1, port-mac68k started using a port of the port-sparc
40 * (port-sun3?) zs.c driver (which was in turn based on code in the
41 * Berkeley 4.4 Lite release). Bill Studenmund did the port, with
42 * help from Allen Briggs and Gordon Ross <gwr@NetBSD.org>. Noud de
43 * Brouwer field-tested the driver at a local ISP.
45 * Bill Studenmund and Gordon Ross then ported the machine-independent
46 * z8530 driver to work with port-mac68k. NetBSD 1.2 contained an
47 * intermediate version (mac68k using a local, patched version of
48 * the m.i. drivers), with NetBSD 1.3 containing a full version.
51 #include <sys/cdefs.h>
52 __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.48 2008/12/07 08:24:26 tsutsui Exp $");
57 #include <sys/param.h>
58 #include <sys/systm.h>
60 #include <sys/device.h>
63 #include <sys/ioctl.h>
66 #include <sys/kernel.h>
67 #include <sys/syslog.h>
75 #include <dev/ofw/openfirm.h>
76 #include <dev/ic/z8530reg.h>
78 #include <machine/z8530var.h>
79 #include <machine/autoconf.h>
80 #include <machine/pio.h>
82 /* Are these in a header file anywhere? */
83 /* Booter flags interface */
84 #define ZSMAC_RAW 0x01
85 #define ZSMAC_LOCALTALK 0x02
88 * Some warts needed by z8530tty.c -
90 int zs_def_cflag
= (CREAD
| CS8
| HUPCL
);
93 * abort detection on console will now timeout after iterating on a loop
94 * the following # of times. Cheep hack. Also, abort detection is turned
95 * off after a timeout (i.e. maybe there's not a terminal hooked up).
97 #define ZSABORT_DELAY 3000000
100 /* Yes, they are backwards. */
101 struct zschan zs_chan_b
;
102 struct zschan zs_chan_a
;
105 static int zs_defspeed
[2] = {
111 void *zs_conschan
= 0;
112 int zs_conschannel
= -1;
113 #ifdef ZS_CONSOLE_ABORT
114 int zs_cons_canabort
= 1;
116 int zs_cons_canabort
= 0;
117 #endif /* ZS_CONSOLE_ABORT*/
119 /* device to which the console is attached--if serial. */
122 static int zs_get_speed(struct zs_chanstate
*);
125 * Even though zsparam will set up the clock multiples, etc., we
126 * still set them here as: 1) mice & keyboards don't use zsparam,
127 * and 2) the console stuff uses these defaults before device
131 static uint8_t zs_init_reg
[16] = {
132 0, /* 0: CMD (reset, etc.) */
133 0, /* 1: No interrupts yet. */
135 ZSWR3_RX_8
| ZSWR3_RX_ENABLE
,
136 ZSWR4_CLK_X16
| ZSWR4_ONESB
| ZSWR4_EVENP
,
137 ZSWR5_TX_8
| ZSWR5_TX_ENABLE
,
138 0, /* 6: TXSYNC/SYNCLO */
139 0, /* 7: RXSYNC/SYNCHI */
140 0, /* 8: alias for data port */
142 0, /*10: Misc. TX/RX control bits */
143 ZSWR11_TXCLK_BAUD
| ZSWR11_RXCLK_BAUD
,
144 ((PCLK
/32)/38400)-2, /*12: BAUDLO (default=38400) */
145 0, /*13: BAUDHI (default=38400) */
150 /****************************************************************
152 ****************************************************************/
154 /* Definition of the driver for autoconfig. */
155 static int zsc_match(device_t
, cfdata_t
, void *);
156 static void zsc_attach(device_t
, device_t
, void *);
157 static int zsc_print(void *, const char *);
159 CFATTACH_DECL_NEW(zsc
, sizeof(struct zsc_softc
),
160 zsc_match
, zsc_attach
, NULL
, NULL
);
162 extern struct cfdriver zsc_cd
;
168 static int zs_txdma_int(void *);
171 void zscnprobe(struct consdev
*);
172 void zscninit(struct consdev
*);
174 void zscnputc(dev_t
, int);
175 void zscnpollc(dev_t
, int);
178 * Is the zs chip present?
181 zsc_match(device_t parent
, cfdata_t cf
, void *aux
)
183 struct confargs
*ca
= aux
;
185 if (strcmp(ca
->ca_name
, "escc") != 0)
197 * Match slave number to zs unit number, so that misconfiguration will
198 * not set up the keyboard as ttya, etc.
201 zsc_attach(device_t parent
, device_t self
, void *aux
)
203 struct zsc_softc
*zsc
= device_private(self
);
204 struct confargs
*ca
= aux
;
205 struct zsc_attach_args zsc_args
;
206 volatile struct zschan
*zc
;
207 struct xzs_chanstate
*xcs
;
208 struct zs_chanstate
*cs
;
209 struct zsdevice
*zsd
;
211 int s
, chip
, theflags
;
212 int node
, intr
[2][3];
220 ca
->ca_reg
[0] += ca
->ca_baseaddr
;
221 zsd
= mapiodev(ca
->ca_reg
[0], ca
->ca_reg
[1]);
223 node
= OF_child(ca
->ca_node
); /* ch-a */
225 for (channel
= 0; channel
< 2; channel
++) {
226 if (OF_getprop(node
, "AAPL,interrupts",
227 intr
[channel
], sizeof(intr
[0])) == -1 &&
228 OF_getprop(node
, "interrupts",
229 intr
[channel
], sizeof(intr
[0])) == -1) {
230 aprint_error(": cannot find interrupt property\n");
234 if (OF_getprop(node
, "reg", regs
, sizeof(regs
)) < 24) {
235 aprint_error(": cannot find reg property\n");
238 regs
[2] += ca
->ca_baseaddr
;
239 regs
[4] += ca
->ca_baseaddr
;
241 zsc
->zsc_txdmareg
[channel
] = mapiodev(regs
[2], regs
[3]);
242 zsc
->zsc_txdmacmd
[channel
] =
243 dbdma_alloc(sizeof(dbdma_command_t
) * 3);
244 memset(zsc
->zsc_txdmacmd
[channel
], 0,
245 sizeof(dbdma_command_t
) * 3);
246 dbdma_reset(zsc
->zsc_txdmareg
[channel
]);
248 node
= OF_peer(node
); /* ch-b */
251 aprint_normal(" irq %d,%d\n", intr
[0][0], intr
[1][0]);
254 * Initialize software state for each channel.
256 for (channel
= 0; channel
< 2; channel
++) {
257 zsc_args
.channel
= channel
;
258 zsc_args
.hwflags
= (channel
== zs_conschannel
?
259 ZS_HWFLAG_CONSOLE
: 0);
260 xcs
= &zsc
->xzsc_xcs_store
[channel
];
262 zsc
->zsc_cs
[channel
] = cs
;
265 cs
->cs_channel
= channel
;
266 cs
->cs_private
= NULL
;
267 cs
->cs_ops
= &zsops_null
;
269 zc
= (channel
== 0) ? &zsd
->zs_chan_a
: &zsd
->zs_chan_b
;
271 cs
->cs_reg_csr
= &zc
->zc_csr
;
272 cs
->cs_reg_data
= &zc
->zc_data
;
274 memcpy(cs
->cs_creg
, zs_init_reg
, 16);
275 memcpy(cs
->cs_preg
, zs_init_reg
, 16);
277 /* Current BAUD rate generator clock. */
278 cs
->cs_brg_clk
= PCLK
/ 16; /* RTxC is 230400*16, so use 230400 */
279 if (zsc_args
.hwflags
& ZS_HWFLAG_CONSOLE
)
280 cs
->cs_defspeed
= zs_get_speed(cs
);
282 cs
->cs_defspeed
= zs_defspeed
[channel
];
283 cs
->cs_defcflag
= zs_def_cflag
;
285 /* Make these correspond to cs_defcflag (-crtscts) */
286 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
288 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
292 cs
->cs_slave_type
= ZS_SLAVE_NONE
;
295 /* Define BAUD rate stuff. */
296 xcs
->cs_clocks
[0].clk
= PCLK
;
297 xcs
->cs_clocks
[0].flags
= ZSC_RTXBRG
| ZSC_RTXDIV
;
298 xcs
->cs_clocks
[1].flags
=
299 ZSC_RTXBRG
| ZSC_RTXDIV
| ZSC_VARIABLE
| ZSC_EXTERN
;
300 xcs
->cs_clocks
[2].flags
= ZSC_TRXDIV
| ZSC_VARIABLE
;
301 xcs
->cs_clock_count
= 3;
303 theflags
= 0; /*mac68k_machine.modem_flags;*/
304 /*xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;*/
305 /*xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;*/
306 xcs
->cs_clocks
[1].clk
= 0;
307 xcs
->cs_clocks
[2].clk
= 0;
309 theflags
= 0; /*mac68k_machine.print_flags;*/
310 xcs
->cs_clocks
[1].flags
= ZSC_VARIABLE
;
312 * Yes, we aren't defining ANY clock source enables for the
313 * printer's DCD clock in. The hardware won't let us
314 * use it. But a clock will freak out the chip, so we
315 * let you set it, telling us to bar interrupts on the line.
317 /*xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;*/
318 /*xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;*/
319 xcs
->cs_clocks
[1].clk
= 0;
320 xcs
->cs_clocks
[2].clk
= 0;
322 if (xcs
->cs_clocks
[1].clk
)
323 zsc_args
.hwflags
|= ZS_HWFLAG_NO_DCD
;
324 if (xcs
->cs_clocks
[2].clk
)
325 zsc_args
.hwflags
|= ZS_HWFLAG_NO_CTS
;
327 /* Set defaults in our "extended" chanstate. */
330 xcs
->cs_cclk_flag
= 0; /* Nothing fancy by default */
331 xcs
->cs_pclk_flag
= 0;
333 if (theflags
& ZSMAC_RAW
) {
334 zsc_args
.hwflags
|= ZS_HWFLAG_RAW
;
335 printf(" (raw defaults)");
339 * XXX - This might be better done with a "stub" driver
340 * (to replace zstty) that ignores LocalTalk for now.
342 if (theflags
& ZSMAC_LOCALTALK
) {
343 printf(" shielding from LocalTalk");
345 cs
->cs_creg
[ZSRR_BAUDLO
] = cs
->cs_preg
[ZSRR_BAUDLO
] = 0xff;
346 cs
->cs_creg
[ZSRR_BAUDHI
] = cs
->cs_preg
[ZSRR_BAUDHI
] = 0xff;
347 zs_write_reg(cs
, ZSRR_BAUDLO
, 0xff);
348 zs_write_reg(cs
, ZSRR_BAUDHI
, 0xff);
350 * If we might have LocalTalk, then make sure we have the
351 * Baud rate low-enough to not do any damage.
356 * We used to disable chip interrupts here, but we now
357 * do that in zscnprobe, just in case MacOS left the chip on.
362 /* Stash away a copy of the final H/W flags. */
363 xcs
->cs_hwflags
= zsc_args
.hwflags
;
366 * Look for a child driver for this channel.
367 * The child attach will setup the hardware.
369 if (!config_found(self
, (void *)&zsc_args
, zsc_print
)) {
370 /* No sub-driver. Just reset it. */
371 uint8_t reset
= (channel
== 0) ?
372 ZSWR9_A_RESET
: ZSWR9_B_RESET
;
374 zs_write_reg(cs
, 9, reset
);
379 /* XXX - Now safe to install interrupt handlers. */
380 intr_establish(intr
[0][0], IST_EDGE
, IPL_TTY
, zshard
, zsc
);
381 intr_establish(intr
[1][0], IST_EDGE
, IPL_TTY
, zshard
, zsc
);
383 intr_establish(intr
[0][1], IST_EDGE
, IPL_TTY
, zs_txdma_int
, (void *)0);
384 intr_establish(intr
[1][1], IST_EDGE
, IPL_TTY
, zs_txdma_int
, (void *)1);
387 zsc
->zsc_si
= softint_establish(SOFTINT_SERIAL
,
388 (void (*)(void *)) zsc_intr_soft
, zsc
);
391 * Set the master interrupt enable and interrupt vector.
392 * (common to both channels, do it on A)
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]);
404 zsc_print(void *aux
, const char *name
)
406 struct zsc_attach_args
*args
= aux
;
409 aprint_normal("%s: ", name
);
411 if (args
->channel
!= -1)
412 aprint_normal(" channel %d", args
->channel
);
418 zsmdioctl(struct zs_chanstate
*cs
, u_long cmd
, void *data
)
422 return (EPASSTHROUGH
);
428 zsmd_setclock(struct zs_chanstate
*cs
)
431 struct xzs_chanstate
*xcs
= (void *)cs
;
433 if (cs
->cs_channel
!= 0)
437 * If the new clock has the external bit set, then select the
440 via_set_modem((xcs
->cs_pclk_flag
& ZSC_EXTERN
) ? 1 : 0);
447 struct zsc_softc
*zsc
;
451 rval
= zsc_intr_hard(zsc
);
452 if ((zsc
->zsc_cs
[0]->cs_softreq
) || (zsc
->zsc_cs
[1]->cs_softreq
))
453 softint_schedule(zsc
->zsc_si
);
460 zs_txdma_int(void *arg
)
463 struct zsc_softc
*zsc
;
464 struct zs_chanstate
*cs
;
466 zsc
= device_lookup_private(&zsc_cd
, ch
);
468 panic("zs_txdma_int");
470 cs
= zsc
->zsc_cs
[ch
];
474 softint_schedule(zsc
->zsc_si
);
480 zs_dma_setup(struct zs_chanstate
*cs
, void *pa
, int len
)
482 struct zsc_softc
*zsc
;
483 dbdma_command_t
*cmdp
;
484 int ch
= cs
->cs_channel
;
486 zsc
= device_lookup_private(&zsc_cd
, ch
);
487 cmdp
= zsc
->zsc_txdmacmd
[ch
];
489 DBDMA_BUILD(cmdp
, DBDMA_CMD_OUT_LAST
, 0, len
, kvtop(pa
),
490 DBDMA_INT_ALWAYS
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
492 DBDMA_BUILD(cmdp
, DBDMA_CMD_STOP
, 0, 0, 0,
493 DBDMA_INT_NEVER
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
495 __asm
volatile("eieio");
497 dbdma_start(zsc
->zsc_txdmareg
[ch
], zsc
->zsc_txdmacmd
[ch
]);
502 * Compute the current baud rate given a ZS channel.
503 * XXX Assume internal BRG.
506 zs_get_speed(struct zs_chanstate
*cs
)
510 tconst
= zs_read_reg(cs
, 12);
511 tconst
|= zs_read_reg(cs
, 13) << 8;
512 return TCONST_TO_BPS(cs
->cs_brg_clk
, tconst
);
516 #define ZS_TOLERANCE 51
517 /* 5% in tenths of a %, plus 1 so that exactly 5% will be ok. */
521 * Search through the signal sources in the channel, and
522 * pick the best one for the baud rate requested. Return
523 * a -1 if not achievable in tolerance. Otherwise return 0
524 * and fill in the values.
526 * This routine draws inspiration from the Atari port's zs.c
527 * driver in NetBSD 1.1 which did the same type of source switching.
528 * Tolerance code inspired by comspeed routine in isa/com.c.
530 * By Bill Studenmund, 1996-05-12
533 zs_set_speed(struct zs_chanstate
*cs
, int bps
)
535 struct xzs_chanstate
*xcs
= (void *) cs
;
536 int i
, tc
, tc0
= 0, tc1
, s
, sf
= 0;
537 int src
, rate0
, rate1
, err
, tol
;
542 src
= -1; /* no valid source yet */
546 * Step through all the sources and see which one matches
547 * the best. A source has to match BETTER than tol to be chosen.
548 * Thus if two sources give the same error, the first one will be
549 * chosen. Also, allow for the possability that one source might run
550 * both the BRG and the direct divider (i.e. RTxC).
552 for (i
= 0; i
< xcs
->cs_clock_count
; i
++) {
553 if (xcs
->cs_clocks
[i
].clk
<= 0)
554 continue; /* skip non-existent or bad clocks */
555 if (xcs
->cs_clocks
[i
].flags
& ZSC_BRG
) {
556 /* check out BRG at /16 */
557 tc1
= BPS_TO_TCONST(xcs
->cs_clocks
[i
].clk
>> 4, bps
);
559 rate1
= TCONST_TO_BPS(xcs
->cs_clocks
[i
].clk
>> 4, tc1
);
560 err
= abs(((rate1
- bps
)*1000)/bps
);
564 sf
= xcs
->cs_clocks
[i
].flags
& ~ZSC_DIV
;
570 if (xcs
->cs_clocks
[i
].flags
& ZSC_DIV
) {
572 * Check out either /1, /16, /32, or /64
573 * Note: for /1, you'd better be using a synchronized
576 int b0
= xcs
->cs_clocks
[i
].clk
, e0
= abs(b0
-bps
);
577 int b1
= b0
>> 4, e1
= abs(b1
-bps
);
578 int b2
= b1
>> 1, e2
= abs(b2
-bps
);
579 int b3
= b2
>> 1, e3
= abs(b3
-bps
);
581 if (e0
< e1
&& e0
< e2
&& e0
< e3
) {
585 } else if (e0
> e1
&& e1
< e2
&& e1
< e3
) {
589 } else if (e0
> e2
&& e1
> e2
&& e2
< e3
) {
599 err
= (err
* 1000)/bps
;
603 sf
= xcs
->cs_clocks
[i
].flags
& ~ZSC_BRG
;
610 zsprintf("Checking for rate %d. Found source #%d.\n",bps
, src
);
613 return (EINVAL
); /* no can do */
616 * The M.I. layer likes to keep cs_brg_clk current, even though
617 * we are the only ones who should be touching the BRG's rate.
619 * Note: we are assuming that any ZSC_EXTERN signal source comes in
620 * on the RTxC pin. Correct for the mac68k obio zsc.
623 cs
->cs_brg_clk
= xcs
->cs_clocks
[i
].clk
>> 4;
625 cs
->cs_brg_clk
= PCLK
/ 16;
628 * Now we have a source, so set it up.
631 xcs
->cs_psource
= src
;
632 xcs
->cs_pclk_flag
= sf
;
635 cs
->cs_preg
[4] = ZSWR4_CLK_X16
;
636 cs
->cs_preg
[11]= ZSWR11_RXCLK_BAUD
| ZSWR11_TXCLK_BAUD
;
638 cs
->cs_preg
[14] = ZSWR14_BAUD_ENA
| ZSWR14_BAUD_FROM_PCLK
;
640 cs
->cs_preg
[14] = ZSWR14_BAUD_ENA
;
644 cs
->cs_preg
[4] = tc0
;
645 if (sf
& ZSC_RTXDIV
) {
646 cs
->cs_preg
[11] = ZSWR11_RXCLK_RTXC
| ZSWR11_TXCLK_RTXC
;
648 cs
->cs_preg
[11] = ZSWR11_RXCLK_TRXC
| ZSWR11_TXCLK_TRXC
;
653 /* Set the BAUD rate divisor. */
654 cs
->cs_preg
[12] = tc
;
655 cs
->cs_preg
[13] = tc
>> 8;
659 zsprintf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \
661 zsprintf("Registers are: 4 %x, 11 %x, 14 %x\n\n",
662 cs
->cs_preg
[4], cs
->cs_preg
[11], cs
->cs_preg
[14]);
665 cs
->cs_preg
[5] |= ZSWR5_RTS
; /* Make sure the drivers are on! */
667 /* Caller will stuff the pending registers. */
672 zs_set_modes(struct zs_chanstate
*cs
, int cflag
)
674 struct xzs_chanstate
*xcs
= (void*)cs
;
678 * Make sure we don't enable hfc on a signal line we're ignoring.
679 * As we enable CTS interrupts only if we have CRTSCTS or CDTRCTS,
680 * this code also effectivly turns off ZSWR15_CTS_IE.
682 * Also, disable DCD interrupts if we've been told to ignore
683 * the DCD pin. Happens on mac68k because the input line for
684 * DCD can also be used as a clock input. (Just set CLOCAL.)
686 * If someone tries to turn an invalid flow mode on, Just Say No
689 if ((cflag
& CDTRCTS
) && (cflag
& (CRTSCTS
| MDMBUF
)))
691 if (xcs
->cs_hwflags
& ZS_HWFLAG_NO_DCD
) {
696 if ((xcs
->cs_hwflags
& ZS_HWFLAG_NO_CTS
) && (cflag
& (CRTSCTS
| CDTRCTS
)))
700 * Output hardware flow control on the chip is horrendous:
701 * if carrier detect drops, the receiver is disabled, and if
702 * CTS drops, the transmitter is stoped IN MID CHARACTER!
703 * Therefore, NEVER set the HFC bit, and instead use the
704 * status interrupt to detect CTS changes.
707 if ((cflag
& (CLOCAL
| MDMBUF
)) != 0)
710 cs
->cs_rr0_dcd
= ZSRR0_DCD
;
712 * The mac hardware only has one output, DTR (HSKo in Mac
713 * parlance). In HFC mode, we use it for the functions
714 * typically served by RTS and DTR on other ports, so we
715 * have to fake the upper layer out some.
717 * CRTSCTS we use CTS as an input which tells us when to shut up.
718 * We make no effort to shut up the other side of the connection.
719 * DTR is used to hang up the modem.
721 * In CDTRCTS, we use CTS to tell us to stop, but we use DTR to
722 * shut up the other side.
724 if ((cflag
& CRTSCTS
) != 0) {
725 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
727 cs
->cs_rr0_cts
= ZSRR0_CTS
;
728 } else if ((cflag
& CDTRCTS
) != 0) {
730 cs
->cs_wr5_rts
= ZSWR5_DTR
;
731 cs
->cs_rr0_cts
= ZSRR0_CTS
;
732 } else if ((cflag
& MDMBUF
) != 0) {
734 cs
->cs_wr5_rts
= ZSWR5_DTR
;
735 cs
->cs_rr0_cts
= ZSRR0_DCD
;
737 cs
->cs_wr5_dtr
= ZSWR5_DTR
;
743 /* Caller will stuff the pending registers. */
749 * Read or write the chip with suitable delays.
750 * MacII hardware has the delay built in.
751 * No need for extra delay. :-) However, some clock-chirped
752 * macs, or zsc's on serial add-on boards might need it.
757 zs_read_reg(struct zs_chanstate
*cs
, uint8_t reg
)
761 out8(cs
->cs_reg_csr
, reg
);
763 val
= in8(cs
->cs_reg_csr
);
769 zs_write_reg(struct zs_chanstate
*cs
, uint8_t reg
, uint8_t val
)
771 out8(cs
->cs_reg_csr
, reg
);
773 out8(cs
->cs_reg_csr
, val
);
778 zs_read_csr(struct zs_chanstate
*cs
)
782 val
= in8(cs
->cs_reg_csr
);
784 /* make up for the fact CTS is wired backwards */
790 zs_write_csr(struct zs_chanstate
*cs
, uint8_t val
)
792 /* Note, the csr does not write CTS... */
793 out8(cs
->cs_reg_csr
, val
);
798 zs_read_data(struct zs_chanstate
*cs
)
802 val
= in8(cs
->cs_reg_data
);
808 zs_write_data(struct zs_chanstate
*cs
, uint8_t val
)
810 out8(cs
->cs_reg_data
, val
);
814 /****************************************************************
815 * Console support functions (powermac specific!)
816 * Note: this code is allowed to know about the layout of
817 * the chip registers, and uses that to keep things simple.
818 * XXX - I think I like the mvme167 code better. -gwr
819 * XXX - Well :-P :-) -wrs
820 ****************************************************************/
822 #define zscnpollc nullcnpollc
825 static int stdin
, stdout
;
832 * zscnprobe is the routine which gets called as the kernel is trying to
833 * figure out where the console should be. Each io driver which might
834 * be the console (as defined in mac68k/conf.c) gets probed. The probe
835 * fills in the consdev structure. Important parts are the device #,
836 * and the console priority. Values are CN_DEAD (don't touch me),
837 * CN_NORMAL (I'm here, but elsewhere might be better), CN_INTERNAL
838 * (the video, better than CN_NORMAL), and CN_REMOTE (pick me!)
840 * As the mac's a bit different, we do extra work here. We mainly check
841 * to see if we have serial echo going on. Also chould check for default
851 volatile struct zschan
*zc
= v
;
855 /* Wait for a character to arrive. */
857 rr0
= in8(&zc
->zc_csr
);
859 } while ((rr0
& ZSRR0_RX_READY
) == 0);
861 c
= in8(&zc
->zc_data
);
866 * This is used by the kd driver to read scan codes,
867 * so don't translate '\r' ==> '\n' here...
873 * Polled output char.
876 zs_putc(void *v
, int c
)
878 volatile struct zschan
*zc
= v
;
883 /* Wait for transmitter to become ready. */
885 rr0
= in8(&zc
->zc_csr
);
887 } while (((rr0
& ZSRR0_TX_READY
) == 0) && (wait
++ < 1000000));
889 if ((rr0
& ZSRR0_TX_READY
) != 0) {
890 out8(&zc
->zc_data
, c
);
898 * Polled console input putchar.
903 volatile struct zschan
*zc
= zs_conschan
;
907 c
= zs_getc(__UNVOLATILE(zc
));
910 OF_read(stdin
, &ch
, 1);
917 * Polled console output putchar.
920 zscnputc(dev_t dev
, int c
)
922 volatile struct zschan
*zc
= zs_conschan
;
925 zs_putc(__UNVOLATILE(zc
), c
);
928 OF_write(stdout
, &ch
, 1);
933 * Handle user request to enter kernel debugger.
936 zs_abort(struct zs_chanstate
*cs
)
938 volatile struct zschan
*zc
= zs_conschan
;
942 if (zs_cons_canabort
== 0)
945 /* Wait for end of break to avoid PROM abort. */
947 rr0
= in8(&zc
->zc_csr
);
949 } while ((rr0
& ZSRR0_BREAK
) && (wait
++ < ZSABORT_DELAY
));
951 if (wait
> ZSABORT_DELAY
) {
952 zs_cons_canabort
= 0;
953 /* If we time out, turn off the abort ability! */
963 extern int ofccngetc(dev_t
);
964 extern void ofccnputc(dev_t
, int);
966 struct consdev consdev_zs
= {
975 zscnprobe(struct consdev
*cp
)
980 if ((chosen
= OF_finddevice("/chosen")) == -1)
983 if (OF_getprop(chosen
, "stdin", &stdin
, sizeof(stdin
)) == -1)
985 if (OF_getprop(chosen
, "stdout", &stdout
, sizeof(stdout
)) == -1)
988 if ((pkg
= OF_instance_to_package(stdin
)) == -1)
991 memset(name
, 0, sizeof(name
));
992 if (OF_getprop(pkg
, "device_type", name
, sizeof(name
)) == -1)
995 if (strcmp(name
, "serial") != 0)
998 memset(name
, 0, sizeof(name
));
999 if (OF_getprop(pkg
, "name", name
, sizeof(name
)) == -1)
1002 cp
->cn_pri
= CN_REMOTE
;
1006 zscninit(struct consdev
*cp
)
1008 int escc
, escc_ch
, obio
, zs_offset
;
1012 if ((escc_ch
= OF_instance_to_package(stdin
)) == -1)
1015 memset(name
, 0, sizeof(name
));
1016 if (OF_getprop(escc_ch
, "name", name
, sizeof(name
)) == -1)
1019 zs_conschannel
= strcmp(name
, "ch-b") == 0;
1021 if (OF_getprop(escc_ch
, "reg", reg
, sizeof(reg
)) < 4)
1025 escc
= OF_parent(escc_ch
);
1026 obio
= OF_parent(escc
);
1028 if (OF_getprop(obio
, "assigned-addresses", reg
, sizeof(reg
)) < 12)
1030 zs_conschan
= (void *)(reg
[2] + zs_offset
);