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