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