1 /* $NetBSD: cd18xx.c,v 1.8 2003/01/06 13:05:09 wiz Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * 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. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /*- 32 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 33 * All rights reserved. 34 * 35 * This code is derived from software contributed to The NetBSD Foundation 36 * by Charles M. Hannum. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by the NetBSD 49 * Foundation, Inc. and its contributors. 50 * 4. Neither the name of The NetBSD Foundation nor the names of its 51 * contributors may be used to endorse or promote products derived 52 * from this software without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 * POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 /* 68 * Copyright (c) 1991 The Regents of the University of California. 69 * All rights reserved. 70 * 71 * Redistribution and use in source and binary forms, with or without 72 * modification, are permitted provided that the following conditions 73 * are met: 74 * 1. Redistributions of source code must retain the above copyright 75 * notice, this list of conditions and the following disclaimer. 76 * 2. Redistributions in binary form must reproduce the above copyright 77 * notice, this list of conditions and the following disclaimer in the 78 * documentation and/or other materials provided with the distribution. 79 * 3. All advertising materials mentioning features or use of this software 80 * must display the following acknowledgement: 81 * This product includes software developed by the University of 82 * California, Berkeley and its contributors. 83 * 4. Neither the name of the University nor the names of its contributors 84 * may be used to endorse or promote products derived from this software 85 * without specific prior written permission. 86 * 87 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 88 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 89 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 90 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 91 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 92 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 93 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 94 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 95 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 96 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 97 * SUCH DAMAGE. 98 * 99 * @(#)com.c 7.5 (Berkeley) 5/16/91 100 */ 101 102 /* 103 * cirrus logic CL-CD180/CD1864/CD1865 driver, based in (large) parts on 104 * the com and z8530 drivers. thanks charles. 105 */ 106 107 #include <sys/cdefs.h> 108 __KERNEL_RCSID(0, "$NetBSD: cd18xx.c,v 1.8 2003/01/06 13:05:09 wiz Exp $"); 109 110 #include <sys/param.h> 111 #include <sys/conf.h> 112 #include <sys/device.h> 113 #include <sys/systm.h> 114 #include <sys/malloc.h> 115 #include <sys/proc.h> 116 #include <sys/kernel.h> 117 #include <sys/tty.h> 118 #include <sys/fcntl.h> 119 120 #include <machine/bus.h> 121 122 #include <dev/ic/cd18xxvar.h> 123 #include <dev/ic/cd18xxreg.h> 124 125 #include "ioconf.h" 126 127 /* 128 * some helpers 129 */ 130 131 /* macros to clear/set/test flags. */ 132 #define SET(t, f) (t) |= (f) 133 #define CLR(t, f) (t) &= ~(f) 134 #define ISSET(t, f) ((t) & (f)) 135 136 static void cdtty_attach(struct cd18xx_softc *, int); 137 138 static __inline void cd18xx_rint(struct cd18xx_softc *, int *); 139 static __inline void cd18xx_tint(struct cd18xx_softc *, int *); 140 static __inline void cd18xx_mint(struct cd18xx_softc *, int *); 141 142 void cdtty_rxsoft(struct cd18xx_softc *, struct cdtty_port *, struct tty *); 143 void cdtty_txsoft(struct cd18xx_softc *, struct cdtty_port *, struct tty *); 144 void cdtty_stsoft(struct cd18xx_softc *, struct cdtty_port *, struct tty *); 145 void cd18xx_softintr(void *); 146 147 dev_type_open(cdttyopen); 148 dev_type_close(cdttyclose); 149 dev_type_read(cdttyread); 150 dev_type_write(cdttywrite); 151 dev_type_ioctl(cdttyioctl); 152 dev_type_stop(cdttystop); 153 dev_type_tty(cdttytty); 154 dev_type_poll(cdttypoll); 155 156 const struct cdevsw cdtty_cdevsw = { 157 cdttyopen, cdttyclose, cdttyread, cdttywrite, cdttyioctl, 158 cdttystop, cdttytty, cdttypoll, nommap, ttykqfilter, D_TTY 159 }; 160 161 static void cdtty_shutdown(struct cd18xx_softc *, struct cdtty_port *); 162 static void cdttystart(struct tty *); 163 static int cdttyparam(struct tty *, struct termios *); 164 static void cdtty_break(struct cd18xx_softc *, struct cdtty_port *, int); 165 static void cdtty_modem(struct cd18xx_softc *, struct cdtty_port *, int); 166 static int cdttyhwiflow(struct tty *, int); 167 static void cdtty_hwiflow(struct cd18xx_softc *, struct cdtty_port *); 168 169 static void cdtty_loadchannelregs(struct cd18xx_softc *, 170 struct cdtty_port *); 171 172 /* default read buffer size */ 173 u_int cdtty_rbuf_size = CDTTY_RING_SIZE; 174 175 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */ 176 u_int cdtty_rbuf_hiwat = (CDTTY_RING_SIZE * 1) / 4; 177 u_int cdtty_rbuf_lowat = (CDTTY_RING_SIZE * 3) / 4; 178 179 #define CD18XXDEBUG 180 #ifdef CD18XXDEBUG 181 #define CDD_INFO 0x0001 182 #define CDD_INTR 0x0002 183 int cd18xx_debug = CDD_INTR|CDD_INFO; 184 # define DPRINTF(l, x) if (cd18xx_debug & l) printf x 185 #else 186 # define DPRINTF(l, x) /* nothing */ 187 #endif 188 189 /* Known supported revisions. */ 190 struct cd18xx_revs { 191 u_char revision; 192 u_char onehundred_pin; 193 char *name; 194 } cd18xx_revs[] = { 195 { CD180_GFRCR_REV_B, 0, "CL-CD180 rev. B" }, 196 { CD180_GFRCR_REV_C, 0, "CL-CD180 rev. C" }, 197 { CD1864_GFRCR_REVISION_A, 1, "CL-CD1864 rev. A" }, 198 { CD1865_GFRCR_REVISION_A, 1, "CL-CD1865 rev. A" }, 199 { CD1865_GFRCR_REVISION_B, 1, "CL-CD1865 rev. B" }, 200 { CD1865_GFRCR_REVISION_C, 1, "CL-CD1865 rev. C" }, 201 { 0, 0, 0 } 202 }; 203 204 /* wait for the CCR to go to zero */ 205 static __inline int cd18xx_wait_ccr(struct cd18xx_softc *); 206 static __inline int 207 cd18xx_wait_ccr(sc) 208 struct cd18xx_softc *sc; 209 { 210 int i = 100000; 211 212 while (--i && 213 bus_space_read_1(sc->sc_tag, sc->sc_handle, CD18xx_CCR) != 0) 214 ; 215 return (i == 0); 216 } 217 218 /* 219 * device attach routine, high-end portion 220 */ 221 void 222 cd18xx_attach(sc) 223 struct cd18xx_softc *sc; 224 { 225 static int chip_id_next = 1; 226 int onehundred_pin, revision, i, port; 227 228 /* read and print the revision */ 229 revision = cd18xx_read(sc, CD18xx_GFRCR); 230 onehundred_pin = ISSET(cd18xx_read(sc, CD18xx_SRCR),CD18xx_SRCR_PKGTYP); 231 for (i = 0; cd18xx_revs[i].name; i++) 232 if (revision == cd18xx_revs[i].revision || 233 onehundred_pin == cd18xx_revs[i].onehundred_pin) { 234 printf(": %s", cd18xx_revs[i].name); 235 break; 236 } 237 238 if (cd18xx_revs[i].name == NULL) { 239 printf("%s: unknown revision, bailing.\n", sc->sc_dev.dv_xname); 240 return; 241 } 242 243 /* prepare for reset */ 244 cd18xx_set_car(sc, 0); 245 cd18xx_write(sc, CD18xx_GSVR, CD18xx_GSVR_CLEAR); 246 247 /* wait for CCR to go to zero */ 248 if (cd18xx_wait_ccr(sc)) { 249 printf("cd18xx_attach: reset change command timed out\n"); 250 return; 251 } 252 253 /* full reset of all channels */ 254 cd18xx_write(sc, CD18xx_CCR, 255 CD18xx_CCR_RESET|CD18xx_CCR_RESET_HARD); 256 257 /* loop until the GSVR is ready */ 258 i = 100000; 259 while (--i && cd18xx_read(sc, CD18xx_GSVR) == CD18xx_GSVR_READY) 260 ; 261 if (i == 0) { 262 printf("\n%s: did not reset!\n", sc->sc_dev.dv_xname); 263 return; 264 } 265 266 /* write the chip_id */ 267 sc->sc_chip_id = chip_id_next++; 268 #ifdef DIAGNOSTIC 269 if (sc->sc_chip_id > 31) 270 panic("more than 31 cd18xx's? help."); 271 #endif 272 cd18xx_write(sc, CD18xx_GSVR, CD18xx_GSVR_SETID(sc)); 273 274 /* rx/tx/modem service match vectors, initalised by higher level */ 275 cd18xx_write(sc, CD18xx_MSMR, sc->sc_msmr | 0x80); 276 cd18xx_write(sc, CD18xx_TSMR, sc->sc_tsmr | 0x80); 277 cd18xx_write(sc, CD18xx_RSMR, sc->sc_rsmr | 0x80); 278 279 printf(", gsvr %x msmr %x tsmr %x rsmr %x", 280 cd18xx_read(sc, CD18xx_GSVR), 281 cd18xx_read(sc, CD18xx_MSMR), 282 cd18xx_read(sc, CD18xx_TSMR), 283 cd18xx_read(sc, CD18xx_RSMR)); 284 285 /* prescale registers */ 286 sc->sc_pprh = 0xf0; 287 sc->sc_pprl = 0; 288 cd18xx_write(sc, CD18xx_PPRH, sc->sc_pprh); 289 cd18xx_write(sc, CD18xx_PPRL, sc->sc_pprl); 290 291 /* establish our soft interrupt. */ 292 sc->sc_si = softintr_establish(IPL_SOFTSERIAL, cd18xx_softintr, sc); 293 294 printf(", 8 ports ready (chip id %d)\n", sc->sc_chip_id); 295 296 /* 297 * finally, we loop over all 8 channels initialising them 298 */ 299 for (port = 0; port < 8; port++) 300 cdtty_attach(sc, port); 301 } 302 303 /* tty portion of the code */ 304 305 /* 306 * tty portion attach routine 307 */ 308 void 309 cdtty_attach(sc, port) 310 struct cd18xx_softc *sc; 311 int port; 312 { 313 struct cdtty_port *p = &sc->sc_ports[port]; 314 int i; 315 316 /* load CAR with channel number */ 317 cd18xx_set_car(sc, port); 318 319 /* wait for CCR to go to zero */ 320 if (cd18xx_wait_ccr(sc)) { 321 printf("cd18xx_attach: change command timed out setting " 322 "CAR for port %d\n", i); 323 return; 324 } 325 326 /* set the RPTR to (arbitrary) 8 */ 327 cd18xx_write(sc, CD18xx_RTPR, 8); 328 329 /* reset the modem signal value register */ 330 sc->sc_ports[port].p_msvr = CD18xx_MSVR_RESET; 331 332 /* zero the service request enable register */ 333 cd18xx_write(sc, CD18xx_SRER, 0); 334 335 /* enable the transmitter & receiver */ 336 SET(p->p_chanctl, CD18xx_CCR_CHANCTL | 337 CD18xx_CCR_CHANCTL_TxEN | 338 CD18xx_CCR_CHANCTL_RxEN); 339 340 /* XXX no console or kgdb support yet! */ 341 342 /* get a tty structure */ 343 p->p_tty = ttymalloc(); 344 p->p_tty->t_oproc = cdttystart; 345 p->p_tty->t_param = cdttyparam; 346 p->p_tty->t_hwiflow = cdttyhwiflow; 347 348 p->p_rbuf = malloc(cdtty_rbuf_size << 1, M_DEVBUF, M_WAITOK); 349 p->p_rbput = p->p_rbget = p->p_rbuf; 350 p->p_rbavail = cdtty_rbuf_size; 351 if (p->p_rbuf == NULL) { 352 printf("%s: unable to allocate ring buffer for tty %d\n", 353 sc->sc_dev.dv_xname, port); 354 return; 355 } 356 p->p_ebuf = p->p_rbuf + (cdtty_rbuf_size << 1); 357 358 tty_attach(p->p_tty); 359 } 360 361 /* 362 * cdtty_shutdown: called when the device is last closed. 363 */ 364 void 365 cdtty_shutdown(sc, p) 366 struct cd18xx_softc *sc; 367 struct cdtty_port *p; 368 { 369 struct tty *tp = p->p_tty; 370 int s; 371 372 s = splserial(); 373 374 /* If we were asserting flow control, then deassert it. */ 375 SET(p->p_rx_flags, RX_IBUF_BLOCKED); 376 cdtty_hwiflow(sc, p); 377 378 /* Clear any break condition set with TIOCSBRK. */ 379 cdtty_break(sc, p, 0); 380 381 /* 382 * Hang up if necessary. Wait a bit, so the other side has time to 383 * notice even if we immediately open the port again. 384 * Avoid tsleeping above splhigh(). 385 */ 386 if (ISSET(tp->t_cflag, HUPCL)) { 387 cdtty_modem(sc, p, 0); 388 splx(s); 389 /* XXX tsleep will only timeout */ 390 (void) tsleep(sc, TTIPRI, ttclos, hz); 391 s = splserial(); 392 } 393 394 /* Turn off interrupts. */ 395 p->p_srer = 0; 396 cd18xx_write(sc, CD18xx_SRER, p->p_srer); 397 398 splx(s); 399 } 400 401 /* 402 * cdttyopen: open syscall for cdtty terminals.. 403 */ 404 int 405 cdttyopen(dev, flag, mode, p) 406 dev_t dev; 407 int flag; 408 int mode; 409 struct proc *p; 410 { 411 struct tty *tp; 412 struct cd18xx_softc *sc; 413 struct cdtty_port *port; 414 int channel, instance, s, error; 415 416 channel = CD18XX_CHANNEL(dev); 417 instance = CD18XX_INSTANCE(dev); 418 419 /* ensure instance is valid */ 420 if (instance >= clcd_cd.cd_ndevs) 421 return (ENXIO); 422 423 /* get softc and port */ 424 sc = clcd_cd.cd_devs[instance]; 425 if (sc == NULL) 426 return (ENXIO); 427 port = &sc->sc_ports[channel]; 428 if (port == NULL || port->p_rbuf == NULL) 429 return (ENXIO); 430 431 /* kgdb support? maybe later... */ 432 433 tp = port->p_tty; 434 435 /* enforce exclude */ 436 if (tp == NULL || 437 (ISSET(tp->t_state, TS_ISOPEN) && 438 ISSET(tp->t_state, TS_XCLUDE) && 439 (p->p_ucred->cr_uid != 0))) 440 return (EBUSY); 441 442 s = spltty(); 443 444 /* 445 * Do the following iff this is a first open. 446 */ 447 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 448 struct termios t; 449 450 /* set up things in tp as necessary */ 451 tp->t_dev = dev; 452 453 /* 454 * Initialize the termios status to the defaults. Add in the 455 * sticky bits from TIOCSFLAGS. 456 */ 457 t.c_ispeed = 0; 458 t.c_ospeed = TTYDEF_SPEED; 459 t.c_cflag = TTYDEF_CFLAG; 460 461 if (ISSET(port->p_swflags, TIOCFLAG_CLOCAL)) 462 SET(t.c_cflag, CLOCAL); 463 if (ISSET(port->p_swflags, TIOCFLAG_CRTSCTS)) 464 SET(t.c_cflag, CRTSCTS); 465 if (ISSET(port->p_swflags, TIOCFLAG_CDTRCTS)) 466 SET(t.c_cflag, CDTRCTS); 467 if (ISSET(port->p_swflags, TIOCFLAG_MDMBUF)) 468 SET(t.c_cflag, MDMBUF); 469 470 /* Make sure param will see changes. */ 471 tp->t_ospeed = 0; /* XXX set above ignored? */ 472 (void)cdttyparam(tp, &t); 473 474 tp->t_iflag = TTYDEF_IFLAG; 475 tp->t_oflag = TTYDEF_OFLAG; 476 tp->t_lflag = TTYDEF_LFLAG; 477 ttychars(tp); 478 ttsetwater(tp); 479 480 (void)splserial(); 481 482 /* turn on rx and modem interrupts */ 483 cd18xx_set_car(sc, CD18XX_CHANNEL(dev)); 484 SET(port->p_srer, CD18xx_SRER_Rx | 485 CD18xx_SRER_RxSC | 486 CD18xx_SRER_CD); 487 cd18xx_write(sc, CD18xx_SRER, port->p_srer); 488 489 /* always turn on DTR when open */ 490 cdtty_modem(sc, port, 1); 491 492 /* initialise ring buffer */ 493 port->p_rbget = port->p_rbput = port->p_rbuf; 494 port->p_rbavail = cdtty_rbuf_size; 495 CLR(port->p_rx_flags, RX_ANY_BLOCK); 496 cdtty_hwiflow(sc, port); 497 } 498 499 /* drop spl back before going into the line open */ 500 splx(s); 501 502 error = ttyopen(tp, CD18XX_DIALOUT(dev), ISSET(flag, O_NONBLOCK)); 503 if (error == 0) 504 error = (*tp->t_linesw->l_open)(dev, tp); 505 506 return (error); 507 } 508 509 /* 510 * cdttyclose: close syscall for cdtty terminals.. 511 */ 512 int 513 cdttyclose(dev, flag, mode, p) 514 dev_t dev; 515 int flag; 516 int mode; 517 struct proc *p; 518 { 519 struct cd18xx_softc *sc; 520 struct cdtty_port *port; 521 struct tty *tp; 522 int channel, instance; 523 524 channel = CD18XX_CHANNEL(dev); 525 instance = CD18XX_INSTANCE(dev); 526 527 /* ensure instance is valid */ 528 if (instance >= clcd_cd.cd_ndevs) 529 return (ENXIO); 530 531 /* get softc and port */ 532 sc = clcd_cd.cd_devs[instance]; 533 if (sc == NULL) 534 return (ENXIO); 535 port = &sc->sc_ports[channel]; 536 537 tp = port->p_tty; 538 539 (*tp->t_linesw->l_close)(tp, flag); 540 ttyclose(tp); 541 542 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 543 /* 544 * Although we got a last close, the device may still be in 545 * use; e.g. if this was the dialout node, and there are still 546 * processes waiting for carrier on the non-dialout node. 547 */ 548 cdtty_shutdown(sc, port); 549 } 550 551 return (0); 552 } 553 554 /* 555 * cdttyread: read syscall for cdtty terminals.. 556 */ 557 int 558 cdttyread(dev, uio, flag) 559 dev_t dev; 560 struct uio *uio; 561 int flag; 562 { 563 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(dev)]; 564 struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 565 struct tty *tp = port->p_tty; 566 567 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 568 } 569 570 /* 571 * cdttywrite: write syscall for cdtty terminals.. 572 */ 573 int 574 cdttywrite(dev, uio, flag) 575 dev_t dev; 576 struct uio *uio; 577 int flag; 578 { 579 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(dev)]; 580 struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 581 struct tty *tp = port->p_tty; 582 583 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 584 } 585 586 int 587 cdttypoll(dev, events, p) 588 dev_t dev; 589 int events; 590 struct proc *p; 591 { 592 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(dev)]; 593 struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 594 struct tty *tp = port->p_tty; 595 596 return ((*tp->t_linesw->l_poll)(tp, events, p)); 597 } 598 599 /* 600 * cdttytty: return a pointer to our (cdtty) tp. 601 */ 602 struct tty * 603 cdttytty(dev) 604 dev_t dev; 605 { 606 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(dev)]; 607 struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 608 609 return (port->p_tty); 610 } 611 612 /* 613 * cdttyioctl: ioctl syscall for cdtty terminals.. 614 */ 615 int 616 cdttyioctl(dev, cmd, data, flag, p) 617 dev_t dev; 618 u_long cmd; 619 caddr_t data; 620 int flag; 621 struct proc *p; 622 { 623 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(dev)]; 624 struct cdtty_port *port = &sc->sc_ports[CD18XX_CHANNEL(dev)]; 625 struct tty *tp = port->p_tty; 626 int error, s; 627 628 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 629 if (error != EPASSTHROUGH) 630 return (error); 631 632 error = ttioctl(tp, cmd, data, flag, p); 633 if (error != EPASSTHROUGH) 634 return (error); 635 636 s = splserial(); 637 638 switch (cmd) { 639 case TIOCSBRK: 640 cdtty_break(sc, port, 1); 641 break; 642 643 case TIOCCBRK: 644 cdtty_break(sc, port, 0); 645 break; 646 647 case TIOCSDTR: 648 cdtty_modem(sc, port, 1); 649 break; 650 651 case TIOCCDTR: 652 cdtty_modem(sc, port, 0); 653 break; 654 655 case TIOCGFLAGS: 656 *(int *)data = port->p_swflags; 657 break; 658 659 case TIOCSFLAGS: 660 error = suser(p->p_ucred, &p->p_acflag); 661 if (error) 662 return (error); 663 port->p_swflags = *(int *)data; 664 break; 665 666 case TIOCMSET: 667 case TIOCMBIS: 668 case TIOCMBIC: 669 case TIOCMGET: 670 default: 671 return (EPASSTHROUGH); 672 } 673 674 splx(s); 675 return (0); 676 } 677 678 /* 679 * Start or restart transmission. 680 */ 681 static void 682 cdttystart(tp) 683 struct tty *tp; 684 { 685 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(tp->t_dev)]; 686 struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 687 int s; 688 689 s = spltty(); 690 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) 691 goto out; 692 if (p->p_tx_stopped) 693 goto out; 694 695 if (tp->t_outq.c_cc <= tp->t_lowat) { 696 if (ISSET(tp->t_state, TS_ASLEEP)) { 697 CLR(tp->t_state, TS_ASLEEP); 698 wakeup((caddr_t)&tp->t_outq); 699 } 700 selwakeup(&tp->t_wsel); 701 if (tp->t_outq.c_cc == 0) 702 goto out; 703 } 704 705 /* Grab the first contiguous region of buffer space. */ 706 { 707 u_char *tba; 708 int tbc; 709 710 tba = tp->t_outq.c_cf; 711 tbc = ndqb(&tp->t_outq, 0); 712 713 (void)splserial(); 714 715 p->p_tba = tba; 716 p->p_tbc = tbc; 717 } 718 719 SET(tp->t_state, TS_BUSY); 720 p->p_tx_busy = 1; 721 722 /* turn on tx interrupts */ 723 if ((p->p_srer & CD18xx_SRER_Tx) == 0) { 724 cd18xx_set_car(sc, CD18XX_CHANNEL(tp->t_dev)); 725 SET(p->p_srer, CD18xx_SRER_Tx); 726 cd18xx_write(sc, CD18xx_SRER, p->p_srer); 727 } 728 729 /* 730 * Now bail; we can't actually transmit bytes until we're in a 731 * transmit interrupt service routine. 732 */ 733 out: 734 splx(s); 735 return; 736 } 737 738 /* 739 * cdttystop: handing ^S or other stop signals, for a cdtty 740 */ 741 void 742 cdttystop(tp, flag) 743 struct tty *tp; 744 int flag; 745 { 746 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(tp->t_dev)]; 747 struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 748 int s; 749 750 s = splserial(); 751 if (ISSET(tp->t_state, TS_BUSY)) { 752 /* Stop transmitting at the next chunk. */ 753 p->p_tbc = 0; 754 p->p_heldtbc = 0; 755 if (!ISSET(tp->t_state, TS_TTSTOP)) 756 SET(tp->t_state, TS_FLUSH); 757 } 758 splx(s); 759 } 760 761 /* 762 * load a channel's registers. 763 */ 764 void 765 cdtty_loadchannelregs(sc, p) 766 struct cd18xx_softc *sc; 767 struct cdtty_port *p; 768 { 769 770 cd18xx_set_car(sc, CD18XX_CHANNEL(p->p_tty->t_dev)); 771 cd18xx_write(sc, CD18xx_SRER, p->p_srer); 772 cd18xx_write(sc, CD18xx_MSVR, p->p_msvr_active = p->p_msvr); 773 cd18xx_write(sc, CD18xx_COR1, p->p_cor1); 774 cd18xx_write(sc, CD18xx_COR2, p->p_cor2); 775 cd18xx_write(sc, CD18xx_COR3, p->p_cor3); 776 /* 777 * COR2 and COR3 change commands are not required here for 778 * the CL-CD1865 but we do them anyway for simplicity. 779 */ 780 cd18xx_write(sc, CD18xx_CCR, CD18xx_CCR_CORCHG | 781 CD18xx_CCR_CORCHG_COR1 | 782 CD18xx_CCR_CORCHG_COR2 | 783 CD18xx_CCR_CORCHG_COR3); 784 cd18xx_write(sc, CD18xx_RBPRH, p->p_rbprh); 785 cd18xx_write(sc, CD18xx_RBPRL, p->p_rbprl); 786 cd18xx_write(sc, CD18xx_TBPRH, p->p_tbprh); 787 cd18xx_write(sc, CD18xx_TBPRL, p->p_tbprl); 788 if (cd18xx_wait_ccr(sc)) { 789 DPRINTF(CDD_INFO, 790 ("%s: cdtty_loadchannelregs ccr wait timed out\n", 791 sc->sc_dev.dv_xname)); 792 } 793 cd18xx_write(sc, CD18xx_CCR, p->p_chanctl); 794 } 795 796 /* 797 * Set tty parameters from termios. 798 * XXX - Should just copy the whole termios after 799 * making sure all the changes could be done. 800 */ 801 static int 802 cdttyparam(tp, t) 803 struct tty *tp; 804 struct termios *t; 805 { 806 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(tp->t_dev)]; 807 struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 808 int s; 809 810 /* Check requested parameters. */ 811 if (t->c_ospeed < 0) 812 return (EINVAL); 813 if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 814 return (EINVAL); 815 816 /* 817 * For the console, always force CLOCAL and !HUPCL, so that the port 818 * is always active. 819 */ 820 if (ISSET(p->p_swflags, TIOCFLAG_SOFTCAR)) { 821 SET(t->c_cflag, CLOCAL); 822 CLR(t->c_cflag, HUPCL); 823 } 824 825 /* 826 * If there were no changes, don't do anything. This avoids dropping 827 * input and improves performance when all we did was frob things like 828 * VMIN and VTIME. 829 */ 830 if (tp->t_ospeed == t->c_ospeed && 831 tp->t_cflag == t->c_cflag) 832 return (0); 833 834 /* 835 * Block interrupts so that state will not 836 * be altered until we are done setting it up. 837 */ 838 s = splserial(); 839 840 /* 841 * Copy across the size, parity and stop bit info. 842 */ 843 switch (t->c_cflag & CSIZE) { 844 case CS5: 845 p->p_cor1 = CD18xx_COR1_CS5; 846 break; 847 case CS6: 848 p->p_cor1 = CD18xx_COR1_CS6; 849 break; 850 case CS7: 851 p->p_cor1 = CD18xx_COR1_CS7; 852 break; 853 default: 854 p->p_cor1 = CD18xx_COR1_CS8; 855 break; 856 } 857 if (ISSET(t->c_cflag, PARENB)) { 858 SET(p->p_cor1, CD18xx_COR1_PARITY_NORMAL); 859 if (ISSET(t->c_cflag, PARODD)) 860 SET(p->p_cor1, CD18xx_COR1_PARITY_ODD); 861 } 862 if (!ISSET(t->c_iflag, INPCK)) 863 SET(p->p_cor1, CD18xx_COR1_IGNORE); 864 if (ISSET(t->c_cflag, CSTOPB)) 865 SET(p->p_cor1, CD18xx_COR1_STOPBIT_2); 866 867 /* 868 * If we're not in a mode that assumes a connection is present, then 869 * ignore carrier changes. 870 */ 871 if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) 872 p->p_msvr_dcd = 0; 873 else 874 p->p_msvr_dcd = CD18xx_MSVR_CD; 875 876 /* 877 * Set the flow control pins depending on the current flow control 878 * mode. 879 */ 880 if (ISSET(t->c_cflag, CRTSCTS)) { 881 p->p_mcor1_dtr = CD18xx_MCOR1_DTR; 882 p->p_msvr_rts = CD18xx_MSVR_RTS; 883 p->p_msvr_cts = CD18xx_MSVR_CTS; 884 p->p_cor2 = CD18xx_COR2_RTSAOE|CD18xx_COR2_CTSAE; 885 } else if (ISSET(t->c_cflag, MDMBUF)) { 886 /* 887 * For DTR/DCD flow control, make sure we don't toggle DTR for 888 * carrier detection. 889 */ 890 p->p_mcor1_dtr = 0; 891 p->p_msvr_rts = CD18xx_MSVR_DTR; 892 p->p_msvr_cts = CD18xx_MSVR_CD; 893 p->p_cor2 = 0; 894 } else { 895 /* 896 * If no flow control, then always set RTS. This will make 897 * the other side happy if it mistakenly thinks we're doing 898 * RTS/CTS flow control. 899 */ 900 p->p_mcor1_dtr = CD18xx_MSVR_DTR; 901 p->p_msvr_rts = 0; 902 p->p_msvr_cts = 0; 903 p->p_cor2 = 0; 904 } 905 p->p_msvr_mask = p->p_msvr_cts | p->p_msvr_dcd; 906 907 /* 908 * Set the FIFO threshold based on the receive speed. 909 * 910 * * If it's a low speed, it's probably a mouse or some other 911 * interactive device, so set the threshold low. 912 * * If it's a high speed, trim the trigger level down to prevent 913 * overflows. 914 * * Otherwise set it a bit higher. 915 */ 916 p->p_cor3 = (t->c_ospeed <= 1200 ? 1 : 917 t->c_ospeed <= 38400 ? 8 : 4); 918 919 #define PORT_RATE(o, s) \ 920 (((((o) + (s)/2) / (s)) + CD18xx_xBRPR_TPC/2) / CD18xx_xBRPR_TPC) 921 /* Compute BPS for the requested speeds */ 922 if (t->c_ospeed) { 923 u_int32_t tbpr = PORT_RATE(sc->sc_osc, t->c_ospeed); 924 925 if (tbpr == 0 || tbpr > 0xffff) 926 return (EINVAL); 927 928 p->p_tbprh = tbpr >> 8; 929 p->p_tbprl = tbpr & 0xff; 930 } 931 932 if (t->c_ispeed) { 933 u_int32_t rbpr = PORT_RATE(sc->sc_osc, t->c_ispeed); 934 935 if (rbpr == 0 || rbpr > 0xffff) 936 return (EINVAL); 937 938 p->p_rbprh = rbpr >> 8; 939 p->p_rbprl = rbpr & 0xff; 940 } 941 942 /* And copy to tty. */ 943 tp->t_ispeed = 0; 944 tp->t_ospeed = t->c_ospeed; 945 tp->t_cflag = t->c_cflag; 946 947 if (!p->p_heldchange) { 948 if (p->p_tx_busy) { 949 p->p_heldtbc = p->p_tbc; 950 p->p_tbc = 0; 951 p->p_heldchange = 1; 952 } else 953 cdtty_loadchannelregs(sc, p); 954 } 955 956 if (!ISSET(t->c_cflag, CHWFLOW)) { 957 /* Disable the high water mark. */ 958 p->p_r_hiwat = 0; 959 p->p_r_lowat = 0; 960 if (ISSET(p->p_rx_flags, RX_TTY_OVERFLOWED)) { 961 CLR(p->p_rx_flags, RX_TTY_OVERFLOWED); 962 softintr_schedule(sc->sc_si); 963 } 964 if (ISSET(p->p_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { 965 CLR(p->p_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); 966 cdtty_hwiflow(sc, p); 967 } 968 } else { 969 p->p_r_hiwat = cdtty_rbuf_hiwat; 970 p->p_r_lowat = cdtty_rbuf_lowat; 971 } 972 973 splx(s); 974 975 /* 976 * Update the tty layer's idea of the carrier bit, in case we changed 977 * CLOCAL or MDMBUF. We don't hang up here; we only do that by 978 * explicit request. 979 */ 980 (void) (*tp->t_linesw->l_modem)(tp, ISSET(p->p_msvr, CD18xx_MSVR_CD)); 981 982 if (!ISSET(t->c_cflag, CHWFLOW)) { 983 if (p->p_tx_stopped) { 984 p->p_tx_stopped = 0; 985 cdttystart(tp); 986 } 987 } 988 989 return (0); 990 } 991 992 static void 993 cdtty_break(sc, p, onoff) 994 struct cd18xx_softc *sc; 995 struct cdtty_port *p; 996 int onoff; 997 { 998 999 /* tell tx intr handler we need a break */ 1000 p->p_needbreak = !!onoff; 1001 1002 /* turn on tx interrupts if break has changed */ 1003 if (p->p_needbreak != p->p_break) 1004 SET(p->p_srer, CD18xx_SRER_Tx); 1005 1006 if (!p->p_heldchange) { 1007 if (p->p_tx_busy) { 1008 p->p_heldtbc = p->p_tbc; 1009 p->p_tbc = 0; 1010 p->p_heldchange = 1; 1011 } else 1012 cdtty_loadchannelregs(sc, p); 1013 } 1014 } 1015 1016 /* 1017 * Raise or lower modem control (DTR/RTS) signals. If a character is 1018 * in transmission, the change is deferred. 1019 */ 1020 static void 1021 cdtty_modem(sc, p, onoff) 1022 struct cd18xx_softc *sc; 1023 struct cdtty_port *p; 1024 int onoff; 1025 { 1026 1027 if (p->p_mcor1_dtr == 0) 1028 return; 1029 1030 if (onoff) 1031 CLR(p->p_mcor1, p->p_mcor1_dtr); 1032 else 1033 SET(p->p_mcor1, p->p_mcor1_dtr); 1034 1035 if (!p->p_heldchange) { 1036 if (p->p_tx_busy) { 1037 p->p_heldtbc = p->p_tbc; 1038 p->p_tbc = 0; 1039 p->p_heldchange = 1; 1040 } else 1041 cdtty_loadchannelregs(sc, p); 1042 } 1043 } 1044 1045 /* 1046 * Try to block or unblock input using hardware flow-control. 1047 * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and 1048 * if this function returns non-zero, the TS_TBLOCK flag will 1049 * be set or cleared according to the "block" arg passed. 1050 */ 1051 int 1052 cdttyhwiflow(tp, block) 1053 struct tty *tp; 1054 int block; 1055 { 1056 struct cd18xx_softc *sc = clcd_cd.cd_devs[CD18XX_INSTANCE(tp->t_dev)]; 1057 struct cdtty_port *p = &sc->sc_ports[CD18XX_CHANNEL(tp->t_dev)]; 1058 int s; 1059 1060 if (p->p_msvr_rts == 0) 1061 return (0); 1062 1063 s = splserial(); 1064 if (block) { 1065 if (!ISSET(p->p_rx_flags, RX_TTY_BLOCKED)) { 1066 SET(p->p_rx_flags, RX_TTY_BLOCKED); 1067 cdtty_hwiflow(sc, p); 1068 } 1069 } else { 1070 if (ISSET(p->p_rx_flags, RX_TTY_OVERFLOWED)) { 1071 CLR(p->p_rx_flags, RX_TTY_OVERFLOWED); 1072 softintr_schedule(sc->sc_si); 1073 } 1074 if (ISSET(p->p_rx_flags, RX_TTY_BLOCKED)) { 1075 CLR(p->p_rx_flags, RX_TTY_BLOCKED); 1076 cdtty_hwiflow(sc, p); 1077 } 1078 } 1079 splx(s); 1080 return (1); 1081 } 1082 1083 /* 1084 * Internal version of cdttyhwiflow, called at cdtty's priority. 1085 */ 1086 static void 1087 cdtty_hwiflow(sc, p) 1088 struct cd18xx_softc *sc; 1089 struct cdtty_port *p; 1090 { 1091 1092 if (p->p_msvr_rts == 0) 1093 return; 1094 1095 if (ISSET(p->p_rx_flags, RX_ANY_BLOCK)) { 1096 CLR(p->p_msvr, p->p_msvr_rts); 1097 CLR(p->p_msvr_active, p->p_msvr_rts); 1098 } else { 1099 SET(p->p_msvr, p->p_msvr_rts); 1100 SET(p->p_msvr_active, p->p_msvr_rts); 1101 } 1102 cd18xx_set_car(sc, CD18XX_CHANNEL(p->p_tty->t_dev)); 1103 cd18xx_write(sc, CD18xx_MSVR, p->p_msvr_active); 1104 } 1105 1106 /* 1107 * indiviual interrupt routines. 1108 */ 1109 1110 /* 1111 * this is the number of interrupts allowed, total. set it to 0 1112 * to allow unlimited interrpts 1113 */ 1114 #define INTR_MAX_ALLOWED 0 1115 1116 #if INTR_MAX_ALLOWED == 0 1117 #define GOTINTR(sc, p) /* nothing */ 1118 #else 1119 int intrcount; 1120 #define GOTINTR(sc, p) \ 1121 do { \ 1122 if (intrcount++ == INTR_MAX_ALLOWED) { \ 1123 CLR(p->p_srer, CD18xx_SRER_Tx); \ 1124 cd18xx_write(sc, CD18xx_SRER, p->p_srer); \ 1125 } \ 1126 DPRINTF(CDD_INTR, (", intrcount %d srer %x", intrcount, p->p_srer)); \ 1127 } while (0) 1128 #endif 1129 1130 /* receiver interrupt */ 1131 static __inline void 1132 cd18xx_rint(sc, ns) 1133 struct cd18xx_softc *sc; 1134 int *ns; 1135 { 1136 struct cdtty_port *p; 1137 u_int channel, count; 1138 u_char *put, *end; 1139 u_int cc; 1140 1141 /* work out the channel and softc */ 1142 channel = cd18xx_get_gscr1_channel(sc); 1143 p = &sc->sc_ports[channel]; 1144 DPRINTF(CDD_INTR, ("%s: rint: channel %d", sc->sc_dev.dv_xname, channel)); 1145 GOTINTR(sc, p); 1146 1147 end = p->p_ebuf; 1148 put = p->p_rbput; 1149 cc = p->p_rbavail; 1150 1151 /* read as many bytes as necessary */ 1152 count = cd18xx_read(sc, CD18xx_RDCR); 1153 DPRINTF(CDD_INTR, (", %d bytes available: ", count)); 1154 1155 while (cc > 0 && count > 0) { 1156 u_char rcsr = cd18xx_read(sc, CD18xx_RCSR); 1157 1158 put[0] = cd18xx_read(sc, CD18xx_RDR); 1159 put[1] = rcsr; 1160 1161 if (rcsr) 1162 *ns = 1; 1163 1164 put += 2; 1165 if (put >= end) 1166 put = p->p_rbuf; 1167 1168 DPRINTF(CDD_INTR, (".")); 1169 cc--; 1170 count--; 1171 } 1172 1173 DPRINTF(CDD_INTR, (" finished reading")); 1174 1175 /* 1176 * Current string of incoming characters ended because 1177 * no more data was available or we ran out of space. 1178 * If we're out of space, turn off receive interrupts. 1179 */ 1180 p->p_rbput = put; 1181 p->p_rbavail = cc; 1182 if (!ISSET(p->p_rx_flags, RX_TTY_OVERFLOWED)) { 1183 p->p_rx_ready = 1; 1184 } 1185 1186 /* 1187 * If we're out of space, disable receive interrupts 1188 * until the queue has drained a bit. 1189 */ 1190 if (!cc) { 1191 SET(p->p_rx_flags, RX_IBUF_OVERFLOWED); 1192 CLR(p->p_srer, CD18xx_SRER_Rx | 1193 CD18xx_SRER_RxSC | 1194 CD18xx_SRER_CD); 1195 cd18xx_write(sc, CD18xx_SRER, p->p_srer); 1196 } 1197 1198 /* finish the interrupt transaction with the IC */ 1199 cd18xx_write(sc, CD18xx_EOSRR, 0); 1200 DPRINTF(CDD_INTR, (", done\n")); 1201 } 1202 1203 /* 1204 * transmitter interrupt 1205 * 1206 * note this relys on the fact that we allow the transmitter FIFO to 1207 * drain completely 1208 */ 1209 static __inline void 1210 cd18xx_tint(sc, ns) 1211 struct cd18xx_softc *sc; 1212 int *ns; 1213 { 1214 struct cdtty_port *p; 1215 u_int channel; 1216 1217 /* work out the channel and softc */ 1218 channel = cd18xx_get_gscr1_channel(sc); 1219 p = &sc->sc_ports[channel]; 1220 DPRINTF(CDD_INTR, ("%s: tint: channel %d", sc->sc_dev.dv_xname, 1221 channel)); 1222 GOTINTR(sc, p); 1223 1224 /* if the current break condition is wrong, fix it */ 1225 if (p->p_break != p->p_needbreak) { 1226 u_char buf[2]; 1227 1228 DPRINTF(CDD_INTR, (", changing break to %d", p->p_needbreak)); 1229 1230 /* turn on ETC processing */ 1231 cd18xx_write(sc, CD18xx_COR2, p->p_cor2 | CD18xx_COR2_ETC); 1232 1233 buf[0] = CD18xx_TDR_ETC_BYTE; 1234 buf[1] = p->p_needbreak ? CD18xx_TDR_BREAK_BYTE : 1235 CD18xx_TDR_NOBREAK_BYTE; 1236 cd18xx_write_multi(sc, CD18xx_TDR, buf, 2); 1237 1238 p->p_break = p->p_needbreak; 1239 1240 /* turn off ETC processing */ 1241 cd18xx_write(sc, CD18xx_COR2, p->p_cor2); 1242 } 1243 1244 /* 1245 * If we've delayed a parameter change, do it now, and restart 1246 * output. 1247 */ 1248 if (p->p_heldchange) { 1249 cdtty_loadchannelregs(sc, p); 1250 p->p_heldchange = 0; 1251 p->p_tbc = p->p_heldtbc; 1252 p->p_heldtbc = 0; 1253 } 1254 1255 /* Output the next chunk of the contiguous buffer, if any. */ 1256 if (p->p_tbc > 0) { 1257 int n; 1258 1259 n = p->p_tbc; 1260 if (n > 8) /* write up to 8 entries */ 1261 n = 8; 1262 DPRINTF(CDD_INTR, (", writing %d bytes to TDR", n)); 1263 cd18xx_write_multi(sc, CD18xx_TDR, p->p_tba, n); 1264 p->p_tbc -= n; 1265 p->p_tba += n; 1266 } 1267 1268 /* Disable transmit completion interrupts if we ran out of bytes. */ 1269 if (p->p_tbc == 0) { 1270 /* Note that Tx interrupts should already be enabled */ 1271 if (ISSET(p->p_srer, CD18xx_SRER_Tx)) { 1272 DPRINTF(CDD_INTR, (", disabling tx interrupts")); 1273 CLR(p->p_srer, CD18xx_SRER_Tx); 1274 cd18xx_write(sc, CD18xx_SRER, p->p_srer); 1275 } 1276 if (p->p_tx_busy) { 1277 p->p_tx_busy = 0; 1278 p->p_tx_done = 1; 1279 } 1280 } 1281 *ns = 1; 1282 1283 /* finish the interrupt transaction with the IC */ 1284 cd18xx_write(sc, CD18xx_EOSRR, 0); 1285 DPRINTF(CDD_INTR, (", done\n")); 1286 } 1287 1288 /* modem signal change interrupt */ 1289 static __inline void 1290 cd18xx_mint(sc, ns) 1291 struct cd18xx_softc *sc; 1292 int *ns; 1293 { 1294 struct cdtty_port *p; 1295 u_int channel; 1296 u_char msvr, delta; 1297 1298 /* work out the channel and softc */ 1299 channel = cd18xx_get_gscr1_channel(sc); 1300 p = &sc->sc_ports[channel]; 1301 DPRINTF(CDD_INTR, ("%s: mint: channel %d", sc->sc_dev.dv_xname, channel)); 1302 GOTINTR(sc, p); 1303 1304 /* 1305 * We ignore the MCR register, and handle detecting deltas 1306 * via software, like many other serial drivers. 1307 */ 1308 msvr = cd18xx_read(sc, CD18xx_MSVR); 1309 delta = msvr ^ p->p_msvr; 1310 DPRINTF(CDD_INTR, (", msvr %d", msvr)); 1311 1312 /* 1313 * Process normal status changes 1314 */ 1315 if (ISSET(delta, p->p_msvr_mask)) { 1316 SET(p->p_msvr_delta, delta); 1317 1318 DPRINTF(CDD_INTR, (", status changed delta %d", delta)); 1319 /* 1320 * Stop output immediately if we lose the output 1321 * flow control signal or carrier detect. 1322 */ 1323 if (ISSET(~msvr, p->p_msvr_mask)) { 1324 p->p_tbc = 0; 1325 p->p_heldtbc = 0; 1326 /* Stop modem interrupt processing */ 1327 } 1328 p->p_st_check = 1; 1329 *ns = 1; 1330 } 1331 1332 /* reset the modem signal register */ 1333 cd18xx_write(sc, CD18xx_MCR, 0); 1334 1335 /* finish the interrupt transaction with the IC */ 1336 cd18xx_write(sc, CD18xx_EOSRR, 0); 1337 DPRINTF(CDD_INTR, (", done\n")); 1338 } 1339 1340 /* 1341 * hardware interrupt routine. call the relevant interrupt routines until 1342 * no interrupts are pending. 1343 * 1344 * note: we do receive interrupts before all others (as we'd rather lose 1345 * a chance to transmit, than lose a character). and we do transmit 1346 * interrupts before modem interrupts. 1347 * 1348 * we have to traverse all of the cd18xx's attached, unfortunately. 1349 */ 1350 int 1351 cd18xx_hardintr(v) 1352 void *v; 1353 { 1354 int i, rv = 0; 1355 u_char ack; 1356 1357 DPRINTF(CDD_INTR, ("cd18xx_hardintr (ndevs %d):\n", clcd_cd.cd_ndevs)); 1358 for (i = 0; i < clcd_cd.cd_ndevs; i++) 1359 { 1360 struct cd18xx_softc *sc = clcd_cd.cd_devs[i]; 1361 int status, ns = 0; 1362 int count = 1; /* process only 1 interrupts at a time for now */ 1363 1364 if (sc == NULL) 1365 continue; 1366 1367 DPRINTF(CDD_INTR, ("%s:", sc->sc_dev.dv_xname)); 1368 while (count-- && 1369 (status = (cd18xx_read(sc, CD18xx_SRSR) & 1370 CD18xx_SRSR_PENDING))) { 1371 rv = 1; 1372 1373 DPRINTF(CDD_INTR, (" status %x:", status)); 1374 if (ISSET(status, CD18xx_SRSR_RxPEND)) { 1375 ack = (*sc->sc_ackfunc)(sc->sc_ackfunc_arg, 1376 CD18xx_INTRACK_RxINT); 1377 DPRINTF(CDD_INTR, (" rx: ack1 %x\n", ack)); 1378 cd18xx_rint(sc, &ns); 1379 } 1380 if (ISSET(status, CD18xx_SRSR_TxPEND)) { 1381 ack = (*sc->sc_ackfunc)(sc->sc_ackfunc_arg, 1382 CD18xx_INTRACK_TxINT); 1383 DPRINTF(CDD_INTR, (" tx: ack1 %x\n", ack)); 1384 cd18xx_tint(sc, &ns); 1385 1386 } 1387 if (ISSET(status, CD18xx_SRSR_MxPEND)) { 1388 ack = (*sc->sc_ackfunc)(sc->sc_ackfunc_arg, 1389 CD18xx_INTRACK_MxINT); 1390 DPRINTF(CDD_INTR, (" mx: ack1 %x\n", ack)); 1391 cd18xx_mint(sc, &ns); 1392 } 1393 } 1394 if (ns) 1395 softintr_schedule(sc->sc_si); 1396 } 1397 1398 return (rv); 1399 } 1400 1401 /* 1402 * software interrupt 1403 */ 1404 1405 void 1406 cdtty_rxsoft(sc, p, tp) 1407 struct cd18xx_softc *sc; 1408 struct cdtty_port *p; 1409 struct tty *tp; 1410 { 1411 u_char *get, *end; 1412 u_int cc, scc; 1413 u_char rcsr; 1414 int code; 1415 int s; 1416 1417 end = p->p_ebuf; 1418 get = p->p_rbget; 1419 scc = cc = cdtty_rbuf_size - p->p_rbavail; 1420 1421 if (cc == cdtty_rbuf_size) { 1422 p->p_floods++; 1423 #if 0 1424 if (p->p_errors++ == 0) 1425 callout_reset(&p->p_diag_callout, 60 * hz, 1426 cdttydiag, p); 1427 #endif 1428 } 1429 1430 while (cc) { 1431 code = get[0]; 1432 rcsr = get[1]; 1433 if (ISSET(rcsr, CD18xx_RCSR_OVERRUNERR | CD18xx_RCSR_BREAK | 1434 CD18xx_RCSR_FRAMERR | CD18xx_RCSR_PARITYERR)) { 1435 if (ISSET(rcsr, CD18xx_RCSR_OVERRUNERR)) { 1436 p->p_overflows++; 1437 #if 0 1438 if (p->p_errors++ == 0) 1439 callout_reset(&p->p_diag_callout, 1440 60 * hz, cdttydiag, p); 1441 #endif 1442 } 1443 if (ISSET(rcsr, CD18xx_RCSR_BREAK|CD18xx_RCSR_FRAMERR)) 1444 SET(code, TTY_FE); 1445 if (ISSET(rcsr, CD18xx_RCSR_PARITYERR)) 1446 SET(code, TTY_PE); 1447 } 1448 if ((*tp->t_linesw->l_rint)(code, tp) == -1) { 1449 /* 1450 * The line discipline's buffer is out of space. 1451 */ 1452 if (!ISSET(p->p_rx_flags, RX_TTY_BLOCKED)) { 1453 /* 1454 * We're either not using flow control, or the 1455 * line discipline didn't tell us to block for 1456 * some reason. Either way, we have no way to 1457 * know when there's more space available, so 1458 * just drop the rest of the data. 1459 */ 1460 get += cc << 1; 1461 if (get >= end) 1462 get -= cdtty_rbuf_size << 1; 1463 cc = 0; 1464 } else { 1465 /* 1466 * Don't schedule any more receive processing 1467 * until the line discipline tells us there's 1468 * space available (through cdttyhwiflow()). 1469 * Leave the rest of the data in the input 1470 * buffer. 1471 */ 1472 SET(p->p_rx_flags, RX_TTY_OVERFLOWED); 1473 } 1474 break; 1475 } 1476 get += 2; 1477 if (get >= end) 1478 get = p->p_rbuf; 1479 cc--; 1480 } 1481 1482 if (cc != scc) { 1483 p->p_rbget = get; 1484 s = splserial(); 1485 1486 cc = p->p_rbavail += scc - cc; 1487 /* Buffers should be ok again, release possible block. */ 1488 if (cc >= p->p_r_lowat) { 1489 if (ISSET(p->p_rx_flags, RX_IBUF_OVERFLOWED)) { 1490 CLR(p->p_rx_flags, RX_IBUF_OVERFLOWED); 1491 cd18xx_set_car(sc, CD18XX_CHANNEL(tp->t_dev)); 1492 SET(p->p_srer, CD18xx_SRER_Rx | 1493 CD18xx_SRER_RxSC | 1494 CD18xx_SRER_CD); 1495 cd18xx_write(sc, CD18xx_SRER, p->p_srer); 1496 } 1497 if (ISSET(p->p_rx_flags, RX_IBUF_BLOCKED)) { 1498 CLR(p->p_rx_flags, RX_IBUF_BLOCKED); 1499 cdtty_hwiflow(sc, p); 1500 } 1501 } 1502 splx(s); 1503 } 1504 } 1505 1506 void 1507 cdtty_txsoft(sc, p, tp) 1508 struct cd18xx_softc *sc; 1509 struct cdtty_port *p; 1510 struct tty *tp; 1511 { 1512 1513 CLR(tp->t_state, TS_BUSY); 1514 if (ISSET(tp->t_state, TS_FLUSH)) 1515 CLR(tp->t_state, TS_FLUSH); 1516 else 1517 ndflush(&tp->t_outq, (int)(p->p_tba - tp->t_outq.c_cf)); 1518 (*tp->t_linesw->l_start)(tp); 1519 } 1520 1521 void 1522 cdtty_stsoft(sc, p, tp) 1523 struct cd18xx_softc *sc; 1524 struct cdtty_port *p; 1525 struct tty *tp; 1526 { 1527 u_char msvr, delta; 1528 int s; 1529 1530 s = splserial(); 1531 msvr = p->p_msvr; 1532 delta = p->p_msvr_delta; 1533 p->p_msvr_delta = 0; 1534 splx(s); 1535 1536 if (ISSET(delta, p->p_msvr_dcd)) { 1537 /* 1538 * Inform the tty layer that carrier detect changed. 1539 */ 1540 (void) (*tp->t_linesw->l_modem)(tp, ISSET(msvr, CD18xx_MSVR_CD)); 1541 } 1542 1543 if (ISSET(delta, p->p_msvr_cts)) { 1544 /* Block or unblock output according to flow control. */ 1545 if (ISSET(msvr, p->p_msvr_cts)) { 1546 p->p_tx_stopped = 0; 1547 (*tp->t_linesw->l_start)(tp); 1548 } else { 1549 p->p_tx_stopped = 1; 1550 } 1551 } 1552 } 1553 1554 void 1555 cd18xx_softintr(v) 1556 void *v; 1557 { 1558 struct cd18xx_softc *sc = v; 1559 struct cdtty_port *p; 1560 struct tty *tp; 1561 int i; 1562 1563 for (i = 0; i < 8; i++) { 1564 p = &sc->sc_ports[i]; 1565 1566 tp = p->p_tty; 1567 if (tp == NULL) 1568 continue; 1569 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) 1570 continue; 1571 1572 if (p->p_rx_ready) { 1573 p->p_rx_ready = 0; 1574 cdtty_rxsoft(sc, p, tp); 1575 } 1576 1577 if (p->p_st_check) { 1578 p->p_st_check = 0; 1579 cdtty_stsoft(sc, p, tp); 1580 } 1581 1582 if (p->p_tx_done) { 1583 p->p_tx_done = 0; 1584 cdtty_txsoft(sc, p, tp); 1585 } 1586 } 1587 } 1588