1 /* $NetBSD: zs.c,v 1.7 1999/02/11 15:28:05 mycroft 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 FOUNDATION OR CONTRIBUTORS 30 * BE 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 * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves. 45 */ 46 47 /* This was snarfed from the netbsd sparc/dev/zs.c at version 1.56 48 * and then updated to reflect changes in 1.59 49 * by Darrin B Jewell <jewell@mit.edu> Mon Mar 30 20:24:46 1998 50 */ 51 52 #include "opt_ddb.h" 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/conf.h> 57 #include <sys/device.h> 58 #include <sys/file.h> 59 #include <sys/ioctl.h> 60 #include <sys/kernel.h> 61 #include <sys/proc.h> 62 #include <sys/tty.h> 63 #include <sys/time.h> 64 #include <sys/syslog.h> 65 66 #include <machine/autoconf.h> 67 #include <machine/cpu.h> 68 #include <machine/psl.h> 69 70 #include <dev/cons.h> 71 72 #include <dev/ic/z8530reg.h> 73 #include <machine/z8530var.h> 74 75 #include <next68k/next68k/isr.h> 76 77 #include "zsc.h" /* NZSC */ 78 79 #if (NZSC < 0) 80 #error "No serial controllers?" 81 #endif 82 83 /* 84 * Some warts needed by z8530tty.c - 85 * The default parity REALLY needs to be the same as the PROM uses, 86 * or you can not see messages done with printf during boot-up... 87 */ 88 int zs_def_cflag = (CREAD | CS8 | HUPCL); 89 int zs_major = 12; 90 91 /* 92 * The NeXT provides a 3.686400 MHz clock to the ZS chips. 93 */ 94 #if 1 95 #define PCLK (9600 * 384) /* PCLK pin input clock rate */ 96 #else 97 #define PCLK 10000000 98 #endif 99 100 #define ZS_DELAY() delay(2) 101 102 /* The layout of this is hardware-dependent (padding, order). */ 103 struct zschan { 104 volatile u_char zc_csr; /* ctrl,status, and indirect access */ 105 u_char zc_xxx0; 106 volatile u_char zc_data; /* data */ 107 u_char zc_xxx1; 108 }; 109 110 static char *zsaddr[NZSC]; 111 112 /* Flags from cninit() */ 113 static int zs_hwflags[NZSC][2]; 114 115 /* Default speed for each channel */ 116 static int zs_defspeed[NZSC][2] = { 117 { 9600, /* ttya */ 118 9600 }, /* ttyb */ 119 }; 120 121 static u_char zs_init_reg[16] = { 122 0, /* 0: CMD (reset, etc.) */ 123 0, /* 1: No interrupts yet. */ 124 0x18 + NEXT_I_IPL(NEXT_I_SCC), /* 2: IVECT */ 125 ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 126 ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 127 ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 128 0, /* 6: TXSYNC/SYNCLO */ 129 0, /* 7: RXSYNC/SYNCHI */ 130 0, /* 8: alias for data port */ 131 ZSWR9_MASTER_IE, 132 0, /*10: Misc. TX/RX control bits */ 133 ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 134 ((PCLK/32)/9600)-2, /*12: BAUDLO (default=9600) */ 135 0, /*13: BAUDHI (default=9600) */ 136 ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK, 137 ZSWR15_BREAK_IE, 138 }; 139 140 static struct zschan * 141 zs_get_chan_addr __P((int zsc_unit, int channel)); 142 143 static struct zschan * 144 zs_get_chan_addr(zs_unit, channel) 145 int zs_unit, channel; 146 { 147 char *addr; 148 struct zschan *zc; 149 150 if (zs_unit >= NZSC) 151 return (NULL); 152 addr = zsaddr[zs_unit]; 153 if (addr == NULL) 154 return (NULL); 155 if (channel == 0) { 156 /* handle the fact the ports are intertwined. */ 157 zc = (struct zschan *)(addr+1); 158 } else { 159 zc = (struct zschan *)(addr); 160 } 161 return (zc); 162 } 163 164 165 /**************************************************************** 166 * Autoconfig 167 ****************************************************************/ 168 169 /* Definition of the driver for autoconfig. */ 170 static int zs_match __P((struct device *, struct cfdata *, void *)); 171 static void zs_attach __P((struct device *, struct device *, void *)); 172 static int zs_print __P((void *, const char *name)); 173 174 extern int zs_getc __P((void *arg)); 175 extern void zs_putc __P((void *arg, int c)); 176 177 struct cfattach zsc_ca = { 178 sizeof(struct zsc_softc), zs_match, zs_attach 179 }; 180 181 extern struct cfdriver zsc_cd; 182 183 /* Interrupt handlers. */ 184 static int zshard __P((void *)); 185 static int zssoft __P((void *)); 186 187 static int zs_get_speed __P((struct zs_chanstate *)); 188 189 190 /* 191 * Is the zs chip present? 192 */ 193 static int 194 zs_match(parent, cf, aux) 195 struct device *parent; 196 struct cfdata *cf; 197 void *aux; 198 { 199 return(1); 200 } 201 202 /* 203 * Attach a found zs. 204 * 205 * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR 206 * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE? 207 */ 208 static void 209 zs_attach(parent, self, aux) 210 struct device *parent; 211 struct device *self; 212 void *aux; 213 { 214 struct zsc_softc *zsc = (void *) self; 215 struct zsc_attach_args zsc_args; 216 volatile struct zschan *zc; 217 struct zs_chanstate *cs; 218 int s, zs_unit, channel; 219 220 printf("\n"); 221 222 zs_unit = zsc->zsc_dev.dv_unit; 223 224 if (zsaddr[zs_unit] == NULL) 225 panic("zs_attach: zs%d not mapped\n", zs_unit); 226 227 /* 228 * Initialize software state for each channel. 229 */ 230 for (channel = 0; channel < 2; channel++) { 231 zsc_args.channel = channel; 232 zsc_args.hwflags = zs_hwflags[zs_unit][channel]; 233 cs = &zsc->zsc_cs_store[channel]; 234 zsc->zsc_cs[channel] = cs; 235 236 cs->cs_channel = channel; 237 cs->cs_private = NULL; 238 cs->cs_ops = &zsops_null; 239 cs->cs_brg_clk = PCLK / 16; 240 241 zc = zs_get_chan_addr(zs_unit, channel); 242 cs->cs_reg_csr = &zc->zc_csr; 243 cs->cs_reg_data = &zc->zc_data; 244 245 bcopy(zs_init_reg, cs->cs_creg, 16); 246 bcopy(zs_init_reg, cs->cs_preg, 16); 247 248 /* XXX: Get these from the PROM properties! */ 249 /* XXX: See the mvme167 code. Better. */ 250 if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) 251 cs->cs_defspeed = zs_get_speed(cs); 252 else 253 cs->cs_defspeed = zs_defspeed[zs_unit][channel]; 254 cs->cs_defcflag = zs_def_cflag; 255 256 /* Make these correspond to cs_defcflag (-crtscts) */ 257 cs->cs_rr0_dcd = ZSRR0_DCD; 258 cs->cs_rr0_cts = 0; 259 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 260 cs->cs_wr5_rts = 0; 261 262 /* 263 * Clear the master interrupt enable. 264 * The INTENA is common to both channels, 265 * so just do it on the A channel. 266 */ 267 if (channel == 0) { 268 zs_write_reg(cs, 9, 0); 269 } 270 271 /* 272 * Look for a child driver for this channel. 273 * The child attach will setup the hardware. 274 */ 275 if (!config_found(self, (void *)&zsc_args, zs_print)) { 276 /* No sub-driver. Just reset it. */ 277 u_char reset = (channel == 0) ? 278 ZSWR9_A_RESET : ZSWR9_B_RESET; 279 s = splzs(); 280 zs_write_reg(cs, 9, reset); 281 splx(s); 282 } 283 } 284 285 isrlink_autovec(zshard, NULL, NEXT_I_IPL(NEXT_I_SCC), 0); 286 INTR_ENABLE(NEXT_I_SCC); 287 288 { 289 int sir; 290 sir = allocate_sir(zssoft, zsc); 291 if (sir != SIR_SERIAL) { 292 panic("Unexpected zssoft sir"); 293 } 294 } 295 296 /* 297 * Set the master interrupt enable and interrupt vector. 298 * (common to both channels, do it on A) 299 */ 300 cs = zsc->zsc_cs[0]; 301 s = splhigh(); 302 /* interrupt vector */ 303 zs_write_reg(cs, 2, zs_init_reg[2]); 304 /* master interrupt control (enable) */ 305 zs_write_reg(cs, 9, zs_init_reg[9]); 306 splx(s); 307 308 } 309 310 static int 311 zs_print(aux, name) 312 void *aux; 313 const char *name; 314 { 315 struct zsc_attach_args *args = aux; 316 317 if (name != NULL) 318 printf("%s: ", name); 319 320 if (args->channel != -1) 321 printf(" channel %d", args->channel); 322 323 return (UNCONF); 324 } 325 326 static volatile int zssoftpending; 327 328 /* 329 * Our ZS chips all share a common, autovectored interrupt, 330 * so we have to look at all of them on each interrupt. 331 */ 332 static int 333 zshard(arg) 334 void *arg; 335 { 336 register struct zsc_softc *zsc; 337 register int unit, rr3, rval, softreq; 338 if (!INTR_OCCURRED(NEXT_I_SCC)) return 0; 339 340 rval = softreq = 0; 341 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { 342 zsc = zsc_cd.cd_devs[unit]; 343 if (zsc == NULL) 344 continue; 345 rr3 = zsc_intr_hard(zsc); 346 /* Count up the interrupts. */ 347 if (rr3) { 348 rval |= rr3; 349 zsc->zsc_intrcnt.ev_count++; 350 } 351 softreq |= zsc->zsc_cs[0]->cs_softreq; 352 softreq |= zsc->zsc_cs[1]->cs_softreq; 353 } 354 355 /* We are at splzs here, so no need to lock. */ 356 if (softreq && (zssoftpending == 0)) { 357 zssoftpending = 1; 358 setsoftserial(); 359 } 360 return(1); 361 } 362 363 /* 364 * Similar scheme as for zshard (look at all of them) 365 */ 366 static int 367 zssoft(arg) 368 void *arg; 369 { 370 register struct zsc_softc *zsc; 371 register int s, unit; 372 373 /* This is not the only ISR on this IPL. */ 374 if (zssoftpending == 0) 375 return (0); 376 377 /* 378 * The soft intr. bit will be set by zshard only if 379 * the variable zssoftpending is zero. The order of 380 * these next two statements prevents our clearing 381 * the soft intr bit just after zshard has set it. 382 */ 383 /* ienab_bic(IE_ZSSOFT); */ 384 zssoftpending = 0; 385 386 /* Make sure we call the tty layer at spltty. */ 387 s = spltty(); 388 for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { 389 zsc = zsc_cd.cd_devs[unit]; 390 if (zsc == NULL) 391 continue; 392 (void)zsc_intr_soft(zsc); 393 } 394 splx(s); 395 return (1); 396 } 397 398 399 /* 400 * Compute the current baud rate given a ZS channel. 401 */ 402 static int 403 zs_get_speed(cs) 404 struct zs_chanstate *cs; 405 { 406 int tconst; 407 408 tconst = zs_read_reg(cs, 12); 409 tconst |= zs_read_reg(cs, 13) << 8; 410 return (TCONST_TO_BPS(cs->cs_brg_clk, tconst)); 411 } 412 413 /* 414 * MD functions for setting the baud rate and control modes. 415 */ 416 int 417 zs_set_speed(cs, bps) 418 struct zs_chanstate *cs; 419 int bps; /* bits per second */ 420 { 421 int tconst, real_bps; 422 423 if (bps == 0) 424 return (0); 425 426 #ifdef DIAGNOSTIC 427 if (cs->cs_brg_clk == 0) 428 panic("zs_set_speed"); 429 #endif 430 431 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 432 if (tconst < 0) 433 return (EINVAL); 434 435 /* Convert back to make sure we can do it. */ 436 real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 437 438 /* XXX - Allow some tolerance here? */ 439 if (real_bps != bps) 440 return (EINVAL); 441 442 cs->cs_preg[12] = tconst; 443 cs->cs_preg[13] = tconst >> 8; 444 445 /* Caller will stuff the pending registers. */ 446 return (0); 447 } 448 449 int 450 zs_set_modes(cs, cflag) 451 struct zs_chanstate *cs; 452 int cflag; /* bits per second */ 453 { 454 int s; 455 456 /* 457 * Output hardware flow control on the chip is horrendous: 458 * if carrier detect drops, the receiver is disabled, and if 459 * CTS drops, the transmitter is stoped IN MID CHARACTER! 460 * Therefore, NEVER set the HFC bit, and instead use the 461 * status interrupt to detect CTS changes. 462 */ 463 s = splzs(); 464 if ((cflag & (CLOCAL | MDMBUF)) != 0) 465 cs->cs_rr0_dcd = 0; 466 else 467 cs->cs_rr0_dcd = ZSRR0_DCD; 468 if ((cflag & CRTSCTS) != 0) { 469 cs->cs_wr5_dtr = ZSWR5_DTR; 470 cs->cs_wr5_rts = ZSWR5_RTS; 471 cs->cs_rr0_cts = ZSRR0_CTS; 472 } else if ((cflag & CDTRCTS) != 0) { 473 cs->cs_wr5_dtr = 0; 474 cs->cs_wr5_rts = ZSWR5_DTR; 475 cs->cs_rr0_cts = ZSRR0_CTS; 476 } else if ((cflag & MDMBUF) != 0) { 477 cs->cs_wr5_dtr = 0; 478 cs->cs_wr5_rts = ZSWR5_DTR; 479 cs->cs_rr0_cts = ZSRR0_DCD; 480 } else { 481 cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; 482 cs->cs_wr5_rts = 0; 483 cs->cs_rr0_cts = 0; 484 } 485 splx(s); 486 487 /* Caller will stuff the pending registers. */ 488 return (0); 489 } 490 491 /* 492 * Read or write the chip with suitable delays. 493 */ 494 495 u_char 496 zs_read_reg(cs, reg) 497 struct zs_chanstate *cs; 498 u_char reg; 499 { 500 u_char val; 501 502 *cs->cs_reg_csr = reg; 503 ZS_DELAY(); 504 val = *cs->cs_reg_csr; 505 ZS_DELAY(); 506 return (val); 507 } 508 509 void 510 zs_write_reg(cs, reg, val) 511 struct zs_chanstate *cs; 512 u_char reg, val; 513 { 514 *cs->cs_reg_csr = reg; 515 ZS_DELAY(); 516 *cs->cs_reg_csr = val; 517 ZS_DELAY(); 518 } 519 520 u_char 521 zs_read_csr(cs) 522 struct zs_chanstate *cs; 523 { 524 register u_char val; 525 526 val = *cs->cs_reg_csr; 527 ZS_DELAY(); 528 return (val); 529 } 530 531 void zs_write_csr(cs, val) 532 struct zs_chanstate *cs; 533 u_char val; 534 { 535 *cs->cs_reg_csr = val; 536 ZS_DELAY(); 537 } 538 539 u_char zs_read_data(cs) 540 struct zs_chanstate *cs; 541 { 542 register u_char val; 543 544 val = *cs->cs_reg_data; 545 ZS_DELAY(); 546 return (val); 547 } 548 549 void zs_write_data(cs, val) 550 struct zs_chanstate *cs; 551 u_char val; 552 { 553 *cs->cs_reg_data = val; 554 ZS_DELAY(); 555 } 556 557 /**************************************************************** 558 * Console support functions (Sun specific!) 559 * Note: this code is allowed to know about the layout of 560 * the chip registers, and uses that to keep things simple. 561 * XXX - I think I like the mvme167 code better. -gwr 562 ****************************************************************/ 563 564 extern void Debugger __P((void)); 565 void *zs_conschan; 566 int zs_consunit = 0; 567 568 /* 569 * Handle user request to enter kernel debugger. 570 */ 571 void 572 zs_abort(cs) 573 struct zs_chanstate *cs; 574 { 575 register volatile struct zschan *zc = zs_conschan; 576 int rr0; 577 578 /* Wait for end of break to avoid PROM abort. */ 579 /* XXX - Limit the wait? */ 580 do { 581 rr0 = zc->zc_csr; 582 ZS_DELAY(); 583 } while (rr0 & ZSRR0_BREAK); 584 585 #if defined(KGDB) 586 zskgdb(cs); 587 #elif defined(DDB) 588 Debugger(); 589 #else 590 printf("stopping on keyboard abort\n"); 591 callrom(); 592 #endif 593 } 594 595 /* 596 * Polled input char. 597 */ 598 int 599 zs_getc(arg) 600 void *arg; 601 { 602 register volatile struct zschan *zc = arg; 603 register int s, c, rr0; 604 605 s = splhigh(); 606 /* Wait for a character to arrive. */ 607 do { 608 rr0 = zc->zc_csr; 609 ZS_DELAY(); 610 } while ((rr0 & ZSRR0_RX_READY) == 0); 611 612 c = zc->zc_data; 613 ZS_DELAY(); 614 splx(s); 615 616 /* 617 * This is used by the kd driver to read scan codes, 618 * so don't translate '\r' ==> '\n' here... 619 */ 620 return (c); 621 } 622 623 /* 624 * Polled output char. 625 */ 626 void 627 zs_putc(arg, c) 628 void *arg; 629 int c; 630 { 631 register volatile struct zschan *zc = arg; 632 register int s, rr0; 633 634 s = splhigh(); 635 /* Wait for transmitter to become ready. */ 636 do { 637 rr0 = zc->zc_csr; 638 ZS_DELAY(); 639 } while ((rr0 & ZSRR0_TX_READY) == 0); 640 641 642 zc->zc_data = c; 643 ZS_DELAY(); 644 645 splx(s); 646 } 647 648 /*****************************************************************/ 649 650 void zscninit __P((struct consdev *)); 651 int zscngetc __P((dev_t)); 652 void zscnputc __P((dev_t, int)); 653 void zscnprobe __P((struct consdev *)); 654 extern int zsopen __P(( dev_t dev, int flags, int mode, struct proc *p)); 655 656 void 657 zscnprobe(cp) 658 struct consdev * cp; 659 { 660 int maj; 661 for (maj = 0; maj < nchrdev; maj++) { 662 if (cdevsw[maj].d_open == zsopen) { 663 break; 664 } 665 } 666 if (maj != nchrdev) { 667 cp->cn_pri = CN_NORMAL; /* Lower than CN_INTERNAL */ 668 zs_major = maj; 669 zs_consunit = 0; 670 zsaddr[0] = (void *)IIOV(NEXT_P_SCC); 671 cp->cn_dev = makedev(maj, zs_consunit); 672 zs_conschan = zs_get_chan_addr(0, zs_consunit); 673 } else { 674 cp->cn_pri = CN_DEAD; 675 } 676 } 677 678 679 void 680 zscninit(cn) 681 struct consdev *cn; 682 { 683 zs_hwflags[0][zs_consunit] = ZS_HWFLAG_CONSOLE; 684 685 { 686 struct zs_chanstate xcs; 687 struct zs_chanstate *cs; 688 volatile struct zschan *zc; 689 int tconst, s; 690 691 /* Setup temporary chanstate. */ 692 bzero((caddr_t)&xcs, sizeof(xcs)); 693 cs = &xcs; 694 zc = zs_conschan; 695 cs->cs_reg_csr = &zc->zc_csr; 696 cs->cs_reg_data = &zc->zc_data; 697 cs->cs_channel = zs_consunit; 698 cs->cs_brg_clk = PCLK / 16; 699 700 bcopy(zs_init_reg, cs->cs_preg, 16); 701 cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS; 702 cs->cs_preg[15] = ZSWR15_BREAK_IE; 703 704 tconst = BPS_TO_TCONST(cs->cs_brg_clk, 705 zs_defspeed[0][zs_consunit]); 706 cs->cs_preg[12] = tconst; 707 cs->cs_preg[13] = tconst >> 8; 708 /* can't use zs_set_speed as we haven't set up the 709 * signal sources, and it's not worth it for now 710 */ 711 712 cs->cs_preg[9] &= ~ZSWR9_MASTER_IE; 713 /* no interrupts until later, after attach. */ 714 715 s = splhigh(); 716 zs_loadchannelregs(cs); 717 splx(s); 718 } 719 720 printf("\nNetBSD/next68k console\n"); 721 } 722 723 /* 724 * Polled console input putchar. 725 */ 726 int 727 zscngetc(dev) 728 dev_t dev; 729 { 730 return (zs_getc(zs_conschan)); 731 } 732 733 /* 734 * Polled console output putchar. 735 */ 736 void 737 zscnputc(dev, c) 738 dev_t dev; 739 int c; 740 { 741 zs_putc(zs_conschan, c); 742 } 743 744 /*****************************************************************/ 745