zs_hb.c revision 1.11 1 1.11 tsutsui /* $NetBSD: zs_hb.c,v 1.11 2003/04/26 18:43:20 tsutsui Exp $ */
2 1.1 tsubai
3 1.1 tsubai /*-
4 1.1 tsubai * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 1.1 tsubai * All rights reserved.
6 1.1 tsubai *
7 1.1 tsubai * This code is derived from software contributed to The NetBSD Foundation
8 1.1 tsubai * by Gordon W. Ross.
9 1.1 tsubai *
10 1.1 tsubai * Redistribution and use in source and binary forms, with or without
11 1.1 tsubai * modification, are permitted provided that the following conditions
12 1.1 tsubai * are met:
13 1.1 tsubai * 1. Redistributions of source code must retain the above copyright
14 1.1 tsubai * notice, this list of conditions and the following disclaimer.
15 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 tsubai * notice, this list of conditions and the following disclaimer in the
17 1.1 tsubai * documentation and/or other materials provided with the distribution.
18 1.1 tsubai * 3. All advertising materials mentioning features or use of this software
19 1.1 tsubai * must display the following acknowledgement:
20 1.1 tsubai * This product includes software developed by the NetBSD
21 1.1 tsubai * Foundation, Inc. and its contributors.
22 1.1 tsubai * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 tsubai * contributors may be used to endorse or promote products derived
24 1.1 tsubai * from this software without specific prior written permission.
25 1.1 tsubai *
26 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 tsubai * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 tsubai * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 tsubai * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 tsubai * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 tsubai * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 tsubai * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 tsubai * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 tsubai * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 tsubai * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 tsubai * POSSIBILITY OF SUCH DAMAGE.
37 1.1 tsubai */
38 1.1 tsubai
39 1.1 tsubai /*
40 1.1 tsubai * Zilog Z8530 Dual UART driver (machine-dependent part)
41 1.1 tsubai *
42 1.1 tsubai * Runs two serial lines per chip using slave drivers.
43 1.1 tsubai * Plain tty/async lines use the zs_async slave.
44 1.1 tsubai * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
45 1.1 tsubai */
46 1.1 tsubai
47 1.1 tsubai #include <sys/param.h>
48 1.1 tsubai #include <sys/systm.h>
49 1.1 tsubai #include <sys/device.h>
50 1.1 tsubai #include <sys/tty.h>
51 1.5 gehenna #include <sys/conf.h>
52 1.1 tsubai
53 1.1 tsubai #include <machine/adrsmap.h>
54 1.1 tsubai #include <machine/autoconf.h>
55 1.1 tsubai #include <machine/cpu.h>
56 1.1 tsubai #include <machine/z8530var.h>
57 1.1 tsubai
58 1.1 tsubai #include <dev/cons.h>
59 1.1 tsubai #include <dev/ic/z8530reg.h>
60 1.1 tsubai
61 1.1 tsubai #include "zsc.h" /* NZSC */
62 1.1 tsubai #define NZS NZSC
63 1.1 tsubai
64 1.1 tsubai /* Make life easier for the initialized arrays here. */
65 1.1 tsubai #if NZS < 2
66 1.1 tsubai #undef NZS
67 1.1 tsubai #define NZS 2
68 1.1 tsubai #endif
69 1.1 tsubai
70 1.3 tsubai #define ZSCFLAG_EX 0x01 /* expansion board */
71 1.3 tsubai
72 1.1 tsubai /*
73 1.1 tsubai * The news3400 provides a 4.9152 MHz clock to the ZS chips.
74 1.1 tsubai */
75 1.3 tsubai #define PCLK (9600 * 512) /* PCLK pin input clock rate */
76 1.3 tsubai #define PCLK_EX (9600 * 384)
77 1.1 tsubai
78 1.1 tsubai /*
79 1.1 tsubai * Define interrupt levels.
80 1.1 tsubai */
81 1.1 tsubai #define ZSHARD_PRI 64
82 1.1 tsubai
83 1.1 tsubai #define ZS_DELAY() {(void)*(volatile char *)INTEN1; delay(2);}
84 1.1 tsubai
85 1.1 tsubai /* The layout of this is hardware-dependent (padding, order). */
86 1.1 tsubai struct zschan {
87 1.1 tsubai volatile u_char zc_csr; /* ctrl,status, and indirect access */
88 1.1 tsubai volatile u_char zc_data; /* data */
89 1.1 tsubai };
90 1.1 tsubai struct zsdevice {
91 1.1 tsubai /* Yes, they are backwards. */
92 1.1 tsubai struct zschan zs_chan_b;
93 1.1 tsubai struct zschan zs_chan_a;
94 1.1 tsubai };
95 1.1 tsubai
96 1.1 tsubai extern int zs_def_cflag;
97 1.1 tsubai
98 1.1 tsubai static struct zsdevice *zsaddr[NZS];
99 1.1 tsubai
100 1.1 tsubai /* Flags from cninit() */
101 1.1 tsubai static int zs_hwflags[NZS][2];
102 1.1 tsubai
103 1.1 tsubai /* Default speed for all channels */
104 1.1 tsubai static int zs_defspeed = 9600;
105 1.1 tsubai
106 1.1 tsubai static u_char zs_init_reg[16] = {
107 1.1 tsubai 0, /* 0: CMD (reset, etc.) */
108 1.1 tsubai 0, /* 1: No interrupts yet. */
109 1.1 tsubai ZSHARD_PRI, /* IVECT */
110 1.1 tsubai ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
111 1.1 tsubai ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
112 1.1 tsubai ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
113 1.1 tsubai 0, /* 6: TXSYNC/SYNCLO */
114 1.1 tsubai 0, /* 7: RXSYNC/SYNCHI */
115 1.1 tsubai 0, /* 8: alias for data port */
116 1.1 tsubai ZSWR9_MASTER_IE,
117 1.1 tsubai 0, /*10: Misc. TX/RX control bits */
118 1.1 tsubai ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
119 1.3 tsubai ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */
120 1.1 tsubai 0, /*13: BAUDHI (default=9600) */
121 1.1 tsubai ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
122 1.1 tsubai ZSWR15_BREAK_IE,
123 1.1 tsubai };
124 1.1 tsubai
125 1.1 tsubai static struct zschan * zs_get_chan_addr __P((int, int));
126 1.1 tsubai static void zs_hb_delay __P((void));
127 1.2 tsubai static int zshard_hb __P((void *));
128 1.1 tsubai static int zs_getc __P((void *));
129 1.1 tsubai static void zs_putc __P((void *, int));
130 1.1 tsubai
131 1.2 tsubai struct zschan *
132 1.1 tsubai zs_get_chan_addr(zs_unit, channel)
133 1.1 tsubai int zs_unit, channel;
134 1.1 tsubai {
135 1.1 tsubai struct zsdevice *addr;
136 1.1 tsubai struct zschan *zc;
137 1.1 tsubai
138 1.1 tsubai if (zs_unit >= NZS)
139 1.1 tsubai return NULL;
140 1.1 tsubai addr = zsaddr[zs_unit];
141 1.1 tsubai if (addr == NULL)
142 1.1 tsubai return NULL;
143 1.1 tsubai if (channel == 0) {
144 1.1 tsubai zc = &addr->zs_chan_a;
145 1.1 tsubai } else {
146 1.1 tsubai zc = &addr->zs_chan_b;
147 1.1 tsubai }
148 1.1 tsubai return (zc);
149 1.1 tsubai }
150 1.1 tsubai
151 1.11 tsutsui static void
152 1.1 tsubai zs_hb_delay()
153 1.1 tsubai {
154 1.11 tsutsui
155 1.1 tsubai ZS_DELAY();
156 1.1 tsubai }
157 1.1 tsubai
158 1.1 tsubai /****************************************************************
159 1.1 tsubai * Autoconfig
160 1.1 tsubai ****************************************************************/
161 1.1 tsubai
162 1.1 tsubai /* Definition of the driver for autoconfig. */
163 1.1 tsubai int zs_hb_match __P((struct device *, struct cfdata *, void *));
164 1.1 tsubai void zs_hb_attach __P((struct device *, struct device *, void *));
165 1.1 tsubai
166 1.7 thorpej CFATTACH_DECL(zsc_hb, sizeof(struct zsc_softc),
167 1.7 thorpej zs_hb_match, zs_hb_attach, NULL, NULL);
168 1.1 tsubai
169 1.1 tsubai /*
170 1.1 tsubai * Is the zs chip present?
171 1.1 tsubai */
172 1.1 tsubai int
173 1.1 tsubai zs_hb_match(parent, cf, aux)
174 1.1 tsubai struct device *parent;
175 1.1 tsubai struct cfdata *cf;
176 1.1 tsubai void *aux;
177 1.1 tsubai {
178 1.1 tsubai struct confargs *ca = aux;
179 1.1 tsubai
180 1.1 tsubai if (strcmp(ca->ca_name, "zsc"))
181 1.1 tsubai return 0;
182 1.1 tsubai
183 1.1 tsubai /* This returns -1 on a fault (bus error). */
184 1.1 tsubai if (badaddr((char *)cf->cf_addr, 1))
185 1.1 tsubai return 0;
186 1.1 tsubai
187 1.1 tsubai return 1;
188 1.1 tsubai }
189 1.1 tsubai
190 1.1 tsubai /*
191 1.1 tsubai * Attach a found zs.
192 1.1 tsubai *
193 1.1 tsubai * Match slave number to zs unit number, so that misconfiguration will
194 1.1 tsubai * not set up the keyboard as ttya, etc.
195 1.1 tsubai */
196 1.1 tsubai void
197 1.1 tsubai zs_hb_attach(parent, self, aux)
198 1.1 tsubai struct device *parent;
199 1.1 tsubai struct device *self;
200 1.1 tsubai void *aux;
201 1.1 tsubai {
202 1.1 tsubai struct zsc_softc *zsc = (void *)self;
203 1.1 tsubai /* struct confargs *ca = aux; */
204 1.1 tsubai struct zsc_attach_args zsc_args;
205 1.1 tsubai volatile struct zschan *zc;
206 1.1 tsubai struct zs_chanstate *cs;
207 1.1 tsubai int s, zs_unit, channel, intlevel;
208 1.1 tsubai static int didintr;
209 1.1 tsubai
210 1.1 tsubai zs_unit = zsc->zsc_dev.dv_unit;
211 1.1 tsubai intlevel = zsc->zsc_dev.dv_cfdata->cf_level;
212 1.1 tsubai zsaddr[zs_unit] = (void *)zsc->zsc_dev.dv_cfdata->cf_addr;
213 1.1 tsubai
214 1.1 tsubai if (intlevel == -1) {
215 1.1 tsubai #if 0
216 1.1 tsubai printf(": interrupt level not configured\n");
217 1.1 tsubai return;
218 1.1 tsubai #else
219 1.1 tsubai printf(": interrupt level not configured; using");
220 1.1 tsubai intlevel = 1;
221 1.1 tsubai #endif
222 1.1 tsubai }
223 1.1 tsubai
224 1.1 tsubai printf(" level %d\n", intlevel);
225 1.1 tsubai
226 1.1 tsubai zs_delay = zs_hb_delay;
227 1.1 tsubai
228 1.1 tsubai /*
229 1.1 tsubai * Initialize software state for each channel.
230 1.1 tsubai */
231 1.1 tsubai for (channel = 0; channel < 2; channel++) {
232 1.1 tsubai zsc_args.channel = channel;
233 1.1 tsubai zsc_args.hwflags = zs_hwflags[zs_unit][channel];
234 1.1 tsubai cs = &zsc->zsc_cs_store[channel];
235 1.1 tsubai zsc->zsc_cs[channel] = cs;
236 1.1 tsubai
237 1.8 pk simple_lock_init(&cs->cs_lock);
238 1.1 tsubai cs->cs_channel = channel;
239 1.1 tsubai cs->cs_private = NULL;
240 1.1 tsubai cs->cs_ops = &zsops_null;
241 1.3 tsubai if ((zsc->zsc_dev.dv_cfdata->cf_flags & ZSCFLAG_EX) == 0)
242 1.3 tsubai cs->cs_brg_clk = PCLK / 16;
243 1.1 tsubai else
244 1.3 tsubai cs->cs_brg_clk = PCLK_EX / 16;
245 1.1 tsubai
246 1.1 tsubai zc = zs_get_chan_addr(zs_unit, channel);
247 1.1 tsubai cs->cs_reg_csr = &zc->zc_csr;
248 1.1 tsubai cs->cs_reg_data = &zc->zc_data;
249 1.1 tsubai
250 1.1 tsubai bcopy(zs_init_reg, cs->cs_creg, 16);
251 1.1 tsubai bcopy(zs_init_reg, cs->cs_preg, 16);
252 1.1 tsubai
253 1.1 tsubai /* XXX: Get these from the EEPROM instead? */
254 1.1 tsubai /* XXX: See the mvme167 code. Better. */
255 1.1 tsubai if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
256 1.1 tsubai cs->cs_defspeed = zs_get_speed(cs);
257 1.1 tsubai else
258 1.1 tsubai cs->cs_defspeed = zs_defspeed;
259 1.1 tsubai cs->cs_defcflag = zs_def_cflag;
260 1.1 tsubai
261 1.1 tsubai /* Make these correspond to cs_defcflag (-crtscts) */
262 1.1 tsubai cs->cs_rr0_dcd = ZSRR0_DCD;
263 1.1 tsubai cs->cs_rr0_cts = 0;
264 1.1 tsubai cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
265 1.1 tsubai cs->cs_wr5_rts = 0;
266 1.1 tsubai
267 1.1 tsubai /*
268 1.1 tsubai * Clear the master interrupt enable.
269 1.1 tsubai * The INTENA is common to both channels,
270 1.1 tsubai * so just do it on the A channel.
271 1.1 tsubai */
272 1.1 tsubai if (channel == 0) {
273 1.1 tsubai zs_write_reg(cs, 9, 0);
274 1.1 tsubai }
275 1.1 tsubai
276 1.1 tsubai /*
277 1.1 tsubai * Look for a child driver for this channel.
278 1.1 tsubai * The child attach will setup the hardware.
279 1.1 tsubai */
280 1.1 tsubai if (!config_found(self, (void *)&zsc_args, zs_print)) {
281 1.1 tsubai /* No sub-driver. Just reset it. */
282 1.1 tsubai u_char reset = (channel == 0) ?
283 1.1 tsubai ZSWR9_A_RESET : ZSWR9_B_RESET;
284 1.1 tsubai s = splhigh();
285 1.1 tsubai zs_write_reg(cs, 9, reset);
286 1.1 tsubai splx(s);
287 1.1 tsubai }
288 1.1 tsubai }
289 1.1 tsubai
290 1.1 tsubai /*
291 1.1 tsubai * Now safe to install interrupt handlers. Note the arguments
292 1.1 tsubai * to the interrupt handlers aren't used. Note, we only do this
293 1.1 tsubai * once since both SCCs interrupt at the same level and vector.
294 1.1 tsubai */
295 1.1 tsubai if (!didintr) {
296 1.1 tsubai didintr = 1;
297 1.1 tsubai
298 1.2 tsubai hb_intr_establish(intlevel, IPL_SERIAL, zshard_hb, NULL);
299 1.1 tsubai }
300 1.1 tsubai /* XXX; evcnt_attach() ? */
301 1.1 tsubai
302 1.1 tsubai /*
303 1.1 tsubai * Set the master interrupt enable and interrupt vector.
304 1.1 tsubai * (common to both channels, do it on A)
305 1.1 tsubai */
306 1.1 tsubai cs = zsc->zsc_cs[0];
307 1.1 tsubai s = splhigh();
308 1.1 tsubai /* interrupt vector */
309 1.1 tsubai zs_write_reg(cs, 2, zs_init_reg[2]);
310 1.1 tsubai /* master interrupt control (enable) */
311 1.1 tsubai zs_write_reg(cs, 9, zs_init_reg[9]);
312 1.1 tsubai splx(s);
313 1.1 tsubai }
314 1.1 tsubai
315 1.1 tsubai /*
316 1.1 tsubai * Our ZS chips all share a common, autovectored interrupt,
317 1.1 tsubai * so we have to look at all of them on each interrupt.
318 1.1 tsubai */
319 1.1 tsubai static int
320 1.2 tsubai zshard_hb(arg)
321 1.1 tsubai void *arg;
322 1.1 tsubai {
323 1.1 tsubai (void) *(volatile u_char *)SCCVECT;
324 1.1 tsubai
325 1.2 tsubai return zshard(arg);
326 1.1 tsubai }
327 1.1 tsubai
328 1.1 tsubai /*
329 1.1 tsubai * Polled input char.
330 1.1 tsubai */
331 1.1 tsubai int
332 1.1 tsubai zs_getc(arg)
333 1.1 tsubai void *arg;
334 1.1 tsubai {
335 1.11 tsutsui volatile struct zschan *zc = arg;
336 1.11 tsutsui int s, c, rr0;
337 1.1 tsubai
338 1.1 tsubai s = splhigh();
339 1.1 tsubai /* Wait for a character to arrive. */
340 1.1 tsubai do {
341 1.1 tsubai rr0 = zc->zc_csr;
342 1.1 tsubai ZS_DELAY();
343 1.1 tsubai } while ((rr0 & ZSRR0_RX_READY) == 0);
344 1.1 tsubai
345 1.1 tsubai c = zc->zc_data;
346 1.1 tsubai ZS_DELAY();
347 1.1 tsubai splx(s);
348 1.1 tsubai
349 1.1 tsubai /*
350 1.1 tsubai * This is used by the kd driver to read scan codes,
351 1.1 tsubai * so don't translate '\r' ==> '\n' here...
352 1.1 tsubai */
353 1.1 tsubai return (c);
354 1.1 tsubai }
355 1.1 tsubai
356 1.1 tsubai /*
357 1.1 tsubai * Polled output char.
358 1.1 tsubai */
359 1.1 tsubai void
360 1.1 tsubai zs_putc(arg, c)
361 1.1 tsubai void *arg;
362 1.1 tsubai int c;
363 1.1 tsubai {
364 1.11 tsutsui volatile struct zschan *zc = arg;
365 1.11 tsutsui int s, rr0;
366 1.1 tsubai
367 1.1 tsubai s = splhigh();
368 1.1 tsubai /* Wait for transmitter to become ready. */
369 1.1 tsubai do {
370 1.1 tsubai rr0 = zc->zc_csr;
371 1.1 tsubai ZS_DELAY();
372 1.1 tsubai } while ((rr0 & ZSRR0_TX_READY) == 0);
373 1.1 tsubai
374 1.1 tsubai zc->zc_data = c;
375 1.1 tsubai ZS_DELAY();
376 1.1 tsubai splx(s);
377 1.1 tsubai }
378 1.1 tsubai
379 1.1 tsubai /*****************************************************************/
380 1.1 tsubai
381 1.1 tsubai static void zscnprobe __P((struct consdev *));
382 1.1 tsubai static void zscninit __P((struct consdev *));
383 1.1 tsubai static int zscngetc __P((dev_t));
384 1.1 tsubai static void zscnputc __P((dev_t, int));
385 1.1 tsubai
386 1.1 tsubai struct consdev consdev_zs = {
387 1.1 tsubai zscnprobe,
388 1.1 tsubai zscninit,
389 1.1 tsubai zscngetc,
390 1.1 tsubai zscnputc,
391 1.11 tsutsui nullcnpollc,
392 1.11 tsutsui NULL,
393 1.11 tsutsui NULL,
394 1.4 thorpej NULL,
395 1.11 tsutsui NODEV,
396 1.11 tsutsui CN_DEAD
397 1.1 tsubai };
398 1.1 tsubai
399 1.11 tsutsui static void
400 1.1 tsubai zscnprobe(cn)
401 1.1 tsubai struct consdev *cn;
402 1.1 tsubai {
403 1.1 tsubai }
404 1.1 tsubai
405 1.11 tsutsui static void
406 1.1 tsubai zscninit(cn)
407 1.1 tsubai struct consdev *cn;
408 1.1 tsubai {
409 1.5 gehenna extern const struct cdevsw zstty_cdevsw;
410 1.5 gehenna
411 1.5 gehenna cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), 0);
412 1.1 tsubai cn->cn_pri = CN_REMOTE;
413 1.1 tsubai zs_hwflags[0][0] = ZS_HWFLAG_CONSOLE;
414 1.1 tsubai }
415 1.1 tsubai
416 1.11 tsutsui static int
417 1.1 tsubai zscngetc(dev)
418 1.1 tsubai dev_t dev;
419 1.1 tsubai {
420 1.11 tsutsui
421 1.1 tsubai return zs_getc((void *)SCCPORT0A);
422 1.1 tsubai }
423 1.1 tsubai
424 1.11 tsutsui static void
425 1.1 tsubai zscnputc(dev, c)
426 1.1 tsubai dev_t dev;
427 1.1 tsubai int c;
428 1.1 tsubai {
429 1.11 tsutsui
430 1.1 tsubai zs_putc((void *)SCCPORT0A, c);
431 1.1 tsubai }
432