rc.c revision 131096
1/* 2 * Copyright (C) 1995 by Pavel Antonov, Moscow, Russia. 3 * Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia. 4 * Copyright (C) 2002 by John Baldwin <jhb@FreeBSD.org> 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: head/sys/dev/rc/rc.c 131096 2004-06-25 10:54:46Z phk $ 29 */ 30 31/* 32 * SDL Communications Riscom/8 (based on Cirrus Logic CL-CD180) driver 33 * 34 */ 35 36/*#define RCDEBUG*/ 37 38#include "opt_tty.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/bus.h> 43#include <sys/conf.h> 44#include <sys/fcntl.h> 45#include <sys/interrupt.h> 46#include <sys/kernel.h> 47#include <sys/malloc.h> 48#include <sys/module.h> 49#include <sys/serial.h> 50#include <sys/tty.h> 51#include <machine/bus.h> 52#include <machine/resource.h> 53#include <sys/rman.h> 54 55#include <dev/ic/cd180.h> 56#include <dev/rc/rcreg.h> 57#include <isa/isavar.h> 58 59#define IOBASE_ADDRS 14 60 61#define DEV_TO_RC(dev) (struct rc_chans *)((dev)->si_drv1) 62#define TTY_TO_RC(tty) DEV_TO_RC((tty)->t_dev) 63 64#define rcin(sc, port) RC_IN(sc, port) 65#define rcout(sc, port, v) RC_OUT(sc, port, v) 66 67#define WAITFORCCR(sc, chan) rc_wait0((sc), (chan), __LINE__) 68 69#define CCRCMD(sc, chan, cmd) do { \ 70 WAITFORCCR((sc), (chan)); \ 71 rcout((sc), CD180_CCR, (cmd)); \ 72} while (0) 73 74#define RC_IBUFSIZE 256 75#define RB_I_HIGH_WATER (TTYHOG - 2 * RC_IBUFSIZE) 76#define RC_OBUFSIZE 512 77#define RC_IHIGHWATER (3 * RC_IBUFSIZE / 4) 78#define INPUT_FLAGS_SHIFT (2 * RC_IBUFSIZE) 79#define LOTS_OF_EVENTS 64 80 81#define RC_FAKEID 0x10 82 83#define CALLOUT(dev) (((intptr_t)(dev)->si_drv2) != 0) 84 85/* Per-channel structure */ 86struct rc_chans { 87 struct rc_softc *rc_rcb; /* back ptr */ 88 struct cdev *rc_dev; /* non-callout device */ 89 struct cdev *rc_cdev; /* callout device */ 90 u_short rc_flags; /* Misc. flags */ 91 int rc_chan; /* Channel # */ 92 u_char rc_ier; /* intr. enable reg */ 93 u_char rc_msvr; /* modem sig. status */ 94 u_char rc_cor2; /* options reg */ 95 u_char rc_pendcmd; /* special cmd pending */ 96 u_int rc_dtrwait; /* dtr timeout */ 97 u_int rc_dcdwaits; /* how many waits DCD in open */ 98 u_char rc_hotchar; /* end packed optimize */ 99 struct tty rc_tp; /* tty struct */ 100 u_char *rc_iptr; /* Chars input buffer */ 101 u_char *rc_hiwat; /* hi-water mark */ 102 u_char *rc_bufend; /* end of buffer */ 103 u_char *rc_optr; /* ptr in output buf */ 104 u_char *rc_obufend; /* end of output buf */ 105 u_char rc_ibuf[4 * RC_IBUFSIZE]; /* input buffer */ 106 u_char rc_obuf[RC_OBUFSIZE]; /* output buffer */ 107 struct callout rc_dtrcallout; 108}; 109 110/* Per-board structure */ 111struct rc_softc { 112 device_t sc_dev; 113 struct resource *sc_irq; 114 struct resource *sc_port[IOBASE_ADDRS]; 115 int sc_irqrid; 116 void *sc_hwicookie; 117 bus_space_tag_t sc_bt; 118 bus_space_handle_t sc_bh; 119 u_int sc_unit; /* unit # */ 120 u_char sc_dtr; /* DTR status */ 121 int sc_opencount; 122 int sc_scheduled_event; 123 void *sc_swicookie; 124 struct rc_chans sc_channels[CD180_NCHAN]; /* channels */ 125}; 126 127/* Static prototypes */ 128static int rc_break(struct tty *, int); 129static void rc_release_resources(device_t dev); 130static void rc_intr(void *); 131static void rc_hwreset(struct rc_softc *, unsigned int); 132static int rc_test(struct rc_softc *); 133static void rc_discard_output(struct rc_chans *); 134static void rc_hardclose(struct rc_chans *); 135static int rc_modem(struct tty *, int, int); 136static void rc_start(struct tty *); 137static void rc_stop(struct tty *, int rw); 138static int rc_param(struct tty *, struct termios *); 139static void rc_pollcard(void *); 140static void rc_reinit(struct rc_softc *); 141#ifdef RCDEBUG 142static void printrcflags(); 143#endif 144static void rc_dtrwakeup(void *); 145static void rc_wait0(struct rc_softc *sc, int chan, int line); 146 147static d_open_t rcopen; 148static d_close_t rcclose; 149static d_ioctl_t rcioctl; 150 151static struct cdevsw rc_cdevsw = { 152 .d_version = D_VERSION, 153 .d_open = rcopen, 154 .d_close = rcclose, 155 .d_ioctl = rcioctl, 156 .d_name = "rc", 157 .d_flags = D_TTY | D_NEEDGIANT, 158}; 159 160static devclass_t rc_devclass; 161 162/* Flags */ 163#define RC_DTR_OFF 0x0001 /* DTR wait, for close/open */ 164#define RC_ACTOUT 0x0002 /* Dial-out port active */ 165#define RC_RTSFLOW 0x0004 /* RTS flow ctl enabled */ 166#define RC_CTSFLOW 0x0008 /* CTS flow ctl enabled */ 167#define RC_DORXFER 0x0010 /* RXFER event planned */ 168#define RC_DOXXFER 0x0020 /* XXFER event planned */ 169#define RC_MODCHG 0x0040 /* Modem status changed */ 170#define RC_OSUSP 0x0080 /* Output suspended */ 171#define RC_OSBUSY 0x0100 /* start() routine in progress */ 172#define RC_WAS_BUFOVFL 0x0200 /* low-level buffer ovferflow */ 173#define RC_WAS_SILOVFL 0x0400 /* silo buffer overflow */ 174#define RC_SEND_RDY 0x0800 /* ready to send */ 175 176/* Table for translation of RCSR status bits to internal form */ 177static int rc_rcsrt[16] = { 178 0, TTY_OE, TTY_FE, 179 TTY_FE|TTY_OE, TTY_PE, TTY_PE|TTY_OE, 180 TTY_PE|TTY_FE, TTY_PE|TTY_FE|TTY_OE, TTY_BI, 181 TTY_BI|TTY_OE, TTY_BI|TTY_FE, TTY_BI|TTY_FE|TTY_OE, 182 TTY_BI|TTY_PE, TTY_BI|TTY_PE|TTY_OE, TTY_BI|TTY_PE|TTY_FE, 183 TTY_BI|TTY_PE|TTY_FE|TTY_OE 184}; 185 186static int rc_ports[] = 187 { 0x220, 0x240, 0x250, 0x260, 0x2a0, 0x2b0, 0x300, 0x320 }; 188static int iobase_addrs[IOBASE_ADDRS] = 189 { 0, 0x400, 0x800, 0xc00, 0x1400, 0x1800, 0x1c00, 0x2000, 190 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x8000 }; 191 192/**********************************************/ 193 194static int 195rc_probe(device_t dev) 196{ 197 u_int port; 198 int i, found; 199 200 /* 201 * We don't know of any PnP ID's for these cards. 202 */ 203 if (isa_get_logicalid(dev) != 0) 204 return (ENXIO); 205 206 /* 207 * We have to have an IO port hint that is valid. 208 */ 209 port = isa_get_port(dev); 210 if (port == -1) 211 return (ENXIO); 212 found = 0; 213 for (i = 0; i < sizeof(rc_ports) / sizeof(int); i++) 214 if (rc_ports[i] == port) { 215 found = 1; 216 break; 217 } 218 if (!found) 219 return (ENXIO); 220 221 /* 222 * We have to have an IRQ hint. 223 */ 224 if (isa_get_irq(dev) == -1) 225 return (ENXIO); 226 227 device_set_desc(dev, "SDL Riscom/8"); 228 return (0); 229} 230 231static int 232rc_attach(device_t dev) 233{ 234 struct rc_chans *rc; 235 struct tty *tp; 236 struct rc_softc *sc; 237 u_int port; 238 int base, chan, error, i, x; 239 struct cdev *cdev; 240 241 sc = device_get_softc(dev); 242 sc->sc_dev = dev; 243 244 /* 245 * We need to have IO ports. Lots of them. We need 246 * the following ranges relative to the base port: 247 * 0x0 - 0x10 248 * 0x400 - 0x410 249 * 0x800 - 0x810 250 * 0xc00 - 0xc10 251 * 0x1400 - 0x1410 252 * 0x1800 - 0x1810 253 * 0x1c00 - 0x1c10 254 * 0x2000 - 0x2010 255 * 0x3000 - 0x3010 256 * 0x3400 - 0x3410 257 * 0x3800 - 0x3810 258 * 0x3c00 - 0x3c10 259 * 0x4000 - 0x4010 260 * 0x8000 - 0x8010 261 */ 262 port = isa_get_port(dev); 263 for (i = 0; i < IOBASE_ADDRS; i++) 264 if (bus_set_resource(dev, SYS_RES_IOPORT, i, 265 port + iobase_addrs[i], 0x10) != 0) 266 return (ENXIO); 267 error = ENOMEM; 268 for (i = 0; i < IOBASE_ADDRS; i++) { 269 x = i; 270 sc->sc_port[i] = bus_alloc_resource(dev, SYS_RES_IOPORT, &x, 271 0ul, ~0ul, 0x10, RF_ACTIVE); 272 if (x != i) { 273 device_printf(dev, "ioport %d was rid %d\n", i, x); 274 goto fail; 275 } 276 if (sc->sc_port[i] == NULL) { 277 device_printf(dev, "failed to alloc ioports %x-%x\n", 278 port + iobase_addrs[i], 279 port + iobase_addrs[i] + 0x10); 280 goto fail; 281 } 282 } 283 sc->sc_bt = rman_get_bustag(sc->sc_port[0]); 284 sc->sc_bh = rman_get_bushandle(sc->sc_port[0]); 285 286 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid, 287 RF_ACTIVE); 288 if (sc->sc_irq == NULL) { 289 device_printf(dev, "failed to alloc IRQ\n"); 290 goto fail; 291 } 292 293 /* 294 * Now do some actual tests to make sure it works. 295 */ 296 error = ENXIO; 297 rcout(sc, CD180_PPRL, 0x22); /* Random values to Prescale reg. */ 298 rcout(sc, CD180_PPRH, 0x11); 299 if (rcin(sc, CD180_PPRL) != 0x22 || rcin(sc, CD180_PPRH) != 0x11) 300 goto fail; 301 if (rc_test(sc)) 302 goto fail; 303 304 /* 305 * Ok, start actually hooking things up. 306 */ 307 sc->sc_unit = device_get_unit(dev); 308 /*sc->sc_chipid = 0x10 + device_get_unit(dev);*/ 309 device_printf(dev, "%d chans, firmware rev. %c\n", 310 CD180_NCHAN, (rcin(sc, CD180_GFRCR) & 0xF) + 'A'); 311 rc = sc->sc_channels; 312 base = CD180_NCHAN * sc->sc_unit; 313 for (chan = 0; chan < CD180_NCHAN; chan++, rc++) { 314 rc->rc_rcb = sc; 315 rc->rc_chan = chan; 316 rc->rc_iptr = rc->rc_ibuf; 317 rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE]; 318 rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER]; 319 rc->rc_optr = rc->rc_obufend = rc->rc_obuf; 320 rc->rc_dtrwait = 3 * hz; 321 callout_init(&rc->rc_dtrcallout, 0); 322 tp = &rc->rc_tp; 323 ttychars(tp); 324 tp->t_lflag = tp->t_iflag = tp->t_oflag = 0; 325 tp->t_cflag = TTYDEF_CFLAG; 326 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 327 cdev = make_dev(&rc_cdevsw, chan + base, 328 UID_ROOT, GID_WHEEL, 0600, "ttym%d", chan + base); 329 cdev->si_drv1 = rc; 330 cdev->si_drv2 = 0; 331 cdev->si_tty = tp; 332 rc->rc_dev = cdev; 333 cdev = make_dev(&rc_cdevsw, chan + base + 128, 334 UID_UUCP, GID_DIALER, 0660, "cuam%d", chan + base); 335 cdev->si_drv1 = rc; 336 cdev->si_drv2 = (void *)1; 337 cdev->si_tty = tp; 338 rc->rc_cdev = cdev; 339 } 340 341 error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_TTY, rc_intr, sc, 342 &sc->sc_hwicookie); 343 if (error) { 344 device_printf(dev, "failed to register interrupt handler\n"); 345 goto fail; 346 } 347 348 swi_add(&tty_ithd, "tty:rc", rc_pollcard, sc, SWI_TTY, 0, 349 &sc->sc_swicookie); 350 return (0); 351 352fail: 353 rc_release_resources(dev); 354 return (error); 355} 356 357static int 358rc_detach(device_t dev) 359{ 360 struct rc_softc *sc; 361 struct rc_chans *rc; 362 int error, i, s; 363 364 sc = device_get_softc(dev); 365 if (sc->sc_opencount > 0) 366 return (EBUSY); 367 sc->sc_opencount = -1; 368 369 rc = sc->sc_channels; 370 for (i = 0; i < CD180_NCHAN; i++, rc++) { 371 destroy_dev(rc->rc_dev); 372 destroy_dev(rc->rc_cdev); 373 } 374 375 rc = sc->sc_channels; 376 s = splsoftclock(); 377 for (i = 0; i < CD180_NCHAN; i++) { 378 if ((rc->rc_flags & RC_DTR_OFF) && 379 !callout_stop(&rc->rc_dtrcallout)) 380 tsleep(&rc->rc_dtrwait, TTIPRI, "rcdtrdet", 0); 381 } 382 383 error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie); 384 if (error) 385 device_printf(dev, "failed to deregister interrupt handler\n"); 386 ithread_remove_handler(sc->sc_swicookie); 387 rc_release_resources(dev); 388 389 return (0); 390} 391 392static void 393rc_release_resources(device_t dev) 394{ 395 struct rc_softc *sc; 396 int i; 397 398 sc = device_get_softc(dev); 399 if (sc->sc_irq != NULL) { 400 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid, 401 sc->sc_irq); 402 sc->sc_irq = NULL; 403 } 404 for (i = 0; i < IOBASE_ADDRS; i++) { 405 if (sc->sc_port[i] == NULL) 406 break; 407 bus_release_resource(dev, SYS_RES_IOPORT, i, sc->sc_port[i]); 408 sc->sc_port[i] = NULL; 409 } 410} 411 412/* RC interrupt handling */ 413static void 414rc_intr(void *arg) 415{ 416 struct rc_softc *sc; 417 struct rc_chans *rc; 418 int resid, chan; 419 u_char val, iack, bsr, ucnt, *optr; 420 int good_data, t_state; 421 422 sc = (struct rc_softc *)arg; 423 bsr = ~(rcin(sc, RC_BSR)); 424 if (!(bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT))) { 425 device_printf(sc->sc_dev, "extra interrupt\n"); 426 rcout(sc, CD180_EOIR, 0); 427 return; 428 } 429 430 while (bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT)) { 431#ifdef RCDEBUG_DETAILED 432 device_printf(sc->sc_dev, "intr (%p) %s%s%s%s\n", arg, bsr, 433 (bsr & RC_BSR_TOUT)?"TOUT ":"", 434 (bsr & RC_BSR_RXINT)?"RXINT ":"", 435 (bsr & RC_BSR_TXINT)?"TXINT ":"", 436 (bsr & RC_BSR_MOINT)?"MOINT":""); 437#endif 438 if (bsr & RC_BSR_TOUT) { 439 device_printf(sc->sc_dev, 440 "hardware failure, reset board\n"); 441 rcout(sc, RC_CTOUT, 0); 442 rc_reinit(sc); 443 return; 444 } 445 if (bsr & RC_BSR_RXINT) { 446 iack = rcin(sc, RC_PILR_RX); 447 good_data = (iack == (GIVR_IT_RGDI | RC_FAKEID)); 448 if (!good_data && iack != (GIVR_IT_REI | RC_FAKEID)) { 449 device_printf(sc->sc_dev, 450 "fake rxint: %02x\n", iack); 451 goto more_intrs; 452 } 453 chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); 454 rc = &sc->sc_channels[chan]; 455 t_state = rc->rc_tp.t_state; 456 /* Do RTS flow control stuff */ 457 if ( (rc->rc_flags & RC_RTSFLOW) 458 || !(t_state & TS_ISOPEN) 459 ) { 460 if ( ( !(t_state & TS_ISOPEN) 461 || (t_state & TS_TBLOCK) 462 ) 463 && (rc->rc_msvr & MSVR_RTS) 464 ) 465 rcout(sc, CD180_MSVR, 466 rc->rc_msvr &= ~MSVR_RTS); 467 else if (!(rc->rc_msvr & MSVR_RTS)) 468 rcout(sc, CD180_MSVR, 469 rc->rc_msvr |= MSVR_RTS); 470 } 471 ucnt = rcin(sc, CD180_RDCR) & 0xF; 472 resid = 0; 473 474 if (t_state & TS_ISOPEN) { 475 /* check for input buffer overflow */ 476 if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) { 477 resid = ucnt; 478 ucnt = rc->rc_bufend - rc->rc_iptr; 479 resid -= ucnt; 480 if (!(rc->rc_flags & RC_WAS_BUFOVFL)) { 481 rc->rc_flags |= RC_WAS_BUFOVFL; 482 sc->sc_scheduled_event++; 483 } 484 } 485 optr = rc->rc_iptr; 486 /* check foor good data */ 487 if (good_data) { 488 while (ucnt-- > 0) { 489 val = rcin(sc, CD180_RDR); 490 optr[0] = val; 491 optr[INPUT_FLAGS_SHIFT] = 0; 492 optr++; 493 sc->sc_scheduled_event++; 494 if (val != 0 && val == rc->rc_hotchar) 495 swi_sched(sc->sc_swicookie, 0); 496 } 497 } else { 498 /* Store also status data */ 499 while (ucnt-- > 0) { 500 iack = rcin(sc, CD180_RCSR); 501 if (iack & RCSR_Timeout) 502 break; 503 if ( (iack & RCSR_OE) 504 && !(rc->rc_flags & RC_WAS_SILOVFL)) { 505 rc->rc_flags |= RC_WAS_SILOVFL; 506 sc->sc_scheduled_event++; 507 } 508 val = rcin(sc, CD180_RDR); 509 /* 510 Don't store PE if IGNPAR and BREAK if IGNBRK, 511 this hack allows "raw" tty optimization 512 works even if IGN* is set. 513 */ 514 if ( !(iack & (RCSR_PE|RCSR_FE|RCSR_Break)) 515 || ((!(iack & (RCSR_PE|RCSR_FE)) 516 || !(rc->rc_tp.t_iflag & IGNPAR)) 517 && (!(iack & RCSR_Break) 518 || !(rc->rc_tp.t_iflag & IGNBRK)))) { 519 if ( (iack & (RCSR_PE|RCSR_FE)) 520 && (t_state & TS_CAN_BYPASS_L_RINT) 521 && ((iack & RCSR_FE) 522 || ((iack & RCSR_PE) 523 && (rc->rc_tp.t_iflag & INPCK)))) 524 val = 0; 525 else if (val != 0 && val == rc->rc_hotchar) 526 swi_sched(sc->sc_swicookie, 0); 527 optr[0] = val; 528 optr[INPUT_FLAGS_SHIFT] = iack; 529 optr++; 530 sc->sc_scheduled_event++; 531 } 532 } 533 } 534 rc->rc_iptr = optr; 535 rc->rc_flags |= RC_DORXFER; 536 } else 537 resid = ucnt; 538 /* Clear FIFO if necessary */ 539 while (resid-- > 0) { 540 if (!good_data) 541 iack = rcin(sc, CD180_RCSR); 542 else 543 iack = 0; 544 if (iack & RCSR_Timeout) 545 break; 546 (void) rcin(sc, CD180_RDR); 547 } 548 goto more_intrs; 549 } 550 if (bsr & RC_BSR_MOINT) { 551 iack = rcin(sc, RC_PILR_MODEM); 552 if (iack != (GIVR_IT_MSCI | RC_FAKEID)) { 553 device_printf(sc->sc_dev, "fake moint: %02x\n", 554 iack); 555 goto more_intrs; 556 } 557 chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); 558 rc = &sc->sc_channels[chan]; 559 iack = rcin(sc, CD180_MCR); 560 rc->rc_msvr = rcin(sc, CD180_MSVR); 561 rcout(sc, CD180_MCR, 0); 562#ifdef RCDEBUG 563 printrcflags(rc, "moint"); 564#endif 565 if (rc->rc_flags & RC_CTSFLOW) { 566 if (rc->rc_msvr & MSVR_CTS) 567 rc->rc_flags |= RC_SEND_RDY; 568 else 569 rc->rc_flags &= ~RC_SEND_RDY; 570 } else 571 rc->rc_flags |= RC_SEND_RDY; 572 if ((iack & MCR_CDchg) && !(rc->rc_flags & RC_MODCHG)) { 573 sc->sc_scheduled_event += LOTS_OF_EVENTS; 574 rc->rc_flags |= RC_MODCHG; 575 swi_sched(sc->sc_swicookie, 0); 576 } 577 goto more_intrs; 578 } 579 if (bsr & RC_BSR_TXINT) { 580 iack = rcin(sc, RC_PILR_TX); 581 if (iack != (GIVR_IT_TDI | RC_FAKEID)) { 582 device_printf(sc->sc_dev, "fake txint: %02x\n", 583 iack); 584 goto more_intrs; 585 } 586 chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); 587 rc = &sc->sc_channels[chan]; 588 if ( (rc->rc_flags & RC_OSUSP) 589 || !(rc->rc_flags & RC_SEND_RDY) 590 ) 591 goto more_intrs; 592 /* Handle breaks and other stuff */ 593 if (rc->rc_pendcmd) { 594 rcout(sc, CD180_COR2, rc->rc_cor2 |= COR2_ETC); 595 rcout(sc, CD180_TDR, CD180_C_ESC); 596 rcout(sc, CD180_TDR, rc->rc_pendcmd); 597 rcout(sc, CD180_COR2, rc->rc_cor2 &= ~COR2_ETC); 598 rc->rc_pendcmd = 0; 599 goto more_intrs; 600 } 601 optr = rc->rc_optr; 602 resid = rc->rc_obufend - optr; 603 if (resid > CD180_NFIFO) 604 resid = CD180_NFIFO; 605 while (resid-- > 0) 606 rcout(sc, CD180_TDR, *optr++); 607 rc->rc_optr = optr; 608 609 /* output completed? */ 610 if (optr >= rc->rc_obufend) { 611 rcout(sc, CD180_IER, rc->rc_ier &= ~IER_TxRdy); 612#ifdef RCDEBUG 613 device_printf(sc->sc_dev, 614 "channel %d: output completed\n", 615 rc->rc_chan); 616#endif 617 if (!(rc->rc_flags & RC_DOXXFER)) { 618 sc->sc_scheduled_event += LOTS_OF_EVENTS; 619 rc->rc_flags |= RC_DOXXFER; 620 swi_sched(sc->sc_swicookie, 0); 621 } 622 } 623 } 624 more_intrs: 625 rcout(sc, CD180_EOIR, 0); /* end of interrupt */ 626 rcout(sc, RC_CTOUT, 0); 627 bsr = ~(rcin(sc, RC_BSR)); 628 } 629} 630 631/* Feed characters to output buffer */ 632static void 633rc_start(struct tty *tp) 634{ 635 struct rc_softc *sc; 636 struct rc_chans *rc; 637 int s; 638 639 rc = TTY_TO_RC(tp); 640 if (rc->rc_flags & RC_OSBUSY) 641 return; 642 sc = rc->rc_rcb; 643 s = spltty(); 644 rc->rc_flags |= RC_OSBUSY; 645 critical_enter(); 646 if (tp->t_state & TS_TTSTOP) 647 rc->rc_flags |= RC_OSUSP; 648 else 649 rc->rc_flags &= ~RC_OSUSP; 650 /* Do RTS flow control stuff */ 651 if ( (rc->rc_flags & RC_RTSFLOW) 652 && (tp->t_state & TS_TBLOCK) 653 && (rc->rc_msvr & MSVR_RTS) 654 ) { 655 rcout(sc, CD180_CAR, rc->rc_chan); 656 rcout(sc, CD180_MSVR, rc->rc_msvr &= ~MSVR_RTS); 657 } else if (!(rc->rc_msvr & MSVR_RTS)) { 658 rcout(sc, CD180_CAR, rc->rc_chan); 659 rcout(sc, CD180_MSVR, rc->rc_msvr |= MSVR_RTS); 660 } 661 critical_exit(); 662 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 663 goto out; 664#ifdef RCDEBUG 665 printrcflags(rc, "rcstart"); 666#endif 667 ttwwakeup(tp); 668#ifdef RCDEBUG 669 printf("rcstart: outq = %d obuf = %d\n", 670 tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr); 671#endif 672 if (tp->t_state & TS_BUSY) 673 goto out; /* output still in progress ... */ 674 675 if (tp->t_outq.c_cc > 0) { 676 u_int ocnt; 677 678 tp->t_state |= TS_BUSY; 679 ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf); 680 critical_enter(); 681 rc->rc_optr = rc->rc_obuf; 682 rc->rc_obufend = rc->rc_optr + ocnt; 683 critical_exit(); 684 if (!(rc->rc_ier & IER_TxRdy)) { 685#ifdef RCDEBUG 686 device_printf(sc->sc_dev, 687 "channel %d: rcstart enable txint\n", rc->rc_chan); 688#endif 689 rcout(sc, CD180_CAR, rc->rc_chan); 690 rcout(sc, CD180_IER, rc->rc_ier |= IER_TxRdy); 691 } 692 } 693out: 694 rc->rc_flags &= ~RC_OSBUSY; 695 (void) splx(s); 696} 697 698/* Handle delayed events. */ 699void 700rc_pollcard(void *arg) 701{ 702 struct rc_softc *sc; 703 struct rc_chans *rc; 704 struct tty *tp; 705 u_char *tptr, *eptr; 706 int chan, icnt; 707 708 sc = (struct rc_softc *)arg; 709 if (sc->sc_scheduled_event == 0) 710 return; 711 do { 712 rc = sc->sc_channels; 713 for (chan = 0; chan < CD180_NCHAN; rc++, chan++) { 714 tp = &rc->rc_tp; 715#ifdef RCDEBUG 716 if (rc->rc_flags & (RC_DORXFER|RC_DOXXFER|RC_MODCHG| 717 RC_WAS_BUFOVFL|RC_WAS_SILOVFL)) 718 printrcflags(rc, "rcevent"); 719#endif 720 if (rc->rc_flags & RC_WAS_BUFOVFL) { 721 critical_enter(); 722 rc->rc_flags &= ~RC_WAS_BUFOVFL; 723 sc->sc_scheduled_event--; 724 critical_exit(); 725 device_printf(sc->sc_dev, 726 "channel %d: interrupt-level buffer overflow\n", 727 chan); 728 } 729 if (rc->rc_flags & RC_WAS_SILOVFL) { 730 critical_enter(); 731 rc->rc_flags &= ~RC_WAS_SILOVFL; 732 sc->sc_scheduled_event--; 733 critical_exit(); 734 device_printf(sc->sc_dev, 735 "channel %d: silo overflow\n", chan); 736 } 737 if (rc->rc_flags & RC_MODCHG) { 738 critical_enter(); 739 rc->rc_flags &= ~RC_MODCHG; 740 sc->sc_scheduled_event -= LOTS_OF_EVENTS; 741 critical_exit(); 742 ttyld_modem(tp, !!(rc->rc_msvr & MSVR_CD)); 743 } 744 if (rc->rc_flags & RC_DORXFER) { 745 critical_enter(); 746 rc->rc_flags &= ~RC_DORXFER; 747 eptr = rc->rc_iptr; 748 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) 749 tptr = &rc->rc_ibuf[RC_IBUFSIZE]; 750 else 751 tptr = rc->rc_ibuf; 752 icnt = eptr - tptr; 753 if (icnt > 0) { 754 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) { 755 rc->rc_iptr = rc->rc_ibuf; 756 rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE]; 757 rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER]; 758 } else { 759 rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE]; 760 rc->rc_bufend = &rc->rc_ibuf[2 * RC_IBUFSIZE]; 761 rc->rc_hiwat = 762 &rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER]; 763 } 764 if ( (rc->rc_flags & RC_RTSFLOW) 765 && (tp->t_state & TS_ISOPEN) 766 && !(tp->t_state & TS_TBLOCK) 767 && !(rc->rc_msvr & MSVR_RTS) 768 ) { 769 rcout(sc, CD180_CAR, chan); 770 rcout(sc, CD180_MSVR, 771 rc->rc_msvr |= MSVR_RTS); 772 } 773 sc->sc_scheduled_event -= icnt; 774 } 775 critical_exit(); 776 777 if (icnt <= 0 || !(tp->t_state & TS_ISOPEN)) 778 goto done1; 779 780 if ( (tp->t_state & TS_CAN_BYPASS_L_RINT) 781 && !(tp->t_state & TS_LOCAL)) { 782 if ((tp->t_rawq.c_cc + icnt) >= RB_I_HIGH_WATER 783 && ((rc->rc_flags & RC_RTSFLOW) || (tp->t_iflag & IXOFF)) 784 && !(tp->t_state & TS_TBLOCK)) 785 ttyblock(tp); 786 tk_nin += icnt; 787 tk_rawcc += icnt; 788 tp->t_rawcc += icnt; 789 if (b_to_q(tptr, icnt, &tp->t_rawq)) 790 device_printf(sc->sc_dev, 791 "channel %d: tty-level buffer overflow\n", 792 chan); 793 ttwakeup(tp); 794 if ((tp->t_state & TS_TTSTOP) && ((tp->t_iflag & IXANY) 795 || (tp->t_cc[VSTART] == tp->t_cc[VSTOP]))) { 796 tp->t_state &= ~TS_TTSTOP; 797 tp->t_lflag &= ~FLUSHO; 798 rc_start(tp); 799 } 800 } else { 801 for (; tptr < eptr; tptr++) 802 ttyld_rint(tp, 803 (tptr[0] | 804 rc_rcsrt[tptr[INPUT_FLAGS_SHIFT] & 0xF])); 805 } 806done1: ; 807 } 808 if (rc->rc_flags & RC_DOXXFER) { 809 critical_enter(); 810 sc->sc_scheduled_event -= LOTS_OF_EVENTS; 811 rc->rc_flags &= ~RC_DOXXFER; 812 rc->rc_tp.t_state &= ~TS_BUSY; 813 critical_exit(); 814 ttyld_start(tp); 815 } 816 if (sc->sc_scheduled_event == 0) 817 break; 818 } 819 } while (sc->sc_scheduled_event >= LOTS_OF_EVENTS); 820} 821 822static void 823rc_stop(struct tty *tp, int rw) 824{ 825 struct rc_softc *sc; 826 struct rc_chans *rc; 827 u_char *tptr, *eptr; 828 829 rc = TTY_TO_RC(tp); 830 sc = rc->rc_rcb; 831#ifdef RCDEBUG 832 device_printf(sc->sc_dev, "channel %d: rc_stop %s%s\n", 833 rc->rc_chan, (rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":""); 834#endif 835 if (rw & FWRITE) 836 rc_discard_output(rc); 837 critical_enter(); 838 if (rw & FREAD) { 839 rc->rc_flags &= ~RC_DORXFER; 840 eptr = rc->rc_iptr; 841 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) { 842 tptr = &rc->rc_ibuf[RC_IBUFSIZE]; 843 rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE]; 844 } else { 845 tptr = rc->rc_ibuf; 846 rc->rc_iptr = rc->rc_ibuf; 847 } 848 sc->sc_scheduled_event -= eptr - tptr; 849 } 850 if (tp->t_state & TS_TTSTOP) 851 rc->rc_flags |= RC_OSUSP; 852 else 853 rc->rc_flags &= ~RC_OSUSP; 854 critical_exit(); 855} 856 857static int 858rcopen(struct cdev *dev, int flag, int mode, d_thread_t *td) 859{ 860 struct rc_softc *sc; 861 struct rc_chans *rc; 862 struct tty *tp; 863 int s, error = 0; 864 865 rc = DEV_TO_RC(dev); 866 sc = rc->rc_rcb; 867 tp = &rc->rc_tp; 868 if (sc->sc_opencount < 0) 869 return (ENXIO); 870 sc->sc_opencount++; 871#ifdef RCDEBUG 872 device_printf(sc->sc_dev, "channel %d: rcopen: dev %p\n", 873 rc->rc_chan, dev); 874#endif 875 s = spltty(); 876 877again: 878 while (rc->rc_flags & RC_DTR_OFF) { 879 error = tsleep(&(rc->rc_dtrwait), TTIPRI | PCATCH, "rcdtr", 0); 880 if (error != 0) 881 goto out; 882 } 883 if (tp->t_state & TS_ISOPEN) { 884 if (CALLOUT(dev)) { 885 if (!(rc->rc_flags & RC_ACTOUT)) { 886 error = EBUSY; 887 goto out; 888 } 889 } else { 890 if (rc->rc_flags & RC_ACTOUT) { 891 if (flag & O_NONBLOCK) { 892 error = EBUSY; 893 goto out; 894 } 895 error = tsleep(&rc->rc_rcb, 896 TTIPRI|PCATCH, "rcbi", 0); 897 if (error) 898 goto out; 899 goto again; 900 } 901 } 902 if (tp->t_state & TS_XCLUDE && 903 suser(td)) { 904 error = EBUSY; 905 goto out; 906 } 907 } else { 908 tp->t_oproc = rc_start; 909 tp->t_param = rc_param; 910 tp->t_modem = rc_modem; 911 tp->t_break = rc_break; 912 tp->t_stop = rc_stop; 913 tp->t_dev = dev; 914 915 if (CALLOUT(dev)) 916 tp->t_cflag |= CLOCAL; 917 else 918 tp->t_cflag &= ~CLOCAL; 919 920 error = rc_param(tp, &tp->t_termios); 921 if (error) 922 goto out; 923 (void) rc_modem(tp, SER_DTR | SER_RTS, 0); 924 925 if ((rc->rc_msvr & MSVR_CD) || CALLOUT(dev)) 926 ttyld_modem(tp, 1); 927 } 928 if (!(tp->t_state & TS_CARR_ON) && !CALLOUT(dev) 929 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 930 rc->rc_dcdwaits++; 931 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "rcdcd", 0); 932 rc->rc_dcdwaits--; 933 if (error != 0) 934 goto out; 935 goto again; 936 } 937 error = ttyld_open(tp, dev); 938 rc->rc_hotchar = ttyldoptim(tp); 939 if ((tp->t_state & TS_ISOPEN) && CALLOUT(dev)) 940 rc->rc_flags |= RC_ACTOUT; 941out: 942 (void) splx(s); 943 944 if(rc->rc_dcdwaits == 0 && !(tp->t_state & TS_ISOPEN)) 945 rc_hardclose(rc); 946 947 return error; 948} 949 950static int 951rcclose(struct cdev *dev, int flag, int mode, d_thread_t *td) 952{ 953 struct rc_softc *sc; 954 struct rc_chans *rc; 955 struct tty *tp; 956 int s; 957 958 rc = DEV_TO_RC(dev); 959 sc = rc->rc_rcb; 960 tp = &rc->rc_tp; 961#ifdef RCDEBUG 962 device_printf(sc->sc_dev, "channel %d: rcclose dev %p\n", 963 rc->rc_chan, dev); 964#endif 965 s = spltty(); 966 ttyld_close(tp, flag); 967 rc->rc_hotchar = ttyldoptim(tp); 968 rc_hardclose(rc); 969 ttyclose(tp); 970 splx(s); 971 KASSERT(sc->sc_opencount > 0, ("rcclose: non-positive open count")); 972 sc->sc_opencount--; 973 return 0; 974} 975 976static void 977rc_hardclose(struct rc_chans *rc) 978{ 979 struct rc_softc *sc; 980 struct tty *tp; 981 int s; 982 983 tp = &rc->rc_tp; 984 sc = rc->rc_rcb; 985 s = spltty(); 986 rcout(sc, CD180_CAR, rc->rc_chan); 987 988 /* Disable rx/tx intrs */ 989 rcout(sc, CD180_IER, rc->rc_ier = 0); 990 if ( (tp->t_cflag & HUPCL) 991 || (!(rc->rc_flags & RC_ACTOUT) 992 && !(rc->rc_msvr & MSVR_CD) 993 && !(tp->t_cflag & CLOCAL)) 994 || !(tp->t_state & TS_ISOPEN) 995 ) { 996 CCRCMD(sc, rc->rc_chan, CCR_ResetChan); 997 WAITFORCCR(sc, rc->rc_chan); 998 (void) rc_modem(tp, SER_RTS, 0); 999 if (rc->rc_dtrwait) { 1000 callout_reset(&rc->rc_dtrcallout, rc->rc_dtrwait, 1001 rc_dtrwakeup, rc); 1002 rc->rc_flags |= RC_DTR_OFF; 1003 } 1004 } 1005 rc->rc_flags &= ~RC_ACTOUT; 1006 wakeup( &rc->rc_rcb); /* wake bi */ 1007 wakeup(TSA_CARR_ON(tp)); 1008 (void) splx(s); 1009} 1010 1011/* Reset the bastard */ 1012static void 1013rc_hwreset(struct rc_softc *sc, u_int chipid) 1014{ 1015 CCRCMD(sc, -1, CCR_HWRESET); /* Hardware reset */ 1016 DELAY(20000); 1017 WAITFORCCR(sc, -1); 1018 1019 rcout(sc, RC_CTOUT, 0); /* Clear timeout */ 1020 rcout(sc, CD180_GIVR, chipid); 1021 rcout(sc, CD180_GICR, 0); 1022 1023 /* Set Prescaler Registers (1 msec) */ 1024 rcout(sc, CD180_PPRL, ((RC_OSCFREQ + 999) / 1000) & 0xFF); 1025 rcout(sc, CD180_PPRH, ((RC_OSCFREQ + 999) / 1000) >> 8); 1026 1027 /* Initialize Priority Interrupt Level Registers */ 1028 rcout(sc, CD180_PILR1, RC_PILR_MODEM); 1029 rcout(sc, CD180_PILR2, RC_PILR_TX); 1030 rcout(sc, CD180_PILR3, RC_PILR_RX); 1031 1032 /* Reset DTR */ 1033 rcout(sc, RC_DTREG, ~0); 1034} 1035 1036/* Set channel parameters */ 1037static int 1038rc_param(struct tty *tp, struct termios *ts) 1039{ 1040 struct rc_softc *sc; 1041 struct rc_chans *rc; 1042 int idivs, odivs, s, val, cflag, iflag, lflag, inpflow; 1043 1044 if ( ts->c_ospeed < 0 || ts->c_ospeed > 76800 1045 || ts->c_ispeed < 0 || ts->c_ispeed > 76800 1046 ) 1047 return (EINVAL); 1048 if (ts->c_ispeed == 0) 1049 ts->c_ispeed = ts->c_ospeed; 1050 odivs = RC_BRD(ts->c_ospeed); 1051 idivs = RC_BRD(ts->c_ispeed); 1052 1053 rc = TTY_TO_RC(tp); 1054 sc = rc->rc_rcb; 1055 s = spltty(); 1056 1057 /* Select channel */ 1058 rcout(sc, CD180_CAR, rc->rc_chan); 1059 1060 /* If speed == 0, hangup line */ 1061 if (ts->c_ospeed == 0) { 1062 CCRCMD(sc, rc->rc_chan, CCR_ResetChan); 1063 WAITFORCCR(sc, rc->rc_chan); 1064 (void) rc_modem(tp, 0, SER_DTR); 1065 } 1066 1067 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 1068 cflag = ts->c_cflag; 1069 iflag = ts->c_iflag; 1070 lflag = ts->c_lflag; 1071 1072 if (idivs > 0) { 1073 rcout(sc, CD180_RBPRL, idivs & 0xFF); 1074 rcout(sc, CD180_RBPRH, idivs >> 8); 1075 } 1076 if (odivs > 0) { 1077 rcout(sc, CD180_TBPRL, odivs & 0xFF); 1078 rcout(sc, CD180_TBPRH, odivs >> 8); 1079 } 1080 1081 /* set timeout value */ 1082 if (ts->c_ispeed > 0) { 1083 int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1; 1084 1085 if ( !(lflag & ICANON) 1086 && ts->c_cc[VMIN] != 0 && ts->c_cc[VTIME] != 0 1087 && ts->c_cc[VTIME] * 10 > itm) 1088 itm = ts->c_cc[VTIME] * 10; 1089 1090 rcout(sc, CD180_RTPR, itm <= 255 ? itm : 255); 1091 } 1092 1093 switch (cflag & CSIZE) { 1094 case CS5: val = COR1_5BITS; break; 1095 case CS6: val = COR1_6BITS; break; 1096 case CS7: val = COR1_7BITS; break; 1097 default: 1098 case CS8: val = COR1_8BITS; break; 1099 } 1100 if (cflag & PARENB) { 1101 val |= COR1_NORMPAR; 1102 if (cflag & PARODD) 1103 val |= COR1_ODDP; 1104 if (!(cflag & INPCK)) 1105 val |= COR1_Ignore; 1106 } else 1107 val |= COR1_Ignore; 1108 if (cflag & CSTOPB) 1109 val |= COR1_2SB; 1110 rcout(sc, CD180_COR1, val); 1111 1112 /* Set FIFO threshold */ 1113 val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2; 1114 inpflow = 0; 1115 if ( (iflag & IXOFF) 1116 && ( ts->c_cc[VSTOP] != _POSIX_VDISABLE 1117 && ( ts->c_cc[VSTART] != _POSIX_VDISABLE 1118 || (iflag & IXANY) 1119 ) 1120 ) 1121 ) { 1122 inpflow = 1; 1123 val |= COR3_SCDE|COR3_FCT; 1124 } 1125 rcout(sc, CD180_COR3, val); 1126 1127 /* Initialize on-chip automatic flow control */ 1128 val = 0; 1129 rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY); 1130 if (cflag & CCTS_OFLOW) { 1131 rc->rc_flags |= RC_CTSFLOW; 1132 val |= COR2_CtsAE; 1133 } else 1134 rc->rc_flags |= RC_SEND_RDY; 1135 if (tp->t_state & TS_TTSTOP) 1136 rc->rc_flags |= RC_OSUSP; 1137 else 1138 rc->rc_flags &= ~RC_OSUSP; 1139 if (cflag & CRTS_IFLOW) 1140 rc->rc_flags |= RC_RTSFLOW; 1141 else 1142 rc->rc_flags &= ~RC_RTSFLOW; 1143 1144 if (inpflow) { 1145 if (ts->c_cc[VSTART] != _POSIX_VDISABLE) 1146 rcout(sc, CD180_SCHR1, ts->c_cc[VSTART]); 1147 rcout(sc, CD180_SCHR2, ts->c_cc[VSTOP]); 1148 val |= COR2_TxIBE; 1149 if (iflag & IXANY) 1150 val |= COR2_IXM; 1151 } 1152 1153 rcout(sc, CD180_COR2, rc->rc_cor2 = val); 1154 1155 CCRCMD(sc, rc->rc_chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); 1156 1157 rc->rc_hotchar = ttyldoptim(tp); 1158 1159 /* modem ctl */ 1160 val = cflag & CLOCAL ? 0 : MCOR1_CDzd; 1161 if (cflag & CCTS_OFLOW) 1162 val |= MCOR1_CTSzd; 1163 rcout(sc, CD180_MCOR1, val); 1164 1165 val = cflag & CLOCAL ? 0 : MCOR2_CDod; 1166 if (cflag & CCTS_OFLOW) 1167 val |= MCOR2_CTSod; 1168 rcout(sc, CD180_MCOR2, val); 1169 1170 /* enable i/o and interrupts */ 1171 CCRCMD(sc, rc->rc_chan, 1172 CCR_XMTREN | ((cflag & CREAD) ? CCR_RCVREN : CCR_RCVRDIS)); 1173 WAITFORCCR(sc, rc->rc_chan); 1174 1175 rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD; 1176 if (cflag & CCTS_OFLOW) 1177 rc->rc_ier |= IER_CTS; 1178 if (cflag & CREAD) 1179 rc->rc_ier |= IER_RxData; 1180 if (tp->t_state & TS_BUSY) 1181 rc->rc_ier |= IER_TxRdy; 1182 if (ts->c_ospeed != 0) 1183 rc_modem(tp, SER_DTR, 0); 1184 if ((cflag & CCTS_OFLOW) && (rc->rc_msvr & MSVR_CTS)) 1185 rc->rc_flags |= RC_SEND_RDY; 1186 rcout(sc, CD180_IER, rc->rc_ier); 1187 (void) splx(s); 1188 return 0; 1189} 1190 1191/* Re-initialize board after bogus interrupts */ 1192static void 1193rc_reinit(struct rc_softc *sc) 1194{ 1195 struct rc_chans *rc; 1196 int i; 1197 1198 rc_hwreset(sc, RC_FAKEID); 1199 rc = sc->sc_channels; 1200 for (i = 0; i < CD180_NCHAN; i++, rc++) 1201 (void) rc_param(&rc->rc_tp, &rc->rc_tp.t_termios); 1202} 1203 1204static int 1205rcioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, d_thread_t *td) 1206{ 1207 struct rc_chans *rc; 1208 struct tty *tp; 1209 int s, error; 1210 1211 rc = DEV_TO_RC(dev); 1212 tp = &rc->rc_tp; 1213 error = ttyioctl(dev, cmd, data, flag, td); 1214 rc->rc_hotchar = ttyldoptim(tp); 1215 if (error != ENOTTY) 1216 return (error); 1217 s = spltty(); 1218 1219 switch (cmd) { 1220 case TIOCMSDTRWAIT: 1221 error = suser(td); 1222 if (error != 0) { 1223 splx(s); 1224 return (error); 1225 } 1226 rc->rc_dtrwait = *(int *)data * hz / 100; 1227 break; 1228 1229 case TIOCMGDTRWAIT: 1230 *(int *)data = rc->rc_dtrwait * 100 / hz; 1231 break; 1232 1233 default: 1234 (void) splx(s); 1235 return ENOTTY; 1236 } 1237 (void) splx(s); 1238 return 0; 1239} 1240 1241 1242/* Modem control routines */ 1243 1244static int 1245rc_modem(struct tty *tp, int biton, int bitoff) 1246{ 1247 struct rc_chans *rc; 1248 struct rc_softc *sc; 1249 u_char *dtr; 1250 u_char msvr; 1251 1252 rc = DEV_TO_RC(tp->t_dev); 1253 sc = rc->rc_rcb; 1254 dtr = &sc->sc_dtr; 1255 rcout(sc, CD180_CAR, rc->rc_chan); 1256 1257 if (biton == 0 && bitoff == 0) { 1258 msvr = rc->rc_msvr = rcin(sc, CD180_MSVR); 1259 1260 if (msvr & MSVR_RTS) 1261 biton |= SER_RTS; 1262 if (msvr & MSVR_CTS) 1263 biton |= SER_CTS; 1264 if (msvr & MSVR_DSR) 1265 biton |= SER_DSR; 1266 if (msvr & MSVR_DTR) 1267 biton |= SER_DTR; 1268 if (msvr & MSVR_CD) 1269 biton |= SER_DCD; 1270 if (~rcin(sc, RC_RIREG) & (1 << rc->rc_chan)) 1271 biton |= SER_RI; 1272 return biton; 1273 } 1274 if (biton & SER_DTR) 1275 rcout(sc, RC_DTREG, ~(*dtr |= 1 << rc->rc_chan)); 1276 if (bitoff & SER_DTR) 1277 rcout(sc, RC_DTREG, ~(*dtr &= ~(1 << rc->rc_chan))); 1278 msvr = rcin(sc, CD180_MSVR); 1279 if (biton & SER_DTR) 1280 msvr |= MSVR_DTR; 1281 if (bitoff & SER_DTR) 1282 msvr &= ~MSVR_DTR; 1283 if (biton & SER_RTS) 1284 msvr |= MSVR_RTS; 1285 if (bitoff & SER_RTS) 1286 msvr &= ~MSVR_RTS; 1287 rcout(sc, CD180_MSVR, msvr); 1288 return 0; 1289} 1290 1291static int 1292rc_break(struct tty *tp, int brk) 1293{ 1294 struct rc_chans *rc; 1295 1296 rc = DEV_TO_RC(tp->t_dev); 1297 1298 if (brk) 1299 rc->rc_pendcmd = CD180_C_SBRK; 1300 else 1301 rc->rc_pendcmd = CD180_C_EBRK; 1302 return (0); 1303} 1304 1305#define ERR(s) do { \ 1306 device_printf(sc->sc_dev, "%s", ""); \ 1307 printf s ; \ 1308 printf("\n"); \ 1309 (void) splx(old_level); \ 1310 return 1; \ 1311} while (0) 1312 1313/* Test the board. */ 1314int 1315rc_test(struct rc_softc *sc) 1316{ 1317 int chan = 0; 1318 int i = 0, rcnt, old_level; 1319 unsigned int iack, chipid; 1320 unsigned short divs; 1321 static u_char ctest[] = "\377\125\252\045\244\0\377"; 1322#define CTLEN 8 1323 1324 struct rtest { 1325 u_char txbuf[CD180_NFIFO]; /* TX buffer */ 1326 u_char rxbuf[CD180_NFIFO]; /* RX buffer */ 1327 int rxptr; /* RX pointer */ 1328 int txptr; /* TX pointer */ 1329 } tchans[CD180_NCHAN]; 1330 1331 old_level = spltty(); 1332 1333 chipid = RC_FAKEID; 1334 1335 /* First, reset board to inital state */ 1336 rc_hwreset(sc, chipid); 1337 1338 divs = RC_BRD(19200); 1339 1340 /* Initialize channels */ 1341 for (chan = 0; chan < CD180_NCHAN; chan++) { 1342 1343 /* Select and reset channel */ 1344 rcout(sc, CD180_CAR, chan); 1345 CCRCMD(sc, chan, CCR_ResetChan); 1346 WAITFORCCR(sc, chan); 1347 1348 /* Set speed */ 1349 rcout(sc, CD180_RBPRL, divs & 0xFF); 1350 rcout(sc, CD180_RBPRH, divs >> 8); 1351 rcout(sc, CD180_TBPRL, divs & 0xFF); 1352 rcout(sc, CD180_TBPRH, divs >> 8); 1353 1354 /* set timeout value */ 1355 rcout(sc, CD180_RTPR, 0); 1356 1357 /* Establish local loopback */ 1358 rcout(sc, CD180_COR1, COR1_NOPAR | COR1_8BITS | COR1_1SB); 1359 rcout(sc, CD180_COR2, COR2_LLM); 1360 rcout(sc, CD180_COR3, CD180_NFIFO); 1361 CCRCMD(sc, chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); 1362 CCRCMD(sc, chan, CCR_RCVREN | CCR_XMTREN); 1363 WAITFORCCR(sc, chan); 1364 rcout(sc, CD180_MSVR, MSVR_RTS); 1365 1366 /* Fill TXBUF with test data */ 1367 for (i = 0; i < CD180_NFIFO; i++) { 1368 tchans[chan].txbuf[i] = ctest[i]; 1369 tchans[chan].rxbuf[i] = 0; 1370 } 1371 tchans[chan].txptr = tchans[chan].rxptr = 0; 1372 1373 /* Now, start transmit */ 1374 rcout(sc, CD180_IER, IER_TxMpty|IER_RxData); 1375 } 1376 /* Pseudo-interrupt poll stuff */ 1377 for (rcnt = 10000; rcnt-- > 0; rcnt--) { 1378 i = ~(rcin(sc, RC_BSR)); 1379 if (i & RC_BSR_TOUT) 1380 ERR(("BSR timeout bit set\n")); 1381 else if (i & RC_BSR_TXINT) { 1382 iack = rcin(sc, RC_PILR_TX); 1383 if (iack != (GIVR_IT_TDI | chipid)) 1384 ERR(("Bad TX intr ack (%02x != %02x)\n", 1385 iack, GIVR_IT_TDI | chipid)); 1386 chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH; 1387 /* If no more data to transmit, disable TX intr */ 1388 if (tchans[chan].txptr >= CD180_NFIFO) { 1389 iack = rcin(sc, CD180_IER); 1390 rcout(sc, CD180_IER, iack & ~IER_TxMpty); 1391 } else { 1392 for (iack = tchans[chan].txptr; 1393 iack < CD180_NFIFO; iack++) 1394 rcout(sc, CD180_TDR, 1395 tchans[chan].txbuf[iack]); 1396 tchans[chan].txptr = iack; 1397 } 1398 rcout(sc, CD180_EOIR, 0); 1399 } else if (i & RC_BSR_RXINT) { 1400 u_char ucnt; 1401 1402 iack = rcin(sc, RC_PILR_RX); 1403 if (iack != (GIVR_IT_RGDI | chipid) && 1404 iack != (GIVR_IT_REI | chipid)) 1405 ERR(("Bad RX intr ack (%02x != %02x)\n", 1406 iack, GIVR_IT_RGDI | chipid)); 1407 chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH; 1408 ucnt = rcin(sc, CD180_RDCR) & 0xF; 1409 while (ucnt-- > 0) { 1410 iack = rcin(sc, CD180_RCSR); 1411 if (iack & RCSR_Timeout) 1412 break; 1413 if (iack & 0xF) 1414 ERR(("Bad char chan %d (RCSR = %02X)\n", 1415 chan, iack)); 1416 if (tchans[chan].rxptr > CD180_NFIFO) 1417 ERR(("Got extra chars chan %d\n", 1418 chan)); 1419 tchans[chan].rxbuf[tchans[chan].rxptr++] = 1420 rcin(sc, CD180_RDR); 1421 } 1422 rcout(sc, CD180_EOIR, 0); 1423 } 1424 rcout(sc, RC_CTOUT, 0); 1425 for (iack = chan = 0; chan < CD180_NCHAN; chan++) 1426 if (tchans[chan].rxptr >= CD180_NFIFO) 1427 iack++; 1428 if (iack == CD180_NCHAN) 1429 break; 1430 } 1431 for (chan = 0; chan < CD180_NCHAN; chan++) { 1432 /* Select and reset channel */ 1433 rcout(sc, CD180_CAR, chan); 1434 CCRCMD(sc, chan, CCR_ResetChan); 1435 } 1436 1437 if (!rcnt) 1438 ERR(("looses characters during local loopback\n")); 1439 /* Now, check data */ 1440 for (chan = 0; chan < CD180_NCHAN; chan++) 1441 for (i = 0; i < CD180_NFIFO; i++) 1442 if (ctest[i] != tchans[chan].rxbuf[i]) 1443 ERR(("data mismatch chan %d ptr %d (%d != %d)\n", 1444 chan, i, ctest[i], tchans[chan].rxbuf[i])); 1445 (void) splx(old_level); 1446 return 0; 1447} 1448 1449#ifdef RCDEBUG 1450static void 1451printrcflags(struct rc_chans *rc, char *comment) 1452{ 1453 struct rc_softc *sc; 1454 u_short f = rc->rc_flags; 1455 1456 sc = rc->rc_rcb; 1457 printf("rc%d/%d: %s flags: %s%s%s%s%s%s%s%s%s%s%s%s\n", 1458 rc->rc_rcb->rcb_unit, rc->rc_chan, comment, 1459 (f & RC_DTR_OFF)?"DTR_OFF " :"", 1460 (f & RC_ACTOUT) ?"ACTOUT " :"", 1461 (f & RC_RTSFLOW)?"RTSFLOW " :"", 1462 (f & RC_CTSFLOW)?"CTSFLOW " :"", 1463 (f & RC_DORXFER)?"DORXFER " :"", 1464 (f & RC_DOXXFER)?"DOXXFER " :"", 1465 (f & RC_MODCHG) ?"MODCHG " :"", 1466 (f & RC_OSUSP) ?"OSUSP " :"", 1467 (f & RC_OSBUSY) ?"OSBUSY " :"", 1468 (f & RC_WAS_BUFOVFL) ?"BUFOVFL " :"", 1469 (f & RC_WAS_SILOVFL) ?"SILOVFL " :"", 1470 (f & RC_SEND_RDY) ?"SEND_RDY":""); 1471 1472 rcout(sc, CD180_CAR, rc->rc_chan); 1473 1474 printf("rc%d/%d: msvr %02x ier %02x ccsr %02x\n", 1475 rc->rc_rcb->rcb_unit, rc->rc_chan, 1476 rcin(sc, CD180_MSVR), 1477 rcin(sc, CD180_IER), 1478 rcin(sc, CD180_CCSR)); 1479} 1480#endif /* RCDEBUG */ 1481 1482static void 1483rc_dtrwakeup(void *arg) 1484{ 1485 struct rc_chans *rc; 1486 1487 rc = (struct rc_chans *)arg; 1488 rc->rc_flags &= ~RC_DTR_OFF; 1489 wakeup(&rc->rc_dtrwait); 1490} 1491 1492static void 1493rc_discard_output(struct rc_chans *rc) 1494{ 1495 critical_enter(); 1496 if (rc->rc_flags & RC_DOXXFER) { 1497 rc->rc_rcb->sc_scheduled_event -= LOTS_OF_EVENTS; 1498 rc->rc_flags &= ~RC_DOXXFER; 1499 } 1500 rc->rc_optr = rc->rc_obufend; 1501 rc->rc_tp.t_state &= ~TS_BUSY; 1502 critical_exit(); 1503 ttwwakeup(&rc->rc_tp); 1504} 1505 1506static void 1507rc_wait0(struct rc_softc *sc, int chan, int line) 1508{ 1509 int rcnt; 1510 1511 for (rcnt = 50; rcnt && rcin(sc, CD180_CCR); rcnt--) 1512 DELAY(30); 1513 if (rcnt == 0) 1514 device_printf(sc->sc_dev, 1515 "channel %d command timeout, rc.c line: %d\n", chan, line); 1516} 1517 1518static device_method_t rc_methods[] = { 1519 /* Device interface */ 1520 DEVMETHOD(device_probe, rc_probe), 1521 DEVMETHOD(device_attach, rc_attach), 1522 DEVMETHOD(device_detach, rc_detach), 1523 { 0, 0 } 1524}; 1525 1526static driver_t rc_driver = { 1527 "rc", 1528 rc_methods, sizeof(struct rc_softc), 1529}; 1530 1531DRIVER_MODULE(rc, isa, rc_driver, rc_devclass, 0, 0); 1532