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