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