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