zs.c revision 1.33 1 1.33 thorpej /* $NetBSD: zs.c,v 1.33 2021/08/07 16:19:00 thorpej Exp $ */
2 1.1 tsutsui
3 1.1 tsutsui /*-
4 1.1 tsutsui * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 1.1 tsutsui * All rights reserved.
6 1.1 tsutsui *
7 1.1 tsutsui * This code is derived from software contributed to The NetBSD Foundation
8 1.1 tsutsui * by Gordon W. Ross.
9 1.1 tsutsui *
10 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
11 1.1 tsutsui * modification, are permitted provided that the following conditions
12 1.1 tsutsui * are met:
13 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
14 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
15 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
17 1.1 tsutsui * documentation and/or other materials provided with the distribution.
18 1.1 tsutsui *
19 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 tsutsui * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 tsutsui * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 tsutsui * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 tsutsui * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 tsutsui * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 tsutsui * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 tsutsui * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 tsutsui * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 tsutsui * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE.
30 1.1 tsutsui */
31 1.1 tsutsui
32 1.1 tsutsui /*
33 1.1 tsutsui * Zilog Z8530 Dual UART driver (machine-dependent part)
34 1.1 tsutsui *
35 1.1 tsutsui * Runs two serial lines per chip using slave drivers.
36 1.1 tsutsui * Plain tty/async lines use the zs_async slave.
37 1.1 tsutsui */
38 1.1 tsutsui
39 1.1 tsutsui /*
40 1.1 tsutsui * news68k/dev/zs.c - based on {newsmips,x68k,mvme68k}/dev/zs.c
41 1.1 tsutsui */
42 1.18 lukem
43 1.18 lukem #include <sys/cdefs.h>
44 1.33 thorpej __KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.33 2021/08/07 16:19:00 thorpej Exp $");
45 1.1 tsutsui
46 1.1 tsutsui #include "opt_ddb.h"
47 1.1 tsutsui
48 1.1 tsutsui #include <sys/param.h>
49 1.1 tsutsui #include <sys/systm.h>
50 1.1 tsutsui #include <sys/conf.h>
51 1.1 tsutsui #include <sys/device.h>
52 1.1 tsutsui #include <sys/tty.h>
53 1.28 ad #include <sys/cpu.h>
54 1.28 ad #include <sys/intr.h>
55 1.1 tsutsui
56 1.1 tsutsui #include <machine/z8530var.h>
57 1.1 tsutsui
58 1.1 tsutsui #include <dev/cons.h>
59 1.1 tsutsui #include <dev/ic/z8530reg.h>
60 1.1 tsutsui
61 1.1 tsutsui #include <news68k/dev/hbvar.h>
62 1.1 tsutsui
63 1.19 tsutsui #include "ioconf.h"
64 1.19 tsutsui
65 1.10 tsutsui int zs_getc(void *);
66 1.10 tsutsui void zs_putc(void *, int);
67 1.1 tsutsui
68 1.1 tsutsui /*
69 1.1 tsutsui * Some warts needed by z8530tty.c -
70 1.1 tsutsui * The default parity REALLY needs to be the same as the PROM uses,
71 1.1 tsutsui * or you can not see messages done with printf during boot-up...
72 1.1 tsutsui */
73 1.1 tsutsui int zs_def_cflag = (CREAD | CS8 | HUPCL);
74 1.1 tsutsui
75 1.1 tsutsui /*
76 1.3 tsutsui * The news68k machines use three different clocks for the ZS chips.
77 1.1 tsutsui */
78 1.3 tsutsui #define NPCLK 3
79 1.3 tsutsui #define PCLK0 (9600 * 416) /* news1700: 3.9936MHz */
80 1.3 tsutsui #define PCLK1 (9600 * 512) /* news1200: 4.9152MHz */
81 1.3 tsutsui #define PCLK2 (9600 * 384) /* external: 3.6864MHz */
82 1.3 tsutsui
83 1.3 tsutsui static const u_int pclk[NPCLK] = {
84 1.3 tsutsui PCLK0,
85 1.3 tsutsui PCLK1,
86 1.3 tsutsui PCLK2,
87 1.3 tsutsui };
88 1.1 tsutsui
89 1.1 tsutsui /*
90 1.1 tsutsui * Define interrupt levels.
91 1.1 tsutsui */
92 1.1 tsutsui #define ZSHARD_PRI 5
93 1.1 tsutsui #define ZS_IVECT 64
94 1.1 tsutsui
95 1.1 tsutsui #define ZS_DELAY() /* delay(2) */
96 1.1 tsutsui
97 1.1 tsutsui /* The layout of this is hardware-dependent (padding, order). */
98 1.1 tsutsui struct zschan {
99 1.29 tsutsui volatile uint8_t zc_csr; /* ctrl,status, and indirect access */
100 1.29 tsutsui volatile uint8_t zc_data; /* data */
101 1.1 tsutsui };
102 1.1 tsutsui struct zsdevice {
103 1.1 tsutsui /* Yes, they are backwards. */
104 1.1 tsutsui struct zschan zs_chan_b;
105 1.1 tsutsui struct zschan zs_chan_a;
106 1.1 tsutsui };
107 1.1 tsutsui
108 1.1 tsutsui /* Default speed for all channels */
109 1.1 tsutsui static int zs_defspeed = 9600;
110 1.1 tsutsui
111 1.5 tsutsui /* console status from cninit */
112 1.5 tsutsui static struct zs_chanstate zs_conschan_store;
113 1.5 tsutsui static struct zs_chanstate *zs_conschan;
114 1.5 tsutsui static struct zschan *zc_cons;
115 1.5 tsutsui
116 1.29 tsutsui static uint8_t zs_init_reg[16] = {
117 1.1 tsutsui 0, /* 0: CMD (reset, etc.) */
118 1.1 tsutsui 0, /* 1: No interrupts yet. */
119 1.1 tsutsui ZS_IVECT, /* IVECT */
120 1.1 tsutsui ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
121 1.1 tsutsui ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
122 1.1 tsutsui ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
123 1.1 tsutsui 0, /* 6: TXSYNC/SYNCLO */
124 1.1 tsutsui 0, /* 7: RXSYNC/SYNCHI */
125 1.1 tsutsui 0, /* 8: alias for data port */
126 1.1 tsutsui ZSWR9_MASTER_IE,
127 1.1 tsutsui 0, /*10: Misc. TX/RX control bits */
128 1.1 tsutsui ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
129 1.5 tsutsui BPS_TO_TCONST((PCLK0/16), 9600), /*12: BAUDLO (default=9600) */
130 1.1 tsutsui 0, /*13: BAUDHI (default=9600) */
131 1.1 tsutsui ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
132 1.1 tsutsui ZSWR15_BREAK_IE,
133 1.1 tsutsui };
134 1.1 tsutsui
135 1.1 tsutsui
136 1.1 tsutsui /****************************************************************
137 1.1 tsutsui * Autoconfig
138 1.1 tsutsui ****************************************************************/
139 1.1 tsutsui
140 1.1 tsutsui /* Definition of the driver for autoconfig. */
141 1.29 tsutsui static int zs_match(device_t, cfdata_t, void *);
142 1.29 tsutsui static void zs_attach(device_t, device_t, void *);
143 1.10 tsutsui static int zs_print(void *, const char *name);
144 1.1 tsutsui
145 1.29 tsutsui CFATTACH_DECL_NEW(zsc, sizeof(struct zsc_softc),
146 1.9 thorpej zs_match, zs_attach, NULL, NULL);
147 1.1 tsutsui
148 1.10 tsutsui static int zshard(void *);
149 1.5 tsutsui #if 0
150 1.10 tsutsui static int zs_get_speed(struct zs_chanstate *);
151 1.5 tsutsui #endif
152 1.1 tsutsui
153 1.1 tsutsui /*
154 1.1 tsutsui * Is the zs chip present?
155 1.1 tsutsui */
156 1.1 tsutsui static int
157 1.29 tsutsui zs_match(device_t parent, cfdata_t cf, void *aux)
158 1.1 tsutsui {
159 1.1 tsutsui struct hb_attach_args *ha = aux;
160 1.3 tsutsui u_int addr;
161 1.1 tsutsui
162 1.1 tsutsui if (strcmp(ha->ha_name, "zsc"))
163 1.1 tsutsui return 0;
164 1.1 tsutsui
165 1.1 tsutsui /* XXX no default address */
166 1.12 tsutsui if (ha->ha_address == (u_int)-1)
167 1.1 tsutsui return 0;
168 1.1 tsutsui
169 1.31 tsutsui addr = (ha->ha_address);
170 1.1 tsutsui /* This returns -1 on a fault (bus error). */
171 1.1 tsutsui if (badaddr((void *)addr, 1))
172 1.1 tsutsui return 0;
173 1.1 tsutsui
174 1.1 tsutsui return 1;
175 1.1 tsutsui }
176 1.1 tsutsui
177 1.1 tsutsui /*
178 1.1 tsutsui * Attach a found zs.
179 1.1 tsutsui */
180 1.1 tsutsui static void
181 1.29 tsutsui zs_attach(device_t parent, device_t self, void *aux)
182 1.1 tsutsui {
183 1.29 tsutsui struct zsc_softc *zsc = device_private(self);
184 1.23 thorpej struct cfdata *cf = device_cfdata(self);
185 1.1 tsutsui struct hb_attach_args *ha = aux;
186 1.1 tsutsui struct zsc_attach_args zsc_args;
187 1.5 tsutsui struct zsdevice *zs;
188 1.5 tsutsui struct zschan *zc;
189 1.1 tsutsui struct zs_chanstate *cs;
190 1.5 tsutsui int s, channel, clk;
191 1.1 tsutsui
192 1.29 tsutsui zsc->zsc_dev = self;
193 1.29 tsutsui
194 1.31 tsutsui zs = (void *)(ha->ha_address);
195 1.1 tsutsui
196 1.3 tsutsui clk = cf->cf_flags;
197 1.3 tsutsui if (clk < 0 || clk >= NPCLK)
198 1.3 tsutsui clk = 0;
199 1.3 tsutsui
200 1.29 tsutsui aprint_normal("\n");
201 1.1 tsutsui
202 1.1 tsutsui /*
203 1.1 tsutsui * Initialize software state for each channel.
204 1.1 tsutsui */
205 1.1 tsutsui for (channel = 0; channel < 2; channel++) {
206 1.1 tsutsui zsc_args.channel = channel;
207 1.1 tsutsui cs = &zsc->zsc_cs_store[channel];
208 1.13 pk
209 1.1 tsutsui zsc->zsc_cs[channel] = cs;
210 1.5 tsutsui zc = (channel == 0) ? &zs->zs_chan_a : &zs->zs_chan_b;
211 1.1 tsutsui
212 1.1 tsutsui if (ha->ha_vect != -1)
213 1.1 tsutsui zs_init_reg[2] = ha->ha_vect;
214 1.1 tsutsui
215 1.5 tsutsui if (zc == zc_cons) {
216 1.6 tsutsui memcpy(cs, zs_conschan, sizeof(struct zs_chanstate));
217 1.5 tsutsui zs_conschan = cs;
218 1.5 tsutsui zsc_args.hwflags = ZS_HWFLAG_CONSOLE;
219 1.5 tsutsui } else {
220 1.5 tsutsui cs->cs_reg_csr = &zc->zc_csr;
221 1.5 tsutsui cs->cs_reg_data = &zc->zc_data;
222 1.6 tsutsui memcpy(cs->cs_creg, zs_init_reg, 16);
223 1.6 tsutsui memcpy(cs->cs_preg, zs_init_reg, 16);
224 1.1 tsutsui cs->cs_defspeed = zs_defspeed;
225 1.5 tsutsui zsc_args.hwflags = 0;
226 1.5 tsutsui }
227 1.5 tsutsui
228 1.27 ad zs_lock_init(cs);
229 1.1 tsutsui cs->cs_defcflag = zs_def_cflag;
230 1.1 tsutsui
231 1.5 tsutsui cs->cs_channel = channel;
232 1.5 tsutsui cs->cs_private = NULL;
233 1.5 tsutsui cs->cs_ops = &zsops_null;
234 1.5 tsutsui cs->cs_brg_clk = pclk[clk] / 16;
235 1.5 tsutsui
236 1.1 tsutsui /* Make these correspond to cs_defcflag (-crtscts) */
237 1.1 tsutsui cs->cs_rr0_dcd = ZSRR0_DCD;
238 1.1 tsutsui cs->cs_rr0_cts = 0;
239 1.1 tsutsui cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
240 1.1 tsutsui cs->cs_wr5_rts = 0;
241 1.1 tsutsui
242 1.1 tsutsui /*
243 1.1 tsutsui * Clear the master interrupt enable.
244 1.1 tsutsui * The INTENA is common to both channels,
245 1.1 tsutsui * so just do it on the A channel.
246 1.1 tsutsui */
247 1.1 tsutsui if (channel == 0) {
248 1.1 tsutsui s = splhigh();
249 1.1 tsutsui zs_write_reg(cs, 9, 0);
250 1.1 tsutsui splx(s);
251 1.1 tsutsui }
252 1.1 tsutsui
253 1.1 tsutsui /*
254 1.1 tsutsui * Look for a child driver for this channel.
255 1.1 tsutsui * The child attach will setup the hardware.
256 1.1 tsutsui */
257 1.32 thorpej if (!config_found(self, (void *)&zsc_args, zs_print,
258 1.33 thorpej CFARGS_NONE)) {
259 1.1 tsutsui /* No sub-driver. Just reset it. */
260 1.29 tsutsui uint8_t reset = (channel == 0) ?
261 1.1 tsutsui ZSWR9_A_RESET : ZSWR9_B_RESET;
262 1.1 tsutsui s = splhigh();
263 1.1 tsutsui zs_write_reg(cs, 9, reset);
264 1.1 tsutsui splx(s);
265 1.1 tsutsui }
266 1.1 tsutsui }
267 1.1 tsutsui
268 1.1 tsutsui /*
269 1.1 tsutsui * Now safe to install interrupt handlers.
270 1.1 tsutsui */
271 1.1 tsutsui hb_intr_establish(zs_init_reg[2], zshard, ZSHARD_PRI, zsc);
272 1.28 ad zsc->zsc_softintr_cookie = softint_establish(SOFTINT_SERIAL,
273 1.24 tsutsui (void (*)(void *))zsc_intr_soft, zsc);
274 1.1 tsutsui
275 1.1 tsutsui /*
276 1.1 tsutsui * Set the master interrupt enable and interrupt vector.
277 1.1 tsutsui * (common to both channels, do it on A)
278 1.1 tsutsui */
279 1.1 tsutsui cs = zsc->zsc_cs[0];
280 1.1 tsutsui s = splhigh();
281 1.1 tsutsui /* interrupt vector */
282 1.1 tsutsui zs_write_reg(cs, 2, zs_init_reg[2]);
283 1.1 tsutsui /* master interrupt control (enable) */
284 1.1 tsutsui zs_write_reg(cs, 9, zs_init_reg[9]);
285 1.1 tsutsui splx(s);
286 1.1 tsutsui
287 1.1 tsutsui }
288 1.1 tsutsui
289 1.1 tsutsui static int
290 1.20 tsutsui zs_print(void *aux, const char *name)
291 1.1 tsutsui {
292 1.1 tsutsui struct zsc_attach_args *args = aux;
293 1.1 tsutsui
294 1.1 tsutsui if (name != NULL)
295 1.11 thorpej aprint_normal("%s: ", name);
296 1.1 tsutsui
297 1.1 tsutsui if (args->channel != -1)
298 1.11 thorpej aprint_normal(" channel %d", args->channel);
299 1.1 tsutsui
300 1.1 tsutsui return UNCONF;
301 1.1 tsutsui }
302 1.1 tsutsui
303 1.1 tsutsui /*
304 1.1 tsutsui * For news68k-port, we don't use autovectored interrupt.
305 1.1 tsutsui * We do not need to look at all of the zs chips.
306 1.1 tsutsui */
307 1.1 tsutsui static int
308 1.20 tsutsui zshard(void *arg)
309 1.1 tsutsui {
310 1.1 tsutsui struct zsc_softc *zsc = arg;
311 1.1 tsutsui int rval;
312 1.1 tsutsui
313 1.1 tsutsui rval = zsc_intr_hard(zsc);
314 1.1 tsutsui
315 1.1 tsutsui /* We are at splzs here, so no need to lock. */
316 1.1 tsutsui if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq) {
317 1.28 ad softint_schedule(zsc->zsc_softintr_cookie);
318 1.1 tsutsui }
319 1.1 tsutsui
320 1.16 tsutsui return rval;
321 1.1 tsutsui }
322 1.1 tsutsui
323 1.1 tsutsui /*
324 1.1 tsutsui * Compute the current baud rate given a ZS channel.
325 1.1 tsutsui */
326 1.5 tsutsui #if 0
327 1.1 tsutsui static int
328 1.20 tsutsui zs_get_speed(struct zs_chanstate *cs)
329 1.1 tsutsui {
330 1.1 tsutsui int tconst;
331 1.1 tsutsui
332 1.1 tsutsui tconst = zs_read_reg(cs, 12);
333 1.1 tsutsui tconst |= zs_read_reg(cs, 13) << 8;
334 1.16 tsutsui return TCONST_TO_BPS(cs->cs_brg_clk, tconst);
335 1.1 tsutsui }
336 1.5 tsutsui #endif
337 1.1 tsutsui
338 1.1 tsutsui /*
339 1.1 tsutsui * MD functions for setting the baud rate and control modes.
340 1.1 tsutsui */
341 1.1 tsutsui int
342 1.20 tsutsui zs_set_speed(struct zs_chanstate *cs, int bps)
343 1.1 tsutsui {
344 1.1 tsutsui int tconst, real_bps;
345 1.1 tsutsui
346 1.1 tsutsui if (bps == 0)
347 1.16 tsutsui return 0;
348 1.1 tsutsui
349 1.1 tsutsui #ifdef DIAGNOSTIC
350 1.1 tsutsui if (cs->cs_brg_clk == 0)
351 1.1 tsutsui panic("zs_set_speed");
352 1.1 tsutsui #endif
353 1.1 tsutsui
354 1.1 tsutsui tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
355 1.1 tsutsui if (tconst < 0)
356 1.16 tsutsui return EINVAL;
357 1.1 tsutsui
358 1.1 tsutsui /* Convert back to make sure we can do it. */
359 1.1 tsutsui real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
360 1.1 tsutsui
361 1.1 tsutsui /* XXX - Allow some tolerance here? */
362 1.1 tsutsui if (real_bps != bps)
363 1.16 tsutsui return EINVAL;
364 1.1 tsutsui
365 1.1 tsutsui cs->cs_preg[12] = tconst;
366 1.1 tsutsui cs->cs_preg[13] = tconst >> 8;
367 1.1 tsutsui
368 1.1 tsutsui /* Caller will stuff the pending registers. */
369 1.16 tsutsui return 0;
370 1.1 tsutsui }
371 1.1 tsutsui
372 1.1 tsutsui int
373 1.20 tsutsui zs_set_modes(struct zs_chanstate *cs, int cflag)
374 1.1 tsutsui {
375 1.1 tsutsui int s;
376 1.1 tsutsui
377 1.1 tsutsui /*
378 1.1 tsutsui * Output hardware flow control on the chip is horrendous:
379 1.1 tsutsui * if carrier detect drops, the receiver is disabled, and if
380 1.1 tsutsui * CTS drops, the transmitter is stoped IN MID CHARACTER!
381 1.1 tsutsui * Therefore, NEVER set the HFC bit, and instead use the
382 1.1 tsutsui * status interrupt to detect CTS changes.
383 1.1 tsutsui */
384 1.1 tsutsui s = splzs();
385 1.1 tsutsui cs->cs_rr0_pps = 0;
386 1.1 tsutsui if ((cflag & (CLOCAL | MDMBUF)) != 0) {
387 1.1 tsutsui cs->cs_rr0_dcd = 0;
388 1.1 tsutsui if ((cflag & MDMBUF) == 0)
389 1.1 tsutsui cs->cs_rr0_pps = ZSRR0_DCD;
390 1.1 tsutsui } else
391 1.1 tsutsui cs->cs_rr0_dcd = ZSRR0_DCD;
392 1.1 tsutsui if ((cflag & CRTSCTS) != 0) {
393 1.1 tsutsui cs->cs_wr5_dtr = ZSWR5_DTR;
394 1.1 tsutsui cs->cs_wr5_rts = ZSWR5_RTS;
395 1.1 tsutsui cs->cs_rr0_cts = ZSRR0_CTS;
396 1.1 tsutsui } else if ((cflag & MDMBUF) != 0) {
397 1.1 tsutsui cs->cs_wr5_dtr = 0;
398 1.1 tsutsui cs->cs_wr5_rts = ZSWR5_DTR;
399 1.1 tsutsui cs->cs_rr0_cts = ZSRR0_DCD;
400 1.1 tsutsui } else {
401 1.1 tsutsui cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
402 1.1 tsutsui cs->cs_wr5_rts = 0;
403 1.1 tsutsui cs->cs_rr0_cts = 0;
404 1.1 tsutsui }
405 1.1 tsutsui splx(s);
406 1.1 tsutsui
407 1.1 tsutsui /* Caller will stuff the pending registers. */
408 1.16 tsutsui return 0;
409 1.1 tsutsui }
410 1.1 tsutsui
411 1.1 tsutsui
412 1.1 tsutsui /*
413 1.1 tsutsui * Read or write the chip with suitable delays.
414 1.1 tsutsui */
415 1.1 tsutsui
416 1.29 tsutsui uint8_t
417 1.29 tsutsui zs_read_reg(struct zs_chanstate *cs, uint8_t reg)
418 1.1 tsutsui {
419 1.29 tsutsui uint8_t val;
420 1.1 tsutsui
421 1.1 tsutsui *cs->cs_reg_csr = reg;
422 1.1 tsutsui ZS_DELAY();
423 1.1 tsutsui val = *cs->cs_reg_csr;
424 1.1 tsutsui ZS_DELAY();
425 1.1 tsutsui return val;
426 1.1 tsutsui }
427 1.1 tsutsui
428 1.1 tsutsui void
429 1.29 tsutsui zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val)
430 1.1 tsutsui {
431 1.16 tsutsui
432 1.1 tsutsui *cs->cs_reg_csr = reg;
433 1.1 tsutsui ZS_DELAY();
434 1.1 tsutsui *cs->cs_reg_csr = val;
435 1.1 tsutsui ZS_DELAY();
436 1.1 tsutsui }
437 1.1 tsutsui
438 1.29 tsutsui uint8_t
439 1.20 tsutsui zs_read_csr(struct zs_chanstate *cs)
440 1.1 tsutsui {
441 1.29 tsutsui uint8_t val;
442 1.1 tsutsui
443 1.1 tsutsui val = *cs->cs_reg_csr;
444 1.1 tsutsui ZS_DELAY();
445 1.1 tsutsui return val;
446 1.1 tsutsui }
447 1.1 tsutsui
448 1.3 tsutsui void
449 1.29 tsutsui zs_write_csr(struct zs_chanstate *cs, uint8_t val)
450 1.1 tsutsui {
451 1.16 tsutsui
452 1.1 tsutsui *cs->cs_reg_csr = val;
453 1.1 tsutsui ZS_DELAY();
454 1.1 tsutsui }
455 1.1 tsutsui
456 1.29 tsutsui uint8_t
457 1.20 tsutsui zs_read_data(struct zs_chanstate *cs)
458 1.1 tsutsui {
459 1.29 tsutsui uint8_t val;
460 1.1 tsutsui
461 1.1 tsutsui val = *cs->cs_reg_data;
462 1.1 tsutsui ZS_DELAY();
463 1.1 tsutsui return val;
464 1.1 tsutsui }
465 1.1 tsutsui
466 1.3 tsutsui void
467 1.29 tsutsui zs_write_data(struct zs_chanstate *cs, uint8_t val)
468 1.1 tsutsui {
469 1.16 tsutsui
470 1.1 tsutsui *cs->cs_reg_data = val;
471 1.1 tsutsui ZS_DELAY();
472 1.1 tsutsui }
473 1.1 tsutsui
474 1.1 tsutsui void
475 1.20 tsutsui zs_abort(struct zs_chanstate *cs)
476 1.1 tsutsui {
477 1.16 tsutsui
478 1.1 tsutsui #ifdef DDB
479 1.1 tsutsui Debugger();
480 1.1 tsutsui #endif
481 1.1 tsutsui }
482 1.1 tsutsui
483 1.1 tsutsui /*
484 1.1 tsutsui * Polled input char.
485 1.1 tsutsui */
486 1.1 tsutsui int
487 1.20 tsutsui zs_getc(void *arg)
488 1.1 tsutsui {
489 1.5 tsutsui struct zs_chanstate *cs = arg;
490 1.1 tsutsui int s, c, rr0;
491 1.1 tsutsui
492 1.1 tsutsui s = splhigh();
493 1.1 tsutsui /* Wait for a character to arrive. */
494 1.1 tsutsui do {
495 1.5 tsutsui rr0 = *cs->cs_reg_csr;
496 1.1 tsutsui ZS_DELAY();
497 1.1 tsutsui } while ((rr0 & ZSRR0_RX_READY) == 0);
498 1.1 tsutsui
499 1.5 tsutsui c = *cs->cs_reg_data;
500 1.1 tsutsui ZS_DELAY();
501 1.1 tsutsui splx(s);
502 1.1 tsutsui
503 1.1 tsutsui return c;
504 1.1 tsutsui }
505 1.1 tsutsui
506 1.1 tsutsui /*
507 1.1 tsutsui * Polled output char.
508 1.1 tsutsui */
509 1.1 tsutsui void
510 1.20 tsutsui zs_putc(void *arg, int c)
511 1.1 tsutsui {
512 1.5 tsutsui struct zs_chanstate *cs = arg;
513 1.1 tsutsui int s, rr0;
514 1.1 tsutsui
515 1.1 tsutsui s = splhigh();
516 1.1 tsutsui /* Wait for transmitter to become ready. */
517 1.1 tsutsui do {
518 1.5 tsutsui rr0 = *cs->cs_reg_csr;
519 1.1 tsutsui ZS_DELAY();
520 1.1 tsutsui } while ((rr0 & ZSRR0_TX_READY) == 0);
521 1.1 tsutsui
522 1.5 tsutsui *cs->cs_reg_data = c;
523 1.1 tsutsui ZS_DELAY();
524 1.1 tsutsui splx(s);
525 1.1 tsutsui }
526 1.1 tsutsui
527 1.1 tsutsui /*****************************************************************/
528 1.1 tsutsui
529 1.10 tsutsui static void zscnprobe(struct consdev *);
530 1.10 tsutsui static void zscninit(struct consdev *);
531 1.10 tsutsui static int zscngetc(dev_t);
532 1.10 tsutsui static void zscnputc(dev_t, int);
533 1.1 tsutsui
534 1.1 tsutsui struct consdev consdev_zs = {
535 1.1 tsutsui zscnprobe,
536 1.1 tsutsui zscninit,
537 1.1 tsutsui zscngetc,
538 1.1 tsutsui zscnputc,
539 1.4 thorpej nullcnpollc,
540 1.4 thorpej NULL,
541 1.17 tsutsui NULL,
542 1.17 tsutsui NULL,
543 1.17 tsutsui NODEV,
544 1.17 tsutsui CN_DEAD
545 1.1 tsutsui };
546 1.1 tsutsui
547 1.3 tsutsui static void
548 1.20 tsutsui zscnprobe(struct consdev *cn)
549 1.1 tsutsui {
550 1.1 tsutsui }
551 1.1 tsutsui
552 1.3 tsutsui static void
553 1.20 tsutsui zscninit(struct consdev *cn)
554 1.1 tsutsui {
555 1.5 tsutsui struct zs_chanstate *cs;
556 1.5 tsutsui
557 1.17 tsutsui extern const struct cdevsw zstty_cdevsw;
558 1.17 tsutsui extern int tty00_is_console;
559 1.21 tsutsui extern uint32_t sccport0a;
560 1.17 tsutsui
561 1.17 tsutsui cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
562 1.17 tsutsui if (tty00_is_console)
563 1.17 tsutsui cn->cn_pri = CN_REMOTE;
564 1.17 tsutsui else
565 1.17 tsutsui cn->cn_pri = CN_NORMAL;
566 1.3 tsutsui
567 1.5 tsutsui zc_cons = (struct zschan *)sccport0a; /* XXX */
568 1.5 tsutsui
569 1.5 tsutsui zs_conschan = cs = &zs_conschan_store;
570 1.5 tsutsui
571 1.5 tsutsui /* Setup temporary chanstate. */
572 1.5 tsutsui cs->cs_reg_csr = &zc_cons->zc_csr;
573 1.5 tsutsui cs->cs_reg_data = &zc_cons->zc_data;
574 1.5 tsutsui
575 1.5 tsutsui /* Initialize the pending registers. */
576 1.6 tsutsui memcpy(cs->cs_preg, zs_init_reg, 16);
577 1.5 tsutsui cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
578 1.5 tsutsui
579 1.5 tsutsui cs->cs_preg[12] = BPS_TO_TCONST(pclk[systype] / 16, 9600); /* XXX */
580 1.5 tsutsui cs->cs_preg[13] = 0;
581 1.5 tsutsui cs->cs_defspeed = 9600;
582 1.5 tsutsui
583 1.5 tsutsui /* Clear the master interrupt enable. */
584 1.5 tsutsui zs_write_reg(cs, 9, 0);
585 1.5 tsutsui
586 1.5 tsutsui /* Reset the whole SCC chip. */
587 1.5 tsutsui zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
588 1.5 tsutsui
589 1.5 tsutsui /* Copy "pending" to "current" and H/W */
590 1.5 tsutsui zs_loadchannelregs(cs);
591 1.1 tsutsui }
592 1.1 tsutsui
593 1.3 tsutsui static int
594 1.20 tsutsui zscngetc(dev_t dev)
595 1.1 tsutsui {
596 1.16 tsutsui
597 1.5 tsutsui return zs_getc((void *)zs_conschan);
598 1.1 tsutsui }
599 1.1 tsutsui
600 1.3 tsutsui static void
601 1.20 tsutsui zscnputc(dev_t dev, int c)
602 1.1 tsutsui {
603 1.16 tsutsui
604 1.5 tsutsui zs_putc((void *)zs_conschan, c);
605 1.1 tsutsui }
606