1 /* $NetBSD: zs_ioasic.c,v 1.2 2000/07/05 07:50:57 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.2 2000/07/05 07:50:57 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_char 524 zs_read_reg(cs, reg) 525 struct zs_chanstate *cs; 526 u_char 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_char 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_char 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_char 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_char 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_char 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