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