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