zs.c revision 1.7 1 1.7 cgd /* $NetBSD: zs.c,v 1.7 1996/08/27 21:56:23 cgd Exp $ */
2 1.1 chuck
3 1.1 chuck /*
4 1.4 chuck * Copyright (c) 1995 Gordon W. Ross
5 1.1 chuck * All rights reserved.
6 1.1 chuck *
7 1.1 chuck * Redistribution and use in source and binary forms, with or without
8 1.1 chuck * modification, are permitted provided that the following conditions
9 1.1 chuck * are met:
10 1.1 chuck * 1. Redistributions of source code must retain the above copyright
11 1.1 chuck * notice, this list of conditions and the following disclaimer.
12 1.1 chuck * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 chuck * notice, this list of conditions and the following disclaimer in the
14 1.1 chuck * documentation and/or other materials provided with the distribution.
15 1.1 chuck * 3. The name of the author may not be used to endorse or promote products
16 1.4 chuck * derived from this software without specific prior written permission.
17 1.4 chuck * 4. All advertising materials mentioning features or use of this software
18 1.4 chuck * must display the following acknowledgement:
19 1.4 chuck * This product includes software developed by Gordon Ross
20 1.1 chuck *
21 1.1 chuck * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 1.1 chuck * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 1.1 chuck * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 1.1 chuck * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 1.1 chuck * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 1.1 chuck * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 1.1 chuck * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 1.1 chuck * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 1.1 chuck * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 1.1 chuck * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 1.1 chuck */
32 1.4 chuck
33 1.1 chuck /*
34 1.4 chuck * Zilog Z8530 Dual UART driver (machine-dependent part)
35 1.4 chuck *
36 1.4 chuck * Runs two serial lines per chip using slave drivers.
37 1.4 chuck * Plain tty/async lines use the zs_async slave.
38 1.4 chuck *
39 1.4 chuck * Modified for NetBSD/mvme68k by Jason R. Thorpe <thorpej (at) NetBSD.ORG>
40 1.1 chuck */
41 1.4 chuck
42 1.1 chuck #include <sys/param.h>
43 1.4 chuck #include <sys/systm.h>
44 1.4 chuck #include <sys/proc.h>
45 1.4 chuck #include <sys/device.h>
46 1.1 chuck #include <sys/conf.h>
47 1.4 chuck #include <sys/file.h>
48 1.1 chuck #include <sys/ioctl.h>
49 1.1 chuck #include <sys/tty.h>
50 1.4 chuck #include <sys/time.h>
51 1.1 chuck #include <sys/kernel.h>
52 1.1 chuck #include <sys/syslog.h>
53 1.4 chuck
54 1.1 chuck #include <dev/cons.h>
55 1.4 chuck #include <dev/ic/z8530reg.h>
56 1.4 chuck #include <machine/z8530var.h>
57 1.1 chuck
58 1.4 chuck #include <machine/cpu.h>
59 1.1 chuck
60 1.4 chuck #include <mvme68k/dev/zsvar.h>
61 1.1 chuck
62 1.4 chuck static u_long zs_sir; /* software interrupt cookie */
63 1.1 chuck
64 1.4 chuck /* Flags from zscnprobe() */
65 1.4 chuck static int zs_hwflags[NZS][2];
66 1.1 chuck
67 1.4 chuck /* Default speed for each channel */
68 1.4 chuck static int zs_defspeed[NZS][2] = {
69 1.4 chuck { 9600, /* port 1 */
70 1.4 chuck 9600 }, /* port 2 */
71 1.4 chuck { 9600, /* port 3 */
72 1.4 chuck 9600 }, /* port 4 */
73 1.4 chuck };
74 1.1 chuck
75 1.4 chuck static struct zs_chanstate zs_conschan_store;
76 1.4 chuck static struct zs_chanstate *zs_conschan;
77 1.1 chuck
78 1.4 chuck u_char zs_init_reg[16] = {
79 1.4 chuck 0, /* 0: CMD (reset, etc.) */
80 1.4 chuck ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE,
81 1.4 chuck 0x18 + ZSHARD_PRI, /* IVECT */
82 1.4 chuck ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
83 1.4 chuck ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
84 1.4 chuck ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
85 1.4 chuck 0, /* 6: TXSYNC/SYNCLO */
86 1.4 chuck 0, /* 7: RXSYNC/SYNCHI */
87 1.4 chuck 0, /* 8: alias for data port */
88 1.4 chuck ZSWR9_MASTER_IE,
89 1.4 chuck 0, /*10: Misc. TX/RX control bits */
90 1.4 chuck ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
91 1.4 chuck 14, /*12: BAUDLO (default=9600) */
92 1.4 chuck 0, /*13: BAUDHI (default=9600) */
93 1.4 chuck ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
94 1.4 chuck ZSWR15_BREAK_IE | ZSWR15_DCD_IE,
95 1.2 thorpej };
96 1.2 thorpej
97 1.1 chuck
98 1.4 chuck /****************************************************************
99 1.4 chuck * Autoconfig
100 1.4 chuck ****************************************************************/
101 1.1 chuck
102 1.4 chuck /* Definition of the driver for autoconfig. */
103 1.7 cgd static int zsc_print __P((void *, const char *name));
104 1.1 chuck
105 1.4 chuck struct cfdriver zsc_cd = {
106 1.4 chuck NULL, "zsc", DV_DULL
107 1.4 chuck };
108 1.1 chuck
109 1.1 chuck
110 1.4 chuck /*
111 1.4 chuck * Configure children of an SCC.
112 1.4 chuck */
113 1.4 chuck void
114 1.4 chuck zs_config(zsc, chan_addr)
115 1.4 chuck struct zsc_softc *zsc;
116 1.4 chuck struct zschan *(*chan_addr) __P((int, int));
117 1.4 chuck {
118 1.4 chuck struct zsc_attach_args zsc_args;
119 1.4 chuck volatile struct zschan *zc;
120 1.4 chuck struct zs_chanstate *cs;
121 1.4 chuck int zsc_unit, channel, s;
122 1.4 chuck u_char reset;
123 1.4 chuck
124 1.4 chuck zsc_unit = zsc->zsc_dev.dv_unit;
125 1.4 chuck printf(": Zilog 8530 SCC\n");
126 1.4 chuck
127 1.4 chuck /*
128 1.4 chuck * Initialize software state for each channel.
129 1.4 chuck */
130 1.4 chuck for (channel = 0; channel < 2; channel++) {
131 1.4 chuck cs = &zsc->zsc_cs[channel];
132 1.4 chuck
133 1.4 chuck /*
134 1.4 chuck * If we're the console, copy the channel state, and
135 1.4 chuck * adjust the console channel pointer.
136 1.4 chuck */
137 1.4 chuck if (zs_hwflags[zsc_unit][channel] & ZS_HWFLAG_CONSOLE) {
138 1.4 chuck bcopy(zs_conschan, cs, sizeof(struct zs_chanstate));
139 1.4 chuck zs_conschan = cs;
140 1.4 chuck } else {
141 1.4 chuck zc = (*chan_addr)(zsc_unit, channel);
142 1.4 chuck cs->cs_reg_csr = &zc->zc_csr;
143 1.4 chuck cs->cs_reg_data = &zc->zc_data;
144 1.1 chuck
145 1.4 chuck /* Define BAUD rate clock for the MI code. */
146 1.6 thorpej cs->cs_brg_clk = PCLK / 16;
147 1.1 chuck
148 1.4 chuck cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
149 1.1 chuck
150 1.4 chuck bcopy(zs_init_reg, cs->cs_creg, 16);
151 1.4 chuck bcopy(zs_init_reg, cs->cs_preg, 16);
152 1.4 chuck }
153 1.1 chuck
154 1.4 chuck cs->cs_channel = channel;
155 1.4 chuck cs->cs_private = NULL;
156 1.4 chuck cs->cs_ops = &zsops_null;
157 1.4 chuck
158 1.4 chuck /*
159 1.4 chuck * Clear the master interrupt enable.
160 1.4 chuck * The INTENA is common to both channels,
161 1.4 chuck * so just do it on the A channel.
162 1.4 chuck */
163 1.4 chuck if (channel == 0) {
164 1.4 chuck zs_write_reg(cs, 9, 0);
165 1.4 chuck }
166 1.1 chuck
167 1.4 chuck /*
168 1.4 chuck * Look for a child driver for this channel.
169 1.4 chuck * The child attach will setup the hardware.
170 1.4 chuck */
171 1.4 chuck zsc_args.channel = channel;
172 1.4 chuck zsc_args.hwflags = zs_hwflags[zsc_unit][channel];
173 1.4 chuck if (config_found(&zsc->zsc_dev, (void *)&zsc_args,
174 1.4 chuck zsc_print) == NULL) {
175 1.4 chuck /* No sub-driver. Just reset it. */
176 1.4 chuck reset = (channel == 0) ?
177 1.4 chuck ZSWR9_A_RESET : ZSWR9_B_RESET;
178 1.4 chuck s = splzs();
179 1.4 chuck zs_write_reg(cs, 9, reset);
180 1.4 chuck splx(s);
181 1.4 chuck }
182 1.4 chuck }
183 1.1 chuck
184 1.4 chuck /*
185 1.4 chuck * Allocate a software interrupt cookie. Note that the argument
186 1.4 chuck * "zsc" is never actually used in the software interrupt
187 1.4 chuck * handler.
188 1.4 chuck */
189 1.4 chuck if (zs_sir == 0)
190 1.4 chuck zs_sir = allocate_sir(zssoft, zsc);
191 1.1 chuck }
192 1.1 chuck
193 1.4 chuck static int
194 1.4 chuck zsc_print(aux, name)
195 1.4 chuck void *aux;
196 1.7 cgd const char *name;
197 1.1 chuck {
198 1.4 chuck struct zsc_attach_args *args = aux;
199 1.1 chuck
200 1.4 chuck if (name != NULL)
201 1.4 chuck printf("%s: ", name);
202 1.1 chuck
203 1.4 chuck if (args->channel != -1)
204 1.4 chuck printf(" channel %d", args->channel);
205 1.1 chuck
206 1.4 chuck return UNCONF;
207 1.1 chuck }
208 1.1 chuck
209 1.1 chuck int
210 1.4 chuck zshard(arg)
211 1.4 chuck void *arg;
212 1.4 chuck {
213 1.4 chuck struct zsc_softc *zsc;
214 1.4 chuck int unit, rval;
215 1.1 chuck
216 1.4 chuck rval = 0;
217 1.4 chuck for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) {
218 1.4 chuck zsc = zsc_cd.cd_devs[unit];
219 1.4 chuck if (zsc != NULL) {
220 1.4 chuck rval |= zsc_intr_hard(zsc);
221 1.4 chuck }
222 1.1 chuck }
223 1.4 chuck return (rval);
224 1.1 chuck }
225 1.1 chuck
226 1.4 chuck int zssoftpending;
227 1.1 chuck
228 1.1 chuck void
229 1.4 chuck zsc_req_softint(zsc)
230 1.4 chuck struct zsc_softc *zsc;
231 1.4 chuck {
232 1.4 chuck if (zssoftpending == 0) {
233 1.4 chuck /* We are at splzs here, so no need to lock. */
234 1.4 chuck zssoftpending = 1;
235 1.4 chuck setsoftint(zs_sir);
236 1.1 chuck }
237 1.1 chuck }
238 1.1 chuck
239 1.4 chuck int
240 1.4 chuck zssoft(arg)
241 1.4 chuck void *arg;
242 1.1 chuck {
243 1.4 chuck struct zsc_softc *zsc;
244 1.4 chuck int unit;
245 1.4 chuck
246 1.4 chuck /* This is not the only ISR on this IPL. */
247 1.4 chuck if (zssoftpending == 0)
248 1.4 chuck return (0);
249 1.4 chuck
250 1.4 chuck /*
251 1.4 chuck * The soft intr. bit will be set by zshard only if
252 1.4 chuck * the variable zssoftpending is zero.
253 1.4 chuck */
254 1.4 chuck zssoftpending = 0;
255 1.4 chuck
256 1.4 chuck for (unit = 0; unit < zsc_cd.cd_ndevs; ++unit) {
257 1.4 chuck zsc = zsc_cd.cd_devs[unit];
258 1.4 chuck if (zsc != NULL) {
259 1.4 chuck (void) zsc_intr_soft(zsc);
260 1.1 chuck }
261 1.1 chuck }
262 1.4 chuck return (1);
263 1.1 chuck }
264 1.1 chuck
265 1.1 chuck
266 1.4 chuck /*
267 1.4 chuck * Read or write the chip with suitable delays.
268 1.4 chuck */
269 1.1 chuck
270 1.4 chuck u_char
271 1.4 chuck zs_read_reg(cs, reg)
272 1.4 chuck struct zs_chanstate *cs;
273 1.4 chuck u_char reg;
274 1.4 chuck {
275 1.4 chuck u_char val;
276 1.4 chuck
277 1.4 chuck *cs->cs_reg_csr = reg;
278 1.4 chuck ZS_DELAY();
279 1.4 chuck val = *cs->cs_reg_csr;
280 1.4 chuck ZS_DELAY();
281 1.4 chuck return val;
282 1.1 chuck }
283 1.1 chuck
284 1.4 chuck void
285 1.4 chuck zs_write_reg(cs, reg, val)
286 1.4 chuck struct zs_chanstate *cs;
287 1.4 chuck u_char reg, val;
288 1.4 chuck {
289 1.4 chuck *cs->cs_reg_csr = reg;
290 1.4 chuck ZS_DELAY();
291 1.4 chuck *cs->cs_reg_csr = val;
292 1.4 chuck ZS_DELAY();
293 1.1 chuck }
294 1.1 chuck
295 1.4 chuck u_char zs_read_csr(cs)
296 1.4 chuck struct zs_chanstate *cs;
297 1.1 chuck {
298 1.4 chuck register u_char v;
299 1.1 chuck
300 1.4 chuck v = *cs->cs_reg_csr;
301 1.4 chuck ZS_DELAY();
302 1.4 chuck return v;
303 1.1 chuck }
304 1.1 chuck
305 1.4 chuck u_char zs_read_data(cs)
306 1.4 chuck struct zs_chanstate *cs;
307 1.1 chuck {
308 1.4 chuck register u_char v;
309 1.1 chuck
310 1.4 chuck v = *cs->cs_reg_data;
311 1.4 chuck ZS_DELAY();
312 1.4 chuck return v;
313 1.1 chuck }
314 1.1 chuck
315 1.4 chuck void zs_write_csr(cs, val)
316 1.4 chuck struct zs_chanstate *cs;
317 1.4 chuck u_char val;
318 1.1 chuck {
319 1.4 chuck *cs->cs_reg_csr = val;
320 1.4 chuck ZS_DELAY();
321 1.1 chuck }
322 1.1 chuck
323 1.4 chuck void zs_write_data(cs, val)
324 1.4 chuck struct zs_chanstate *cs;
325 1.4 chuck u_char val;
326 1.1 chuck {
327 1.4 chuck *cs->cs_reg_data = val;
328 1.4 chuck ZS_DELAY();
329 1.1 chuck }
330 1.1 chuck
331 1.4 chuck /****************************************************************
332 1.4 chuck * Console support functions (MVME specific!)
333 1.4 chuck ****************************************************************/
334 1.4 chuck
335 1.1 chuck /*
336 1.4 chuck * Polled input char.
337 1.1 chuck */
338 1.1 chuck int
339 1.4 chuck zs_getc(arg)
340 1.4 chuck void *arg;
341 1.1 chuck {
342 1.4 chuck register struct zs_chanstate *cs = arg;
343 1.4 chuck register int s, c, rr0, stat;
344 1.1 chuck
345 1.4 chuck s = splhigh();
346 1.4 chuck top:
347 1.4 chuck /* Wait for a character to arrive. */
348 1.4 chuck do {
349 1.5 chuck rr0 = *cs->cs_reg_csr;
350 1.4 chuck ZS_DELAY();
351 1.4 chuck } while ((rr0 & ZSRR0_RX_READY) == 0);
352 1.4 chuck
353 1.4 chuck /* Read error register. */
354 1.4 chuck stat = zs_read_reg(cs, 1) & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE);
355 1.4 chuck if (stat) {
356 1.4 chuck zs_write_csr(cs, ZSM_RESET_ERR);
357 1.4 chuck goto top;
358 1.4 chuck }
359 1.4 chuck
360 1.4 chuck /* Read character. */
361 1.4 chuck c = *cs->cs_reg_data;
362 1.4 chuck ZS_DELAY();
363 1.4 chuck splx(s);
364 1.1 chuck
365 1.4 chuck return (c);
366 1.1 chuck }
367 1.1 chuck
368 1.4 chuck /*
369 1.4 chuck * Polled output char.
370 1.4 chuck */
371 1.1 chuck void
372 1.4 chuck zs_putc(arg, c)
373 1.4 chuck void *arg;
374 1.4 chuck int c;
375 1.4 chuck {
376 1.4 chuck register struct zs_chanstate *cs = arg;
377 1.4 chuck register int s, rr0;
378 1.4 chuck
379 1.4 chuck s = splhigh();
380 1.4 chuck /* Wait for transmitter to become ready. */
381 1.4 chuck do {
382 1.4 chuck rr0 = *cs->cs_reg_csr;
383 1.4 chuck ZS_DELAY();
384 1.4 chuck } while ((rr0 & ZSRR0_TX_READY) == 0);
385 1.1 chuck
386 1.4 chuck *cs->cs_reg_data = c;
387 1.4 chuck ZS_DELAY();
388 1.4 chuck splx(s);
389 1.1 chuck }
390 1.1 chuck
391 1.1 chuck /*
392 1.4 chuck * Common parts of console init.
393 1.1 chuck */
394 1.4 chuck void
395 1.4 chuck zs_cnconfig(zsc_unit, channel, zcp)
396 1.4 chuck int zsc_unit, channel;
397 1.4 chuck struct zschan *zcp;
398 1.4 chuck {
399 1.4 chuck volatile struct zschan *zc = (volatile struct zschan *)zcp;
400 1.4 chuck struct zs_chanstate *cs;
401 1.4 chuck
402 1.4 chuck /*
403 1.4 chuck * Pointer to channel state. Later, the console channel
404 1.4 chuck * state is copied into the softc, and the console channel
405 1.4 chuck * pointer adjusted to point to the new copy.
406 1.4 chuck */
407 1.4 chuck zs_conschan = cs = &zs_conschan_store;
408 1.4 chuck
409 1.4 chuck zs_hwflags[zsc_unit][channel] = ZS_HWFLAG_CONSOLE;
410 1.4 chuck
411 1.4 chuck cs->cs_reg_csr = &zc->zc_csr;
412 1.4 chuck cs->cs_reg_data = &zc->zc_data;
413 1.4 chuck
414 1.4 chuck cs->cs_channel = channel;
415 1.4 chuck cs->cs_private = NULL;
416 1.4 chuck cs->cs_ops = &zsops_null;
417 1.4 chuck
418 1.4 chuck /* Define BAUD rate clock for the MI code. */
419 1.6 thorpej cs->cs_brg_clk = PCLK / 16;
420 1.4 chuck
421 1.4 chuck cs->cs_defspeed = zs_defspeed[zsc_unit][channel];
422 1.4 chuck
423 1.4 chuck bcopy(zs_init_reg, cs->cs_creg, 16);
424 1.4 chuck bcopy(zs_init_reg, cs->cs_preg, 16);
425 1.4 chuck
426 1.4 chuck /*
427 1.4 chuck * Clear the master interrupt enable.
428 1.4 chuck * The INTENA is common to both channels,
429 1.4 chuck * so just do it on the A channel.
430 1.4 chuck */
431 1.4 chuck if (channel == 0) {
432 1.4 chuck zs_write_reg(cs, 9, 0);
433 1.4 chuck }
434 1.4 chuck
435 1.4 chuck /* Reset the SCC chip. */
436 1.4 chuck zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
437 1.4 chuck
438 1.4 chuck /* Initialize a few important registers. */
439 1.4 chuck zs_write_reg(cs, 10, cs->cs_creg[10]);
440 1.4 chuck zs_write_reg(cs, 11, cs->cs_creg[11]);
441 1.4 chuck zs_write_reg(cs, 14, cs->cs_creg[14]);
442 1.4 chuck
443 1.4 chuck /* Assert DTR and RTS. */
444 1.4 chuck cs->cs_creg[5] |= (ZSWR5_DTR | ZSWR5_RTS);
445 1.4 chuck cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS);
446 1.4 chuck zs_write_reg(cs, 5, cs->cs_creg[5]);
447 1.1 chuck }
448 1.1 chuck
449 1.4 chuck /*
450 1.4 chuck * Polled console input putchar.
451 1.4 chuck */
452 1.1 chuck int
453 1.4 chuck zscngetc(dev)
454 1.4 chuck dev_t dev;
455 1.1 chuck {
456 1.4 chuck register volatile struct zs_chanstate *cs = zs_conschan;
457 1.4 chuck register int c;
458 1.1 chuck
459 1.4 chuck c = zs_getc(cs);
460 1.4 chuck return (c);
461 1.1 chuck }
462 1.1 chuck
463 1.4 chuck /*
464 1.4 chuck * Polled console output putchar.
465 1.4 chuck */
466 1.4 chuck void
467 1.4 chuck zscnputc(dev, c)
468 1.4 chuck dev_t dev;
469 1.4 chuck int c;
470 1.1 chuck {
471 1.4 chuck register volatile struct zs_chanstate *cs = zs_conschan;
472 1.1 chuck
473 1.4 chuck zs_putc(cs, c);
474 1.1 chuck }
475 1.1 chuck
476 1.4 chuck /*
477 1.4 chuck * Handle user request to enter kernel debugger.
478 1.4 chuck */
479 1.4 chuck void
480 1.4 chuck zs_abort()
481 1.1 chuck {
482 1.4 chuck register volatile struct zs_chanstate *cs = zs_conschan;
483 1.4 chuck int rr0;
484 1.1 chuck
485 1.4 chuck /* Wait for end of break to avoid PROM abort. */
486 1.4 chuck /* XXX - Limit the wait? */
487 1.4 chuck do {
488 1.4 chuck rr0 = *cs->cs_reg_csr;
489 1.4 chuck ZS_DELAY();
490 1.4 chuck } while (rr0 & ZSRR0_BREAK);
491 1.1 chuck
492 1.4 chuck mvme68k_abort("SERIAL LINE ABORT");
493 1.1 chuck }
494