z8530tty.c revision 1.55
1/* $NetBSD: z8530tty.c,v 1.55 1999/01/25 17:53:13 wrstuden Exp $ */ 2 3/*- 4 * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 5 * Charles M. Hannum. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Charles M. Hannum. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * Copyright (c) 1994 Gordon W. Ross 35 * Copyright (c) 1992, 1993 36 * The Regents of the University of California. All rights reserved. 37 * 38 * This software was developed by the Computer Systems Engineering group 39 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 40 * contributed to Berkeley. 41 * 42 * All advertising materials mentioning features or use of this software 43 * must display the following acknowledgement: 44 * This product includes software developed by the University of 45 * California, Lawrence Berkeley Laboratory. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by the University of 58 * California, Berkeley and its contributors. 59 * 4. Neither the name of the University nor the names of its contributors 60 * may be used to endorse or promote products derived from this software 61 * without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 * SUCH DAMAGE. 74 * 75 * @(#)zs.c 8.1 (Berkeley) 7/19/93 76 */ 77 78/* 79 * Zilog Z8530 Dual UART driver (tty interface) 80 * 81 * This is the "slave" driver that will be attached to 82 * the "zsc" driver for plain "tty" async. serial lines. 83 * 84 * Credits, history: 85 * 86 * The original version of this code was the sparc/dev/zs.c driver 87 * as distributed with the Berkeley 4.4 Lite release. Since then, 88 * Gordon Ross reorganized the code into the current parent/child 89 * driver scheme, separating the Sun keyboard and mouse support 90 * into independent child drivers. 91 * 92 * RTS/CTS flow-control support was a collaboration of: 93 * Gordon Ross <gwr@netbsd.org>, 94 * Bill Studenmund <wrstuden@loki.stanford.edu> 95 * Ian Dall <Ian.Dall@dsto.defence.gov.au> 96 */ 97 98#include <sys/param.h> 99#include <sys/systm.h> 100#include <sys/proc.h> 101#include <sys/device.h> 102#include <sys/conf.h> 103#include <sys/file.h> 104#include <sys/ioctl.h> 105#include <sys/malloc.h> 106#include <sys/tty.h> 107#include <sys/time.h> 108#include <sys/kernel.h> 109#include <sys/syslog.h> 110 111#include <dev/ic/z8530reg.h> 112#include <machine/z8530var.h> 113 114#include <dev/cons.h> 115 116#include "locators.h" 117 118/* 119 * How many input characters we can buffer. 120 * The port-specific var.h may override this. 121 * Note: must be a power of two! 122 */ 123#ifndef ZSTTY_RING_SIZE 124#define ZSTTY_RING_SIZE 2048 125#endif 126 127/* 128 * Make this an option variable one can patch. 129 * But be warned: this must be a power of 2! 130 */ 131u_int zstty_rbuf_size = ZSTTY_RING_SIZE; 132 133/* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 134u_int zstty_rbuf_hiwat = (ZSTTY_RING_SIZE * 1) / 4; 135u_int zstty_rbuf_lowat = (ZSTTY_RING_SIZE * 3) / 4; 136 137struct zstty_softc { 138 struct device zst_dev; /* required first: base device */ 139 struct tty *zst_tty; 140 struct zs_chanstate *zst_cs; 141 142 u_int zst_overflows, 143 zst_floods, 144 zst_errors; 145 146 int zst_hwflags, /* see z8530var.h */ 147 zst_swflags; /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */ 148 149 u_int zst_r_hiwat, 150 zst_r_lowat; 151 u_char *volatile zst_rbget, 152 *volatile zst_rbput; 153 volatile u_int zst_rbavail; 154 u_char *zst_rbuf, 155 *zst_ebuf; 156 157 /* 158 * The transmit byte count and address are used for pseudo-DMA 159 * output in the hardware interrupt code. PDMA can be suspended 160 * to get pending changes done; heldtbc is used for this. It can 161 * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state. 162 */ 163 u_char *zst_tba; /* transmit buffer address */ 164 u_int zst_tbc, /* transmit byte count */ 165 zst_heldtbc; /* held tbc while xmission stopped */ 166 167 /* Flags to communicate with zstty_softint() */ 168 volatile u_char zst_rx_flags, /* receiver blocked */ 169#define RX_TTY_BLOCKED 0x01 170#define RX_TTY_OVERFLOWED 0x02 171#define RX_IBUF_BLOCKED 0x04 172#define RX_IBUF_OVERFLOWED 0x08 173#define RX_ANY_BLOCK 0x0f 174 zst_tx_busy, /* working on an output chunk */ 175 zst_tx_done, /* done with one output chunk */ 176 zst_tx_stopped, /* H/W level stop (lost CTS) */ 177 zst_st_check, /* got a status interrupt */ 178 zst_rx_ready; 179}; 180 181/* Macros to clear/set/test flags. */ 182#define SET(t, f) (t) |= (f) 183#define CLR(t, f) (t) &= ~(f) 184#define ISSET(t, f) ((t) & (f)) 185 186/* Definition of the driver for autoconfig. */ 187static int zstty_match(struct device *, struct cfdata *, void *); 188static void zstty_attach(struct device *, struct device *, void *); 189 190struct cfattach zstty_ca = { 191 sizeof(struct zstty_softc), zstty_match, zstty_attach 192}; 193 194extern struct cfdriver zstty_cd; 195 196struct zsops zsops_tty; 197 198/* Routines called from other code. */ 199cdev_decl(zs); /* open, close, read, write, ioctl, stop, ... */ 200 201static void zs_shutdown __P((struct zstty_softc *)); 202static void zsstart __P((struct tty *)); 203static int zsparam __P((struct tty *, struct termios *)); 204static void zs_modem __P((struct zstty_softc *, int)); 205static void tiocm_to_zs __P((struct zstty_softc *, struct zs_chanstate *, 206 int, int)); 207static int zs_to_tiocm __P((struct zs_chanstate *)); 208static int zshwiflow __P((struct tty *, int)); 209static void zs_hwiflow __P((struct zstty_softc *)); 210 211#define ZSUNIT(x) (minor(x) & 0x7ffff) 212#define ZSDIALOUT(x) (minor(x) & 0x80000) 213 214/* 215 * zstty_match: how is this zs channel configured? 216 */ 217int 218zstty_match(parent, cf, aux) 219 struct device *parent; 220 struct cfdata *cf; 221 void *aux; 222{ 223 struct zsc_attach_args *args = aux; 224 225 /* Exact match is better than wildcard. */ 226 if (cf->cf_loc[ZSCCF_CHANNEL] == args->channel) 227 return 2; 228 229 /* This driver accepts wildcard. */ 230 if (cf->cf_loc[ZSCCF_CHANNEL] == ZSCCF_CHANNEL_DEFAULT) 231 return 1; 232 233 return 0; 234} 235 236void 237zstty_attach(parent, self, aux) 238 struct device *parent, *self; 239 void *aux; 240 241{ 242 struct zsc_softc *zsc = (void *) parent; 243 struct zstty_softc *zst = (void *) self; 244 struct cfdata *cf = self->dv_cfdata; 245 struct zsc_attach_args *args = aux; 246 struct zs_chanstate *cs; 247 struct tty *tp; 248 int channel, s, tty_unit; 249 dev_t dev; 250 251 tty_unit = zst->zst_dev.dv_unit; 252 channel = args->channel; 253 cs = zsc->zsc_cs[channel]; 254 cs->cs_private = zst; 255 cs->cs_ops = &zsops_tty; 256 257 zst->zst_cs = cs; 258 zst->zst_swflags = cf->cf_flags; /* softcar, etc. */ 259 zst->zst_hwflags = args->hwflags; 260 dev = makedev(zs_major, tty_unit); 261 262 if (zst->zst_swflags) 263 printf(" flags 0x%x", zst->zst_swflags); 264 265 if (ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) { 266 printf(" (console)"); 267 cn_tab->cn_dev = dev; 268 } else { 269#ifdef KGDB 270 /* 271 * Allow kgdb to "take over" this port. Returns true 272 * if this serial port is in-use by kgdb. 273 */ 274 if (zs_check_kgdb(cs, dev)) { 275 printf(" (kgdb)\n"); 276 /* 277 * This is the kgdb port (exclusive use) 278 * so skip the normal attach code. 279 */ 280 return; 281 } 282#endif 283 } 284 printf("\n"); 285 286 tp = ttymalloc(); 287 tp->t_dev = dev; 288 tp->t_oproc = zsstart; 289 tp->t_param = zsparam; 290 tp->t_hwiflow = zshwiflow; 291 tty_attach(tp); 292 293 zst->zst_tty = tp; 294 zst->zst_rbuf = malloc(zstty_rbuf_size << 1, M_DEVBUF, M_WAITOK); 295 zst->zst_ebuf = zst->zst_rbuf + (zstty_rbuf_size << 1); 296 /* Disable the high water mark. */ 297 zst->zst_r_hiwat = 0; 298 zst->zst_r_lowat = 0; 299 zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf; 300 zst->zst_rbavail = zstty_rbuf_size; 301 302 /* XXX - Do we need an MD hook here? */ 303 304 /* 305 * Hardware init 306 */ 307 if (ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) { 308 /* Call zsparam similar to open. */ 309 struct termios t; 310 311 DELAY(20000); 312 313 s = splzs(); 314 315 /* Fetch the current modem control status, needed later. */ 316 cs->cs_rr0 = zs_read_csr(cs); 317 318 splx(s); 319 320 /* Setup the "new" parameters in t. */ 321 t.c_ispeed = 0; 322 t.c_ospeed = cs->cs_defspeed; 323 t.c_cflag = cs->cs_defcflag; 324 /* Make sure zsparam will see changes. */ 325 tp->t_ospeed = 0; 326 327 /* Turn on interrupts when zsparam writes the chip. */ 328 cs->cs_creg[1] = cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE; 329 330 (void) zsparam(tp, &t); 331 332 s = splzs(); 333 334 /* Make sure DTR is on now. */ 335 zs_modem(zst, 1); 336 337 splx(s); 338 } else { 339 /* Not the console; may need reset. */ 340 int reset; 341 342 reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; 343 344 s = splzs(); 345 346 zs_write_reg(cs, 9, reset); 347 348 /* Will raise DTR in open. */ 349 zs_modem(zst, 0); 350 351 splx(s); 352 } 353} 354 355 356/* 357 * Return pointer to our tty. 358 */ 359struct tty * 360zstty(dev) 361 dev_t dev; 362{ 363 struct zstty_softc *zst; 364 int unit = ZSUNIT(dev); 365 366#ifdef DIAGNOSTIC 367 if (unit >= zstty_cd.cd_ndevs) 368 panic("zstty"); 369#endif 370 zst = zstty_cd.cd_devs[unit]; 371 return (zst->zst_tty); 372} 373 374 375void 376zs_shutdown(zst) 377 struct zstty_softc *zst; 378{ 379 struct zs_chanstate *cs = zst->zst_cs; 380 struct tty *tp = zst->zst_tty; 381 int s; 382 383 s = splzs(); 384 385 /* If we were asserting flow control, then deassert it. */ 386 SET(zst->zst_rx_flags, RX_IBUF_BLOCKED); 387 zs_hwiflow(zst); 388 389 /* Clear any break condition set with TIOCSBRK. */ 390 zs_break(cs, 0); 391 392 /* 393 * Hang up if necessary. Wait a bit, so the other side has time to 394 * notice even if we immediately open the port again. 395 */ 396 if (ISSET(tp->t_cflag, HUPCL)) { 397 zs_modem(zst, 0); 398 (void) tsleep(cs, TTIPRI, ttclos, hz); 399 } 400 401 /* Turn off interrupts if not the console. */ 402 if (ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) 403 cs->cs_creg[1] = cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE; 404 else 405 cs->cs_creg[1] = cs->cs_preg[1] = 0; 406 zs_write_reg(cs, 1, cs->cs_creg[1]); 407 408 splx(s); 409} 410 411/* 412 * Open a zs serial (tty) port. 413 */ 414int 415zsopen(dev, flags, mode, p) 416 dev_t dev; 417 int flags; 418 int mode; 419 struct proc *p; 420{ 421 int unit = ZSUNIT(dev); 422 struct zstty_softc *zst; 423 struct zs_chanstate *cs; 424 struct tty *tp; 425 int s, s2; 426 int error; 427 428 if (unit >= zstty_cd.cd_ndevs) 429 return (ENXIO); 430 zst = zstty_cd.cd_devs[unit]; 431 if (zst == 0) 432 return (ENXIO); 433 tp = zst->zst_tty; 434 cs = zst->zst_cs; 435 436 /* If KGDB took the line, then tp==NULL */ 437 if (tp == NULL) 438 return (EBUSY); 439 440 if (ISSET(tp->t_state, TS_ISOPEN) && 441 ISSET(tp->t_state, TS_XCLUDE) && 442 p->p_ucred->cr_uid != 0) 443 return (EBUSY); 444 445 s = spltty(); 446 447 /* 448 * Do the following iff this is a first open. 449 */ 450 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 451 struct termios t; 452 453 tp->t_dev = dev; 454 455 s2 = splzs(); 456 457 /* Turn on interrupts. */ 458 cs->cs_creg[1] = cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE; 459 zs_write_reg(cs, 1, cs->cs_creg[1]); 460 461 /* Fetch the current modem control status, needed later. */ 462 cs->cs_rr0 = zs_read_csr(cs); 463 464 splx(s2); 465 466 /* 467 * Initialize the termios status to the defaults. Add in the 468 * sticky bits from TIOCSFLAGS. 469 */ 470 t.c_ispeed = 0; 471 t.c_ospeed = cs->cs_defspeed; 472 t.c_cflag = cs->cs_defcflag; 473 if (ISSET(zst->zst_swflags, TIOCFLAG_CLOCAL)) 474 SET(t.c_cflag, CLOCAL); 475 if (ISSET(zst->zst_swflags, TIOCFLAG_CRTSCTS)) 476 SET(t.c_cflag, CRTSCTS); 477 if (ISSET(zst->zst_swflags, TIOCFLAG_CDTRCTS)) 478 SET(t.c_cflag, CDTRCTS); 479 if (ISSET(zst->zst_swflags, TIOCFLAG_MDMBUF)) 480 SET(t.c_cflag, MDMBUF); 481 /* Make sure zsparam will see changes. */ 482 tp->t_ospeed = 0; 483 (void) zsparam(tp, &t); 484 /* 485 * Note: zsparam has done: cflag, ispeed, ospeed 486 * so we just need to do: iflag, oflag, lflag, cc 487 * For "raw" mode, just leave all zeros. 488 */ 489 if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_RAW)) { 490 tp->t_iflag = TTYDEF_IFLAG; 491 tp->t_oflag = TTYDEF_OFLAG; 492 tp->t_lflag = TTYDEF_LFLAG; 493 } else { 494 tp->t_iflag = 0; 495 tp->t_oflag = 0; 496 tp->t_lflag = 0; 497 } 498 ttychars(tp); 499 ttsetwater(tp); 500 501 s2 = splzs(); 502 503 /* 504 * Turn on DTR. We must always do this, even if carrier is not 505 * present, because otherwise we'd have to use TIOCSDTR 506 * immediately after setting CLOCAL, which applications do not 507 * expect. We always assert DTR while the device is open 508 * unless explicitly requested to deassert it. 509 */ 510 zs_modem(zst, 1); 511 512 /* Clear the input ring, and unblock. */ 513 zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf; 514 zst->zst_rbavail = zstty_rbuf_size; 515 zs_iflush(cs); 516 CLR(zst->zst_rx_flags, RX_ANY_BLOCK); 517 zs_hwiflow(zst); 518 519 splx(s2); 520 } 521 522 splx(s); 523 524 error = ttyopen(tp, ZSDIALOUT(dev), ISSET(flags, O_NONBLOCK)); 525 if (error) 526 goto bad; 527 528 error = (*linesw[tp->t_line].l_open)(dev, tp); 529 if (error) 530 goto bad; 531 532 return (0); 533 534bad: 535 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 536 /* 537 * We failed to open the device, and nobody else had it opened. 538 * Clean up the state as appropriate. 539 */ 540 zs_shutdown(zst); 541 } 542 543 return (error); 544} 545 546/* 547 * Close a zs serial port. 548 */ 549int 550zsclose(dev, flags, mode, p) 551 dev_t dev; 552 int flags; 553 int mode; 554 struct proc *p; 555{ 556 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(dev)]; 557 struct tty *tp = zst->zst_tty; 558 559 /* XXX This is for cons.c. */ 560 if (!ISSET(tp->t_state, TS_ISOPEN)) 561 return 0; 562 563 (*linesw[tp->t_line].l_close)(tp, flags); 564 ttyclose(tp); 565 566 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 567 /* 568 * Although we got a last close, the device may still be in 569 * use; e.g. if this was the dialout node, and there are still 570 * processes waiting for carrier on the non-dialout node. 571 */ 572 zs_shutdown(zst); 573 } 574 575 return (0); 576} 577 578/* 579 * Read/write zs serial port. 580 */ 581int 582zsread(dev, uio, flags) 583 dev_t dev; 584 struct uio *uio; 585 int flags; 586{ 587 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(dev)]; 588 struct tty *tp = zst->zst_tty; 589 590 return ((*linesw[tp->t_line].l_read)(tp, uio, flags)); 591} 592 593int 594zswrite(dev, uio, flags) 595 dev_t dev; 596 struct uio *uio; 597 int flags; 598{ 599 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(dev)]; 600 struct tty *tp = zst->zst_tty; 601 602 return ((*linesw[tp->t_line].l_write)(tp, uio, flags)); 603} 604 605int 606zsioctl(dev, cmd, data, flag, p) 607 dev_t dev; 608 u_long cmd; 609 caddr_t data; 610 int flag; 611 struct proc *p; 612{ 613 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(dev)]; 614 struct zs_chanstate *cs = zst->zst_cs; 615 struct tty *tp = zst->zst_tty; 616 int error; 617 int s; 618 619 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 620 if (error >= 0) 621 return (error); 622 623 error = ttioctl(tp, cmd, data, flag, p); 624 if (error >= 0) 625 return (error); 626 627#ifdef ZS_MD_IOCTL 628 error = ZS_MD_IOCTL; 629 if (error >= 0) 630 return (error); 631#endif /* ZS_MD_IOCTL */ 632 633 error = 0; 634 635 s = splzs(); 636 637 switch (cmd) { 638 case TIOCSBRK: 639 zs_break(cs, 1); 640 break; 641 642 case TIOCCBRK: 643 zs_break(cs, 0); 644 break; 645 646 case TIOCGFLAGS: 647 *(int *)data = zst->zst_swflags; 648 break; 649 650 case TIOCSFLAGS: 651 error = suser(p->p_ucred, &p->p_acflag); 652 if (error) 653 break; 654 zst->zst_swflags = *(int *)data; 655 break; 656 657 case TIOCSDTR: 658 zs_modem(zst, 1); 659 break; 660 661 case TIOCCDTR: 662 zs_modem(zst, 0); 663 break; 664 665 case TIOCMSET: 666 case TIOCMBIS: 667 case TIOCMBIC: 668 tiocm_to_zs(zst, cs, cmd, *(int *)data); 669 break; 670 671 case TIOCMGET: 672 *(int *)data = zs_to_tiocm(cs); 673 break; 674 675 default: 676 error = ENOTTY; 677 break; 678 } 679 680 splx(s); 681 682 return (error); 683} 684 685/* 686 * Start or restart transmission. 687 */ 688static void 689zsstart(tp) 690 struct tty *tp; 691{ 692 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(tp->t_dev)]; 693 struct zs_chanstate *cs = zst->zst_cs; 694 int s; 695 696 s = spltty(); 697 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 698 goto out; 699 if (zst->zst_tx_stopped) 700 goto out; 701 702 if (tp->t_outq.c_cc <= tp->t_lowat) { 703 if (ISSET(tp->t_state, TS_ASLEEP)) { 704 CLR(tp->t_state, TS_ASLEEP); 705 wakeup((caddr_t)&tp->t_outq); 706 } 707 selwakeup(&tp->t_wsel); 708 if (tp->t_outq.c_cc == 0) 709 goto out; 710 } 711 712 /* Grab the first contiguous region of buffer space. */ 713 { 714 u_char *tba; 715 int tbc; 716 717 tba = tp->t_outq.c_cf; 718 tbc = ndqb(&tp->t_outq, 0); 719 720 (void) splzs(); 721 722 zst->zst_tba = tba; 723 zst->zst_tbc = tbc; 724 } 725 726 SET(tp->t_state, TS_BUSY); 727 zst->zst_tx_busy = 1; 728 729 /* Enable transmit completion interrupts if necessary. */ 730 if (!ISSET(cs->cs_preg[1], ZSWR1_TIE)) { 731 SET(cs->cs_preg[1], ZSWR1_TIE); 732 cs->cs_creg[1] = cs->cs_preg[1]; 733 zs_write_reg(cs, 1, cs->cs_creg[1]); 734 } 735 736 /* Output the first character of the contiguous buffer. */ 737 { 738 zs_write_data(cs, *zst->zst_tba); 739 zst->zst_tbc--; 740 zst->zst_tba++; 741 } 742out: 743 splx(s); 744 return; 745} 746 747/* 748 * Stop output, e.g., for ^S or output flush. 749 */ 750void 751zsstop(tp, flag) 752 struct tty *tp; 753 int flag; 754{ 755 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(tp->t_dev)]; 756 int s; 757 758 s = splzs(); 759 if (ISSET(tp->t_state, TS_BUSY)) { 760 /* Stop transmitting at the next chunk. */ 761 zst->zst_tbc = 0; 762 zst->zst_heldtbc = 0; 763 if (!ISSET(tp->t_state, TS_TTSTOP)) 764 SET(tp->t_state, TS_FLUSH); 765 } 766 splx(s); 767} 768 769/* 770 * Set ZS tty parameters from termios. 771 * XXX - Should just copy the whole termios after 772 * making sure all the changes could be done. 773 */ 774static int 775zsparam(tp, t) 776 struct tty *tp; 777 struct termios *t; 778{ 779 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(tp->t_dev)]; 780 struct zs_chanstate *cs = zst->zst_cs; 781 int ospeed, cflag; 782 u_char tmp3, tmp4, tmp5, tmp15; 783 int s, error; 784 785 ospeed = t->c_ospeed; 786 cflag = t->c_cflag; 787 788 /* Check requested parameters. */ 789 if (ospeed < 0) 790 return (EINVAL); 791 if (t->c_ispeed && t->c_ispeed != ospeed) 792 return (EINVAL); 793 794 /* 795 * For the console, always force CLOCAL and !HUPCL, so that the port 796 * is always active. 797 */ 798 if (ISSET(zst->zst_swflags, TIOCFLAG_SOFTCAR) || 799 ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) { 800 SET(cflag, CLOCAL); 801 CLR(cflag, HUPCL); 802 } 803 804 /* 805 * Only whack the UART when params change. 806 * Some callers need to clear tp->t_ospeed 807 * to make sure initialization gets done. 808 */ 809 if (tp->t_ospeed == ospeed && 810 tp->t_cflag == cflag) 811 return (0); 812 813 /* 814 * Call MD functions to deal with changed 815 * clock modes or H/W flow control modes. 816 * The BRG divisor is set now. (reg 12,13) 817 */ 818 error = zs_set_speed(cs, ospeed); 819 if (error) 820 return (error); 821 error = zs_set_modes(cs, cflag); 822 if (error) 823 return (error); 824 825 /* 826 * Block interrupts so that state will not 827 * be altered until we are done setting it up. 828 * 829 * Initial values in cs_preg are set before 830 * our attach routine is called. The master 831 * interrupt enable is handled by zsc.c 832 * 833 */ 834 s = splzs(); 835 836 cs->cs_rr0_mask = cs->cs_rr0_cts | cs->cs_rr0_dcd; 837 tmp15 = cs->cs_preg[15]; 838#if 1 839 if (ISSET(cs->cs_rr0_mask, ZSRR0_DCD)) 840 SET(tmp15, ZSWR15_DCD_IE); 841 else 842 CLR(tmp15, ZSWR15_DCD_IE); 843 if (ISSET(cs->cs_rr0_mask, ZSRR0_CTS)) 844 SET(tmp15, ZSWR15_CTS_IE); 845 else 846 CLR(tmp15, ZSWR15_CTS_IE); 847#else 848 SET(tmp15, ZSWR15_DCD_IE | ZSWR15_CTS_IE); 849#endif 850 cs->cs_preg[15] = tmp15; 851 852 /* Recompute character size bits. */ 853 tmp3 = cs->cs_preg[3]; 854 tmp5 = cs->cs_preg[5]; 855 CLR(tmp3, ZSWR3_RXSIZE); 856 CLR(tmp5, ZSWR5_TXSIZE); 857 switch (ISSET(cflag, CSIZE)) { 858 case CS5: 859 SET(tmp3, ZSWR3_RX_5); 860 SET(tmp5, ZSWR5_TX_5); 861 break; 862 case CS6: 863 SET(tmp3, ZSWR3_RX_6); 864 SET(tmp5, ZSWR5_TX_6); 865 break; 866 case CS7: 867 SET(tmp3, ZSWR3_RX_7); 868 SET(tmp5, ZSWR5_TX_7); 869 break; 870 case CS8: 871 SET(tmp3, ZSWR3_RX_8); 872 SET(tmp5, ZSWR5_TX_8); 873 break; 874 } 875 cs->cs_preg[3] = tmp3; 876 cs->cs_preg[5] = tmp5; 877 878 /* 879 * Recompute the stop bits and parity bits. Note that 880 * zs_set_speed() may have set clock selection bits etc. 881 * in wr4, so those must preserved. 882 */ 883 tmp4 = cs->cs_preg[4]; 884 CLR(tmp4, ZSWR4_SBMASK | ZSWR4_PARMASK); 885 if (ISSET(cflag, CSTOPB)) 886 SET(tmp4, ZSWR4_TWOSB); 887 else 888 SET(tmp4, ZSWR4_ONESB); 889 if (!ISSET(cflag, PARODD)) 890 SET(tmp4, ZSWR4_EVENP); 891 if (ISSET(cflag, PARENB)) 892 SET(tmp4, ZSWR4_PARENB); 893 cs->cs_preg[4] = tmp4; 894 895 /* And copy to tty. */ 896 tp->t_ispeed = 0; 897 tp->t_ospeed = ospeed; 898 tp->t_cflag = cflag; 899 900 /* 901 * If nothing is being transmitted, set up new current values, 902 * else mark them as pending. 903 */ 904 if (!cs->cs_heldchange) { 905 if (zst->zst_tx_busy) { 906 zst->zst_heldtbc = zst->zst_tbc; 907 zst->zst_tbc = 0; 908 cs->cs_heldchange = 1; 909 } else 910 zs_loadchannelregs(cs); 911 } 912 913 if (!ISSET(cflag, CHWFLOW)) { 914 /* Disable the high water mark. */ 915 zst->zst_r_hiwat = 0; 916 zst->zst_r_lowat = 0; 917 if (ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) { 918 CLR(zst->zst_rx_flags, RX_TTY_OVERFLOWED); 919 zst->zst_rx_ready = 1; 920 cs->cs_softreq = 1; 921 } 922 if (ISSET(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 923 CLR(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 924 zs_hwiflow(zst); 925 } 926 } else { 927 zst->zst_r_hiwat = zstty_rbuf_hiwat; 928 zst->zst_r_lowat = zstty_rbuf_lowat; 929 } 930 931 splx(s); 932 933 /* 934 * Update the tty layer's idea of the carrier bit, in case we changed 935 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 936 * explicit request. 937 */ 938 (void) (*linesw[tp->t_line].l_modem)(tp, 939 ISSET(cs->cs_rr0, ZSRR0_DCD)); 940 941 if (!ISSET(cflag, CHWFLOW)) { 942 if (zst->zst_tx_stopped) { 943 zst->zst_tx_stopped = 0; 944 zsstart(tp); 945 } 946 } 947 948 return (0); 949} 950 951/* 952 * Raise or lower modem control (DTR/RTS) signals. If a character is 953 * in transmission, the change is deferred. 954 */ 955static void 956zs_modem(zst, onoff) 957 struct zstty_softc *zst; 958 int onoff; 959{ 960 struct zs_chanstate *cs = zst->zst_cs; 961 962 if (cs->cs_wr5_dtr == 0) 963 return; 964 965 if (onoff) 966 SET(cs->cs_preg[5], cs->cs_wr5_dtr); 967 else 968 CLR(cs->cs_preg[5], cs->cs_wr5_dtr); 969 970 if (!cs->cs_heldchange) { 971 if (zst->zst_tx_busy) { 972 zst->zst_heldtbc = zst->zst_tbc; 973 zst->zst_tbc = 0; 974 cs->cs_heldchange = 1; 975 } else 976 zs_loadchannelregs(cs); 977 } 978} 979 980static void 981tiocm_to_zs(zst, cs, how, val) 982 struct zstty_softc *zst; 983 struct zs_chanstate *cs; 984 int how, val; 985{ 986 int bits = 0, s; 987 988 if (val & TIOCM_DTR); 989 bits |= ZSWR5_DTR; 990 if (val & TIOCM_RTS) 991 bits |= ZSWR5_RTS; 992 993 s = splzs(); 994 995 switch (how) { 996 case TIOCMBIC: 997 cs->cs_preg[5] &= ~bits; 998 break; 999 1000 case TIOCMBIS: 1001 cs->cs_preg[5] |= bits; 1002 break; 1003 1004 case TIOCMSET: 1005 cs->cs_preg[5] &= ~(ZSWR5_RTS | ZSWR5_DTR); 1006 cs->cs_preg[5] |= bits; 1007 break; 1008 default: 1009 panic("zs: bad command"); 1010 break; 1011 } 1012 1013 if (!cs->cs_heldchange) { 1014 if (zst->zst_tx_busy) { 1015 zst->zst_heldtbc = zst->zst_tbc; 1016 zst->zst_tbc = 0; 1017 cs->cs_heldchange = 1; 1018 } else { 1019 cs->cs_creg[5] = cs->cs_preg[5]; 1020 zs_write_reg(cs, 5, cs->cs_creg[5]); 1021 } 1022 } 1023 1024 splx(s); 1025} 1026 1027static int 1028zs_to_tiocm(cs) 1029 struct zs_chanstate *cs; 1030{ 1031 int bits = 0; 1032 u_char m = zs_read_csr(cs); 1033 1034 if (cs->cs_preg[5] & ZSWR5_DTR) 1035 bits |= TIOCM_DTR; 1036 if (cs->cs_preg[5] & ZSWR5_RTS) 1037 bits |= TIOCM_RTS; 1038 1039 if (m & ZSRR0_DCD) 1040 bits |= TIOCM_CD; 1041 if (m & ZSRR0_CTS) 1042 bits |= TIOCM_CTS; 1043 1044 return bits; 1045} 1046 1047/* 1048 * Try to block or unblock input using hardware flow-control. 1049 * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and 1050 * if this function returns non-zero, the TS_TBLOCK flag will 1051 * be set or cleared according to the "block" arg passed. 1052 */ 1053int 1054zshwiflow(tp, block) 1055 struct tty *tp; 1056 int block; 1057{ 1058 struct zstty_softc *zst = zstty_cd.cd_devs[ZSUNIT(tp->t_dev)]; 1059 struct zs_chanstate *cs = zst->zst_cs; 1060 int s; 1061 1062 if (cs->cs_wr5_rts == 0) 1063 return (0); 1064 1065 s = splzs(); 1066 if (block) { 1067 if (!ISSET(zst->zst_rx_flags, RX_TTY_BLOCKED)) { 1068 SET(zst->zst_rx_flags, RX_TTY_BLOCKED); 1069 zs_hwiflow(zst); 1070 } 1071 } else { 1072 if (ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) { 1073 CLR(zst->zst_rx_flags, RX_TTY_OVERFLOWED); 1074 zst->zst_rx_ready = 1; 1075 cs->cs_softreq = 1; 1076 } 1077 if (ISSET(zst->zst_rx_flags, RX_TTY_BLOCKED)) { 1078 CLR(zst->zst_rx_flags, RX_TTY_BLOCKED); 1079 zs_hwiflow(zst); 1080 } 1081 } 1082 splx(s); 1083 return (1); 1084} 1085 1086/* 1087 * Internal version of zshwiflow 1088 * called at splzs 1089 */ 1090static void 1091zs_hwiflow(zst) 1092 struct zstty_softc *zst; 1093{ 1094 struct zs_chanstate *cs = zst->zst_cs; 1095 1096 if (cs->cs_wr5_rts == 0) 1097 return; 1098 1099 if (ISSET(zst->zst_rx_flags, RX_ANY_BLOCK)) { 1100 CLR(cs->cs_preg[5], cs->cs_wr5_rts); 1101 CLR(cs->cs_creg[5], cs->cs_wr5_rts); 1102 } else { 1103 SET(cs->cs_preg[5], cs->cs_wr5_rts); 1104 SET(cs->cs_creg[5], cs->cs_wr5_rts); 1105 } 1106 zs_write_reg(cs, 5, cs->cs_creg[5]); 1107} 1108 1109 1110/**************************************************************** 1111 * Interface to the lower layer (zscc) 1112 ****************************************************************/ 1113 1114static void zstty_rxint __P((struct zs_chanstate *)); 1115static void zstty_txint __P((struct zs_chanstate *)); 1116static void zstty_stint __P((struct zs_chanstate *)); 1117 1118#define integrate static inline 1119static void zstty_softint __P((struct zs_chanstate *)); 1120integrate void zstty_rxsoft __P((struct zstty_softc *, struct tty *)); 1121integrate void zstty_txsoft __P((struct zstty_softc *, struct tty *)); 1122integrate void zstty_stsoft __P((struct zstty_softc *, struct tty *)); 1123static void zstty_diag __P((void *)); 1124 1125/* 1126 * receiver ready interrupt. 1127 * called at splzs 1128 */ 1129static void 1130zstty_rxint(cs) 1131 struct zs_chanstate *cs; 1132{ 1133 struct zstty_softc *zst = cs->cs_private; 1134 u_char *put, *end; 1135 u_int cc; 1136 u_char rr0, rr1, c; 1137 1138 end = zst->zst_ebuf; 1139 put = zst->zst_rbput; 1140 cc = zst->zst_rbavail; 1141 1142 while (cc > 0) { 1143 /* 1144 * First read the status, because reading the received char 1145 * destroys the status of this char. 1146 */ 1147 rr1 = zs_read_reg(cs, 1); 1148 c = zs_read_data(cs); 1149 1150 if (ISSET(rr1, ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { 1151 /* Clear the receive error. */ 1152 zs_write_csr(cs, ZSWR0_RESET_ERRORS); 1153 } 1154 1155 put[0] = c; 1156 put[1] = rr1; 1157 put += 2; 1158 if (put >= end) 1159 put = zst->zst_rbuf; 1160 cc--; 1161 1162 rr0 = zs_read_csr(cs); 1163 if (!ISSET(rr0, ZSRR0_RX_READY)) 1164 break; 1165 } 1166 1167 /* 1168 * Current string of incoming characters ended because 1169 * no more data was available or we ran out of space. 1170 * Schedule a receive event if any data was received. 1171 * If we're out of space, turn off receive interrupts. 1172 */ 1173 zst->zst_rbput = put; 1174 zst->zst_rbavail = cc; 1175 if (!ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) { 1176 zst->zst_rx_ready = 1; 1177 cs->cs_softreq = 1; 1178 } 1179 1180 /* 1181 * See if we are in danger of overflowing a buffer. If 1182 * so, use hardware flow control to ease the pressure. 1183 */ 1184 if (!ISSET(zst->zst_rx_flags, RX_IBUF_BLOCKED) && 1185 cc < zst->zst_r_hiwat) { 1186 SET(zst->zst_rx_flags, RX_IBUF_BLOCKED); 1187 zs_hwiflow(zst); 1188 } 1189 1190 /* 1191 * If we're out of space, disable receive interrupts 1192 * until the queue has drained a bit. 1193 */ 1194 if (!cc) { 1195 SET(zst->zst_rx_flags, RX_IBUF_OVERFLOWED); 1196 CLR(cs->cs_preg[1], ZSWR1_RIE); 1197 cs->cs_creg[1] = cs->cs_preg[1]; 1198 zs_write_reg(cs, 1, cs->cs_creg[1]); 1199 } 1200 1201#if 0 1202 printf("%xH%04d\n", zst->zst_rx_flags, zst->zst_rbavail); 1203#endif 1204} 1205 1206/* 1207 * transmitter ready interrupt. (splzs) 1208 */ 1209static void 1210zstty_txint(cs) 1211 struct zs_chanstate *cs; 1212{ 1213 struct zstty_softc *zst = cs->cs_private; 1214 1215 /* 1216 * If we've delayed a parameter change, do it now, and restart 1217 * output. 1218 */ 1219 if (cs->cs_heldchange) { 1220 zs_loadchannelregs(cs); 1221 cs->cs_heldchange = 0; 1222 zst->zst_tbc = zst->zst_heldtbc; 1223 zst->zst_heldtbc = 0; 1224 } 1225 1226 /* Output the next character in the buffer, if any. */ 1227 if (zst->zst_tbc > 0) { 1228 zs_write_data(cs, *zst->zst_tba); 1229 zst->zst_tbc--; 1230 zst->zst_tba++; 1231 } else { 1232 /* Disable transmit completion interrupts if necessary. */ 1233 if (ISSET(cs->cs_preg[1], ZSWR1_TIE)) { 1234 CLR(cs->cs_preg[1], ZSWR1_TIE); 1235 cs->cs_creg[1] = cs->cs_preg[1]; 1236 zs_write_reg(cs, 1, cs->cs_creg[1]); 1237 } 1238 if (zst->zst_tx_busy) { 1239 zst->zst_tx_busy = 0; 1240 zst->zst_tx_done = 1; 1241 cs->cs_softreq = 1; 1242 } 1243 } 1244} 1245 1246/* 1247 * status change interrupt. (splzs) 1248 */ 1249static void 1250zstty_stint(cs) 1251 struct zs_chanstate *cs; 1252{ 1253 struct zstty_softc *zst = cs->cs_private; 1254 u_char rr0, delta; 1255 1256 rr0 = zs_read_csr(cs); 1257 zs_write_csr(cs, ZSWR0_RESET_STATUS); 1258 1259 /* 1260 * Check here for console break, so that we can abort 1261 * even when interrupts are locking up the machine. 1262 */ 1263 if (ISSET(rr0, ZSRR0_BREAK) && 1264 ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) { 1265 zs_abort(cs); 1266 return; 1267 } 1268 1269 delta = rr0 ^ cs->cs_rr0; 1270 cs->cs_rr0 = rr0; 1271 if (ISSET(delta, cs->cs_rr0_mask)) { 1272 SET(cs->cs_rr0_delta, delta); 1273 1274 /* 1275 * Stop output immediately if we lose the output 1276 * flow control signal or carrier detect. 1277 */ 1278 if (ISSET(~rr0, cs->cs_rr0_mask)) { 1279 zst->zst_tbc = 0; 1280 zst->zst_heldtbc = 0; 1281 } 1282 1283 zst->zst_st_check = 1; 1284 cs->cs_softreq = 1; 1285 } 1286} 1287 1288void 1289zstty_diag(arg) 1290 void *arg; 1291{ 1292 struct zstty_softc *zst = arg; 1293 int overflows, floods; 1294 int s; 1295 1296 s = splzs(); 1297 overflows = zst->zst_overflows; 1298 zst->zst_overflows = 0; 1299 floods = zst->zst_floods; 1300 zst->zst_floods = 0; 1301 zst->zst_errors = 0; 1302 splx(s); 1303 1304 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n", 1305 zst->zst_dev.dv_xname, 1306 overflows, overflows == 1 ? "" : "s", 1307 floods, floods == 1 ? "" : "s"); 1308} 1309 1310integrate void 1311zstty_rxsoft(zst, tp) 1312 struct zstty_softc *zst; 1313 struct tty *tp; 1314{ 1315 struct zs_chanstate *cs = zst->zst_cs; 1316 int (*rint) __P((int c, struct tty *tp)) = linesw[tp->t_line].l_rint; 1317 u_char *get, *end; 1318 u_int cc, scc; 1319 u_char rr1; 1320 int code; 1321 int s; 1322 1323 end = zst->zst_ebuf; 1324 get = zst->zst_rbget; 1325 scc = cc = zstty_rbuf_size - zst->zst_rbavail; 1326 1327 if (cc == zstty_rbuf_size) { 1328 zst->zst_floods++; 1329 if (zst->zst_errors++ == 0) 1330 timeout(zstty_diag, zst, 60 * hz); 1331 } 1332 1333 while (cc) { 1334 code = get[0]; 1335 rr1 = get[1]; 1336 if (ISSET(rr1, ZSRR1_DO | ZSRR1_FE | ZSRR1_PE)) { 1337 if (ISSET(rr1, ZSRR1_DO)) { 1338 zst->zst_overflows++; 1339 if (zst->zst_errors++ == 0) 1340 timeout(zstty_diag, zst, 60 * hz); 1341 } 1342 if (ISSET(rr1, ZSRR1_FE)) 1343 SET(code, TTY_FE); 1344 if (ISSET(rr1, ZSRR1_PE)) 1345 SET(code, TTY_PE); 1346 } 1347 if ((*rint)(code, tp) == -1) { 1348 /* 1349 * The line discipline's buffer is out of space. 1350 */ 1351 if (!ISSET(zst->zst_rx_flags, RX_TTY_BLOCKED)) { 1352 /* 1353 * We're either not using flow control, or the 1354 * line discipline didn't tell us to block for 1355 * some reason. Either way, we have no way to 1356 * know when there's more space available, so 1357 * just drop the rest of the data. 1358 */ 1359 get += cc << 1; 1360 if (get >= end) 1361 get -= zstty_rbuf_size << 1; 1362 cc = 0; 1363 } else { 1364 /* 1365 * Don't schedule any more receive processing 1366 * until the line discipline tells us there's 1367 * space available (through comhwiflow()). 1368 * Leave the rest of the data in the input 1369 * buffer. 1370 */ 1371 SET(zst->zst_rx_flags, RX_TTY_OVERFLOWED); 1372 } 1373 break; 1374 } 1375 get += 2; 1376 if (get >= end) 1377 get = zst->zst_rbuf; 1378 cc--; 1379 } 1380 1381 if (cc != scc) { 1382 zst->zst_rbget = get; 1383 s = splzs(); 1384 cc = zst->zst_rbavail += scc - cc; 1385 /* Buffers should be ok again, release possible block. */ 1386 if (cc >= zst->zst_r_lowat) { 1387 if (ISSET(zst->zst_rx_flags, RX_IBUF_OVERFLOWED)) { 1388 CLR(zst->zst_rx_flags, RX_IBUF_OVERFLOWED); 1389 SET(cs->cs_preg[1], ZSWR1_RIE); 1390 cs->cs_creg[1] = cs->cs_preg[1]; 1391 zs_write_reg(cs, 1, cs->cs_creg[1]); 1392 } 1393 if (ISSET(zst->zst_rx_flags, RX_IBUF_BLOCKED)) { 1394 CLR(zst->zst_rx_flags, RX_IBUF_BLOCKED); 1395 zs_hwiflow(zst); 1396 } 1397 } 1398 splx(s); 1399 } 1400 1401#if 0 1402 printf("%xS%04d\n", zst->zst_rx_flags, zst->zst_rbavail); 1403#endif 1404} 1405 1406integrate void 1407zstty_txsoft(zst, tp) 1408 struct zstty_softc *zst; 1409 struct tty *tp; 1410{ 1411 1412 CLR(tp->t_state, TS_BUSY); 1413 if (ISSET(tp->t_state, TS_FLUSH)) 1414 CLR(tp->t_state, TS_FLUSH); 1415 else 1416 ndflush(&tp->t_outq, (int)(zst->zst_tba - tp->t_outq.c_cf)); 1417 (*linesw[tp->t_line].l_start)(tp); 1418} 1419 1420integrate void 1421zstty_stsoft(zst, tp) 1422 struct zstty_softc *zst; 1423 struct tty *tp; 1424{ 1425 struct zs_chanstate *cs = zst->zst_cs; 1426 u_char rr0, delta; 1427 int s; 1428 1429 s = splzs(); 1430 rr0 = cs->cs_rr0; 1431 delta = cs->cs_rr0_delta; 1432 cs->cs_rr0_delta = 0; 1433 splx(s); 1434 1435 if (ISSET(delta, cs->cs_rr0_dcd)) { 1436 /* 1437 * Inform the tty layer that carrier detect changed. 1438 */ 1439 (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(rr0, ZSRR0_DCD)); 1440 } 1441 1442 if (ISSET(delta, cs->cs_rr0_cts)) { 1443 /* Block or unblock output according to flow control. */ 1444 if (ISSET(rr0, cs->cs_rr0_cts)) { 1445 zst->zst_tx_stopped = 0; 1446 (*linesw[tp->t_line].l_start)(tp); 1447 } else { 1448 zst->zst_tx_stopped = 1; 1449 } 1450 } 1451} 1452 1453/* 1454 * Software interrupt. Called at zssoft 1455 * 1456 * The main job to be done here is to empty the input ring 1457 * by passing its contents up to the tty layer. The ring is 1458 * always emptied during this operation, therefore the ring 1459 * must not be larger than the space after "high water" in 1460 * the tty layer, or the tty layer might drop our input. 1461 * 1462 * Note: an "input blockage" condition is assumed to exist if 1463 * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set. 1464 */ 1465static void 1466zstty_softint(cs) 1467 struct zs_chanstate *cs; 1468{ 1469 struct zstty_softc *zst = cs->cs_private; 1470 struct tty *tp = zst->zst_tty; 1471 int s; 1472 1473 s = spltty(); 1474 1475 if (zst->zst_rx_ready) { 1476 zst->zst_rx_ready = 0; 1477 zstty_rxsoft(zst, tp); 1478 } 1479 1480 if (zst->zst_st_check) { 1481 zst->zst_st_check = 0; 1482 zstty_stsoft(zst, tp); 1483 } 1484 1485 if (zst->zst_tx_done) { 1486 zst->zst_tx_done = 0; 1487 zstty_txsoft(zst, tp); 1488 } 1489 1490 splx(s); 1491} 1492 1493struct zsops zsops_tty = { 1494 zstty_rxint, /* receive char available */ 1495 zstty_stint, /* external/status */ 1496 zstty_txint, /* xmit buffer empty */ 1497 zstty_softint, /* process software interrupt */ 1498}; 1499