zs_ioasic.c revision 1.3 1 /* $NetBSD: zs_ioasic.c,v 1.3 2000/09/09 06:08:42 nisimura Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1998 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, Ken Hornstein, and by Jason R. Thorpe of the
9 * Numerical Aerospace Simulation Facility, NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
41
42 __KERNEL_RCSID(0, "$NetBSD: zs_ioasic.c,v 1.3 2000/09/09 06:08:42 nisimura Exp $");
43
44 /*
45 * Zilog Z8530 Dual UART driver (machine-dependent part). This driver
46 * handles Z8530 chips attached to the Alpha IOASIC. Modified for
47 * NetBSD/alpha by Ken Hornstein and Jason R. Thorpe.
48 *
49 * Runs two serial lines per chip using slave drivers.
50 * Plain tty/async lines use the zstty slave.
51 */
52
53 #include "opt_ddb.h"
54 #include "zskbd.h"
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/conf.h>
59 #include <sys/device.h>
60 #include <sys/file.h>
61 #include <sys/ioctl.h>
62 #include <sys/kernel.h>
63 #include <sys/proc.h>
64 #include <sys/tty.h>
65 #include <sys/time.h>
66 #include <sys/syslog.h>
67
68 #include <machine/autoconf.h>
69 #include <machine/intr.h>
70 #include <machine/z8530var.h>
71
72 #include <dev/cons.h>
73 #include <dev/ic/z8530reg.h>
74
75 #include <dev/tc/tcvar.h>
76 #include <dev/tc/ioasicreg.h>
77 #include <dev/tc/ioasicvar.h>
78
79 #include <dev/tc/zs_ioasicvar.h>
80
81 #if 1
82 #define SPARSE
83 #endif
84
85 /*
86 * Helpers for console support.
87 */
88
89 int zs_ioasic_cngetc __P((dev_t));
90 void zs_ioasic_cnputc __P((dev_t, int));
91 void zs_ioasic_cnpollc __P((dev_t, int));
92
93 struct consdev zs_ioasic_cons = {
94 NULL, NULL, zs_ioasic_cngetc, zs_ioasic_cnputc,
95 zs_ioasic_cnpollc, NULL, NODEV, CN_NORMAL,
96 };
97
98 tc_offset_t zs_ioasic_console_offset;
99 int zs_ioasic_console_channel;
100 int zs_ioasic_console;
101
102 int zs_ioasic_isconsole __P((tc_offset_t, int));
103
104 struct zs_chanstate zs_ioasic_conschanstate_store;
105 struct zs_chanstate *zs_ioasic_conschanstate;
106
107 int zs_getc __P((struct zs_chanstate *));
108 void zs_putc __P((struct zs_chanstate *, int));
109 void zs_ioasic_cninit __P((tc_addr_t, tc_offset_t, int));
110
111 /*
112 * Some warts needed by z8530tty.c
113 */
114 int zs_def_cflag = (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8;
115 int zs_major = 15;
116
117 /*
118 * ZS chips are feeded a 7.372 MHz clock.
119 */
120 #define PCLK (9600 * 768) /* PCLK pin input clock rate */
121
122 /* The layout of this is hardware-dependent (padding, order). */
123 struct zshan {
124 volatile u_int zc_csr; /* ctrl,status, and indirect access */
125 #ifdef SPARSE
126 u_int zc_pad0;
127 #endif
128 volatile u_int zc_data; /* data */
129 #ifdef SPARSE
130 u_int sc_pad1;
131 #endif
132 };
133
134 struct zsdevice {
135 /* Yes, they are backwards. */
136 struct zshan zs_chan_b;
137 struct zshan zs_chan_a;
138 };
139
140 static u_char zs_ioasic_init_reg[16] = {
141 0, /* 0: CMD (reset, etc.) */
142 0, /* 1: No interrupts yet. */
143 0xf0, /* 2: IVECT */
144 ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
145 ZSWR4_CLK_X16 | ZSWR4_ONESB,
146 ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
147 0, /* 6: TXSYNC/SYNCLO */
148 0, /* 7: RXSYNC/SYNCHI */
149 0, /* 8: alias for data port */
150 ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT,
151 0, /*10: Misc. TX/RX control bits */
152 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
153 22, /*12: BAUDLO (default=9600) */
154 0, /*13: BAUDHI (default=9600) */
155 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
156 ZSWR15_BREAK_IE,
157 };
158
159 struct zshan *zs_ioasic_get_chan_addr __P((tc_addr_t, int));
160
161 struct zshan *
162 zs_ioasic_get_chan_addr(zsaddr, channel)
163 tc_addr_t zsaddr;
164 int channel;
165 {
166 struct zsdevice *addr;
167 struct zshan *zc;
168
169 addr = (struct zsdevice *) zsaddr;
170 #ifdef SPARSE
171 addr = (struct zsdevice *) TC_DENSE_TO_SPARSE((tc_addr_t) addr);
172 #endif
173
174 if (channel == 0)
175 zc = &addr->zs_chan_a;
176 else
177 zc = &addr->zs_chan_b;
178
179 return (zc);
180 }
181
182
183 /****************************************************************
184 * Autoconfig
185 ****************************************************************/
186
187 /* Definition of the driver for autoconfig. */
188 int zs_ioasic_match __P((struct device *, struct cfdata *, void *));
189 void zs_ioasic_attach __P((struct device *, struct device *, void *));
190 int zs_ioasic_print __P((void *, const char *name));
191
192 struct cfattach zsc_ioasic_ca = {
193 sizeof(struct zsc_softc), zs_ioasic_match, zs_ioasic_attach
194 };
195
196 /* Interrupt handlers. */
197 int zs_ioasic_hardintr __P((void *));
198 void zs_ioasic_softintr __P((void *));
199
200 extern struct cfdriver ioasic_cd;
201 extern struct cfdriver zsc_cd;
202
203 /*
204 * Is the zs chip present?
205 */
206 int
207 zs_ioasic_match(parent, cf, aux)
208 struct device *parent;
209 struct cfdata *cf;
210 void *aux;
211 {
212 struct ioasicdev_attach_args *d = aux;
213 void *zs_addr;
214
215 if (parent->dv_cfdata->cf_driver != &ioasic_cd)
216 return (0);
217
218 /*
219 * Make sure that we're looking for the right kind of device.
220 */
221 if (strncmp(d->iada_modname, "z8530 ", TC_ROM_LLEN) != 0 &&
222 strncmp(d->iada_modname, "scc", TC_ROM_LLEN) != 0)
223 return (0);
224
225 /*
226 * Check user-specified offset against the ioasic offset.
227 * Allow it to be wildcarded.
228 */
229 if (cf->cf_loc[IOASICCF_OFFSET] != IOASICCF_OFFSET_DEFAULT &&
230 cf->cf_loc[IOASICCF_OFFSET] != d->iada_offset)
231 return (0);
232
233 /*
234 * Find out the device address, and check it for validity.
235 */
236 zs_addr = (void *) d->iada_addr;
237 #ifdef SPARSE
238 zs_addr = (void *) TC_DENSE_TO_SPARSE((tc_addr_t) zs_addr);
239 #endif
240 if (tc_badaddr(zs_addr))
241 return (0);
242
243 return (1);
244 }
245
246 /*
247 * Attach a found zs.
248 */
249 void
250 zs_ioasic_attach(parent, self, aux)
251 struct device *parent;
252 struct device *self;
253 void *aux;
254 {
255 struct zsc_softc *zs = (void *) self;
256 struct zsc_attach_args zs_args;
257 struct zs_chanstate *cs;
258 struct ioasicdev_attach_args *d = aux;
259 volatile struct zshan *zc;
260 tc_addr_t zs_addr;
261 int s, channel;
262
263 printf("\n");
264
265 /*
266 * Initialize software state for each channel.
267 */
268 for (channel = 0; channel < 2; channel++) {
269 zs_args.channel = channel;
270 zs_args.hwflags = 0;
271
272 cs = &zs->zsc_cs_store[channel];
273 zs->zsc_cs[channel] = cs;
274
275 /*
276 * If we're the console, copy the channel state, and
277 * adjust the console channel pointer.
278 */
279 if (zs_ioasic_isconsole(d->iada_offset, channel)) {
280 bcopy(zs_ioasic_conschanstate, cs,
281 sizeof(struct zs_chanstate));
282 zs_ioasic_conschanstate = cs;
283 zs_args.hwflags |= ZS_HWFLAG_CONSOLE;
284 } else {
285 zs_addr = d->iada_addr;
286 zc = zs_ioasic_get_chan_addr(zs_addr, channel);
287 cs->cs_reg_csr = (void *)&zc->zc_csr;
288
289 bcopy(zs_ioasic_init_reg, cs->cs_creg, 16);
290 bcopy(zs_ioasic_init_reg, cs->cs_preg, 16);
291
292 cs->cs_defcflag = zs_def_cflag;
293 cs->cs_defspeed = 9600; /* XXX */
294 (void) zs_set_modes(cs, cs->cs_defcflag);
295 }
296
297 cs->cs_channel = channel;
298 cs->cs_ops = &zsops_null;
299 cs->cs_brg_clk = PCLK / 16;
300
301 /*
302 * DCD and CTS interrupts are only meaningful on
303 * SCC 0/B.
304 *
305 * XXX This is sorta gross.
306 */
307 if (d->iada_offset == 0x00100000 && channel == 1)
308 (u_long)cs->cs_private = ZIP_FLAGS_DCDCTS;
309 else
310 cs->cs_private = NULL;
311
312 /*
313 * Clear the master interrupt enable.
314 * The INTENA is common to both channels,
315 * so just do it on the A channel.
316 */
317 if (channel == 0) {
318 zs_write_reg(cs, 9, 0);
319 }
320
321 #ifdef notyet /* XXX thorpej */
322 /*
323 * Set up the flow/modem control channel pointer to
324 * deal with the weird wiring on the TC Alpha and
325 * DECstation.
326 */
327 if (channel == 1)
328 cs->cs_ctl_chan = zs->zsc_cs[0];
329 else
330 cs->cs_ctl_chan = NULL;
331 #endif
332
333 /*
334 * Look for a child driver for this channel.
335 * The child attach will setup the hardware.
336 */
337 if (config_found(self, (void *)&zs_args, zs_ioasic_print)
338 == NULL) {
339 /* No sub-driver. Just reset it. */
340 u_char reset = (channel == 0) ?
341 ZSWR9_A_RESET : ZSWR9_B_RESET;
342 s = splhigh();
343 zs_write_reg(cs, 9, reset);
344 splx(s);
345 }
346 }
347
348 /*
349 * Set up the ioasic interrupt handler.
350 */
351 ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY,
352 zs_ioasic_hardintr, zs);
353 zs->zsc_sih = softintr_establish(IPL_SOFTSERIAL,
354 zs_ioasic_softintr, zs);
355 if (zs->zsc_sih == NULL)
356 panic("zs_ioasic_attach: unable to register softintr");
357
358 /*
359 * Set the master interrupt enable and interrupt vector. The
360 * Sun does this only on one channel. The old Alpha SCC driver
361 * did it on both. We'll do it on both.
362 */
363 s = splhigh();
364 /* interrupt vector */
365 zs_write_reg(zs->zsc_cs[0], 2, zs_ioasic_init_reg[2]);
366 zs_write_reg(zs->zsc_cs[1], 2, zs_ioasic_init_reg[2]);
367
368 /* master interrupt control (enable) */
369 zs_write_reg(zs->zsc_cs[0], 9, zs_ioasic_init_reg[9]);
370 zs_write_reg(zs->zsc_cs[1], 9, zs_ioasic_init_reg[9]);
371
372 /* ioasic interrupt enable */
373 *(volatile u_int *)(ioasic_base + IOASIC_IMSK) |=
374 IOASIC_INTR_SCC_1 | IOASIC_INTR_SCC_0;
375 tc_mb();
376
377 splx(s);
378 }
379
380 int
381 zs_ioasic_print(aux, name)
382 void *aux;
383 const char *name;
384 {
385 struct zsc_attach_args *args = aux;
386
387 if (name != NULL)
388 printf("%s:", name);
389
390 if (args->channel != -1)
391 printf(" channel %d", args->channel);
392
393 return (UNCONF);
394 }
395
396
397 /*
398 * Hardware interrupt handler.
399 */
400 int
401 zs_ioasic_hardintr(arg)
402 void *arg;
403 {
404 struct zsc_softc *zsc = arg;
405
406 /*
407 * Call the upper-level MI hardware interrupt handler.
408 */
409 zsc_intr_hard(zsc);
410
411 /*
412 * Check to see if we need to schedule any software-level
413 * processing interrupts.
414 */
415 if (zsc->zsc_cs[0]->cs_softreq | zsc->zsc_cs[1]->cs_softreq)
416 softintr_schedule(zsc->zsc_sih);
417
418 return (1);
419 }
420
421 /*
422 * Software-level interrupt (character processing, lower priority).
423 */
424 void
425 zs_ioasic_softintr(arg)
426 void *arg;
427 {
428 struct zsc_softc *zsc = arg;
429 int s;
430
431 s = spltty();
432 (void) zsc_intr_soft(zsc);
433 splx(s);
434 }
435
436 /*
437 * MD functions for setting the baud rate and control modes.
438 */
439 int
440 zs_set_speed(cs, bps)
441 struct zs_chanstate *cs;
442 int bps; /* bits per second */
443 {
444 int tconst, real_bps;
445
446 if (bps == 0)
447 return (0);
448
449 #ifdef DIAGNOSTIC
450 if (cs->cs_brg_clk == 0)
451 panic("zs_set_speed");
452 #endif
453
454 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
455 if (tconst < 0)
456 return (EINVAL);
457
458 /* Convert back to make sure we can do it. */
459 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
460
461 /* XXX - Allow some tolerance here? */
462 if (real_bps != bps)
463 return (EINVAL);
464
465 cs->cs_preg[12] = tconst;
466 cs->cs_preg[13] = tconst >> 8;
467
468 /* Caller will stuff the pending registers. */
469 return (0);
470 }
471
472 int
473 zs_set_modes(cs, cflag)
474 struct zs_chanstate *cs;
475 int cflag; /* bits per second */
476 {
477 u_long privflags = (u_long)cs->cs_private;
478 int s;
479
480 /*
481 * Output hardware flow control on the chip is horrendous:
482 * if carrier detect drops, the receiver is disabled, and if
483 * CTS drops, the transmitter is stoped IN MID CHARACTER!
484 * Therefore, NEVER set the HFC bit, and instead use the
485 * status interrupt to detect CTS changes.
486 */
487 s = splzs();
488 if ((cflag & (CLOCAL | MDMBUF)) != 0)
489 cs->cs_rr0_dcd = 0;
490 else
491 cs->cs_rr0_dcd = ZSRR0_DCD;
492 if ((cflag & CRTSCTS) != 0) {
493 cs->cs_wr5_dtr = ZSWR5_DTR;
494 cs->cs_wr5_rts = ZSWR5_RTS;
495 cs->cs_rr0_cts = ZSRR0_CTS;
496 } else if ((cflag & CDTRCTS) != 0) {
497 cs->cs_wr5_dtr = 0;
498 cs->cs_wr5_rts = ZSWR5_DTR;
499 cs->cs_rr0_cts = ZSRR0_CTS;
500 } else if ((cflag & MDMBUF) != 0) {
501 cs->cs_wr5_dtr = 0;
502 cs->cs_wr5_rts = ZSWR5_DTR;
503 cs->cs_rr0_cts = ZSRR0_DCD;
504 } else {
505 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
506 cs->cs_wr5_rts = 0;
507 cs->cs_rr0_cts = 0;
508 }
509
510 if ((privflags & ZIP_FLAGS_DCDCTS) == 0) {
511 cs->cs_rr0_dcd &= ~(ZSRR0_CTS|ZSRR0_DCD);
512 cs->cs_rr0_cts &= ~(ZSRR0_CTS|ZSRR0_DCD);
513 }
514 splx(s);
515
516 /* Caller will stuff the pending registers. */
517 return (0);
518 }
519
520 /*
521 * Read or write the chip with suitable delays.
522 */
523 u_int
524 zs_read_reg(cs, reg)
525 struct zs_chanstate *cs;
526 u_int reg;
527 {
528 struct zshan *zc = (void *)cs->cs_reg_csr;
529 unsigned val;
530
531 zc->zc_csr = reg << 8;
532 tc_mb();
533 DELAY(5);
534 val = (zc->zc_csr >> 8) & 0xff;
535 tc_mb();
536 DELAY(5);
537 return (val);
538 }
539
540 void
541 zs_write_reg(cs, reg, val)
542 struct zs_chanstate *cs;
543 u_int reg, val;
544 {
545 struct zshan *zc = (void *)cs->cs_reg_csr;
546
547 zc->zc_csr = reg << 8;
548 tc_mb();
549 DELAY(5);
550 zc->zc_csr = val << 8;
551 tc_mb();
552 DELAY(5);
553 }
554
555 u_int
556 zs_read_csr(cs)
557 struct zs_chanstate *cs;
558 {
559 struct zshan *zc = (void *)cs->cs_reg_csr;
560 unsigned val;
561
562 val = (zc->zc_csr >> 8) & 0xff;
563 tc_mb();
564 DELAY(5);
565
566 return (val);
567 }
568
569 void
570 zs_write_csr(cs, val)
571 struct zs_chanstate *cs;
572 u_int val;
573 {
574
575 struct zshan *zc = (void *)cs->cs_reg_csr;
576
577 zc->zc_csr = val << 8;
578 tc_mb();
579 DELAY(5);
580 }
581
582 u_int
583 zs_read_data(cs)
584 struct zs_chanstate *cs;
585 {
586 struct zshan *zc = (void *)cs->cs_reg_csr;
587 unsigned val;
588
589 val = (zc->zc_data) >> 8 & 0xff;
590 tc_mb();
591 DELAY(5);
592
593 return (val);
594 }
595
596 void
597 zs_write_data(cs, val)
598 struct zs_chanstate *cs;
599 u_int val;
600 {
601
602 struct zshan *zc = (void *)cs->cs_reg_csr;
603
604 zc->zc_data = val << 8;
605 tc_mb();
606 DELAY(5);
607 }
608
609 /****************************************************************
610 * Console support functions (Alpha TC specific!)
611 ****************************************************************/
612
613 /*
614 * Handle user request to enter kernel debugger.
615 */
616 void
617 zs_abort(cs)
618 struct zs_chanstate *cs;
619 {
620 int rr0;
621
622 /* Wait for end of break. */
623 /* XXX - Limit the wait? */
624 do {
625 rr0 = zs_read_csr(cs);
626 } while (rr0 & ZSRR0_BREAK);
627
628 #if defined(KGDB)
629 zskgdb(cs);
630 #elif defined(DDB)
631 Debugger();
632 #else
633 printf("zs_abort: ignoring break on console\n");
634 #endif
635 }
636
637 /*
638 * Polled input char.
639 */
640 int
641 zs_getc(cs)
642 struct zs_chanstate *cs;
643 {
644 int s, c, rr0;
645
646 s = splhigh();
647 /* Wait for a character to arrive. */
648 do {
649 rr0 = zs_read_csr(cs);
650 } while ((rr0 & ZSRR0_RX_READY) == 0);
651
652 c = zs_read_data(cs);
653 splx(s);
654
655 /*
656 * This is used by the kd driver to read scan codes,
657 * so don't translate '\r' ==> '\n' here...
658 */
659 return (c);
660 }
661
662 /*
663 * Polled output char.
664 */
665 void
666 zs_putc(cs, c)
667 struct zs_chanstate *cs;
668 int c;
669 {
670 register int s, rr0;
671
672 s = splhigh();
673 /* Wait for transmitter to become ready. */
674 do {
675 rr0 = zs_read_csr(cs);
676 } while ((rr0 & ZSRR0_TX_READY) == 0);
677
678 zs_write_data(cs, c);
679
680 /* Wait for the character to be transmitted. */
681 do {
682 rr0 = zs_read_csr(cs);
683 } while ((rr0 & ZSRR0_TX_READY) == 0);
684 splx(s);
685 }
686
687 /*****************************************************************/
688
689 /*
690 * zs_ioasic_cninit --
691 * Initialize the serial channel for console use--either the
692 * primary keyboard or as the serial console.
693 */
694 void
695 zs_ioasic_cninit(ioasic_addr, zs_offset, channel)
696 tc_addr_t ioasic_addr;
697 tc_offset_t zs_offset;
698 int channel;
699 {
700 struct zs_chanstate *cs;
701 tc_addr_t zs_addr;
702 struct zshan *zc;
703
704 /*
705 * Initialize the console finder helpers.
706 */
707 zs_ioasic_console_offset = zs_offset;
708 zs_ioasic_console_channel = channel;
709 zs_ioasic_console = 1;
710
711 /*
712 * Pointer to channel state. Later, the console channel
713 * state is copied into the softc, and the console channel
714 * pointer adjusted to point to the new copy.
715 */
716 zs_ioasic_conschanstate = cs = &zs_ioasic_conschanstate_store;
717
718 /*
719 * Compute the physical address of the chip, "map" it via
720 * K0SEG, and then get the address of the actual channel.
721 */
722 zs_addr = ALPHA_PHYS_TO_K0SEG(ioasic_addr + zs_offset);
723 zc = zs_ioasic_get_chan_addr(zs_addr, channel);
724
725 /* Setup temporary chanstate. */
726 cs->cs_reg_csr = (volatile u_char *)&zc->zc_csr;
727 cs->cs_reg_data = (volatile u_char *)&zc->zc_data;
728
729 /* Initialize the pending registers. */
730 bcopy(zs_ioasic_init_reg, cs->cs_preg, 16);
731 cs->cs_preg[5] |= (ZSWR5_DTR | ZSWR5_RTS);
732
733 /*
734 * DCD and CTS interrupts are only meaningful on
735 * SCC 0/B.
736 *
737 * XXX This is sorta gross.
738 */
739 if (zs_offset == 0x00100000 && channel == 1)
740 (u_long)cs->cs_private = ZIP_FLAGS_DCDCTS;
741 else
742 cs->cs_private = NULL;
743
744 /* Clear the master interrupt enable. */
745 zs_write_reg(cs, 9, 0);
746
747 /* Reset the whole SCC chip. */
748 zs_write_reg(cs, 9, ZSWR9_HARD_RESET);
749
750 /* Copy "pending" to "current" and H/W. */
751 zs_loadchannelregs(cs);
752 }
753
754 /*
755 * zs_ioasic_cnattach --
756 * Initialize and attach a serial console.
757 */
758 int
759 zs_ioasic_cnattach(ioasic_addr, zs_offset, channel, rate, cflag)
760 tc_addr_t ioasic_addr;
761 tc_offset_t zs_offset;
762 int channel, rate, cflag;
763 {
764 zs_ioasic_cninit(ioasic_addr, zs_offset, channel);
765
766 zs_ioasic_conschanstate->cs_defspeed = rate;
767 zs_ioasic_conschanstate->cs_defcflag = cflag;
768
769 /* Point the console at the SCC. */
770 cn_tab = &zs_ioasic_cons;
771
772 return (0);
773 }
774
775 /*
776 * zs_ioasic_lk201_cnattach --
777 * Initialize and attach the primary keyboard.
778 */
779 int
780 zs_ioasic_lk201_cnattach(ioasic_addr, zs_offset, channel)
781 tc_addr_t ioasic_addr;
782 tc_offset_t zs_offset;
783 int channel;
784 {
785 #if (NZSKBD > 0)
786 zs_ioasic_cninit(ioasic_addr, zs_offset, channel);
787 zs_ioasic_conschanstate->cs_defspeed = 4800;
788 zs_ioasic_conschanstate->cs_defcflag =
789 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8;
790 zs_ioasic_conschanstate->cs_brg_clk = PCLK / 16;
791 return (zskbd_cnattach(zs_ioasic_conschanstate));
792 #else
793 return (ENXIO);
794 #endif
795 }
796
797 int
798 zs_ioasic_isconsole(offset, channel)
799 tc_offset_t offset;
800 int channel;
801 {
802
803 if (zs_ioasic_console &&
804 offset == zs_ioasic_console_offset &&
805 channel == zs_ioasic_console_channel)
806 return (1);
807
808 return (0);
809 }
810
811 /*
812 * Polled console input putchar.
813 */
814 int
815 zs_ioasic_cngetc(dev)
816 dev_t dev;
817 {
818
819 return (zs_getc(zs_ioasic_conschanstate));
820 }
821
822 /*
823 * Polled console output putchar.
824 */
825 void
826 zs_ioasic_cnputc(dev, c)
827 dev_t dev;
828 int c;
829 {
830
831 zs_putc(zs_ioasic_conschanstate, c);
832 }
833
834 /*
835 * Set polling/no polling on console.
836 */
837 void
838 zs_ioasic_cnpollc(dev, onoff)
839 dev_t dev;
840 int onoff;
841 {
842
843 /* XXX ??? */
844 }
845