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