1 /* $OpenBSD: z8530tty.c,v 1.17 2008/01/18 21:36:43 kettenis Exp $ */ 2 /* $NetBSD: z8530tty.c,v 1.13 1996/10/16 20:42:14 gwr Exp $ */ 3 4 /* 5 * Copyright (c) 1994 Gordon W. Ross 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This software was developed by the Computer Systems Engineering group 10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 11 * contributed to Berkeley. 12 * 13 * All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Lawrence Berkeley Laboratory. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 3. Neither the name of the University nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 * 42 * @(#)zs.c 8.1 (Berkeley) 7/19/93 43 */ 44 45 /* 46 * Zilog Z8530 Dual UART driver (tty interface) 47 * 48 * This is the "slave" driver that will be attached to 49 * the "zsc" driver for plain "tty" async. serial lines. 50 * 51 * Credits, history: 52 * 53 * The original version of this code was the sparc/dev/zs.c driver 54 * as distributed with the Berkeley 4.4 Lite release. Since then, 55 * Gordon Ross reorganized the code into the current parent/child 56 * driver scheme, separating the Sun keyboard and mouse support 57 * into independent child drivers. 58 * 59 * RTS/CTS flow-control support was a collaboration of: 60 * Gordon Ross <gwr@netbsd.org>, 61 * Bill Studenmund <wrstuden@loki.stanford.edu> 62 * Ian Dall <Ian.Dall@dsto.defence.gov.au> 63 */ 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/proc.h> 68 #include <sys/device.h> 69 #include <sys/conf.h> 70 #include <sys/file.h> 71 #include <sys/ioctl.h> 72 #include <sys/malloc.h> 73 #include <sys/tty.h> 74 #include <sys/time.h> 75 #include <sys/kernel.h> 76 #include <sys/syslog.h> 77 78 #include <dev/ic/z8530reg.h> 79 #include <machine/z8530var.h> 80 81 #ifdef KGDB 82 extern int zs_check_kgdb(); 83 #endif 84 85 /* 86 * Allow the MD var.h to override the default CFLAG so that 87 * console messages during boot come out with correct parity. 88 */ 89 #ifndef ZSTTY_DEF_CFLAG 90 #define ZSTTY_DEF_CFLAG TTYDEF_CFLAG 91 #endif 92 93 /* 94 * How many input characters we can buffer. 95 * The port-specific var.h may override this. 96 * Note: must be a power of two! 97 */ 98 #ifndef ZSTTY_RING_SIZE 99 #define ZSTTY_RING_SIZE 2048 100 #endif 101 102 /* 103 * Make this an option variable one can patch. 104 * But be warned: this must be a power of 2! 105 */ 106 int zstty_rbuf_size = ZSTTY_RING_SIZE; 107 108 /* This should usually be 3/4 of ZSTTY_RING_SIZE */ 109 int zstty_rbuf_hiwat = (ZSTTY_RING_SIZE - (ZSTTY_RING_SIZE >> 2)); 110 111 struct zstty_softc { 112 struct device zst_dev; /* required first: base device */ 113 struct tty *zst_tty; 114 struct zs_chanstate *zst_cs; 115 116 int zst_hwflags; /* see z8530var.h */ 117 int zst_swflags; /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */ 118 119 /* 120 * Printing an overrun error message often takes long enough to 121 * cause another overrun, so we only print one per second. 122 */ 123 long zst_rotime; /* time of last ring overrun */ 124 long zst_fotime; /* time of last fifo overrun */ 125 126 /* 127 * The receive ring buffer. 128 */ 129 int zst_rbget; /* ring buffer `get' index */ 130 volatile int zst_rbput; /* ring buffer `put' index */ 131 int zst_ringmask; 132 int zst_rbhiwat; 133 134 u_short *zst_rbuf; /* rr1, data pairs */ 135 136 /* 137 * The transmit byte count and address are used for pseudo-DMA 138 * output in the hardware interrupt code. PDMA can be suspended 139 * to get pending changes done; heldtbc is used for this. It can 140 * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state. 141 */ 142 int zst_tbc; /* transmit byte count */ 143 caddr_t zst_tba; /* transmit buffer address */ 144 int zst_heldtbc; /* held tbc while xmission stopped */ 145 146 /* Flags to communicate with zstty_softint() */ 147 volatile char zst_rx_blocked; /* input block at ring */ 148 volatile char zst_rx_overrun; /* ring overrun */ 149 volatile char zst_tx_busy; /* working on an output chunk */ 150 volatile char zst_tx_done; /* done with one output chunk */ 151 volatile char zst_tx_stopped; /* H/W level stop (lost CTS) */ 152 volatile char zst_st_check; /* got a status interrupt */ 153 char pad[2]; 154 }; 155 156 157 /* Definition of the driver for autoconfig. */ 158 static int zstty_match(struct device *, void *, void *); 159 static void zstty_attach(struct device *, struct device *, void *); 160 161 struct cfattach zstty_ca = { 162 sizeof(struct zstty_softc), zstty_match, zstty_attach 163 }; 164 165 struct cfdriver zstty_cd = { 166 NULL, "zstty", DV_TTY 167 }; 168 169 struct zsops zsops_tty; 170 171 /* Routines called from other code. */ 172 cdev_decl(zs); /* open, close, read, write, ioctl, stop, ... */ 173 174 static void zsstart(struct tty *); 175 static int zsparam(struct tty *, struct termios *); 176 static void zs_modem(struct zstty_softc *zst, int onoff); 177 static int zshwiflow(struct tty *, int); 178 static void zs_hwiflow(struct zstty_softc *, int); 179 static void zstty_rxint(register struct zs_chanstate *); 180 static void zstty_txint(register struct zs_chanstate *); 181 static void zstty_stint(register struct zs_chanstate *); 182 static void zstty_softint(struct zs_chanstate *); 183 static void zsoverrun(struct zstty_softc *, long *, char *); 184 /* 185 * zstty_match: how is this zs channel configured? 186 */ 187 int 188 zstty_match(parent, match, aux) 189 struct device *parent; 190 void *match, *aux; 191 { 192 struct cfdata *cf = match; 193 struct zsc_attach_args *args = aux; 194 195 /* Exact match is better than wildcard. */ 196 if (cf->cf_loc[0] == args->channel) 197 return 2; 198 199 /* This driver accepts wildcard. */ 200 if (cf->cf_loc[0] == -1) 201 return 1; 202 203 return 0; 204 } 205 206 void 207 zstty_attach(parent, self, aux) 208 struct device *parent, *self; 209 void *aux; 210 211 { 212 struct zsc_softc *zsc = (void *) parent; 213 struct zstty_softc *zst = (void *) self; 214 struct zsc_attach_args *args = aux; 215 struct zs_chanstate *cs; 216 struct cfdata *cf; 217 struct tty *tp; 218 int channel, tty_unit; 219 dev_t dev; 220 221 cf = zst->zst_dev.dv_cfdata; 222 tty_unit = zst->zst_dev.dv_unit; 223 channel = args->channel; 224 cs = &zsc->zsc_cs[channel]; 225 cs->cs_private = zst; 226 cs->cs_ops = &zsops_tty; 227 228 zst->zst_cs = cs; 229 zst->zst_swflags = cf->cf_flags; /* softcar, etc. */ 230 zst->zst_hwflags = args->hwflags; 231 dev = makedev(ZSTTY_MAJOR, tty_unit); 232 233 if (zst->zst_swflags) 234 printf(" flags 0x%x", zst->zst_swflags); 235 236 if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE) 237 printf(": console"); 238 else { 239 #ifdef KGDB 240 /* 241 * Allow kgdb to "take over" this port. If this port is 242 * NOT the kgdb port, zs_check_kgdb() will return zero. 243 * If it IS the kgdb port, it will print "kgdb,...\n" 244 * and then return non-zero. 245 */ 246 if (zs_check_kgdb(cs, dev)) { 247 /* 248 * This is the kgdb port (exclusive use) 249 * so skip the normal attach code. 250 */ 251 return; 252 } 253 #endif 254 } 255 printf("\n"); 256 257 tp = ttymalloc(); 258 tp->t_dev = dev; 259 tp->t_oproc = zsstart; 260 tp->t_param = zsparam; 261 tp->t_hwiflow = zshwiflow; 262 263 zst->zst_tty = tp; 264 zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */ 265 zst->zst_ringmask = zstty_rbuf_size - 1; 266 zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]), 267 M_DEVBUF, M_WAITOK); 268 269 /* 270 * Hardware init 271 */ 272 if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE) { 273 /* This unit is the console. */ 274 zst->zst_swflags |= TIOCFLAG_SOFTCAR; 275 /* Call _param so interrupts get enabled. */ 276 cs->cs_defspeed = zs_getspeed(cs); 277 tp->t_ispeed = cs->cs_defspeed; 278 tp->t_ospeed = cs->cs_defspeed; 279 tp->t_cflag = ZSTTY_DEF_CFLAG; 280 (void) zsparam(tp, &tp->t_termios); 281 } else { 282 /* Not the console; may need reset. */ 283 int reset, s; 284 reset = (channel == 0) ? 285 ZSWR9_A_RESET : ZSWR9_B_RESET; 286 s = splzs(); 287 zs_write_reg(cs, 9, reset); 288 splx(s); 289 } 290 291 /* 292 * Initialize state of modem control lines (DTR). 293 * If softcar is set, turn on DTR now and leave it. 294 * otherwise, turn off DTR now, and raise in open. 295 * (Keeps modem from answering too early.) 296 */ 297 zs_modem(zst, (zst->zst_swflags & TIOCFLAG_SOFTCAR) ? 1 : 0); 298 } 299 300 301 /* 302 * Return pointer to our tty. 303 */ 304 struct tty * 305 zstty(dev) 306 dev_t dev; 307 { 308 struct zstty_softc *zst; 309 int unit = minor(dev); 310 311 #ifdef DIAGNOSTIC 312 if (unit >= zstty_cd.cd_ndevs) 313 panic("zstty"); 314 #endif 315 zst = zstty_cd.cd_devs[unit]; 316 return (zst->zst_tty); 317 } 318 319 320 /* 321 * Open a zs serial (tty) port. 322 */ 323 int 324 zsopen(dev, flags, mode, p) 325 dev_t dev; 326 int flags; 327 int mode; 328 struct proc *p; 329 { 330 register struct tty *tp; 331 register struct zs_chanstate *cs; 332 struct zstty_softc *zst; 333 int error, s, unit; 334 335 unit = minor(dev); 336 if (unit >= zstty_cd.cd_ndevs) 337 return (ENXIO); 338 zst = zstty_cd.cd_devs[unit]; 339 if (zst == NULL) 340 return (ENXIO); 341 tp = zst->zst_tty; 342 cs = zst->zst_cs; 343 344 /* If KGDB took the line, then tp==NULL */ 345 if (tp == NULL) 346 return (EBUSY); 347 348 /* It's simpler to do this up here. */ 349 if (((tp->t_state & (TS_ISOPEN | TS_XCLUDE)) 350 == (TS_ISOPEN | TS_XCLUDE)) 351 && (p->p_ucred->cr_uid != 0) ) 352 { 353 return (EBUSY); 354 } 355 356 s = spltty(); 357 358 if ((tp->t_state & TS_ISOPEN) == 0) { 359 /* First open. */ 360 ttychars(tp); 361 tp->t_iflag = TTYDEF_IFLAG; 362 tp->t_oflag = TTYDEF_OFLAG; 363 tp->t_cflag = ZSTTY_DEF_CFLAG; 364 if (zst->zst_swflags & TIOCFLAG_CLOCAL) 365 tp->t_cflag |= CLOCAL; 366 if (zst->zst_swflags & TIOCFLAG_CRTSCTS) 367 tp->t_cflag |= CRTSCTS; 368 if (zst->zst_swflags & TIOCFLAG_MDMBUF) 369 tp->t_cflag |= MDMBUF; 370 tp->t_lflag = TTYDEF_LFLAG; 371 tp->t_ispeed = tp->t_ospeed = cs->cs_defspeed; 372 (void) zsparam(tp, &tp->t_termios); 373 ttsetwater(tp); 374 /* Flush any pending input. */ 375 zst->zst_rbget = zst->zst_rbput; 376 zs_iflush(cs); /* XXX */ 377 /* Turn on DTR */ 378 zs_modem(zst, 1); 379 if (zst->zst_swflags & TIOCFLAG_SOFTCAR) { 380 tp->t_state |= TS_CARR_ON; 381 } 382 } 383 error = 0; 384 385 /* Wait for carrier. */ 386 for (;;) { 387 388 /* Might never get status intr if carrier already on. */ 389 cs->cs_rr0 = zs_read_csr(cs); 390 if (cs->cs_rr0 & ZSRR0_DCD) { 391 tp->t_state |= TS_CARR_ON; 392 break; 393 } 394 395 if ((tp->t_state & TS_CARR_ON) || 396 (tp->t_cflag & CLOCAL) || 397 (flags & O_NONBLOCK) ) 398 { 399 break; 400 } 401 402 tp->t_state |= TS_WOPEN; 403 error = ttysleep(tp, (caddr_t)&tp->t_rawq, 404 TTIPRI | PCATCH, ttopen, 0); 405 if (error) { 406 if ((tp->t_state & TS_ISOPEN) == 0) { 407 /* Never get here with softcar */ 408 zs_modem(zst, 0); 409 tp->t_state &= ~TS_WOPEN; 410 ttwakeup(tp); 411 } 412 break; 413 } 414 } 415 416 splx(s); 417 418 if (error == 0) 419 error = linesw[tp->t_line].l_open(dev, tp); 420 421 return (error); 422 } 423 424 /* 425 * Close a zs serial port. 426 */ 427 int 428 zsclose(dev, flags, mode, p) 429 dev_t dev; 430 int flags; 431 int mode; 432 struct proc *p; 433 { 434 struct zstty_softc *zst; 435 register struct zs_chanstate *cs; 436 register struct tty *tp; 437 int hup; 438 439 zst = zstty_cd.cd_devs[minor(dev)]; 440 cs = zst->zst_cs; 441 tp = zst->zst_tty; 442 443 /* XXX This is for cons.c. */ 444 if ((tp->t_state & TS_ISOPEN) == 0) 445 return 0; 446 447 (*linesw[tp->t_line].l_close)(tp, flags); 448 hup = tp->t_cflag & HUPCL; 449 if (zst->zst_swflags & TIOCFLAG_SOFTCAR) 450 hup = 0; 451 if (hup) { 452 zs_modem(zst, 0); 453 /* hold low for 1 second */ 454 (void) tsleep((caddr_t)cs, TTIPRI, ttclos, hz); 455 } 456 if (cs->cs_creg[5] & ZSWR5_BREAK) { 457 zs_break(cs, 0); 458 } 459 /* XXX - turn off interrupts? */ 460 461 ttyclose(tp); 462 return (0); 463 } 464 465 /* 466 * Read/write zs serial port. 467 */ 468 int 469 zsread(dev, uio, flags) 470 dev_t dev; 471 struct uio *uio; 472 int flags; 473 { 474 register struct zstty_softc *zst; 475 register struct tty *tp; 476 477 zst = zstty_cd.cd_devs[minor(dev)]; 478 tp = zst->zst_tty; 479 return (linesw[tp->t_line].l_read(tp, uio, flags)); 480 } 481 482 int 483 zswrite(dev, uio, flags) 484 dev_t dev; 485 struct uio *uio; 486 int flags; 487 { 488 register struct zstty_softc *zst; 489 register struct tty *tp; 490 491 zst = zstty_cd.cd_devs[minor(dev)]; 492 tp = zst->zst_tty; 493 return (linesw[tp->t_line].l_write(tp, uio, flags)); 494 } 495 496 #define TIOCFLAG_ALL (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | \ 497 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF ) 498 499 int 500 zsioctl(dev, cmd, data, flag, p) 501 dev_t dev; 502 u_long cmd; 503 caddr_t data; 504 int flag; 505 struct proc *p; 506 { 507 register struct zstty_softc *zst; 508 register struct zs_chanstate *cs; 509 register struct tty *tp; 510 register int error, tmp; 511 512 zst = zstty_cd.cd_devs[minor(dev)]; 513 cs = zst->zst_cs; 514 tp = zst->zst_tty; 515 516 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 517 if (error >= 0) 518 return (error); 519 error = ttioctl(tp, cmd, data, flag, p); 520 if (error >= 0) 521 return (error); 522 523 switch (cmd) { 524 525 case TIOCSBRK: 526 zs_break(cs, 1); 527 break; 528 529 case TIOCCBRK: 530 zs_break(cs, 0); 531 break; 532 533 case TIOCGFLAGS: 534 *(int *)data = zst->zst_swflags; 535 break; 536 537 case TIOCSFLAGS: 538 error = suser(p, 0); 539 if (error != 0) 540 return (EPERM); 541 tmp = *(int *)data; 542 /* Check for random bits... */ 543 if (tmp & ~TIOCFLAG_ALL) 544 return(EINVAL); 545 /* Silently enforce softcar on the console. */ 546 if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE) 547 tmp |= TIOCFLAG_SOFTCAR; 548 /* These flags take effect during open. */ 549 zst->zst_swflags = tmp; 550 break; 551 552 case TIOCSDTR: 553 zs_modem(zst, 1); 554 break; 555 556 case TIOCCDTR: 557 zs_modem(zst, 0); 558 break; 559 560 case TIOCMSET: 561 case TIOCMBIS: 562 case TIOCMBIC: 563 case TIOCMGET: 564 default: 565 return (ENOTTY); 566 } 567 return (0); 568 } 569 570 /* 571 * Start or restart transmission. 572 */ 573 static void 574 zsstart(tp) 575 register struct tty *tp; 576 { 577 register struct zstty_softc *zst; 578 register struct zs_chanstate *cs; 579 register int s, nch; 580 581 zst = zstty_cd.cd_devs[minor(tp->t_dev)]; 582 cs = zst->zst_cs; 583 584 s = spltty(); 585 586 /* 587 * If currently active or delaying, no need to do anything. 588 */ 589 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 590 goto out; 591 592 /* 593 * If under CRTSCTS hfc and halted, do nothing 594 */ 595 if (tp->t_cflag & CRTSCTS) 596 if (zst->zst_tx_stopped) 597 goto out; 598 599 /* 600 * If there are sleepers, and output has drained below low 601 * water mark, awaken. 602 */ 603 if (tp->t_outq.c_cc <= tp->t_lowat) { 604 if (tp->t_state & TS_ASLEEP) { 605 tp->t_state &= ~TS_ASLEEP; 606 wakeup((caddr_t)&tp->t_outq); 607 } 608 selwakeup(&tp->t_wsel); 609 } 610 611 nch = ndqb(&tp->t_outq, 0); /* XXX */ 612 (void) splzs(); 613 614 if (nch) { 615 register char *p = tp->t_outq.c_cf; 616 617 /* mark busy, enable tx done interrupts, & send first byte */ 618 tp->t_state |= TS_BUSY; 619 zst->zst_tx_busy = 1; 620 cs->cs_preg[1] |= ZSWR1_TIE; 621 cs->cs_creg[1] = cs->cs_preg[1]; 622 zs_write_reg(cs, 1, cs->cs_creg[1]); 623 zs_write_data(cs, *p); 624 zst->zst_tba = p + 1; 625 zst->zst_tbc = nch - 1; 626 } else { 627 /* 628 * Nothing to send, turn off transmit done interrupts. 629 * This is useful if something is doing polled output. 630 */ 631 cs->cs_preg[1] &= ~ZSWR1_TIE; 632 cs->cs_creg[1] = cs->cs_preg[1]; 633 zs_write_reg(cs, 1, cs->cs_creg[1]); 634 } 635 out: 636 splx(s); 637 } 638 639 /* 640 * Stop output, e.g., for ^S or output flush. 641 */ 642 int 643 zsstop(tp, flag) 644 struct tty *tp; 645 int flag; 646 { 647 register struct zstty_softc *zst; 648 register struct zs_chanstate *cs; 649 register int s; 650 651 zst = zstty_cd.cd_devs[minor(tp->t_dev)]; 652 cs = zst->zst_cs; 653 654 s = splzs(); 655 if (tp->t_state & TS_BUSY) { 656 /* 657 * Device is transmitting; must stop it. 658 * Also clear _heldtbc to prevent any 659 * flow-control event from resuming. 660 */ 661 zst->zst_tbc = 0; 662 zst->zst_heldtbc = 0; 663 if ((tp->t_state & TS_TTSTOP) == 0) 664 tp->t_state |= TS_FLUSH; 665 } 666 splx(s); 667 return (0); 668 } 669 670 /* 671 * Set ZS tty parameters from termios. 672 * XXX - Should just copy the whole termios after 673 * making sure all the changes could be done. 674 * XXX - Only whack the UART when params change... 675 */ 676 static int 677 zsparam(tp, t) 678 register struct tty *tp; 679 register struct termios *t; 680 { 681 register struct zstty_softc *zst; 682 register struct zs_chanstate *cs; 683 register int s, bps, cflag, tconst; 684 u_char tmp3, tmp4, tmp5; 685 686 zst = zstty_cd.cd_devs[minor(tp->t_dev)]; 687 cs = zst->zst_cs; 688 689 /* XXX: Need to use an MD function for this. */ 690 bps = t->c_ospeed; 691 if (bps < 0 || (t->c_ispeed && t->c_ispeed != bps)) 692 return (EINVAL); 693 if (bps == 0) { 694 /* stty 0 => drop DTR and RTS */ 695 zs_modem(zst, 0); 696 return (0); 697 } 698 tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps); 699 if (tconst < 0) 700 return (EINVAL); 701 702 /* Convert back to make sure we can do it. */ 703 bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst); 704 if (bps != t->c_ospeed) 705 return (EINVAL); 706 tp->t_ispeed = tp->t_ospeed = bps; 707 708 cflag = t->c_cflag; 709 tp->t_cflag = cflag; 710 711 /* 712 * Block interrupts so that state will not 713 * be altered until we are done setting it up. 714 */ 715 s = splzs(); 716 717 /* 718 * Initial values in cs_preg are set before 719 * our attach routine is called. The master 720 * interrupt enable is handled by zsc.c 721 */ 722 723 cs->cs_preg[12] = tconst; 724 cs->cs_preg[13] = tconst >> 8; 725 726 switch (cflag & CSIZE) { 727 case CS5: 728 tmp3 = ZSWR3_RX_5; 729 tmp5 = ZSWR5_TX_5; 730 break; 731 case CS6: 732 tmp3 = ZSWR3_RX_6; 733 tmp5 = ZSWR5_TX_6; 734 break; 735 case CS7: 736 tmp3 = ZSWR3_RX_7; 737 tmp5 = ZSWR5_TX_7; 738 break; 739 case CS8: 740 default: 741 tmp3 = ZSWR3_RX_8; 742 tmp5 = ZSWR5_TX_8; 743 break; 744 } 745 746 cs->cs_preg[3] = tmp3 | ZSWR3_RX_ENABLE; 747 cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS; 748 749 tmp4 = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB); 750 if ((cflag & PARODD) == 0) 751 tmp4 |= ZSWR4_EVENP; 752 if (cflag & PARENB) 753 tmp4 |= ZSWR4_PARENB; 754 cs->cs_preg[4] = tmp4; 755 756 /* 757 * Output hardware flow control on the chip is horrendous: 758 * if carrier detect drops, the receiver is disabled. 759 * Therefore, NEVER set the HFC bit, and instead use 760 * the status interrupts to detect CTS changes. 761 */ 762 if (cflag & CRTSCTS) { 763 zst->zst_rbhiwat = zstty_rbuf_hiwat; 764 cs->cs_preg[15] |= ZSWR15_CTS_IE; 765 } else { 766 zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */ 767 cs->cs_preg[15] &= ~ZSWR15_CTS_IE; 768 } 769 770 /* 771 * If nothing is being transmitted, set up new current values, 772 * else mark them as pending. 773 */ 774 if (cs->cs_heldchange == 0) { 775 if (zst->zst_tx_busy) { 776 zst->zst_heldtbc = zst->zst_tbc; 777 zst->zst_tbc = 0; 778 cs->cs_heldchange = 0xFF; /* XXX */ 779 } else { 780 zs_loadchannelregs(cs); 781 } 782 } 783 splx(s); 784 return (0); 785 } 786 787 /* 788 * Raise or lower modem control (DTR/RTS) signals. If a character is 789 * in transmission, the change is deferred. 790 */ 791 static void 792 zs_modem(zst, onoff) 793 struct zstty_softc *zst; 794 int onoff; 795 { 796 struct zs_chanstate *cs; 797 struct tty *tp; 798 int s, bis, and; 799 800 cs = zst->zst_cs; 801 tp = zst->zst_tty; 802 803 if (onoff) { 804 bis = ZSWR5_DTR | ZSWR5_RTS; 805 and = ~0; 806 } else { 807 bis = 0; 808 and = ~(ZSWR5_DTR | ZSWR5_RTS); 809 } 810 s = splzs(); 811 cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and; 812 if (cs->cs_heldchange == 0) { 813 if (zst->zst_tx_busy) { 814 zst->zst_heldtbc = zst->zst_tbc; 815 zst->zst_tbc = 0; 816 cs->cs_heldchange = (1<<5); 817 } else { 818 cs->cs_creg[5] = cs->cs_preg[5]; 819 zs_write_reg(cs, 5, cs->cs_creg[5]); 820 } 821 } 822 splx(s); 823 } 824 825 /* 826 * Try to block or unblock input using hardware flow-control. 827 * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and 828 * if this function returns non-zero, the TS_TBLOCK flag will 829 * be set or cleared according to the "stop" arg passed. 830 */ 831 int 832 zshwiflow(tp, stop) 833 struct tty *tp; 834 int stop; 835 { 836 register struct zstty_softc *zst; 837 int s; 838 839 zst = zstty_cd.cd_devs[minor(tp->t_dev)]; 840 841 s = splzs(); 842 if (stop) { 843 /* 844 * The tty layer is asking us to block input. 845 * If we already did it, just return TRUE. 846 */ 847 if (zst->zst_rx_blocked) 848 goto out; 849 zst->zst_rx_blocked = 1; 850 } else { 851 /* 852 * The tty layer is asking us to resume input. 853 * The input ring is always empty by now. 854 */ 855 zst->zst_rx_blocked = 0; 856 } 857 zs_hwiflow(zst, stop); 858 out: 859 splx(s); 860 return 1; 861 } 862 863 /* 864 * Internal version of zshwiflow 865 * called at splzs 866 */ 867 static void 868 zs_hwiflow(zst, stop) 869 register struct zstty_softc *zst; 870 int stop; 871 { 872 register struct zs_chanstate *cs; 873 register struct tty *tp; 874 register int bis, and; 875 876 cs = zst->zst_cs; 877 tp = zst->zst_tty; 878 879 if (stop) { 880 /* Block input (Lower RTS) */ 881 bis = 0; 882 and = ~ZSWR5_RTS; 883 } else { 884 /* Unblock input (Raise RTS) */ 885 bis = ZSWR5_RTS; 886 and = ~0; 887 } 888 889 cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and; 890 if (cs->cs_heldchange == 0) { 891 if (zst->zst_tx_busy) { 892 zst->zst_heldtbc = zst->zst_tbc; 893 zst->zst_tbc = 0; 894 cs->cs_heldchange = (1<<5); 895 } else { 896 cs->cs_creg[5] = cs->cs_preg[5]; 897 zs_write_reg(cs, 5, cs->cs_creg[5]); 898 } 899 } 900 } 901 902 903 /**************************************************************** 904 * Interface to the lower layer (zscc) 905 ****************************************************************/ 906 907 908 /* 909 * receiver ready interrupt. 910 * called at splzs 911 */ 912 static void 913 zstty_rxint(cs) 914 register struct zs_chanstate *cs; 915 { 916 register struct zstty_softc *zst; 917 register int cc, put, put_next, ringmask; 918 register u_char c, rr0, rr1; 919 register u_short ch_rr1; 920 921 zst = cs->cs_private; 922 put = zst->zst_rbput; 923 ringmask = zst->zst_ringmask; 924 925 nextchar: 926 927 /* 928 * First read the status, because reading the received char 929 * destroys the status of this char. 930 */ 931 rr1 = zs_read_reg(cs, 1); 932 c = zs_read_data(cs); 933 ch_rr1 = (c << 8) | rr1; 934 935 if (ch_rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { 936 /* Clear the receive error. */ 937 zs_write_csr(cs, ZSWR0_RESET_ERRORS); 938 } 939 940 /* XXX: Check for the stop character? */ 941 942 zst->zst_rbuf[put] = ch_rr1; 943 put_next = (put + 1) & ringmask; 944 945 /* Would overrun if increment makes (put==get). */ 946 if (put_next == zst->zst_rbget) { 947 zst->zst_rx_overrun = 1; 948 } else { 949 /* OK, really increment. */ 950 put = put_next; 951 } 952 953 /* Keep reading until the FIFO is empty. */ 954 rr0 = zs_read_csr(cs); 955 if (rr0 & ZSRR0_RX_READY) 956 goto nextchar; 957 958 /* Done reading. */ 959 zst->zst_rbput = put; 960 961 /* 962 * If ring is getting too full, try to block input. 963 */ 964 cc = put - zst->zst_rbget; 965 if (cc < 0) 966 cc += zstty_rbuf_size; 967 if ((cc > zst->zst_rbhiwat) && (zst->zst_rx_blocked == 0)) { 968 zst->zst_rx_blocked = 1; 969 zs_hwiflow(zst, 1); 970 } 971 972 /* Ask for softint() call. */ 973 cs->cs_softreq = 1; 974 } 975 976 /* 977 * transmitter ready interrupt. (splzs) 978 */ 979 static void 980 zstty_txint(cs) 981 register struct zs_chanstate *cs; 982 { 983 register struct zstty_softc *zst; 984 register int count; 985 986 zst = cs->cs_private; 987 988 /* 989 * If we suspended output for a "held" change, 990 * then handle that now and resume. 991 * Do flow-control changes ASAP. 992 * When the only change is for flow control, 993 * avoid hitting other registers, because that 994 * often makes the stupid zs drop input... 995 */ 996 if (cs->cs_heldchange) { 997 if (cs->cs_heldchange == (1<<5)) { 998 /* Avoid whacking the chip... */ 999 cs->cs_creg[5] = cs->cs_preg[5]; 1000 zs_write_reg(cs, 5, cs->cs_creg[5]); 1001 } else 1002 zs_loadchannelregs(cs); 1003 cs->cs_heldchange = 0; 1004 count = zst->zst_heldtbc; 1005 } else 1006 count = zst->zst_tbc; 1007 1008 /* 1009 * If our transmit buffer still has data, 1010 * just send the next character. 1011 */ 1012 if (count > 0) { 1013 /* Send the next char. */ 1014 zst->zst_tbc = --count; 1015 zs_write_data(cs, *zst->zst_tba); 1016 zst->zst_tba++; 1017 return; 1018 } 1019 1020 zs_write_csr(cs, ZSWR0_RESET_TXINT); 1021 1022 /* Ask the softint routine for more output. */ 1023 zst->zst_tx_busy = 0; 1024 zst->zst_tx_done = 1; 1025 cs->cs_softreq = 1; 1026 } 1027 1028 /* 1029 * status change interrupt. (splzs) 1030 */ 1031 static void 1032 zstty_stint(cs) 1033 register struct zs_chanstate *cs; 1034 { 1035 register struct zstty_softc *zst; 1036 register struct tty *tp; 1037 register u_char rr0; 1038 1039 zst = cs->cs_private; 1040 tp = zst->zst_tty; 1041 1042 rr0 = zs_read_csr(cs); 1043 zs_write_csr(cs, ZSWR0_RESET_STATUS); 1044 1045 /* 1046 * Check here for console break, so that we can abort 1047 * even when interrupts are locking up the machine. 1048 */ 1049 if ((rr0 & ZSRR0_BREAK) && 1050 (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)) 1051 { 1052 zs_abort(); 1053 return; 1054 } 1055 1056 /* 1057 * Need to handle CTS output flow control here. 1058 * Output remains stopped as long as either the 1059 * zst_tx_stopped or TS_TTSTOP flag is set. 1060 * Never restart here; the softint routine will 1061 * do that after things are ready to move. 1062 */ 1063 if (((rr0 & ZSRR0_CTS) == 0) && (tp->t_cflag & CRTSCTS)) { 1064 zst->zst_tbc = 0; 1065 zst->zst_heldtbc = 0; 1066 zst->zst_tx_stopped = 1; 1067 } 1068 1069 /* 1070 * We have to accumulate status line changes here. 1071 * Otherwise, if we get multiple status interrupts 1072 * before the softint runs, we could fail to notice 1073 * some status line changes in the softint routine. 1074 * Fix from Bill Studenmund, October 1996. 1075 */ 1076 cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0); 1077 1078 ttytstamp(tp, cs->cs_rr0 & ZSRR0_CTS, rr0 & ZSRR0_CTS, 1079 cs->cs_rr0 & ZSRR0_DCD, rr0 & ZSRR0_DCD); 1080 1081 cs->cs_rr0 = rr0; 1082 zst->zst_st_check = 1; 1083 1084 /* Ask for softint() call. */ 1085 cs->cs_softreq = 1; 1086 } 1087 1088 /* 1089 * Print out a ring or fifo overrun error message. 1090 */ 1091 static void 1092 zsoverrun(zst, ptime, what) 1093 struct zstty_softc *zst; 1094 long *ptime; 1095 char *what; 1096 { 1097 1098 if (*ptime != time_second) { 1099 *ptime = time_second; 1100 log(LOG_WARNING, "%s: %s overrun\n", 1101 zst->zst_dev.dv_xname, what); 1102 } 1103 } 1104 1105 /* 1106 * Software interrupt. Called at zssoft 1107 * 1108 * The main job to be done here is to empty the input ring 1109 * by passing its contents up to the tty layer. The ring is 1110 * always emptied during this operation, therefore the ring 1111 * must not be larger than the space after "high water" in 1112 * the tty layer, or the tty layer might drop our input. 1113 * 1114 * Note: an "input blockage" condition is assumed to exist if 1115 * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set. 1116 */ 1117 static void 1118 zstty_softint(cs) 1119 struct zs_chanstate *cs; 1120 { 1121 register struct zstty_softc *zst; 1122 register struct linesw *line; 1123 register struct tty *tp; 1124 register int get, c, s; 1125 int ringmask, overrun; 1126 register u_short ring_data; 1127 register u_char rr0, delta; 1128 1129 zst = cs->cs_private; 1130 tp = zst->zst_tty; 1131 line = &linesw[tp->t_line]; 1132 ringmask = zst->zst_ringmask; 1133 overrun = 0; 1134 1135 /* 1136 * Raise to tty priority while servicing the ring. 1137 */ 1138 s = spltty(); 1139 1140 if (zst->zst_rx_overrun) { 1141 zst->zst_rx_overrun = 0; 1142 zsoverrun(zst, &zst->zst_rotime, "ring"); 1143 } 1144 1145 /* 1146 * Copy data from the receive ring into the tty layer. 1147 */ 1148 get = zst->zst_rbget; 1149 while (get != zst->zst_rbput) { 1150 ring_data = zst->zst_rbuf[get]; 1151 get = (get + 1) & ringmask; 1152 1153 if (ring_data & ZSRR1_DO) 1154 overrun++; 1155 /* low byte of ring_data is rr1 */ 1156 c = (ring_data >> 8) & 0xff; 1157 if (ring_data & ZSRR1_FE) 1158 c |= TTY_FE; 1159 if (ring_data & ZSRR1_PE) 1160 c |= TTY_PE; 1161 1162 line->l_rint(c, tp); 1163 } 1164 zst->zst_rbget = get; 1165 1166 /* 1167 * If the overrun flag is set now, it was set while 1168 * copying char/status pairs from the ring, which 1169 * means this was a hardware (fifo) overrun. 1170 */ 1171 if (overrun) { 1172 zsoverrun(zst, &zst->zst_fotime, "fifo"); 1173 } 1174 1175 /* 1176 * We have emptied the input ring. Maybe unblock input. 1177 * Note: an "input blockage" condition is assumed to exist 1178 * when EITHER zst_rx_blocked or the TS_TBLOCK flag is set, 1179 * so unblock here ONLY if TS_TBLOCK has not been set. 1180 */ 1181 if (zst->zst_rx_blocked && ((tp->t_state & TS_TBLOCK) == 0)) { 1182 (void) splzs(); 1183 zst->zst_rx_blocked = 0; 1184 zs_hwiflow(zst, 0); /* unblock input */ 1185 (void) spltty(); 1186 } 1187 1188 /* 1189 * Do any deferred work for status interrupts. 1190 * The rr0 was saved in the h/w interrupt to 1191 * avoid another splzs in here. 1192 */ 1193 if (zst->zst_st_check) { 1194 zst->zst_st_check = 0; 1195 1196 rr0 = cs->cs_rr0; 1197 delta = cs->cs_rr0_delta; 1198 cs->cs_rr0_delta = 0; 1199 if (delta & ZSRR0_DCD) { 1200 c = ((rr0 & ZSRR0_DCD) != 0); 1201 if (line->l_modem(tp, c) == 0) 1202 zs_modem(zst, c); 1203 } 1204 if ((delta & ZSRR0_CTS) && (tp->t_cflag & CRTSCTS)) { 1205 /* 1206 * Only do restart here. Stop is handled 1207 * at the h/w interrupt level. 1208 */ 1209 if (rr0 & ZSRR0_CTS) { 1210 zst->zst_tx_stopped = 0; 1211 tp->t_state &= ~TS_TTSTOP; 1212 (*line->l_start)(tp); 1213 } 1214 } 1215 } 1216 1217 if (zst->zst_tx_done) { 1218 zst->zst_tx_done = 0; 1219 tp->t_state &= ~TS_BUSY; 1220 if (tp->t_state & TS_FLUSH) 1221 tp->t_state &= ~TS_FLUSH; 1222 else 1223 ndflush(&tp->t_outq, zst->zst_tba - 1224 (caddr_t) tp->t_outq.c_cf); 1225 line->l_start(tp); 1226 } 1227 1228 splx(s); 1229 } 1230 1231 struct zsops zsops_tty = { 1232 zstty_rxint, /* receive char available */ 1233 zstty_stint, /* external/status */ 1234 zstty_txint, /* xmit buffer empty */ 1235 zstty_softint, /* process software interrupt */ 1236 }; 1237 1238