166 * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work. 167 */ 168#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ 169 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) 170#define UNIT_TO_MINOR(unit) (((unit) / CY_MAX_PORTS) << 16 \ 171 | (((unit) & 0xff) & ~MINOR_MAGIC_MASK)) 172 173/* 174 * com state bits. 175 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 176 * than the other bits so that they can be tested as a group without masking 177 * off the low bits. 178 * 179 * The following com and tty flags correspond closely: 180 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 181 * comstop()) 182 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 183 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 184 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 185 * TS_FLUSH is not used. 186 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 187 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 188 */ 189#define CS_BUSY 0x80 /* output in progress */ 190#define CS_TTGO 0x40 /* output not stopped by XOFF */ 191#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 192#define CS_CHECKMSR 1 /* check of MSR scheduled */ 193#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 194#define CS_DTR_OFF 0x10 /* DTR held off */ 195#define CS_ODONE 4 /* output completed */ 196#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 197#define CSE_ODONE 1 /* output transmitted */ 198 199static char const * const error_desc[] = { 200#define CE_OVERRUN 0 201 "silo overflow", 202#define CE_INTERRUPT_BUF_OVERFLOW 1 203 "interrupt-level buffer overflow", 204#define CE_TTY_BUF_OVERFLOW 2 205 "tty-level buffer overflow", 206}; 207 208#define CE_NTYPES 3 209#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 210 211#ifdef SMP 212#define COM_LOCK() mtx_lock_spin(&sio_lock) 213#define COM_UNLOCK() mtx_unlock_spin(&sio_lock) 214#else 215#define COM_LOCK() 216#define COM_UNLOCK() 217#endif 218 219/* types. XXX - should be elsewhere */ 220typedef u_char bool_t; /* boolean */ 221 222/* queue of linear buffers */ 223struct lbq { 224 u_char *l_head; /* next char to process */ 225 u_char *l_tail; /* one past the last char to process */ 226 struct lbq *l_next; /* next in queue */ 227 bool_t l_queued; /* nonzero if queued */ 228}; 229 230/* com device structure */ 231struct com_s { 232 u_char state; /* miscellaneous flag bits */ 233 bool_t active_out; /* nonzero if the callout device is open */ 234#if 0 235 u_char cfcr_image; /* copy of value written to CFCR */ 236#endif 237 u_char etc; /* pending Embedded Transmit Command */ 238 u_char extra_state; /* more flag bits, separate for order trick */ 239#if 0 240 u_char fifo_image; /* copy of value written to FIFO */ 241#endif 242 u_char gfrcr_image; /* copy of value read from GFRCR */ 243#if 0 244 bool_t hasfifo; /* nonzero for 16550 UARTs */ 245 bool_t loses_outints; /* nonzero if device loses output interrupts */ 246#endif 247 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 248 u_char mcr_image; /* copy of value written to MCR */ 249 u_char mcr_rts; /* MCR bit that is wired to RTS */ 250#if 0 251#ifdef COM_MULTIPORT 252 bool_t multiport; /* is this unit part of a multiport device? */ 253#endif /* COM_MULTIPORT */ 254 bool_t no_irq; /* nonzero if irq is not attached */ 255 bool_t poll; /* nonzero if polling is required */ 256 bool_t poll_output; /* nonzero if polling for output is required */ 257#endif 258 int unit; /* unit number */ 259 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 260#if 0 261 u_int tx_fifo_size; 262#endif 263 u_int wopeners; /* # processes waiting for DCD in open() */ 264 265 /* 266 * The high level of the driver never reads status registers directly 267 * because there would be too many side effects to handle conveniently. 268 * Instead, it reads copies of the registers stored here by the 269 * interrupt handler. 270 */ 271 u_char last_modem_status; /* last MSR read by intr handler */ 272 u_char prev_modem_status; /* last MSR handled by high level */ 273 274 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 275 u_char *ibuf; /* start of input buffer */ 276 u_char *ibufend; /* end of input buffer */ 277 u_char *ibufold; /* old input buffer, to be freed */ 278 u_char *ihighwater; /* threshold in input buffer */ 279 u_char *iptr; /* next free spot in input buffer */ 280 int ibufsize; /* size of ibuf (not include error bytes) */ 281 int ierroff; /* offset of error bytes in ibuf */ 282 283 struct lbq obufq; /* head of queue of output buffers */ 284 struct lbq obufs[2]; /* output buffers */ 285 286 int cy_align; /* index for register alignment */ 287 cy_addr cy_iobase; /* base address of this port's cyclom */ 288 cy_addr iobase; /* base address of this port's cd1400 */ 289 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 290 291 struct tty *tp; /* cross reference */ 292 293 /* Initial state. */ 294 struct termios it_in; /* should be in struct tty */ 295 struct termios it_out; 296 297 /* Lock state. */ 298 struct termios lt_in; /* should be in struct tty */ 299 struct termios lt_out; 300 301 bool_t do_timestamp; 302 bool_t do_dcd_timestamp; 303 struct timeval timestamp; 304 struct timeval dcd_timestamp; 305 306 u_long bytes_in; /* statistics */ 307 u_long bytes_out; 308 u_int delta_error_counts[CE_NTYPES]; 309 u_long error_counts[CE_NTYPES]; 310 311 u_int recv_exception; /* exception chars received */ 312 u_int mdm; /* modem signal changes */ 313#ifdef CyDebug 314 u_int start_count; /* no. of calls to comstart() */ 315 u_int start_real; /* no. of calls that did something */ 316#endif 317 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 318 u_char channel_control;/* CD1400 CCR control command shadow */ 319 u_char cor[3]; /* CD1400 COR1-3 shadows */ 320 u_char intr_enable; /* CD1400 SRER shadow */ 321 322 /* 323 * Data area for output buffers. Someday we should build the output 324 * buffer queue without copying data. 325 */ 326 u_char obuf1[256]; 327 u_char obuf2[256]; 328}; 329 330devclass_t cy_devclass; 331char cy_driver_name[] = "cy"; 332 333static void cd1400_channel_cmd(struct com_s *com, int cmd); 334static void cd1400_channel_cmd_wait(struct com_s *com); 335static void cd_etc(struct com_s *com, int etc); 336static int cd_getreg(struct com_s *com, int reg); 337static void cd_setreg(struct com_s *com, int reg, int val); 338static timeout_t siodtrwakeup; 339static void comhardclose(struct com_s *com); 340static void sioinput(struct com_s *com); 341static int commctl(struct com_s *com, int bits, int how); 342static int comparam(struct tty *tp, struct termios *t); 343static void siopoll(void *arg); 344static void siosettimeout(void); 345static int siosetwater(struct com_s *com, speed_t speed); 346static int comspeed(speed_t speed, u_long cy_clock, int *prescaler_io); 347static void comstart(struct tty *tp); 348static void comstop(struct tty *tp, int rw); 349static timeout_t comwakeup; 350static void disc_optim(struct tty *tp, struct termios *t, 351 struct com_s *com); 352 353#ifdef CyDebug 354void cystatus(int unit); 355#endif 356 357static struct mtx sio_lock; 358static int sio_inited; 359 360/* table and macro for fast conversion from a unit number to its com struct */ 361static struct com_s *p_com_addr[NSIO]; 362#define com_addr(unit) (p_com_addr[unit]) 363 364static d_open_t sioopen; 365static d_close_t sioclose; 366static d_write_t siowrite; 367static d_ioctl_t sioioctl; 368 369static struct cdevsw sio_cdevsw = { 370 .d_version = D_VERSION, 371 .d_open = sioopen, 372 .d_close = sioclose, 373 .d_write = siowrite, 374 .d_ioctl = sioioctl, 375 .d_name = cy_driver_name, 376 .d_flags = D_TTY | D_NEEDGIANT, 377}; 378 379static int comconsole = -1; 380static speed_t comdefaultrate = TTYDEF_SPEED; 381static u_int com_events; /* input chars + weighted output completions */ 382static void *sio_fast_ih; 383static void *sio_slow_ih; 384static int sio_timeout; 385static int sio_timeouts_until_log; 386static struct callout_handle sio_timeout_handle 387 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 388 389#ifdef CyDebug 390static u_int cd_inbs; 391static u_int cy_inbs; 392static u_int cd_outbs; 393static u_int cy_outbs; 394static u_int cy_svrr_probes; 395static u_int cy_timeouts; 396#endif 397 398static int cy_chip_offset[] = { 399 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 400}; 401static int cy_nr_cd1400s[NCY]; 402static int cy_total_devices; 403#undef RxFifoThreshold 404static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 405 406int 407cy_units(cy_iobase, cy_align) 408 cy_addr cy_iobase; 409 int cy_align; 410{ 411 int cyu; 412 u_char firmware_version; 413 int i; 414 cy_addr iobase; 415 416 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 417 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 418 419 /* wait for chip to become ready for new command */ 420 for (i = 0; i < 10; i++) { 421 DELAY(50); 422 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 423 break; 424 } 425 426 /* clear the GFRCR register */ 427 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 428 429 /* issue a reset command */ 430 cd_outb(iobase, CD1400_CCR, cy_align, 431 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 432 433 /* XXX bogus initialization to avoid a gcc bug/warning. */ 434 firmware_version = 0; 435 436 /* wait for the CD1400 to initialize itself */ 437 for (i = 0; i < 200; i++) { 438 DELAY(50); 439 440 /* retrieve firmware version */ 441 firmware_version = cd_inb(iobase, CD1400_GFRCR, 442 cy_align); 443 if ((firmware_version & 0xf0) == 0x40) 444 break; 445 } 446 447 /* 448 * Anything in the 0x40-0x4F range is fine. 449 * If one CD1400 is bad then we don't support higher 450 * numbered good ones on this board. 451 */ 452 if ((firmware_version & 0xf0) != 0x40) 453 break; 454 } 455 return (cyu); 456} 457 458void * 459cyattach_common(cy_iobase, cy_align) 460 cy_addr cy_iobase; 461 int cy_align; 462{ 463 int adapter; 464 int cyu; 465 u_char firmware_version; 466 cy_addr iobase; 467 int minorbase; 468 int ncyu; 469 int unit; 470 471 while (sio_inited != 2) 472 if (atomic_cmpset_int(&sio_inited, 0, 1)) { 473 mtx_init(&sio_lock, cy_driver_name, NULL, MTX_SPIN); 474 atomic_store_rel_int(&sio_inited, 2); 475 } 476 477 adapter = cy_total_devices; 478 if ((u_int)adapter >= NCY) { 479 printf( 480 "cy%d: can't attach adapter: insufficient cy devices configured\n", 481 adapter); 482 return (NULL); 483 } 484 ncyu = cy_units(cy_iobase, cy_align); 485 if (ncyu == 0) 486 return (NULL); 487 cy_nr_cd1400s[adapter] = ncyu; 488 cy_total_devices++; 489 490 unit = adapter * CY_MAX_PORTS; 491 for (cyu = 0; cyu < ncyu; ++cyu) { 492 int cdu; 493 494 iobase = (cy_addr) (cy_iobase 495 + (cy_chip_offset[cyu] << cy_align)); 496 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 497 498 /* Set up a receive timeout period of than 1+ ms. */ 499 cd_outb(iobase, CD1400_PPR, cy_align, 500 howmany(CY_CLOCK(firmware_version) 501 / CD1400_PPR_PRESCALER, 1000)); 502 503 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 504 struct com_s *com; 505 int s; 506 507 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); 508 if (com == NULL) 509 break; 510 com->unit = unit; 511 com->gfrcr_image = firmware_version; 512 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 513 com->mcr_dtr = MCR_RTS; 514 com->mcr_rts = MCR_DTR; 515 com->mcr_rts_reg = CD1400_MSVR2; 516 } else { 517 com->mcr_dtr = MCR_DTR; 518 com->mcr_rts = MCR_RTS; 519 com->mcr_rts_reg = CD1400_MSVR1; 520 } 521 com->dtr_wait = 3 * hz; 522 com->obufs[0].l_head = com->obuf1; 523 com->obufs[1].l_head = com->obuf2; 524 525 com->cy_align = cy_align; 526 com->cy_iobase = cy_iobase; 527 com->iobase = iobase; 528 com->car = ~CD1400_CAR_CHAN; 529 530 /* 531 * We don't use all the flags from <sys/ttydefaults.h> since they 532 * are only relevant for logins. It's important to have echo off 533 * initially so that the line doesn't start blathering before the 534 * echo flag can be turned off. 535 */ 536 com->it_in.c_iflag = 0; 537 com->it_in.c_oflag = 0; 538 com->it_in.c_cflag = TTYDEF_CFLAG; 539 com->it_in.c_lflag = 0; 540 if (unit == comconsole) { 541 com->it_in.c_iflag = TTYDEF_IFLAG; 542 com->it_in.c_oflag = TTYDEF_OFLAG; 543 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 544 com->it_in.c_lflag = TTYDEF_LFLAG; 545 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 546 } 547 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 548 free(com, M_DEVBUF); 549 return (NULL); 550 } 551 termioschars(&com->it_in); 552 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 553 com->it_out = com->it_in; 554 555 s = spltty(); 556 com_addr(unit) = com; 557 splx(s); 558 559 if (sio_fast_ih == NULL) { 560 swi_add(&tty_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 561 &sio_fast_ih); 562 swi_add(&clk_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 563 &sio_slow_ih); 564 } 565 minorbase = UNIT_TO_MINOR(unit); 566 make_dev(&sio_cdevsw, minorbase, 567 UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, 568 unit % CY_MAX_PORTS); 569 make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE, 570 UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, 571 unit % CY_MAX_PORTS); 572 make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE, 573 UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, 574 unit % CY_MAX_PORTS); 575 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK, 576 UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, 577 unit % CY_MAX_PORTS); 578 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE, 579 UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, 580 unit % CY_MAX_PORTS); 581 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE, 582 UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, 583 unit % CY_MAX_PORTS); 584 } 585 } 586 587 /* ensure an edge for the next interrupt */ 588 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 589 590 return (com_addr(adapter * CY_MAX_PORTS)); 591} 592 593static int 594sioopen(dev, flag, mode, td) 595 struct cdev *dev; 596 int flag; 597 int mode; 598 struct thread *td; 599{ 600 struct com_s *com; 601 int error; 602 int mynor; 603 int s; 604 struct tty *tp; 605 int unit; 606 607 mynor = minor(dev); 608 unit = MINOR_TO_UNIT(mynor); 609 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 610 return (ENXIO); 611 if (mynor & CONTROL_MASK) 612 return (0); 613 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 614 s = spltty(); 615 /* 616 * We jump to this label after all non-interrupted sleeps to pick 617 * up any changes of the device state. 618 */ 619open_top: 620 while (com->state & CS_DTR_OFF) { 621 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 622 if (error != 0) 623 goto out; 624 } 625 if (tp->t_state & TS_ISOPEN) { 626 /* 627 * The device is open, so everything has been initialized. 628 * Handle conflicts. 629 */ 630 if (mynor & CALLOUT_MASK) { 631 if (!com->active_out) { 632 error = EBUSY; 633 goto out; 634 } 635 } else { 636 if (com->active_out) { 637 if (flag & O_NONBLOCK) { 638 error = EBUSY; 639 goto out; 640 } 641 error = tsleep(&com->active_out, 642 TTIPRI | PCATCH, "cybi", 0); 643 if (error != 0) 644 goto out; 645 goto open_top; 646 } 647 } 648 if (tp->t_state & TS_XCLUDE && 649 suser(td)) { 650 error = EBUSY; 651 goto out; 652 } 653 } else { 654 /* 655 * The device isn't open, so there are no conflicts. 656 * Initialize it. Initialization is done twice in many 657 * cases: to preempt sleeping callin opens if we are 658 * callout, and to complete a callin open after DCD rises. 659 */ 660 tp->t_oproc = comstart; 661 tp->t_stop = comstop; 662 tp->t_param = comparam; 663 tp->t_dev = dev; 664 tp->t_termios = mynor & CALLOUT_MASK 665 ? com->it_out : com->it_in; 666 667 /* Encode per-board unit in LIVR for access in intr routines. */ 668 cd_setreg(com, CD1400_LIVR, 669 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 670 671 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 672#if 0 673 com->poll = com->no_irq; 674 com->poll_output = com->loses_outints; 675#endif 676 ++com->wopeners; 677 error = comparam(tp, &tp->t_termios); 678 --com->wopeners; 679 if (error != 0) 680 goto out; 681#if 0 682 if (com->hasfifo) { 683 /* 684 * (Re)enable and flush fifos. 685 * 686 * Certain SMC chips cause problems if the fifos 687 * are enabled while input is ready. Turn off the 688 * fifo if necessary to clear the input. We test 689 * the input ready bit after enabling the fifos 690 * since we've already enabled them in comparam() 691 * and to handle races between enabling and fresh 692 * input. 693 */ 694 while (TRUE) { 695 outb(iobase + com_fifo, 696 FIFO_RCV_RST | FIFO_XMT_RST 697 | com->fifo_image); 698 DELAY(100); 699 if (!(inb(com->line_status_port) & LSR_RXRDY)) 700 break; 701 outb(iobase + com_fifo, 0); 702 DELAY(100); 703 (void) inb(com->data_port); 704 } 705 } 706 707 critical_enter(); 708 COM_LOCK(); 709 (void) inb(com->line_status_port); 710 (void) inb(com->data_port); 711 com->prev_modem_status = com->last_modem_status 712 = inb(com->modem_status_port); 713 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 714 | IER_EMSC); 715 COM_UNLOCK(); 716 critical_exit(); 717#else /* !0 */ 718 /* 719 * Flush fifos. This requires a full channel reset which 720 * also disables the transmitter and receiver. Recover 721 * from this. 722 */ 723 cd1400_channel_cmd(com, 724 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 725 cd1400_channel_cmd(com, com->channel_control); 726 727 critical_enter(); 728 COM_LOCK(); 729 com->prev_modem_status = com->last_modem_status 730 = cd_getreg(com, CD1400_MSVR2); 731 cd_setreg(com, CD1400_SRER, 732 com->intr_enable 733 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 734 COM_UNLOCK(); 735 critical_exit(); 736#endif /* 0 */ 737 /* 738 * Handle initial DCD. Callout devices get a fake initial 739 * DCD (trapdoor DCD). If we are callout, then any sleeping 740 * callin opens get woken up and resume sleeping on "cybi" 741 * instead of "cydcd". 742 */ 743 /* 744 * XXX `mynor & CALLOUT_MASK' should be 745 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 746 * TRAPDOOR_CARRIER is the default initial state for callout 747 * devices and SOFT_CARRIER is like CLOCAL except it hides 748 * the true carrier. 749 */ 750 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 751 ttyld_modem(tp, 1); 752 } 753 /* 754 * Wait for DCD if necessary. 755 */ 756 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 757 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 758 ++com->wopeners; 759 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 760 --com->wopeners; 761 if (error != 0) 762 goto out; 763 goto open_top; 764 } 765 error = ttyld_open(tp, dev); 766 disc_optim(tp, &tp->t_termios, com); 767 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 768 com->active_out = TRUE; 769 siosettimeout(); 770out: 771 splx(s); 772 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 773 comhardclose(com); 774 return (error); 775} 776 777static int 778sioclose(dev, flag, mode, td) 779 struct cdev *dev; 780 int flag; 781 int mode; 782 struct thread *td; 783{ 784 struct com_s *com; 785 int mynor; 786 int s; 787 struct tty *tp; 788 789 mynor = minor(dev); 790 if (mynor & CONTROL_MASK) 791 return (0); 792 com = com_addr(MINOR_TO_UNIT(mynor)); 793 tp = com->tp; 794 s = spltty(); 795 cd_etc(com, CD1400_ETC_STOPBREAK); 796 ttyld_close(tp, flag); 797 disc_optim(tp, &tp->t_termios, com); 798 comhardclose(com); 799 ttyclose(tp); 800 siosettimeout(); 801 splx(s); 802#ifdef broken /* session holds a ref to the tty; can't deallocate */ 803 ttyfree(tp); 804 com->tp = NULL; 805#endif 806 return (0); 807} 808 809static void 810comhardclose(com) 811 struct com_s *com; 812{ 813 cy_addr iobase; 814 int s; 815 struct tty *tp; 816 int unit; 817 818 unit = com->unit; 819 iobase = com->iobase; 820 s = spltty(); 821#if 0 822 com->poll = FALSE; 823 com->poll_output = FALSE; 824#endif 825 com->do_timestamp = 0; 826#if 0 827 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 828#else 829 /* XXX */ 830 critical_enter(); 831 COM_LOCK(); 832 com->etc = ETC_NONE; 833 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 834 COM_UNLOCK(); 835 critical_exit(); 836 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 837#endif 838 839 { 840#if 0 841 outb(iobase + com_ier, 0); 842#else 843 critical_enter(); 844 COM_LOCK(); 845 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 846 COM_UNLOCK(); 847 critical_exit(); 848#endif 849 tp = com->tp; 850 if ((tp->t_cflag & HUPCL) 851 /* 852 * XXX we will miss any carrier drop between here and the 853 * next open. Perhaps we should watch DCD even when the 854 * port is closed; it is not sufficient to check it at 855 * the next open because it might go up and down while 856 * we're not watching. 857 */ 858 || (!com->active_out 859 && !(com->prev_modem_status & MSR_DCD) 860 && !(com->it_in.c_cflag & CLOCAL)) 861 || !(tp->t_state & TS_ISOPEN)) { 862 (void)commctl(com, TIOCM_DTR, DMBIC); 863 864 /* Disable receiver (leave transmitter enabled). */ 865 com->channel_control = CD1400_CCR_CMDCHANCTL 866 | CD1400_CCR_XMTEN 867 | CD1400_CCR_RCVDIS; 868 cd1400_channel_cmd(com, com->channel_control); 869 870 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 871 timeout(siodtrwakeup, com, com->dtr_wait); 872 com->state |= CS_DTR_OFF; 873 } 874 } 875 } 876#if 0 877 if (com->hasfifo) { 878 /* 879 * Disable fifos so that they are off after controlled 880 * reboots. Some BIOSes fail to detect 16550s when the 881 * fifos are enabled. 882 */ 883 outb(iobase + com_fifo, 0); 884 } 885#endif 886 com->active_out = FALSE; 887 wakeup(&com->active_out); 888 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 889 splx(s); 890} 891 892static int 893siowrite(dev, uio, flag) 894 struct cdev *dev; 895 struct uio *uio; 896 int flag; 897{ 898 int mynor; 899 struct tty *tp; 900 int unit; 901 902 mynor = minor(dev); 903 if (mynor & CONTROL_MASK) 904 return (ENODEV); 905 906 unit = MINOR_TO_UNIT(mynor); 907 tp = com_addr(unit)->tp; 908 /* 909 * (XXX) We disallow virtual consoles if the physical console is 910 * a serial port. This is in case there is a display attached that 911 * is not the console. In that situation we don't need/want the X 912 * server taking over the console. 913 */ 914 if (constty != NULL && unit == comconsole) 915 constty = NULL; 916#ifdef Smarts 917 /* XXX duplicate ttwrite(), but without so much output processing on 918 * CR & LF chars. Hardly worth the effort, given that high-throughput 919 * sessions are raw anyhow. 920 */ 921#else 922 return (ttyld_write(tp, uio, flag)); 923#endif 924} 925 926static void 927siodtrwakeup(chan) 928 void *chan; 929{ 930 struct com_s *com; 931 932 com = (struct com_s *)chan; 933 com->state &= ~CS_DTR_OFF; 934 wakeup(&com->dtr_wait); 935} 936 937/* 938 * This function: 939 * a) needs to be called with COM_LOCK() held, and 940 * b) needs to return with COM_LOCK() held. 941 */ 942static void 943sioinput(com) 944 struct com_s *com; 945{ 946 u_char *buf; 947 int incc; 948 u_char line_status; 949 int recv_data; 950 struct tty *tp; 951 952 buf = com->ibuf; 953 tp = com->tp; 954 if (!(tp->t_state & TS_ISOPEN)) { 955 com_events -= (com->iptr - com->ibuf); 956 com->iptr = com->ibuf; 957 return; 958 } 959 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 960 /* 961 * Avoid the grotesquely inefficient lineswitch routine 962 * (ttyinput) in "raw" mode. It usually takes about 450 963 * instructions (that's without canonical processing or echo!). 964 * slinput is reasonably fast (usually 40 instructions plus 965 * call overhead). 966 */ 967 968 do { 969 /* 970 * This may look odd, but it is using save-and-enable 971 * semantics instead of the save-and-disable semantics 972 * that are used everywhere else. 973 */ 974 COM_UNLOCK(); 975 critical_exit(); 976 incc = com->iptr - buf; 977 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 978 && (com->state & CS_RTS_IFLOW 979 || tp->t_iflag & IXOFF) 980 && !(tp->t_state & TS_TBLOCK)) 981 ttyblock(tp); 982 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 983 += b_to_q((char *)buf, incc, &tp->t_rawq); 984 buf += incc; 985 tk_nin += incc; 986 tk_rawcc += incc; 987 tp->t_rawcc += incc; 988 ttwakeup(tp); 989 if (tp->t_state & TS_TTSTOP 990 && (tp->t_iflag & IXANY 991 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 992 tp->t_state &= ~TS_TTSTOP; 993 tp->t_lflag &= ~FLUSHO; 994 comstart(tp); 995 } 996 critical_enter(); 997 COM_LOCK(); 998 } while (buf < com->iptr); 999 } else { 1000 do { 1001 /* 1002 * This may look odd, but it is using save-and-enable 1003 * semantics instead of the save-and-disable semantics 1004 * that are used everywhere else. 1005 */ 1006 COM_UNLOCK(); 1007 critical_exit(); 1008 line_status = buf[com->ierroff]; 1009 recv_data = *buf++; 1010 if (line_status 1011 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1012 if (line_status & LSR_BI) 1013 recv_data |= TTY_BI; 1014 if (line_status & LSR_FE) 1015 recv_data |= TTY_FE; 1016 if (line_status & LSR_OE) 1017 recv_data |= TTY_OE; 1018 if (line_status & LSR_PE) 1019 recv_data |= TTY_PE; 1020 } 1021 ttyld_rint(tp, recv_data); 1022 critical_enter(); 1023 COM_LOCK(); 1024 } while (buf < com->iptr); 1025 } 1026 com_events -= (com->iptr - com->ibuf); 1027 com->iptr = com->ibuf; 1028 1029 /* 1030 * There is now room for another low-level buffer full of input, 1031 * so enable RTS if it is now disabled and there is room in the 1032 * high-level buffer. 1033 */ 1034 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 1035 !(tp->t_state & TS_TBLOCK)) 1036#if 0 1037 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1038#else 1039 cd_setreg(com, com->mcr_rts_reg, 1040 com->mcr_image |= com->mcr_rts); 1041#endif 1042} 1043 1044void 1045siointr1(vcom) 1046 void *vcom; 1047{ 1048 struct com_s *basecom; 1049 int baseu; 1050 int cy_align; 1051 cy_addr cy_iobase; 1052 int cyu; 1053 cy_addr iobase; 1054 u_char status; 1055 int unit; 1056 1057 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1058 1059 basecom = (struct com_s *)vcom; 1060 baseu = basecom->unit; 1061 cy_align = basecom->cy_align; 1062 cy_iobase = basecom->cy_iobase; 1063 unit = baseu / CY_MAX_PORTS; 1064 1065 /* check each CD1400 in turn */ 1066 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1067 iobase = (cy_addr) (cy_iobase 1068 + (cy_chip_offset[cyu] << cy_align)); 1069 /* poll to see if it has any work */ 1070 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1071 if (status == 0) 1072 continue; 1073#ifdef CyDebug 1074 ++cy_svrr_probes; 1075#endif 1076 /* service requests as appropriate, giving priority to RX */ 1077 if (status & CD1400_SVRR_RXRDY) { 1078 struct com_s *com; 1079 u_int count; 1080 u_char *ioptr; 1081 u_char line_status; 1082 u_char recv_data; 1083 u_char serv_type; 1084#ifdef PollMode 1085 u_char save_rir; 1086#endif 1087 1088#ifdef PollMode 1089 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1090 1091 /* enter rx service */ 1092 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1093 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1094 = save_rir & CD1400_CAR_CHAN; 1095 1096 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1097 com = com_addr(baseu 1098 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1099 & CD1400_xIVR_CHAN)); 1100#else 1101 /* ack receive service */ 1102 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1103 1104 com = com_addr(baseu + 1105 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1106 & CD1400_xIVR_CHAN)); 1107#endif 1108 1109 if (serv_type & CD1400_RIVR_EXCEPTION) { 1110 ++com->recv_exception; 1111 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1112 /* break/unnattached error bits or real input? */ 1113 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1114#ifndef SOFT_HOTCHAR 1115 if (line_status & CD1400_RDSR_SPECIAL 1116 && com->hotchar != 0) 1117 swi_sched(sio_fast_ih, 0); 1118 1119#endif 1120#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1121 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1122 /* 1123 Don't store PE if IGNPAR and BI if IGNBRK, 1124 this hack allows "raw" tty optimization 1125 works even if IGN* is set. 1126 */ 1127 if ( com->tp == NULL 1128 || !(com->tp->t_state & TS_ISOPEN) 1129 || ((line_status & (LSR_PE|LSR_FE)) 1130 && (com->tp->t_iflag & IGNPAR)) 1131 || ((line_status & LSR_BI) 1132 && (com->tp->t_iflag & IGNBRK))) 1133 goto cont; 1134 if ( (line_status & (LSR_PE|LSR_FE)) 1135 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1136 && ((line_status & LSR_FE) 1137 || ((line_status & LSR_PE) 1138 && (com->tp->t_iflag & INPCK)))) 1139 recv_data = 0; 1140 } 1141#endif /* 1 */ 1142 ++com->bytes_in; 1143#ifdef SOFT_HOTCHAR 1144 if (com->hotchar != 0 && recv_data == com->hotchar) 1145 swi_sched(sio_fast_ih, 0); 1146#endif 1147 ioptr = com->iptr; 1148 if (ioptr >= com->ibufend) 1149 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1150 else { 1151 if (com->do_timestamp) 1152 microtime(&com->timestamp); 1153 ++com_events; 1154 ioptr[0] = recv_data; 1155 ioptr[com->ierroff] = line_status; 1156 com->iptr = ++ioptr; 1157 if (ioptr == com->ihighwater 1158 && com->state & CS_RTS_IFLOW) 1159#if 0 1160 outb(com->modem_ctl_port, 1161 com->mcr_image &= ~MCR_RTS); 1162#else 1163 cd_outb(iobase, com->mcr_rts_reg, 1164 cy_align, 1165 com->mcr_image &= 1166 ~com->mcr_rts); 1167#endif 1168 if (line_status & LSR_OE) 1169 CE_RECORD(com, CE_OVERRUN); 1170 } 1171 goto cont; 1172 } else { 1173 int ifree; 1174 1175 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1176 if (!count) 1177 goto cont; 1178 com->bytes_in += count; 1179 ioptr = com->iptr; 1180 ifree = com->ibufend - ioptr; 1181 if (count > ifree) { 1182 count -= ifree; 1183 com_events += ifree; 1184 if (ifree != 0) { 1185 if (com->do_timestamp) 1186 microtime(&com->timestamp); 1187 do { 1188 recv_data = cd_inb(iobase, 1189 CD1400_RDSR, 1190 cy_align); 1191#ifdef SOFT_HOTCHAR 1192 if (com->hotchar != 0 1193 && recv_data 1194 == com->hotchar) 1195 swi_sched(sio_fast_ih, 1196 0); 1197#endif 1198 ioptr[0] = recv_data; 1199 ioptr[com->ierroff] = 0; 1200 ++ioptr; 1201 } while (--ifree != 0); 1202 } 1203 com->delta_error_counts 1204 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1205 do { 1206 recv_data = cd_inb(iobase, CD1400_RDSR, 1207 cy_align); 1208#ifdef SOFT_HOTCHAR 1209 if (com->hotchar != 0 1210 && recv_data == com->hotchar) 1211 swi_sched(sio_fast_ih, 0); 1212#endif 1213 } while (--count != 0); 1214 } else { 1215 if (com->do_timestamp) 1216 microtime(&com->timestamp); 1217 if (ioptr <= com->ihighwater 1218 && ioptr + count > com->ihighwater 1219 && com->state & CS_RTS_IFLOW) 1220#if 0 1221 outb(com->modem_ctl_port, 1222 com->mcr_image &= ~MCR_RTS); 1223#else 1224 cd_outb(iobase, com->mcr_rts_reg, 1225 cy_align, 1226 com->mcr_image 1227 &= ~com->mcr_rts); 1228#endif 1229 com_events += count; 1230 do { 1231 recv_data = cd_inb(iobase, CD1400_RDSR, 1232 cy_align); 1233#ifdef SOFT_HOTCHAR 1234 if (com->hotchar != 0 1235 && recv_data == com->hotchar) 1236 swi_sched(sio_fast_ih, 0); 1237#endif 1238 ioptr[0] = recv_data; 1239 ioptr[com->ierroff] = 0; 1240 ++ioptr; 1241 } while (--count != 0); 1242 } 1243 com->iptr = ioptr; 1244 } 1245cont: 1246 1247 /* terminate service context */ 1248#ifdef PollMode 1249 cd_outb(iobase, CD1400_RIR, cy_align, 1250 save_rir 1251 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1252#else 1253 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1254#endif 1255 } 1256 if (status & CD1400_SVRR_MDMCH) { 1257 struct com_s *com; 1258 u_char modem_status; 1259#ifdef PollMode 1260 u_char save_mir; 1261#else 1262 u_char vector; 1263#endif 1264 1265#ifdef PollMode 1266 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1267 1268 /* enter modem service */ 1269 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1270 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1271 = save_mir & CD1400_CAR_CHAN; 1272 1273 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1274 + (save_mir & CD1400_MIR_CHAN)); 1275#else 1276 /* ack modem service */ 1277 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1278 1279 com = com_addr(baseu 1280 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1281 & CD1400_xIVR_CHAN)); 1282#endif 1283 ++com->mdm; 1284 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1285 if (modem_status != com->last_modem_status) { 1286 if (com->do_dcd_timestamp 1287 && !(com->last_modem_status & MSR_DCD) 1288 && modem_status & MSR_DCD) 1289 microtime(&com->dcd_timestamp); 1290 1291 /* 1292 * Schedule high level to handle DCD changes. Note 1293 * that we don't use the delta bits anywhere. Some 1294 * UARTs mess them up, and it's easy to remember the 1295 * previous bits and calculate the delta. 1296 */ 1297 com->last_modem_status = modem_status; 1298 if (!(com->state & CS_CHECKMSR)) { 1299 com_events += LOTS_OF_EVENTS; 1300 com->state |= CS_CHECKMSR; 1301 swi_sched(sio_fast_ih, 0); 1302 } 1303 1304#ifdef SOFT_CTS_OFLOW 1305 /* handle CTS change immediately for crisp flow ctl */ 1306 if (com->state & CS_CTS_OFLOW) { 1307 if (modem_status & MSR_CTS) { 1308 com->state |= CS_ODEVREADY; 1309 if (com->state >= (CS_BUSY | CS_TTGO 1310 | CS_ODEVREADY) 1311 && !(com->intr_enable 1312 & CD1400_SRER_TXRDY)) 1313 cd_outb(iobase, CD1400_SRER, 1314 cy_align, 1315 com->intr_enable 1316 = com->intr_enable 1317 & ~CD1400_SRER_TXMPTY 1318 | CD1400_SRER_TXRDY); 1319 } else { 1320 com->state &= ~CS_ODEVREADY; 1321 if (com->intr_enable 1322 & CD1400_SRER_TXRDY) 1323 cd_outb(iobase, CD1400_SRER, 1324 cy_align, 1325 com->intr_enable 1326 = com->intr_enable 1327 & ~CD1400_SRER_TXRDY 1328 | CD1400_SRER_TXMPTY); 1329 } 1330 } 1331#endif 1332 } 1333 1334 /* terminate service context */ 1335#ifdef PollMode 1336 cd_outb(iobase, CD1400_MIR, cy_align, 1337 save_mir 1338 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1339#else 1340 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1341#endif 1342 } 1343 if (status & CD1400_SVRR_TXRDY) { 1344 struct com_s *com; 1345#ifdef PollMode 1346 u_char save_tir; 1347#else 1348 u_char vector; 1349#endif 1350 1351#ifdef PollMode 1352 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1353 1354 /* enter tx service */ 1355 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1356 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1357 = save_tir & CD1400_CAR_CHAN; 1358 1359 com = com_addr(baseu 1360 + cyu * CD1400_NO_OF_CHANNELS 1361 + (save_tir & CD1400_TIR_CHAN)); 1362#else 1363 /* ack transmit service */ 1364 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1365 1366 com = com_addr(baseu 1367 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1368 & CD1400_xIVR_CHAN)); 1369#endif 1370 1371 if (com->etc != ETC_NONE) { 1372 if (com->intr_enable & CD1400_SRER_TXRDY) { 1373 /* 1374 * Here due to sloppy SRER_TXRDY 1375 * enabling. Ignore. Come back when 1376 * tx is empty. 1377 */ 1378 cd_outb(iobase, CD1400_SRER, cy_align, 1379 com->intr_enable 1380 = (com->intr_enable 1381 & ~CD1400_SRER_TXRDY) 1382 | CD1400_SRER_TXMPTY); 1383 goto terminate_tx_service; 1384 } 1385 switch (com->etc) { 1386 case CD1400_ETC_SENDBREAK: 1387 case CD1400_ETC_STOPBREAK: 1388 /* 1389 * Start the command. Come back on 1390 * next tx empty interrupt, hopefully 1391 * after command has been executed. 1392 */ 1393 cd_outb(iobase, CD1400_COR2, cy_align, 1394 com->cor[1] |= CD1400_COR2_ETC); 1395 cd_outb(iobase, CD1400_TDR, cy_align, 1396 CD1400_ETC_CMD); 1397 cd_outb(iobase, CD1400_TDR, cy_align, 1398 com->etc); 1399 if (com->etc == CD1400_ETC_SENDBREAK) 1400 com->etc = ETC_BREAK_STARTING; 1401 else 1402 com->etc = ETC_BREAK_ENDING; 1403 goto terminate_tx_service; 1404 case ETC_BREAK_STARTING: 1405 /* 1406 * BREAK is now on. Continue with 1407 * SRER_TXMPTY processing, hopefully 1408 * don't come back. 1409 */ 1410 com->etc = ETC_BREAK_STARTED; 1411 break; 1412 case ETC_BREAK_STARTED: 1413 /* 1414 * Came back due to sloppy SRER_TXMPTY 1415 * enabling. Hope again. 1416 */ 1417 break; 1418 case ETC_BREAK_ENDING: 1419 /* 1420 * BREAK is now off. Continue with 1421 * SRER_TXMPTY processing and don't 1422 * come back. The SWI handler will 1423 * restart tx interrupts if necessary. 1424 */ 1425 cd_outb(iobase, CD1400_COR2, cy_align, 1426 com->cor[1] 1427 &= ~CD1400_COR2_ETC); 1428 com->etc = ETC_BREAK_ENDED; 1429 if (!(com->state & CS_ODONE)) { 1430 com_events += LOTS_OF_EVENTS; 1431 com->state |= CS_ODONE; 1432 swi_sched(sio_fast_ih, 0); 1433 } 1434 break; 1435 case ETC_BREAK_ENDED: 1436 /* 1437 * Shouldn't get here. Hope again. 1438 */ 1439 break; 1440 } 1441 } 1442 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1443 if (!(com->extra_state & CSE_ODONE)) { 1444 com_events += LOTS_OF_EVENTS; 1445 com->extra_state |= CSE_ODONE; 1446 swi_sched(sio_fast_ih, 0); 1447 } 1448 cd_outb(iobase, CD1400_SRER, cy_align, 1449 com->intr_enable 1450 &= ~CD1400_SRER_TXMPTY); 1451 goto terminate_tx_service; 1452 } 1453 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1454 u_char *ioptr; 1455 u_int ocount; 1456 1457 ioptr = com->obufq.l_head; 1458 ocount = com->obufq.l_tail - ioptr; 1459 if (ocount > CD1400_TX_FIFO_SIZE) 1460 ocount = CD1400_TX_FIFO_SIZE; 1461 com->bytes_out += ocount; 1462 do 1463 cd_outb(iobase, CD1400_TDR, cy_align, 1464 *ioptr++); 1465 while (--ocount != 0); 1466 com->obufq.l_head = ioptr; 1467 if (ioptr >= com->obufq.l_tail) { 1468 struct lbq *qp; 1469 1470 qp = com->obufq.l_next; 1471 qp->l_queued = FALSE; 1472 qp = qp->l_next; 1473 if (qp != NULL) { 1474 com->obufq.l_head = qp->l_head; 1475 com->obufq.l_tail = qp->l_tail; 1476 com->obufq.l_next = qp; 1477 } else { 1478 /* output just completed */ 1479 com->state &= ~CS_BUSY; 1480 1481 /* 1482 * The setting of CSE_ODONE may be 1483 * stale here. We currently only 1484 * use it when CS_BUSY is set, and 1485 * fixing it when we clear CS_BUSY 1486 * is easiest. 1487 */ 1488 if (com->extra_state & CSE_ODONE) { 1489 com_events -= LOTS_OF_EVENTS; 1490 com->extra_state &= ~CSE_ODONE; 1491 } 1492 1493 cd_outb(iobase, CD1400_SRER, cy_align, 1494 com->intr_enable 1495 = (com->intr_enable 1496 & ~CD1400_SRER_TXRDY) 1497 | CD1400_SRER_TXMPTY); 1498 } 1499 if (!(com->state & CS_ODONE)) { 1500 com_events += LOTS_OF_EVENTS; 1501 com->state |= CS_ODONE; 1502 1503 /* handle at high level ASAP */ 1504 swi_sched(sio_fast_ih, 0); 1505 } 1506 } 1507 } 1508 1509 /* terminate service context */ 1510terminate_tx_service: 1511#ifdef PollMode 1512 cd_outb(iobase, CD1400_TIR, cy_align, 1513 save_tir 1514 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1515#else 1516 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1517#endif 1518 } 1519 } 1520 1521 /* ensure an edge for the next interrupt */ 1522 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1523 1524 swi_sched(sio_slow_ih, SWI_DELAY); 1525 1526 COM_UNLOCK(); 1527} 1528 1529static int 1530sioioctl(dev, cmd, data, flag, td) 1531 struct cdev *dev; 1532 u_long cmd; 1533 caddr_t data; 1534 int flag; 1535 struct thread *td; 1536{ 1537 struct com_s *com; 1538 int error; 1539 int mynor; 1540 int s; 1541 struct tty *tp; 1542#if defined(COMPAT_43) 1543 int oldcmd; 1544 struct termios term; 1545#endif 1546 1547 mynor = minor(dev); 1548 com = com_addr(MINOR_TO_UNIT(mynor)); 1549 if (mynor & CONTROL_MASK) { 1550 struct termios *ct; 1551 1552 switch (mynor & CONTROL_MASK) { 1553 case CONTROL_INIT_STATE: 1554 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1555 break; 1556 case CONTROL_LOCK_STATE: 1557 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1558 break; 1559 default: 1560 return (ENODEV); /* /dev/nodev */ 1561 } 1562 switch (cmd) { 1563 case TIOCSETA: 1564 error = suser(td); 1565 if (error != 0) 1566 return (error); 1567 *ct = *(struct termios *)data; 1568 return (0); 1569 case TIOCGETA: 1570 *(struct termios *)data = *ct; 1571 return (0); 1572 case TIOCGETD: 1573 *(int *)data = TTYDISC; 1574 return (0); 1575 case TIOCGWINSZ: 1576 bzero(data, sizeof(struct winsize)); 1577 return (0); 1578 default: 1579 return (ENOTTY); 1580 } 1581 } 1582 tp = com->tp; 1583#if defined(COMPAT_43) 1584 term = tp->t_termios; 1585 oldcmd = cmd; 1586 error = ttsetcompat(tp, &cmd, data, &term); 1587 if (error != 0) 1588 return (error); 1589 if (cmd != oldcmd) 1590 data = (caddr_t)&term; 1591#endif 1592 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1593 int cc; 1594 struct termios *dt = (struct termios *)data; 1595 struct termios *lt = mynor & CALLOUT_MASK 1596 ? &com->lt_out : &com->lt_in; 1597 1598 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1599 | (dt->c_iflag & ~lt->c_iflag); 1600 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1601 | (dt->c_oflag & ~lt->c_oflag); 1602 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1603 | (dt->c_cflag & ~lt->c_cflag); 1604 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1605 | (dt->c_lflag & ~lt->c_lflag); 1606 for (cc = 0; cc < NCCS; ++cc) 1607 if (lt->c_cc[cc] != 0) 1608 dt->c_cc[cc] = tp->t_cc[cc]; 1609 if (lt->c_ispeed != 0) 1610 dt->c_ispeed = tp->t_ispeed; 1611 if (lt->c_ospeed != 0) 1612 dt->c_ospeed = tp->t_ospeed; 1613 } 1614 error = ttyioctl(dev, cmd, data, flag, td); 1615 disc_optim(tp, &tp->t_termios, com); 1616 if (error != ENOTTY) 1617 return (error); 1618 s = spltty(); 1619 switch (cmd) { 1620 case TIOCSBRK: 1621#if 0 1622 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1623#else 1624 cd_etc(com, CD1400_ETC_SENDBREAK); 1625#endif 1626 break; 1627 case TIOCCBRK: 1628#if 0 1629 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1630#else 1631 cd_etc(com, CD1400_ETC_STOPBREAK); 1632#endif 1633 break; 1634 case TIOCSDTR: 1635 (void)commctl(com, TIOCM_DTR, DMBIS); 1636 break; 1637 case TIOCCDTR: 1638 (void)commctl(com, TIOCM_DTR, DMBIC); 1639 break; 1640 /* 1641 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1642 * changes get undone on the next call to comparam(). 1643 */ 1644 case TIOCMSET: 1645 (void)commctl(com, *(int *)data, DMSET); 1646 break; 1647 case TIOCMBIS: 1648 (void)commctl(com, *(int *)data, DMBIS); 1649 break; 1650 case TIOCMBIC: 1651 (void)commctl(com, *(int *)data, DMBIC); 1652 break; 1653 case TIOCMGET: 1654 *(int *)data = commctl(com, 0, DMGET); 1655 break; 1656 case TIOCMSDTRWAIT: 1657 /* must be root since the wait applies to following logins */ 1658 error = suser(td); 1659 if (error != 0) { 1660 splx(s); 1661 return (error); 1662 } 1663 com->dtr_wait = *(int *)data * hz / 100; 1664 break; 1665 case TIOCMGDTRWAIT: 1666 *(int *)data = com->dtr_wait * 100 / hz; 1667 break; 1668 case TIOCTIMESTAMP: 1669 com->do_timestamp = TRUE; 1670 *(struct timeval *)data = com->timestamp; 1671 break; 1672 case TIOCDCDTIMESTAMP: 1673 com->do_dcd_timestamp = TRUE; 1674 *(struct timeval *)data = com->dcd_timestamp; 1675 break; 1676 default: 1677 splx(s); 1678 return (ENOTTY); 1679 } 1680 splx(s); 1681 return (0); 1682} 1683 1684static void 1685siopoll(void *arg) 1686{ 1687 int unit; 1688 1689#ifdef CyDebug 1690 ++cy_timeouts; 1691#endif 1692 if (com_events == 0) 1693 return; 1694repeat: 1695 for (unit = 0; unit < NSIO; ++unit) { 1696 struct com_s *com; 1697 int incc; 1698 struct tty *tp; 1699 1700 com = com_addr(unit); 1701 if (com == NULL) 1702 continue; 1703 tp = com->tp; 1704 if (tp == NULL) { 1705 /* 1706 * XXX forget any events related to closed devices 1707 * (actually never opened devices) so that we don't 1708 * loop. 1709 */ 1710 critical_enter(); 1711 COM_LOCK(); 1712 incc = com->iptr - com->ibuf; 1713 com->iptr = com->ibuf; 1714 if (com->state & CS_CHECKMSR) { 1715 incc += LOTS_OF_EVENTS; 1716 com->state &= ~CS_CHECKMSR; 1717 } 1718 com_events -= incc; 1719 COM_UNLOCK(); 1720 critical_exit(); 1721 if (incc != 0) 1722 log(LOG_DEBUG, 1723 "sio%d: %d events for device with no tp\n", 1724 unit, incc); 1725 continue; 1726 } 1727 if (com->iptr != com->ibuf) { 1728 critical_enter(); 1729 COM_LOCK(); 1730 sioinput(com); 1731 COM_UNLOCK(); 1732 critical_exit(); 1733 } 1734 if (com->state & CS_CHECKMSR) { 1735 u_char delta_modem_status; 1736 1737 critical_enter(); 1738 COM_LOCK(); 1739 sioinput(com); 1740 delta_modem_status = com->last_modem_status 1741 ^ com->prev_modem_status; 1742 com->prev_modem_status = com->last_modem_status; 1743 com_events -= LOTS_OF_EVENTS; 1744 com->state &= ~CS_CHECKMSR; 1745 COM_UNLOCK(); 1746 critical_exit(); 1747 if (delta_modem_status & MSR_DCD) 1748 ttyld_modem(tp, 1749 com->prev_modem_status & MSR_DCD); 1750 } 1751 if (com->extra_state & CSE_ODONE) { 1752 critical_enter(); 1753 COM_LOCK(); 1754 com_events -= LOTS_OF_EVENTS; 1755 com->extra_state &= ~CSE_ODONE; 1756 COM_UNLOCK(); 1757 critical_exit(); 1758 if (!(com->state & CS_BUSY)) { 1759 tp->t_state &= ~TS_BUSY; 1760 ttwwakeup(com->tp); 1761 } 1762 if (com->etc != ETC_NONE) { 1763 if (com->etc == ETC_BREAK_ENDED) 1764 com->etc = ETC_NONE; 1765 wakeup(&com->etc); 1766 } 1767 } 1768 if (com->state & CS_ODONE) { 1769 critical_enter(); 1770 COM_LOCK(); 1771 com_events -= LOTS_OF_EVENTS; 1772 com->state &= ~CS_ODONE; 1773 COM_UNLOCK(); 1774 critical_exit(); 1775 ttyld_start(tp); 1776 } 1777 if (com_events == 0) 1778 break; 1779 } 1780 if (com_events >= LOTS_OF_EVENTS) 1781 goto repeat; 1782} 1783 1784static int 1785comparam(tp, t) 1786 struct tty *tp; 1787 struct termios *t; 1788{ 1789 int bits; 1790 int cflag; 1791 struct com_s *com; 1792 u_char cor_change; 1793 u_long cy_clock; 1794 int idivisor; 1795 int iflag; 1796 int iprescaler; 1797 int itimeout; 1798 int odivisor; 1799 int oprescaler; 1800 u_char opt; 1801 int s; 1802 int unit; 1803 1804 unit = DEV_TO_UNIT(tp->t_dev); 1805 com = com_addr(unit); 1806 1807 /* check requested parameters */ 1808 cy_clock = CY_CLOCK(com->gfrcr_image); 1809 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1810 if (idivisor <= 0) 1811 return (EINVAL); 1812 odivisor = comspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed, 1813 cy_clock, &oprescaler); 1814 if (odivisor <= 0) 1815 return (EINVAL); 1816 1817 /* parameters are OK, convert them to the com struct and the device */ 1818 s = spltty(); 1819 if (t->c_ospeed == 0) 1820 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1821 else 1822 (void)commctl(com, TIOCM_DTR, DMBIS); 1823 1824 (void) siosetwater(com, t->c_ispeed); 1825 1826 /* XXX we don't actually change the speed atomically. */ 1827 1828 cd_setreg(com, CD1400_RBPR, idivisor); 1829 cd_setreg(com, CD1400_RCOR, iprescaler); 1830 cd_setreg(com, CD1400_TBPR, odivisor); 1831 cd_setreg(com, CD1400_TCOR, oprescaler); 1832 1833 /* 1834 * channel control 1835 * receiver enable 1836 * transmitter enable (always set) 1837 */ 1838 cflag = t->c_cflag; 1839 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1840 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1841 if (opt != com->channel_control) { 1842 com->channel_control = opt; 1843 cd1400_channel_cmd(com, opt); 1844 } 1845 1846#ifdef Smarts 1847 /* set special chars */ 1848 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1849 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1850 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1851 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1852 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1853 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1854 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1855 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1856 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1857#endif 1858 1859 /* 1860 * set channel option register 1 - 1861 * parity mode 1862 * stop bits 1863 * char length 1864 */ 1865 opt = 0; 1866 /* parity */ 1867 if (cflag & PARENB) { 1868 if (cflag & PARODD) 1869 opt |= CD1400_COR1_PARODD; 1870 opt |= CD1400_COR1_PARNORMAL; 1871 } 1872 iflag = t->c_iflag; 1873 if (!(iflag & INPCK)) 1874 opt |= CD1400_COR1_NOINPCK; 1875 bits = 1 + 1; 1876 /* stop bits */ 1877 if (cflag & CSTOPB) { 1878 ++bits; 1879 opt |= CD1400_COR1_STOP2; 1880 } 1881 /* char length */ 1882 switch (cflag & CSIZE) { 1883 case CS5: 1884 bits += 5; 1885 opt |= CD1400_COR1_CS5; 1886 break; 1887 case CS6: 1888 bits += 6; 1889 opt |= CD1400_COR1_CS6; 1890 break; 1891 case CS7: 1892 bits += 7; 1893 opt |= CD1400_COR1_CS7; 1894 break; 1895 default: 1896 bits += 8; 1897 opt |= CD1400_COR1_CS8; 1898 break; 1899 } 1900 cor_change = 0; 1901 if (opt != com->cor[0]) { 1902 cor_change |= CD1400_CCR_COR1; 1903 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1904 } 1905 1906 /* 1907 * Set receive time-out period, normally to max(one char time, 5 ms). 1908 */ 1909 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1910#ifdef SOFT_HOTCHAR 1911#define MIN_RTP 1 1912#else 1913#define MIN_RTP 5 1914#endif 1915 if (itimeout < MIN_RTP) 1916 itimeout = MIN_RTP; 1917 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1918 && t->c_cc[VTIME] * 10 > itimeout) 1919 itimeout = t->c_cc[VTIME] * 10; 1920 if (itimeout > 255) 1921 itimeout = 255; 1922 cd_setreg(com, CD1400_RTPR, itimeout); 1923 1924 /* 1925 * set channel option register 2 - 1926 * flow control 1927 */ 1928 opt = 0; 1929#ifdef Smarts 1930 if (iflag & IXANY) 1931 opt |= CD1400_COR2_IXANY; 1932 if (iflag & IXOFF) 1933 opt |= CD1400_COR2_IXOFF; 1934#endif 1935#ifndef SOFT_CTS_OFLOW 1936 if (cflag & CCTS_OFLOW) 1937 opt |= CD1400_COR2_CCTS_OFLOW; 1938#endif 1939 critical_enter(); 1940 COM_LOCK(); 1941 if (opt != com->cor[1]) { 1942 cor_change |= CD1400_CCR_COR2; 1943 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 1944 } 1945 COM_UNLOCK(); 1946 critical_exit(); 1947 1948 /* 1949 * set channel option register 3 - 1950 * receiver FIFO interrupt threshold 1951 * flow control 1952 */ 1953 opt = RxFifoThreshold; 1954#ifdef Smarts 1955 if (t->c_lflag & ICANON) 1956 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 1957 if (iflag & IXOFF) 1958 /* detect and transparently handle START and STOP chars */ 1959 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 1960#endif 1961 if (opt != com->cor[2]) { 1962 cor_change |= CD1400_CCR_COR3; 1963 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 1964 } 1965 1966 /* notify the CD1400 if COR1-3 have changed */ 1967 if (cor_change) 1968 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 1969 1970 /* 1971 * set channel option register 4 - 1972 * CR/NL processing 1973 * break processing 1974 * received exception processing 1975 */ 1976 opt = 0; 1977 if (iflag & IGNCR) 1978 opt |= CD1400_COR4_IGNCR; 1979#ifdef Smarts 1980 /* 1981 * we need a new ttyinput() for this, as we don't want to 1982 * have ICRNL && INLCR being done in both layers, or to have 1983 * synchronisation problems 1984 */ 1985 if (iflag & ICRNL) 1986 opt |= CD1400_COR4_ICRNL; 1987 if (iflag & INLCR) 1988 opt |= CD1400_COR4_INLCR; 1989#endif 1990 if (iflag & IGNBRK) 1991 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 1992 /* 1993 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 1994 * so only tell the hardware about -brkint if -parmrk. 1995 */ 1996 if (!(iflag & (BRKINT | PARMRK))) 1997 opt |= CD1400_COR4_NOBRKINT; 1998#if 0 1999 /* XXX using this "intelligence" breaks reporting of overruns. */ 2000 if (iflag & IGNPAR) 2001 opt |= CD1400_COR4_PFO_DISCARD; 2002 else { 2003 if (iflag & PARMRK) 2004 opt |= CD1400_COR4_PFO_ESC; 2005 else 2006 opt |= CD1400_COR4_PFO_NUL; 2007 } 2008#else 2009 opt |= CD1400_COR4_PFO_EXCEPTION; 2010#endif 2011 cd_setreg(com, CD1400_COR4, opt); 2012 2013 /* 2014 * set channel option register 5 - 2015 */ 2016 opt = 0; 2017 if (iflag & ISTRIP) 2018 opt |= CD1400_COR5_ISTRIP; 2019 if (t->c_iflag & IEXTEN) 2020 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2021 opt |= CD1400_COR5_LNEXT; 2022#ifdef Smarts 2023 if (t->c_oflag & ONLCR) 2024 opt |= CD1400_COR5_ONLCR; 2025 if (t->c_oflag & OCRNL) 2026 opt |= CD1400_COR5_OCRNL; 2027#endif 2028 cd_setreg(com, CD1400_COR5, opt); 2029 2030 /* 2031 * We always generate modem status change interrupts for CD changes. 2032 * Among other things, this is necessary to track TS_CARR_ON for 2033 * pstat to print even when the driver doesn't care. CD changes 2034 * should be rare so interrupts for them are not worth extra code to 2035 * avoid. We avoid interrupts for other modem status changes (except 2036 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2037 * simplest and best. 2038 */ 2039 2040 /* 2041 * set modem change option register 1 2042 * generate modem interrupts on which 1 -> 0 input transitions 2043 * also controls auto-DTR output flow-control, which we don't use 2044 */ 2045 opt = CD1400_MCOR1_CDzd; 2046#ifdef SOFT_CTS_OFLOW 2047 if (cflag & CCTS_OFLOW) 2048 opt |= CD1400_MCOR1_CTSzd; 2049#endif 2050 cd_setreg(com, CD1400_MCOR1, opt); 2051 2052 /* 2053 * set modem change option register 2 2054 * generate modem interrupts on specific 0 -> 1 input transitions 2055 */ 2056 opt = CD1400_MCOR2_CDod; 2057#ifdef SOFT_CTS_OFLOW 2058 if (cflag & CCTS_OFLOW) 2059 opt |= CD1400_MCOR2_CTSod; 2060#endif 2061 cd_setreg(com, CD1400_MCOR2, opt); 2062 2063 /* 2064 * XXX should have done this long ago, but there is too much state 2065 * to change all atomically. 2066 */ 2067 critical_enter(); 2068 COM_LOCK(); 2069 2070 com->state &= ~CS_TTGO; 2071 if (!(tp->t_state & TS_TTSTOP)) 2072 com->state |= CS_TTGO; 2073 if (cflag & CRTS_IFLOW) { 2074 com->state |= CS_RTS_IFLOW; 2075 /* 2076 * If CS_RTS_IFLOW just changed from off to on, the change 2077 * needs to be propagated to MCR_RTS. This isn't urgent, 2078 * so do it later by calling comstart() instead of repeating 2079 * a lot of code from comstart() here. 2080 */ 2081 } else if (com->state & CS_RTS_IFLOW) { 2082 com->state &= ~CS_RTS_IFLOW; 2083 /* 2084 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2085 * on here, since comstart() won't do it later. 2086 */ 2087#if 0 2088 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2089#else 2090 cd_setreg(com, com->mcr_rts_reg, 2091 com->mcr_image |= com->mcr_rts); 2092#endif 2093 } 2094 2095 /* 2096 * Set up state to handle output flow control. 2097 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2098 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2099 */ 2100 com->state |= CS_ODEVREADY; 2101#ifdef SOFT_CTS_OFLOW 2102 com->state &= ~CS_CTS_OFLOW; 2103 if (cflag & CCTS_OFLOW) { 2104 com->state |= CS_CTS_OFLOW; 2105 if (!(com->last_modem_status & MSR_CTS)) 2106 com->state &= ~CS_ODEVREADY; 2107 } 2108#endif 2109 /* XXX shouldn't call functions while intrs are disabled. */ 2110 disc_optim(tp, t, com); 2111#if 0 2112 /* 2113 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2114 * unconditionally, but that defeated the careful discarding of 2115 * stale input in sioopen(). 2116 */ 2117 if (com->state >= (CS_BUSY | CS_TTGO)) 2118 siointr1(com); 2119#endif 2120 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2121 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2122 cd_setreg(com, CD1400_SRER, 2123 com->intr_enable 2124 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2125 | CD1400_SRER_TXRDY); 2126 } else { 2127 if (com->intr_enable & CD1400_SRER_TXRDY) 2128 cd_setreg(com, CD1400_SRER, 2129 com->intr_enable 2130 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2131 | CD1400_SRER_TXMPTY); 2132 } 2133 2134 COM_UNLOCK(); 2135 critical_exit(); 2136 splx(s); 2137 comstart(tp); 2138 if (com->ibufold != NULL) { 2139 free(com->ibufold, M_DEVBUF); 2140 com->ibufold = NULL; 2141 } 2142 return (0); 2143} 2144 2145static int 2146siosetwater(com, speed) 2147 struct com_s *com; 2148 speed_t speed; 2149{ 2150 int cp4ticks; 2151 u_char *ibuf; 2152 int ibufsize; 2153 struct tty *tp; 2154 2155 /* 2156 * Make the buffer size large enough to handle a softtty interrupt 2157 * latency of about 2 ticks without loss of throughput or data 2158 * (about 3 ticks if input flow control is not used or not honoured, 2159 * but a bit less for CS5-CS7 modes). 2160 */ 2161 cp4ticks = speed / 10 / hz * 4; 2162 for (ibufsize = 128; ibufsize < cp4ticks;) 2163 ibufsize <<= 1; 2164 if (ibufsize == com->ibufsize) { 2165 return (0); 2166 } 2167 2168 /* 2169 * Allocate input buffer. The extra factor of 2 in the size is 2170 * to allow for an error byte for each input byte. 2171 */ 2172 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2173 if (ibuf == NULL) { 2174 return (ENOMEM); 2175 } 2176 2177 /* Initialize non-critical variables. */ 2178 com->ibufold = com->ibuf; 2179 com->ibufsize = ibufsize; 2180 tp = com->tp; 2181 if (tp != NULL) { 2182 tp->t_ififosize = 2 * ibufsize; 2183 tp->t_ispeedwat = (speed_t)-1; 2184 tp->t_ospeedwat = (speed_t)-1; 2185 } 2186 2187 /* 2188 * Read current input buffer, if any. Continue with interrupts 2189 * disabled. 2190 */ 2191 critical_enter(); 2192 COM_LOCK(); 2193 if (com->iptr != com->ibuf) 2194 sioinput(com); 2195 2196 /*- 2197 * Initialize critical variables, including input buffer watermarks. 2198 * The external device is asked to stop sending when the buffer 2199 * exactly reaches high water, or when the high level requests it. 2200 * The high level is notified immediately (rather than at a later 2201 * clock tick) when this watermark is reached. 2202 * The buffer size is chosen so the watermark should almost never 2203 * be reached. 2204 * The low watermark is invisibly 0 since the buffer is always 2205 * emptied all at once. 2206 */ 2207 com->iptr = com->ibuf = ibuf; 2208 com->ibufend = ibuf + ibufsize; 2209 com->ierroff = ibufsize; 2210 com->ihighwater = ibuf + 3 * ibufsize / 4; 2211 2212 COM_UNLOCK(); 2213 critical_exit(); 2214 return (0); 2215} 2216 2217static void 2218comstart(tp) 2219 struct tty *tp; 2220{ 2221 struct com_s *com; 2222 int s; 2223#ifdef CyDebug 2224 bool_t started; 2225#endif 2226 int unit; 2227 2228 unit = DEV_TO_UNIT(tp->t_dev); 2229 com = com_addr(unit); 2230 s = spltty(); 2231 2232#ifdef CyDebug 2233 ++com->start_count; 2234 started = FALSE; 2235#endif 2236 2237 critical_enter(); 2238 COM_LOCK(); 2239 if (tp->t_state & TS_TTSTOP) { 2240 com->state &= ~CS_TTGO; 2241 if (com->intr_enable & CD1400_SRER_TXRDY) 2242 cd_setreg(com, CD1400_SRER, 2243 com->intr_enable 2244 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2245 | CD1400_SRER_TXMPTY); 2246 } else { 2247 com->state |= CS_TTGO; 2248 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2249 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2250 cd_setreg(com, CD1400_SRER, 2251 com->intr_enable 2252 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2253 | CD1400_SRER_TXRDY); 2254 } 2255 if (tp->t_state & TS_TBLOCK) { 2256 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2257#if 0 2258 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2259#else 2260 cd_setreg(com, com->mcr_rts_reg, 2261 com->mcr_image &= ~com->mcr_rts); 2262#endif 2263 } else { 2264 if (!(com->mcr_image & com->mcr_rts) 2265 && com->iptr < com->ihighwater 2266 && com->state & CS_RTS_IFLOW) 2267#if 0 2268 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2269#else 2270 cd_setreg(com, com->mcr_rts_reg, 2271 com->mcr_image |= com->mcr_rts); 2272#endif 2273 } 2274 COM_UNLOCK(); 2275 critical_exit(); 2276 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2277 ttwwakeup(tp); 2278 splx(s); 2279 return; 2280 } 2281 if (tp->t_outq.c_cc != 0) { 2282 struct lbq *qp; 2283 struct lbq *next; 2284 2285 if (!com->obufs[0].l_queued) { 2286#ifdef CyDebug 2287 started = TRUE; 2288#endif 2289 com->obufs[0].l_tail 2290 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2291 sizeof com->obuf1); 2292 com->obufs[0].l_next = NULL; 2293 com->obufs[0].l_queued = TRUE; 2294 critical_enter(); 2295 COM_LOCK(); 2296 if (com->state & CS_BUSY) { 2297 qp = com->obufq.l_next; 2298 while ((next = qp->l_next) != NULL) 2299 qp = next; 2300 qp->l_next = &com->obufs[0]; 2301 } else { 2302 com->obufq.l_head = com->obufs[0].l_head; 2303 com->obufq.l_tail = com->obufs[0].l_tail; 2304 com->obufq.l_next = &com->obufs[0]; 2305 com->state |= CS_BUSY; 2306 if (com->state >= (CS_BUSY | CS_TTGO 2307 | CS_ODEVREADY)) 2308 cd_setreg(com, CD1400_SRER, 2309 com->intr_enable 2310 = (com->intr_enable 2311 & ~CD1400_SRER_TXMPTY) 2312 | CD1400_SRER_TXRDY); 2313 } 2314 COM_UNLOCK(); 2315 critical_exit(); 2316 } 2317 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2318#ifdef CyDebug 2319 started = TRUE; 2320#endif 2321 com->obufs[1].l_tail 2322 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2323 sizeof com->obuf2); 2324 com->obufs[1].l_next = NULL; 2325 com->obufs[1].l_queued = TRUE; 2326 critical_enter(); 2327 COM_LOCK(); 2328 if (com->state & CS_BUSY) { 2329 qp = com->obufq.l_next; 2330 while ((next = qp->l_next) != NULL) 2331 qp = next; 2332 qp->l_next = &com->obufs[1]; 2333 } else { 2334 com->obufq.l_head = com->obufs[1].l_head; 2335 com->obufq.l_tail = com->obufs[1].l_tail; 2336 com->obufq.l_next = &com->obufs[1]; 2337 com->state |= CS_BUSY; 2338 if (com->state >= (CS_BUSY | CS_TTGO 2339 | CS_ODEVREADY)) 2340 cd_setreg(com, CD1400_SRER, 2341 com->intr_enable 2342 = (com->intr_enable 2343 & ~CD1400_SRER_TXMPTY) 2344 | CD1400_SRER_TXRDY); 2345 } 2346 COM_UNLOCK(); 2347 critical_exit(); 2348 } 2349 tp->t_state |= TS_BUSY; 2350 } 2351#ifdef CyDebug 2352 if (started) 2353 ++com->start_real; 2354#endif 2355#if 0 2356 critical_enter(); 2357 COM_LOCK(); 2358 if (com->state >= (CS_BUSY | CS_TTGO)) 2359 siointr1(com); /* fake interrupt to start output */ 2360 COM_UNLOCK(); 2361 critical_exit(); 2362#endif 2363 ttwwakeup(tp); 2364 splx(s); 2365} 2366 2367static void 2368comstop(tp, rw) 2369 struct tty *tp; 2370 int rw; 2371{ 2372 struct com_s *com; 2373 bool_t wakeup_etc; 2374 2375 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2376 wakeup_etc = FALSE; 2377 critical_enter(); 2378 COM_LOCK(); 2379 if (rw & FWRITE) { 2380 com->obufs[0].l_queued = FALSE; 2381 com->obufs[1].l_queued = FALSE; 2382 if (com->extra_state & CSE_ODONE) { 2383 com_events -= LOTS_OF_EVENTS; 2384 com->extra_state &= ~CSE_ODONE; 2385 if (com->etc != ETC_NONE) { 2386 if (com->etc == ETC_BREAK_ENDED) 2387 com->etc = ETC_NONE; 2388 wakeup_etc = TRUE; 2389 } 2390 } 2391 com->tp->t_state &= ~TS_BUSY; 2392 if (com->state & CS_ODONE) 2393 com_events -= LOTS_OF_EVENTS; 2394 com->state &= ~(CS_ODONE | CS_BUSY); 2395 } 2396 if (rw & FREAD) { 2397 /* XXX no way to reset only input fifo. */ 2398 com_events -= (com->iptr - com->ibuf); 2399 com->iptr = com->ibuf; 2400 } 2401 COM_UNLOCK(); 2402 critical_exit(); 2403 if (wakeup_etc) 2404 wakeup(&com->etc); 2405 if (rw & FWRITE && com->etc == ETC_NONE) 2406 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2407 comstart(tp); 2408} 2409 2410static int 2411commctl(com, bits, how) 2412 struct com_s *com; 2413 int bits; 2414 int how; 2415{ 2416 int mcr; 2417 int msr; 2418 2419 if (how == DMGET) { 2420 if (com->channel_control & CD1400_CCR_RCVEN) 2421 bits |= TIOCM_LE; 2422 mcr = com->mcr_image; 2423 if (mcr & com->mcr_dtr) 2424 bits |= TIOCM_DTR; 2425 if (mcr & com->mcr_rts) 2426 /* XXX wired on for Cyclom-8Ys */ 2427 bits |= TIOCM_RTS; 2428 2429 /* 2430 * We must read the modem status from the hardware because 2431 * we don't generate modem status change interrupts for all 2432 * changes, so com->prev_modem_status is not guaranteed to 2433 * be up to date. This is safe, unlike for sio, because 2434 * reading the status register doesn't clear pending modem 2435 * status change interrupts. 2436 */ 2437 msr = cd_getreg(com, CD1400_MSVR2); 2438 2439 if (msr & MSR_CTS) 2440 bits |= TIOCM_CTS; 2441 if (msr & MSR_DCD) 2442 bits |= TIOCM_CD; 2443 if (msr & MSR_DSR) 2444 bits |= TIOCM_DSR; 2445 if (msr & MSR_RI) 2446 /* XXX not connected except for Cyclom-16Y? */ 2447 bits |= TIOCM_RI; 2448 return (bits); 2449 } 2450 mcr = 0; 2451 if (bits & TIOCM_DTR) 2452 mcr |= com->mcr_dtr; 2453 if (bits & TIOCM_RTS) 2454 mcr |= com->mcr_rts; 2455 critical_enter(); 2456 COM_LOCK(); 2457 switch (how) { 2458 case DMSET: 2459 com->mcr_image = mcr; 2460 cd_setreg(com, CD1400_MSVR1, mcr); 2461 cd_setreg(com, CD1400_MSVR2, mcr); 2462 break; 2463 case DMBIS: 2464 com->mcr_image = mcr = com->mcr_image | mcr; 2465 cd_setreg(com, CD1400_MSVR1, mcr); 2466 cd_setreg(com, CD1400_MSVR2, mcr); 2467 break; 2468 case DMBIC: 2469 com->mcr_image = mcr = com->mcr_image & ~mcr; 2470 cd_setreg(com, CD1400_MSVR1, mcr); 2471 cd_setreg(com, CD1400_MSVR2, mcr); 2472 break; 2473 } 2474 COM_UNLOCK(); 2475 critical_exit(); 2476 return (0); 2477} 2478 2479static void 2480siosettimeout() 2481{ 2482 struct com_s *com; 2483 bool_t someopen; 2484 int unit; 2485 2486 /* 2487 * Set our timeout period to 1 second if no polled devices are open. 2488 * Otherwise set it to max(1/200, 1/hz). 2489 * Enable timeouts iff some device is open. 2490 */ 2491 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2492 sio_timeout = hz; 2493 someopen = FALSE; 2494 for (unit = 0; unit < NSIO; ++unit) { 2495 com = com_addr(unit); 2496 if (com != NULL && com->tp != NULL 2497 && com->tp->t_state & TS_ISOPEN) { 2498 someopen = TRUE; 2499#if 0 2500 if (com->poll || com->poll_output) { 2501 sio_timeout = hz > 200 ? hz / 200 : 1; 2502 break; 2503 } 2504#endif 2505 } 2506 } 2507 if (someopen) { 2508 sio_timeouts_until_log = hz / sio_timeout; 2509 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2510 sio_timeout); 2511 } else { 2512 /* Flush error messages, if any. */ 2513 sio_timeouts_until_log = 1; 2514 comwakeup((void *)NULL); 2515 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2516 } 2517} 2518 2519static void 2520comwakeup(chan) 2521 void *chan; 2522{ 2523 struct com_s *com; 2524 int unit; 2525 2526 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2527 2528#if 0 2529 /* 2530 * Recover from lost output interrupts. 2531 * Poll any lines that don't use interrupts. 2532 */ 2533 for (unit = 0; unit < NSIO; ++unit) { 2534 com = com_addr(unit); 2535 if (com != NULL 2536 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2537 critical_enter(); 2538 COM_LOCK(); 2539 siointr1(com); 2540 COM_UNLOCK(); 2541 critical_exit(); 2542 } 2543 } 2544#endif 2545 2546 /* 2547 * Check for and log errors, but not too often. 2548 */ 2549 if (--sio_timeouts_until_log > 0) 2550 return; 2551 sio_timeouts_until_log = hz / sio_timeout; 2552 for (unit = 0; unit < NSIO; ++unit) { 2553 int errnum; 2554 2555 com = com_addr(unit); 2556 if (com == NULL) 2557 continue; 2558 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2559 u_int delta; 2560 u_long total; 2561 2562 critical_enter(); 2563 COM_LOCK(); 2564 delta = com->delta_error_counts[errnum]; 2565 com->delta_error_counts[errnum] = 0; 2566 COM_UNLOCK(); 2567 critical_exit(); 2568 if (delta == 0) 2569 continue; 2570 total = com->error_counts[errnum] += delta; 2571 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2572 unit, delta, error_desc[errnum], 2573 delta == 1 ? "" : "s", total); 2574 } 2575 } 2576} 2577 2578static void 2579disc_optim(tp, t, com) 2580 struct tty *tp; 2581 struct termios *t; 2582 struct com_s *com; 2583{ 2584#ifndef SOFT_HOTCHAR 2585 u_char opt; 2586#endif 2587 2588 com->hotchar = ttyldoptim(tp); 2589#ifndef SOFT_HOTCHAR 2590 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2591 if (com->hotchar != 0) { 2592 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2593 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2594 opt |= CD1400_COR3_SCD34; 2595 } 2596 if (opt != com->cor[2]) { 2597 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2598 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2599 } 2600#endif 2601} 2602 2603#ifdef Smarts 2604/* standard line discipline input routine */ 2605int 2606cyinput(c, tp) 2607 int c; 2608 struct tty *tp; 2609{ 2610 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2611 * bits, as they are done by the CD1400. Hardly worth the effort, 2612 * given that high-throughput sessions are raw anyhow. 2613 */ 2614} 2615#endif /* Smarts */ 2616 2617static int 2618comspeed(speed, cy_clock, prescaler_io) 2619 speed_t speed; 2620 u_long cy_clock; 2621 int *prescaler_io; 2622{ 2623 int actual; 2624 int error; 2625 int divider; 2626 int prescaler; 2627 int prescaler_unit; 2628 2629 if (speed == 0) 2630 return (0); 2631 if (speed < 0 || speed > 150000) 2632 return (-1); 2633 2634 /* determine which prescaler to use */ 2635 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2636 prescaler_unit--, prescaler >>= 2) { 2637 if (cy_clock / prescaler / speed > 63) 2638 break; 2639 } 2640 2641 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2642 if (divider > 255) 2643 divider = 255; 2644 actual = cy_clock/prescaler/divider; 2645 2646 /* 10 times error in percent: */ 2647 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2648 2649 /* 3.0% max error tolerance */ 2650 if (error < -30 || error > 30) 2651 return (-1); 2652 2653#if 0 2654 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2655 printf("divider = %d (%x)\n", divider, divider); 2656 printf("actual = %d\n", actual); 2657 printf("error = %d\n", error); 2658#endif 2659 2660 *prescaler_io = prescaler_unit; 2661 return (divider); 2662} 2663 2664static void 2665cd1400_channel_cmd(com, cmd) 2666 struct com_s *com; 2667 int cmd; 2668{ 2669 cd1400_channel_cmd_wait(com); 2670 cd_setreg(com, CD1400_CCR, cmd); 2671 cd1400_channel_cmd_wait(com); 2672} 2673 2674static void 2675cd1400_channel_cmd_wait(com) 2676 struct com_s *com; 2677{ 2678 struct timeval start; 2679 struct timeval tv; 2680 long usec; 2681 2682 if (cd_getreg(com, CD1400_CCR) == 0) 2683 return; 2684 microtime(&start); 2685 for (;;) { 2686 if (cd_getreg(com, CD1400_CCR) == 0) 2687 return; 2688 microtime(&tv); 2689 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2690 tv.tv_usec - start.tv_usec; 2691 if (usec >= 5000) { 2692 log(LOG_ERR, 2693 "cy%d: channel command timeout (%ld usec)\n", 2694 com->unit, usec); 2695 return; 2696 } 2697 } 2698} 2699 2700static void 2701cd_etc(com, etc) 2702 struct com_s *com; 2703 int etc; 2704{ 2705 2706 /* 2707 * We can't change the hardware's ETC state while there are any 2708 * characters in the tx fifo, since those characters would be 2709 * interpreted as commands! Unputting characters from the fifo 2710 * is difficult, so we wait up to 12 character times for the fifo 2711 * to drain. The command will be delayed for up to 2 character 2712 * times for the tx to become empty. Unputting characters from 2713 * the tx holding and shift registers is impossible, so we wait 2714 * for the tx to become empty so that the command is sure to be 2715 * executed soon after we issue it. 2716 */ 2717 critical_enter(); 2718 COM_LOCK(); 2719 if (com->etc == etc) 2720 goto wait; 2721 if ((etc == CD1400_ETC_SENDBREAK 2722 && (com->etc == ETC_BREAK_STARTING 2723 || com->etc == ETC_BREAK_STARTED)) 2724 || (etc == CD1400_ETC_STOPBREAK 2725 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2726 || com->etc == ETC_NONE))) { 2727 COM_UNLOCK(); 2728 critical_exit(); 2729 return; 2730 } 2731 com->etc = etc; 2732 cd_setreg(com, CD1400_SRER, 2733 com->intr_enable 2734 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2735wait: 2736 COM_UNLOCK(); 2737 critical_exit(); 2738 while (com->etc == etc 2739 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2740 continue; 2741} 2742 2743static int 2744cd_getreg(com, reg) 2745 struct com_s *com; 2746 int reg; 2747{ 2748 struct com_s *basecom; 2749 u_char car; 2750 int cy_align; 2751 cy_addr iobase; 2752#ifdef SMP 2753 int need_unlock; 2754#endif 2755 int val; 2756 2757 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2758 car = com->unit & CD1400_CAR_CHAN; 2759 cy_align = com->cy_align; 2760 iobase = com->iobase; 2761 critical_enter(); 2762#ifdef SMP 2763 need_unlock = 0; 2764 if (!mtx_owned(&sio_lock)) { 2765 COM_LOCK(); 2766 need_unlock = 1; 2767 } 2768#endif 2769 if (basecom->car != car) 2770 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2771 val = cd_inb(iobase, reg, cy_align); 2772#ifdef SMP 2773 if (need_unlock) 2774 COM_UNLOCK(); 2775#endif 2776 critical_exit(); 2777 return (val); 2778} 2779 2780static void 2781cd_setreg(com, reg, val) 2782 struct com_s *com; 2783 int reg; 2784 int val; 2785{ 2786 struct com_s *basecom; 2787 u_char car; 2788 int cy_align; 2789 cy_addr iobase; 2790#ifdef SMP 2791 int need_unlock; 2792#endif 2793 2794 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2795 car = com->unit & CD1400_CAR_CHAN; 2796 cy_align = com->cy_align; 2797 iobase = com->iobase; 2798 critical_enter(); 2799#ifdef SMP 2800 need_unlock = 0; 2801 if (!mtx_owned(&sio_lock)) { 2802 COM_LOCK(); 2803 need_unlock = 1; 2804 } 2805#endif 2806 if (basecom->car != car) 2807 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2808 cd_outb(iobase, reg, cy_align, val); 2809#ifdef SMP 2810 if (need_unlock) 2811 COM_UNLOCK(); 2812#endif 2813 critical_exit(); 2814} 2815 2816#ifdef CyDebug 2817/* useful in ddb */ 2818void 2819cystatus(unit) 2820 int unit; 2821{ 2822 struct com_s *com; 2823 cy_addr iobase; 2824 u_int ocount; 2825 struct tty *tp; 2826 2827 com = com_addr(unit); 2828 printf("info for channel %d\n", unit); 2829 printf("------------------\n"); 2830 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2831 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2832 if (com == NULL) 2833 return; 2834 iobase = com->iobase; 2835 printf("\n"); 2836 printf("cd1400 base address:\\tt%p\n", iobase); 2837 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2838 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2839 com->cor[0], com->cor[1], com->cor[2]); 2840 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2841 cd_getreg(com, CD1400_SRER), com->intr_enable); 2842 printf("service request register:\t0x%02x\n", 2843 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2844 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2845 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2846 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2847 cd_inb(iobase, CD1400_RIR, com->cy_align), 2848 cd_inb(iobase, CD1400_TIR, com->cy_align), 2849 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2850 printf("\n"); 2851 printf("com state:\t\t\t0x%02x\n", com->state); 2852 printf("calls to comstart():\t\t%d (%d useful)\n", 2853 com->start_count, com->start_real); 2854 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2855 ocount = 0; 2856 if (com->obufs[0].l_queued) 2857 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2858 if (com->obufs[1].l_queued) 2859 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2860 printf("tx buffer chars:\t\t%u\n", ocount); 2861 printf("received chars:\t\t\t%d\n", com->bytes_in); 2862 printf("received exceptions:\t\t%d\n", com->recv_exception); 2863 printf("modem signal deltas:\t\t%d\n", com->mdm); 2864 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2865 printf("\n"); 2866 tp = com->tp; 2867 if (tp != NULL) { 2868 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2869 printf( 2870 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2871 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2872 } else 2873 printf("tty state:\t\t\tclosed\n"); 2874} 2875#endif /* CyDebug */
| 166 * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work. 167 */ 168#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ 169 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) 170#define UNIT_TO_MINOR(unit) (((unit) / CY_MAX_PORTS) << 16 \ 171 | (((unit) & 0xff) & ~MINOR_MAGIC_MASK)) 172 173/* 174 * com state bits. 175 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 176 * than the other bits so that they can be tested as a group without masking 177 * off the low bits. 178 * 179 * The following com and tty flags correspond closely: 180 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 181 * comstop()) 182 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 183 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 184 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 185 * TS_FLUSH is not used. 186 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 187 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 188 */ 189#define CS_BUSY 0x80 /* output in progress */ 190#define CS_TTGO 0x40 /* output not stopped by XOFF */ 191#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 192#define CS_CHECKMSR 1 /* check of MSR scheduled */ 193#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 194#define CS_DTR_OFF 0x10 /* DTR held off */ 195#define CS_ODONE 4 /* output completed */ 196#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 197#define CSE_ODONE 1 /* output transmitted */ 198 199static char const * const error_desc[] = { 200#define CE_OVERRUN 0 201 "silo overflow", 202#define CE_INTERRUPT_BUF_OVERFLOW 1 203 "interrupt-level buffer overflow", 204#define CE_TTY_BUF_OVERFLOW 2 205 "tty-level buffer overflow", 206}; 207 208#define CE_NTYPES 3 209#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 210 211#ifdef SMP 212#define COM_LOCK() mtx_lock_spin(&sio_lock) 213#define COM_UNLOCK() mtx_unlock_spin(&sio_lock) 214#else 215#define COM_LOCK() 216#define COM_UNLOCK() 217#endif 218 219/* types. XXX - should be elsewhere */ 220typedef u_char bool_t; /* boolean */ 221 222/* queue of linear buffers */ 223struct lbq { 224 u_char *l_head; /* next char to process */ 225 u_char *l_tail; /* one past the last char to process */ 226 struct lbq *l_next; /* next in queue */ 227 bool_t l_queued; /* nonzero if queued */ 228}; 229 230/* com device structure */ 231struct com_s { 232 u_char state; /* miscellaneous flag bits */ 233 bool_t active_out; /* nonzero if the callout device is open */ 234#if 0 235 u_char cfcr_image; /* copy of value written to CFCR */ 236#endif 237 u_char etc; /* pending Embedded Transmit Command */ 238 u_char extra_state; /* more flag bits, separate for order trick */ 239#if 0 240 u_char fifo_image; /* copy of value written to FIFO */ 241#endif 242 u_char gfrcr_image; /* copy of value read from GFRCR */ 243#if 0 244 bool_t hasfifo; /* nonzero for 16550 UARTs */ 245 bool_t loses_outints; /* nonzero if device loses output interrupts */ 246#endif 247 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 248 u_char mcr_image; /* copy of value written to MCR */ 249 u_char mcr_rts; /* MCR bit that is wired to RTS */ 250#if 0 251#ifdef COM_MULTIPORT 252 bool_t multiport; /* is this unit part of a multiport device? */ 253#endif /* COM_MULTIPORT */ 254 bool_t no_irq; /* nonzero if irq is not attached */ 255 bool_t poll; /* nonzero if polling is required */ 256 bool_t poll_output; /* nonzero if polling for output is required */ 257#endif 258 int unit; /* unit number */ 259 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 260#if 0 261 u_int tx_fifo_size; 262#endif 263 u_int wopeners; /* # processes waiting for DCD in open() */ 264 265 /* 266 * The high level of the driver never reads status registers directly 267 * because there would be too many side effects to handle conveniently. 268 * Instead, it reads copies of the registers stored here by the 269 * interrupt handler. 270 */ 271 u_char last_modem_status; /* last MSR read by intr handler */ 272 u_char prev_modem_status; /* last MSR handled by high level */ 273 274 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 275 u_char *ibuf; /* start of input buffer */ 276 u_char *ibufend; /* end of input buffer */ 277 u_char *ibufold; /* old input buffer, to be freed */ 278 u_char *ihighwater; /* threshold in input buffer */ 279 u_char *iptr; /* next free spot in input buffer */ 280 int ibufsize; /* size of ibuf (not include error bytes) */ 281 int ierroff; /* offset of error bytes in ibuf */ 282 283 struct lbq obufq; /* head of queue of output buffers */ 284 struct lbq obufs[2]; /* output buffers */ 285 286 int cy_align; /* index for register alignment */ 287 cy_addr cy_iobase; /* base address of this port's cyclom */ 288 cy_addr iobase; /* base address of this port's cd1400 */ 289 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 290 291 struct tty *tp; /* cross reference */ 292 293 /* Initial state. */ 294 struct termios it_in; /* should be in struct tty */ 295 struct termios it_out; 296 297 /* Lock state. */ 298 struct termios lt_in; /* should be in struct tty */ 299 struct termios lt_out; 300 301 bool_t do_timestamp; 302 bool_t do_dcd_timestamp; 303 struct timeval timestamp; 304 struct timeval dcd_timestamp; 305 306 u_long bytes_in; /* statistics */ 307 u_long bytes_out; 308 u_int delta_error_counts[CE_NTYPES]; 309 u_long error_counts[CE_NTYPES]; 310 311 u_int recv_exception; /* exception chars received */ 312 u_int mdm; /* modem signal changes */ 313#ifdef CyDebug 314 u_int start_count; /* no. of calls to comstart() */ 315 u_int start_real; /* no. of calls that did something */ 316#endif 317 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 318 u_char channel_control;/* CD1400 CCR control command shadow */ 319 u_char cor[3]; /* CD1400 COR1-3 shadows */ 320 u_char intr_enable; /* CD1400 SRER shadow */ 321 322 /* 323 * Data area for output buffers. Someday we should build the output 324 * buffer queue without copying data. 325 */ 326 u_char obuf1[256]; 327 u_char obuf2[256]; 328}; 329 330devclass_t cy_devclass; 331char cy_driver_name[] = "cy"; 332 333static void cd1400_channel_cmd(struct com_s *com, int cmd); 334static void cd1400_channel_cmd_wait(struct com_s *com); 335static void cd_etc(struct com_s *com, int etc); 336static int cd_getreg(struct com_s *com, int reg); 337static void cd_setreg(struct com_s *com, int reg, int val); 338static timeout_t siodtrwakeup; 339static void comhardclose(struct com_s *com); 340static void sioinput(struct com_s *com); 341static int commctl(struct com_s *com, int bits, int how); 342static int comparam(struct tty *tp, struct termios *t); 343static void siopoll(void *arg); 344static void siosettimeout(void); 345static int siosetwater(struct com_s *com, speed_t speed); 346static int comspeed(speed_t speed, u_long cy_clock, int *prescaler_io); 347static void comstart(struct tty *tp); 348static void comstop(struct tty *tp, int rw); 349static timeout_t comwakeup; 350static void disc_optim(struct tty *tp, struct termios *t, 351 struct com_s *com); 352 353#ifdef CyDebug 354void cystatus(int unit); 355#endif 356 357static struct mtx sio_lock; 358static int sio_inited; 359 360/* table and macro for fast conversion from a unit number to its com struct */ 361static struct com_s *p_com_addr[NSIO]; 362#define com_addr(unit) (p_com_addr[unit]) 363 364static d_open_t sioopen; 365static d_close_t sioclose; 366static d_write_t siowrite; 367static d_ioctl_t sioioctl; 368 369static struct cdevsw sio_cdevsw = { 370 .d_version = D_VERSION, 371 .d_open = sioopen, 372 .d_close = sioclose, 373 .d_write = siowrite, 374 .d_ioctl = sioioctl, 375 .d_name = cy_driver_name, 376 .d_flags = D_TTY | D_NEEDGIANT, 377}; 378 379static int comconsole = -1; 380static speed_t comdefaultrate = TTYDEF_SPEED; 381static u_int com_events; /* input chars + weighted output completions */ 382static void *sio_fast_ih; 383static void *sio_slow_ih; 384static int sio_timeout; 385static int sio_timeouts_until_log; 386static struct callout_handle sio_timeout_handle 387 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 388 389#ifdef CyDebug 390static u_int cd_inbs; 391static u_int cy_inbs; 392static u_int cd_outbs; 393static u_int cy_outbs; 394static u_int cy_svrr_probes; 395static u_int cy_timeouts; 396#endif 397 398static int cy_chip_offset[] = { 399 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 400}; 401static int cy_nr_cd1400s[NCY]; 402static int cy_total_devices; 403#undef RxFifoThreshold 404static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 405 406int 407cy_units(cy_iobase, cy_align) 408 cy_addr cy_iobase; 409 int cy_align; 410{ 411 int cyu; 412 u_char firmware_version; 413 int i; 414 cy_addr iobase; 415 416 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 417 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 418 419 /* wait for chip to become ready for new command */ 420 for (i = 0; i < 10; i++) { 421 DELAY(50); 422 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 423 break; 424 } 425 426 /* clear the GFRCR register */ 427 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 428 429 /* issue a reset command */ 430 cd_outb(iobase, CD1400_CCR, cy_align, 431 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 432 433 /* XXX bogus initialization to avoid a gcc bug/warning. */ 434 firmware_version = 0; 435 436 /* wait for the CD1400 to initialize itself */ 437 for (i = 0; i < 200; i++) { 438 DELAY(50); 439 440 /* retrieve firmware version */ 441 firmware_version = cd_inb(iobase, CD1400_GFRCR, 442 cy_align); 443 if ((firmware_version & 0xf0) == 0x40) 444 break; 445 } 446 447 /* 448 * Anything in the 0x40-0x4F range is fine. 449 * If one CD1400 is bad then we don't support higher 450 * numbered good ones on this board. 451 */ 452 if ((firmware_version & 0xf0) != 0x40) 453 break; 454 } 455 return (cyu); 456} 457 458void * 459cyattach_common(cy_iobase, cy_align) 460 cy_addr cy_iobase; 461 int cy_align; 462{ 463 int adapter; 464 int cyu; 465 u_char firmware_version; 466 cy_addr iobase; 467 int minorbase; 468 int ncyu; 469 int unit; 470 471 while (sio_inited != 2) 472 if (atomic_cmpset_int(&sio_inited, 0, 1)) { 473 mtx_init(&sio_lock, cy_driver_name, NULL, MTX_SPIN); 474 atomic_store_rel_int(&sio_inited, 2); 475 } 476 477 adapter = cy_total_devices; 478 if ((u_int)adapter >= NCY) { 479 printf( 480 "cy%d: can't attach adapter: insufficient cy devices configured\n", 481 adapter); 482 return (NULL); 483 } 484 ncyu = cy_units(cy_iobase, cy_align); 485 if (ncyu == 0) 486 return (NULL); 487 cy_nr_cd1400s[adapter] = ncyu; 488 cy_total_devices++; 489 490 unit = adapter * CY_MAX_PORTS; 491 for (cyu = 0; cyu < ncyu; ++cyu) { 492 int cdu; 493 494 iobase = (cy_addr) (cy_iobase 495 + (cy_chip_offset[cyu] << cy_align)); 496 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 497 498 /* Set up a receive timeout period of than 1+ ms. */ 499 cd_outb(iobase, CD1400_PPR, cy_align, 500 howmany(CY_CLOCK(firmware_version) 501 / CD1400_PPR_PRESCALER, 1000)); 502 503 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 504 struct com_s *com; 505 int s; 506 507 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); 508 if (com == NULL) 509 break; 510 com->unit = unit; 511 com->gfrcr_image = firmware_version; 512 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 513 com->mcr_dtr = MCR_RTS; 514 com->mcr_rts = MCR_DTR; 515 com->mcr_rts_reg = CD1400_MSVR2; 516 } else { 517 com->mcr_dtr = MCR_DTR; 518 com->mcr_rts = MCR_RTS; 519 com->mcr_rts_reg = CD1400_MSVR1; 520 } 521 com->dtr_wait = 3 * hz; 522 com->obufs[0].l_head = com->obuf1; 523 com->obufs[1].l_head = com->obuf2; 524 525 com->cy_align = cy_align; 526 com->cy_iobase = cy_iobase; 527 com->iobase = iobase; 528 com->car = ~CD1400_CAR_CHAN; 529 530 /* 531 * We don't use all the flags from <sys/ttydefaults.h> since they 532 * are only relevant for logins. It's important to have echo off 533 * initially so that the line doesn't start blathering before the 534 * echo flag can be turned off. 535 */ 536 com->it_in.c_iflag = 0; 537 com->it_in.c_oflag = 0; 538 com->it_in.c_cflag = TTYDEF_CFLAG; 539 com->it_in.c_lflag = 0; 540 if (unit == comconsole) { 541 com->it_in.c_iflag = TTYDEF_IFLAG; 542 com->it_in.c_oflag = TTYDEF_OFLAG; 543 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 544 com->it_in.c_lflag = TTYDEF_LFLAG; 545 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 546 } 547 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 548 free(com, M_DEVBUF); 549 return (NULL); 550 } 551 termioschars(&com->it_in); 552 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 553 com->it_out = com->it_in; 554 555 s = spltty(); 556 com_addr(unit) = com; 557 splx(s); 558 559 if (sio_fast_ih == NULL) { 560 swi_add(&tty_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 561 &sio_fast_ih); 562 swi_add(&clk_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0, 563 &sio_slow_ih); 564 } 565 minorbase = UNIT_TO_MINOR(unit); 566 make_dev(&sio_cdevsw, minorbase, 567 UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, 568 unit % CY_MAX_PORTS); 569 make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE, 570 UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, 571 unit % CY_MAX_PORTS); 572 make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE, 573 UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, 574 unit % CY_MAX_PORTS); 575 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK, 576 UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, 577 unit % CY_MAX_PORTS); 578 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE, 579 UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, 580 unit % CY_MAX_PORTS); 581 make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE, 582 UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, 583 unit % CY_MAX_PORTS); 584 } 585 } 586 587 /* ensure an edge for the next interrupt */ 588 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 589 590 return (com_addr(adapter * CY_MAX_PORTS)); 591} 592 593static int 594sioopen(dev, flag, mode, td) 595 struct cdev *dev; 596 int flag; 597 int mode; 598 struct thread *td; 599{ 600 struct com_s *com; 601 int error; 602 int mynor; 603 int s; 604 struct tty *tp; 605 int unit; 606 607 mynor = minor(dev); 608 unit = MINOR_TO_UNIT(mynor); 609 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 610 return (ENXIO); 611 if (mynor & CONTROL_MASK) 612 return (0); 613 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 614 s = spltty(); 615 /* 616 * We jump to this label after all non-interrupted sleeps to pick 617 * up any changes of the device state. 618 */ 619open_top: 620 while (com->state & CS_DTR_OFF) { 621 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 622 if (error != 0) 623 goto out; 624 } 625 if (tp->t_state & TS_ISOPEN) { 626 /* 627 * The device is open, so everything has been initialized. 628 * Handle conflicts. 629 */ 630 if (mynor & CALLOUT_MASK) { 631 if (!com->active_out) { 632 error = EBUSY; 633 goto out; 634 } 635 } else { 636 if (com->active_out) { 637 if (flag & O_NONBLOCK) { 638 error = EBUSY; 639 goto out; 640 } 641 error = tsleep(&com->active_out, 642 TTIPRI | PCATCH, "cybi", 0); 643 if (error != 0) 644 goto out; 645 goto open_top; 646 } 647 } 648 if (tp->t_state & TS_XCLUDE && 649 suser(td)) { 650 error = EBUSY; 651 goto out; 652 } 653 } else { 654 /* 655 * The device isn't open, so there are no conflicts. 656 * Initialize it. Initialization is done twice in many 657 * cases: to preempt sleeping callin opens if we are 658 * callout, and to complete a callin open after DCD rises. 659 */ 660 tp->t_oproc = comstart; 661 tp->t_stop = comstop; 662 tp->t_param = comparam; 663 tp->t_dev = dev; 664 tp->t_termios = mynor & CALLOUT_MASK 665 ? com->it_out : com->it_in; 666 667 /* Encode per-board unit in LIVR for access in intr routines. */ 668 cd_setreg(com, CD1400_LIVR, 669 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 670 671 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 672#if 0 673 com->poll = com->no_irq; 674 com->poll_output = com->loses_outints; 675#endif 676 ++com->wopeners; 677 error = comparam(tp, &tp->t_termios); 678 --com->wopeners; 679 if (error != 0) 680 goto out; 681#if 0 682 if (com->hasfifo) { 683 /* 684 * (Re)enable and flush fifos. 685 * 686 * Certain SMC chips cause problems if the fifos 687 * are enabled while input is ready. Turn off the 688 * fifo if necessary to clear the input. We test 689 * the input ready bit after enabling the fifos 690 * since we've already enabled them in comparam() 691 * and to handle races between enabling and fresh 692 * input. 693 */ 694 while (TRUE) { 695 outb(iobase + com_fifo, 696 FIFO_RCV_RST | FIFO_XMT_RST 697 | com->fifo_image); 698 DELAY(100); 699 if (!(inb(com->line_status_port) & LSR_RXRDY)) 700 break; 701 outb(iobase + com_fifo, 0); 702 DELAY(100); 703 (void) inb(com->data_port); 704 } 705 } 706 707 critical_enter(); 708 COM_LOCK(); 709 (void) inb(com->line_status_port); 710 (void) inb(com->data_port); 711 com->prev_modem_status = com->last_modem_status 712 = inb(com->modem_status_port); 713 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 714 | IER_EMSC); 715 COM_UNLOCK(); 716 critical_exit(); 717#else /* !0 */ 718 /* 719 * Flush fifos. This requires a full channel reset which 720 * also disables the transmitter and receiver. Recover 721 * from this. 722 */ 723 cd1400_channel_cmd(com, 724 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 725 cd1400_channel_cmd(com, com->channel_control); 726 727 critical_enter(); 728 COM_LOCK(); 729 com->prev_modem_status = com->last_modem_status 730 = cd_getreg(com, CD1400_MSVR2); 731 cd_setreg(com, CD1400_SRER, 732 com->intr_enable 733 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 734 COM_UNLOCK(); 735 critical_exit(); 736#endif /* 0 */ 737 /* 738 * Handle initial DCD. Callout devices get a fake initial 739 * DCD (trapdoor DCD). If we are callout, then any sleeping 740 * callin opens get woken up and resume sleeping on "cybi" 741 * instead of "cydcd". 742 */ 743 /* 744 * XXX `mynor & CALLOUT_MASK' should be 745 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 746 * TRAPDOOR_CARRIER is the default initial state for callout 747 * devices and SOFT_CARRIER is like CLOCAL except it hides 748 * the true carrier. 749 */ 750 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 751 ttyld_modem(tp, 1); 752 } 753 /* 754 * Wait for DCD if necessary. 755 */ 756 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 757 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 758 ++com->wopeners; 759 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 760 --com->wopeners; 761 if (error != 0) 762 goto out; 763 goto open_top; 764 } 765 error = ttyld_open(tp, dev); 766 disc_optim(tp, &tp->t_termios, com); 767 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 768 com->active_out = TRUE; 769 siosettimeout(); 770out: 771 splx(s); 772 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 773 comhardclose(com); 774 return (error); 775} 776 777static int 778sioclose(dev, flag, mode, td) 779 struct cdev *dev; 780 int flag; 781 int mode; 782 struct thread *td; 783{ 784 struct com_s *com; 785 int mynor; 786 int s; 787 struct tty *tp; 788 789 mynor = minor(dev); 790 if (mynor & CONTROL_MASK) 791 return (0); 792 com = com_addr(MINOR_TO_UNIT(mynor)); 793 tp = com->tp; 794 s = spltty(); 795 cd_etc(com, CD1400_ETC_STOPBREAK); 796 ttyld_close(tp, flag); 797 disc_optim(tp, &tp->t_termios, com); 798 comhardclose(com); 799 ttyclose(tp); 800 siosettimeout(); 801 splx(s); 802#ifdef broken /* session holds a ref to the tty; can't deallocate */ 803 ttyfree(tp); 804 com->tp = NULL; 805#endif 806 return (0); 807} 808 809static void 810comhardclose(com) 811 struct com_s *com; 812{ 813 cy_addr iobase; 814 int s; 815 struct tty *tp; 816 int unit; 817 818 unit = com->unit; 819 iobase = com->iobase; 820 s = spltty(); 821#if 0 822 com->poll = FALSE; 823 com->poll_output = FALSE; 824#endif 825 com->do_timestamp = 0; 826#if 0 827 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 828#else 829 /* XXX */ 830 critical_enter(); 831 COM_LOCK(); 832 com->etc = ETC_NONE; 833 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 834 COM_UNLOCK(); 835 critical_exit(); 836 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 837#endif 838 839 { 840#if 0 841 outb(iobase + com_ier, 0); 842#else 843 critical_enter(); 844 COM_LOCK(); 845 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 846 COM_UNLOCK(); 847 critical_exit(); 848#endif 849 tp = com->tp; 850 if ((tp->t_cflag & HUPCL) 851 /* 852 * XXX we will miss any carrier drop between here and the 853 * next open. Perhaps we should watch DCD even when the 854 * port is closed; it is not sufficient to check it at 855 * the next open because it might go up and down while 856 * we're not watching. 857 */ 858 || (!com->active_out 859 && !(com->prev_modem_status & MSR_DCD) 860 && !(com->it_in.c_cflag & CLOCAL)) 861 || !(tp->t_state & TS_ISOPEN)) { 862 (void)commctl(com, TIOCM_DTR, DMBIC); 863 864 /* Disable receiver (leave transmitter enabled). */ 865 com->channel_control = CD1400_CCR_CMDCHANCTL 866 | CD1400_CCR_XMTEN 867 | CD1400_CCR_RCVDIS; 868 cd1400_channel_cmd(com, com->channel_control); 869 870 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 871 timeout(siodtrwakeup, com, com->dtr_wait); 872 com->state |= CS_DTR_OFF; 873 } 874 } 875 } 876#if 0 877 if (com->hasfifo) { 878 /* 879 * Disable fifos so that they are off after controlled 880 * reboots. Some BIOSes fail to detect 16550s when the 881 * fifos are enabled. 882 */ 883 outb(iobase + com_fifo, 0); 884 } 885#endif 886 com->active_out = FALSE; 887 wakeup(&com->active_out); 888 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 889 splx(s); 890} 891 892static int 893siowrite(dev, uio, flag) 894 struct cdev *dev; 895 struct uio *uio; 896 int flag; 897{ 898 int mynor; 899 struct tty *tp; 900 int unit; 901 902 mynor = minor(dev); 903 if (mynor & CONTROL_MASK) 904 return (ENODEV); 905 906 unit = MINOR_TO_UNIT(mynor); 907 tp = com_addr(unit)->tp; 908 /* 909 * (XXX) We disallow virtual consoles if the physical console is 910 * a serial port. This is in case there is a display attached that 911 * is not the console. In that situation we don't need/want the X 912 * server taking over the console. 913 */ 914 if (constty != NULL && unit == comconsole) 915 constty = NULL; 916#ifdef Smarts 917 /* XXX duplicate ttwrite(), but without so much output processing on 918 * CR & LF chars. Hardly worth the effort, given that high-throughput 919 * sessions are raw anyhow. 920 */ 921#else 922 return (ttyld_write(tp, uio, flag)); 923#endif 924} 925 926static void 927siodtrwakeup(chan) 928 void *chan; 929{ 930 struct com_s *com; 931 932 com = (struct com_s *)chan; 933 com->state &= ~CS_DTR_OFF; 934 wakeup(&com->dtr_wait); 935} 936 937/* 938 * This function: 939 * a) needs to be called with COM_LOCK() held, and 940 * b) needs to return with COM_LOCK() held. 941 */ 942static void 943sioinput(com) 944 struct com_s *com; 945{ 946 u_char *buf; 947 int incc; 948 u_char line_status; 949 int recv_data; 950 struct tty *tp; 951 952 buf = com->ibuf; 953 tp = com->tp; 954 if (!(tp->t_state & TS_ISOPEN)) { 955 com_events -= (com->iptr - com->ibuf); 956 com->iptr = com->ibuf; 957 return; 958 } 959 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 960 /* 961 * Avoid the grotesquely inefficient lineswitch routine 962 * (ttyinput) in "raw" mode. It usually takes about 450 963 * instructions (that's without canonical processing or echo!). 964 * slinput is reasonably fast (usually 40 instructions plus 965 * call overhead). 966 */ 967 968 do { 969 /* 970 * This may look odd, but it is using save-and-enable 971 * semantics instead of the save-and-disable semantics 972 * that are used everywhere else. 973 */ 974 COM_UNLOCK(); 975 critical_exit(); 976 incc = com->iptr - buf; 977 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 978 && (com->state & CS_RTS_IFLOW 979 || tp->t_iflag & IXOFF) 980 && !(tp->t_state & TS_TBLOCK)) 981 ttyblock(tp); 982 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 983 += b_to_q((char *)buf, incc, &tp->t_rawq); 984 buf += incc; 985 tk_nin += incc; 986 tk_rawcc += incc; 987 tp->t_rawcc += incc; 988 ttwakeup(tp); 989 if (tp->t_state & TS_TTSTOP 990 && (tp->t_iflag & IXANY 991 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 992 tp->t_state &= ~TS_TTSTOP; 993 tp->t_lflag &= ~FLUSHO; 994 comstart(tp); 995 } 996 critical_enter(); 997 COM_LOCK(); 998 } while (buf < com->iptr); 999 } else { 1000 do { 1001 /* 1002 * This may look odd, but it is using save-and-enable 1003 * semantics instead of the save-and-disable semantics 1004 * that are used everywhere else. 1005 */ 1006 COM_UNLOCK(); 1007 critical_exit(); 1008 line_status = buf[com->ierroff]; 1009 recv_data = *buf++; 1010 if (line_status 1011 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1012 if (line_status & LSR_BI) 1013 recv_data |= TTY_BI; 1014 if (line_status & LSR_FE) 1015 recv_data |= TTY_FE; 1016 if (line_status & LSR_OE) 1017 recv_data |= TTY_OE; 1018 if (line_status & LSR_PE) 1019 recv_data |= TTY_PE; 1020 } 1021 ttyld_rint(tp, recv_data); 1022 critical_enter(); 1023 COM_LOCK(); 1024 } while (buf < com->iptr); 1025 } 1026 com_events -= (com->iptr - com->ibuf); 1027 com->iptr = com->ibuf; 1028 1029 /* 1030 * There is now room for another low-level buffer full of input, 1031 * so enable RTS if it is now disabled and there is room in the 1032 * high-level buffer. 1033 */ 1034 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 1035 !(tp->t_state & TS_TBLOCK)) 1036#if 0 1037 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1038#else 1039 cd_setreg(com, com->mcr_rts_reg, 1040 com->mcr_image |= com->mcr_rts); 1041#endif 1042} 1043 1044void 1045siointr1(vcom) 1046 void *vcom; 1047{ 1048 struct com_s *basecom; 1049 int baseu; 1050 int cy_align; 1051 cy_addr cy_iobase; 1052 int cyu; 1053 cy_addr iobase; 1054 u_char status; 1055 int unit; 1056 1057 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1058 1059 basecom = (struct com_s *)vcom; 1060 baseu = basecom->unit; 1061 cy_align = basecom->cy_align; 1062 cy_iobase = basecom->cy_iobase; 1063 unit = baseu / CY_MAX_PORTS; 1064 1065 /* check each CD1400 in turn */ 1066 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1067 iobase = (cy_addr) (cy_iobase 1068 + (cy_chip_offset[cyu] << cy_align)); 1069 /* poll to see if it has any work */ 1070 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1071 if (status == 0) 1072 continue; 1073#ifdef CyDebug 1074 ++cy_svrr_probes; 1075#endif 1076 /* service requests as appropriate, giving priority to RX */ 1077 if (status & CD1400_SVRR_RXRDY) { 1078 struct com_s *com; 1079 u_int count; 1080 u_char *ioptr; 1081 u_char line_status; 1082 u_char recv_data; 1083 u_char serv_type; 1084#ifdef PollMode 1085 u_char save_rir; 1086#endif 1087 1088#ifdef PollMode 1089 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1090 1091 /* enter rx service */ 1092 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1093 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1094 = save_rir & CD1400_CAR_CHAN; 1095 1096 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1097 com = com_addr(baseu 1098 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1099 & CD1400_xIVR_CHAN)); 1100#else 1101 /* ack receive service */ 1102 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1103 1104 com = com_addr(baseu + 1105 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1106 & CD1400_xIVR_CHAN)); 1107#endif 1108 1109 if (serv_type & CD1400_RIVR_EXCEPTION) { 1110 ++com->recv_exception; 1111 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1112 /* break/unnattached error bits or real input? */ 1113 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1114#ifndef SOFT_HOTCHAR 1115 if (line_status & CD1400_RDSR_SPECIAL 1116 && com->hotchar != 0) 1117 swi_sched(sio_fast_ih, 0); 1118 1119#endif 1120#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1121 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1122 /* 1123 Don't store PE if IGNPAR and BI if IGNBRK, 1124 this hack allows "raw" tty optimization 1125 works even if IGN* is set. 1126 */ 1127 if ( com->tp == NULL 1128 || !(com->tp->t_state & TS_ISOPEN) 1129 || ((line_status & (LSR_PE|LSR_FE)) 1130 && (com->tp->t_iflag & IGNPAR)) 1131 || ((line_status & LSR_BI) 1132 && (com->tp->t_iflag & IGNBRK))) 1133 goto cont; 1134 if ( (line_status & (LSR_PE|LSR_FE)) 1135 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1136 && ((line_status & LSR_FE) 1137 || ((line_status & LSR_PE) 1138 && (com->tp->t_iflag & INPCK)))) 1139 recv_data = 0; 1140 } 1141#endif /* 1 */ 1142 ++com->bytes_in; 1143#ifdef SOFT_HOTCHAR 1144 if (com->hotchar != 0 && recv_data == com->hotchar) 1145 swi_sched(sio_fast_ih, 0); 1146#endif 1147 ioptr = com->iptr; 1148 if (ioptr >= com->ibufend) 1149 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1150 else { 1151 if (com->do_timestamp) 1152 microtime(&com->timestamp); 1153 ++com_events; 1154 ioptr[0] = recv_data; 1155 ioptr[com->ierroff] = line_status; 1156 com->iptr = ++ioptr; 1157 if (ioptr == com->ihighwater 1158 && com->state & CS_RTS_IFLOW) 1159#if 0 1160 outb(com->modem_ctl_port, 1161 com->mcr_image &= ~MCR_RTS); 1162#else 1163 cd_outb(iobase, com->mcr_rts_reg, 1164 cy_align, 1165 com->mcr_image &= 1166 ~com->mcr_rts); 1167#endif 1168 if (line_status & LSR_OE) 1169 CE_RECORD(com, CE_OVERRUN); 1170 } 1171 goto cont; 1172 } else { 1173 int ifree; 1174 1175 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1176 if (!count) 1177 goto cont; 1178 com->bytes_in += count; 1179 ioptr = com->iptr; 1180 ifree = com->ibufend - ioptr; 1181 if (count > ifree) { 1182 count -= ifree; 1183 com_events += ifree; 1184 if (ifree != 0) { 1185 if (com->do_timestamp) 1186 microtime(&com->timestamp); 1187 do { 1188 recv_data = cd_inb(iobase, 1189 CD1400_RDSR, 1190 cy_align); 1191#ifdef SOFT_HOTCHAR 1192 if (com->hotchar != 0 1193 && recv_data 1194 == com->hotchar) 1195 swi_sched(sio_fast_ih, 1196 0); 1197#endif 1198 ioptr[0] = recv_data; 1199 ioptr[com->ierroff] = 0; 1200 ++ioptr; 1201 } while (--ifree != 0); 1202 } 1203 com->delta_error_counts 1204 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1205 do { 1206 recv_data = cd_inb(iobase, CD1400_RDSR, 1207 cy_align); 1208#ifdef SOFT_HOTCHAR 1209 if (com->hotchar != 0 1210 && recv_data == com->hotchar) 1211 swi_sched(sio_fast_ih, 0); 1212#endif 1213 } while (--count != 0); 1214 } else { 1215 if (com->do_timestamp) 1216 microtime(&com->timestamp); 1217 if (ioptr <= com->ihighwater 1218 && ioptr + count > com->ihighwater 1219 && com->state & CS_RTS_IFLOW) 1220#if 0 1221 outb(com->modem_ctl_port, 1222 com->mcr_image &= ~MCR_RTS); 1223#else 1224 cd_outb(iobase, com->mcr_rts_reg, 1225 cy_align, 1226 com->mcr_image 1227 &= ~com->mcr_rts); 1228#endif 1229 com_events += count; 1230 do { 1231 recv_data = cd_inb(iobase, CD1400_RDSR, 1232 cy_align); 1233#ifdef SOFT_HOTCHAR 1234 if (com->hotchar != 0 1235 && recv_data == com->hotchar) 1236 swi_sched(sio_fast_ih, 0); 1237#endif 1238 ioptr[0] = recv_data; 1239 ioptr[com->ierroff] = 0; 1240 ++ioptr; 1241 } while (--count != 0); 1242 } 1243 com->iptr = ioptr; 1244 } 1245cont: 1246 1247 /* terminate service context */ 1248#ifdef PollMode 1249 cd_outb(iobase, CD1400_RIR, cy_align, 1250 save_rir 1251 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1252#else 1253 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1254#endif 1255 } 1256 if (status & CD1400_SVRR_MDMCH) { 1257 struct com_s *com; 1258 u_char modem_status; 1259#ifdef PollMode 1260 u_char save_mir; 1261#else 1262 u_char vector; 1263#endif 1264 1265#ifdef PollMode 1266 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1267 1268 /* enter modem service */ 1269 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1270 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1271 = save_mir & CD1400_CAR_CHAN; 1272 1273 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1274 + (save_mir & CD1400_MIR_CHAN)); 1275#else 1276 /* ack modem service */ 1277 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1278 1279 com = com_addr(baseu 1280 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1281 & CD1400_xIVR_CHAN)); 1282#endif 1283 ++com->mdm; 1284 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1285 if (modem_status != com->last_modem_status) { 1286 if (com->do_dcd_timestamp 1287 && !(com->last_modem_status & MSR_DCD) 1288 && modem_status & MSR_DCD) 1289 microtime(&com->dcd_timestamp); 1290 1291 /* 1292 * Schedule high level to handle DCD changes. Note 1293 * that we don't use the delta bits anywhere. Some 1294 * UARTs mess them up, and it's easy to remember the 1295 * previous bits and calculate the delta. 1296 */ 1297 com->last_modem_status = modem_status; 1298 if (!(com->state & CS_CHECKMSR)) { 1299 com_events += LOTS_OF_EVENTS; 1300 com->state |= CS_CHECKMSR; 1301 swi_sched(sio_fast_ih, 0); 1302 } 1303 1304#ifdef SOFT_CTS_OFLOW 1305 /* handle CTS change immediately for crisp flow ctl */ 1306 if (com->state & CS_CTS_OFLOW) { 1307 if (modem_status & MSR_CTS) { 1308 com->state |= CS_ODEVREADY; 1309 if (com->state >= (CS_BUSY | CS_TTGO 1310 | CS_ODEVREADY) 1311 && !(com->intr_enable 1312 & CD1400_SRER_TXRDY)) 1313 cd_outb(iobase, CD1400_SRER, 1314 cy_align, 1315 com->intr_enable 1316 = com->intr_enable 1317 & ~CD1400_SRER_TXMPTY 1318 | CD1400_SRER_TXRDY); 1319 } else { 1320 com->state &= ~CS_ODEVREADY; 1321 if (com->intr_enable 1322 & CD1400_SRER_TXRDY) 1323 cd_outb(iobase, CD1400_SRER, 1324 cy_align, 1325 com->intr_enable 1326 = com->intr_enable 1327 & ~CD1400_SRER_TXRDY 1328 | CD1400_SRER_TXMPTY); 1329 } 1330 } 1331#endif 1332 } 1333 1334 /* terminate service context */ 1335#ifdef PollMode 1336 cd_outb(iobase, CD1400_MIR, cy_align, 1337 save_mir 1338 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1339#else 1340 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1341#endif 1342 } 1343 if (status & CD1400_SVRR_TXRDY) { 1344 struct com_s *com; 1345#ifdef PollMode 1346 u_char save_tir; 1347#else 1348 u_char vector; 1349#endif 1350 1351#ifdef PollMode 1352 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1353 1354 /* enter tx service */ 1355 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1356 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1357 = save_tir & CD1400_CAR_CHAN; 1358 1359 com = com_addr(baseu 1360 + cyu * CD1400_NO_OF_CHANNELS 1361 + (save_tir & CD1400_TIR_CHAN)); 1362#else 1363 /* ack transmit service */ 1364 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1365 1366 com = com_addr(baseu 1367 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1368 & CD1400_xIVR_CHAN)); 1369#endif 1370 1371 if (com->etc != ETC_NONE) { 1372 if (com->intr_enable & CD1400_SRER_TXRDY) { 1373 /* 1374 * Here due to sloppy SRER_TXRDY 1375 * enabling. Ignore. Come back when 1376 * tx is empty. 1377 */ 1378 cd_outb(iobase, CD1400_SRER, cy_align, 1379 com->intr_enable 1380 = (com->intr_enable 1381 & ~CD1400_SRER_TXRDY) 1382 | CD1400_SRER_TXMPTY); 1383 goto terminate_tx_service; 1384 } 1385 switch (com->etc) { 1386 case CD1400_ETC_SENDBREAK: 1387 case CD1400_ETC_STOPBREAK: 1388 /* 1389 * Start the command. Come back on 1390 * next tx empty interrupt, hopefully 1391 * after command has been executed. 1392 */ 1393 cd_outb(iobase, CD1400_COR2, cy_align, 1394 com->cor[1] |= CD1400_COR2_ETC); 1395 cd_outb(iobase, CD1400_TDR, cy_align, 1396 CD1400_ETC_CMD); 1397 cd_outb(iobase, CD1400_TDR, cy_align, 1398 com->etc); 1399 if (com->etc == CD1400_ETC_SENDBREAK) 1400 com->etc = ETC_BREAK_STARTING; 1401 else 1402 com->etc = ETC_BREAK_ENDING; 1403 goto terminate_tx_service; 1404 case ETC_BREAK_STARTING: 1405 /* 1406 * BREAK is now on. Continue with 1407 * SRER_TXMPTY processing, hopefully 1408 * don't come back. 1409 */ 1410 com->etc = ETC_BREAK_STARTED; 1411 break; 1412 case ETC_BREAK_STARTED: 1413 /* 1414 * Came back due to sloppy SRER_TXMPTY 1415 * enabling. Hope again. 1416 */ 1417 break; 1418 case ETC_BREAK_ENDING: 1419 /* 1420 * BREAK is now off. Continue with 1421 * SRER_TXMPTY processing and don't 1422 * come back. The SWI handler will 1423 * restart tx interrupts if necessary. 1424 */ 1425 cd_outb(iobase, CD1400_COR2, cy_align, 1426 com->cor[1] 1427 &= ~CD1400_COR2_ETC); 1428 com->etc = ETC_BREAK_ENDED; 1429 if (!(com->state & CS_ODONE)) { 1430 com_events += LOTS_OF_EVENTS; 1431 com->state |= CS_ODONE; 1432 swi_sched(sio_fast_ih, 0); 1433 } 1434 break; 1435 case ETC_BREAK_ENDED: 1436 /* 1437 * Shouldn't get here. Hope again. 1438 */ 1439 break; 1440 } 1441 } 1442 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1443 if (!(com->extra_state & CSE_ODONE)) { 1444 com_events += LOTS_OF_EVENTS; 1445 com->extra_state |= CSE_ODONE; 1446 swi_sched(sio_fast_ih, 0); 1447 } 1448 cd_outb(iobase, CD1400_SRER, cy_align, 1449 com->intr_enable 1450 &= ~CD1400_SRER_TXMPTY); 1451 goto terminate_tx_service; 1452 } 1453 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1454 u_char *ioptr; 1455 u_int ocount; 1456 1457 ioptr = com->obufq.l_head; 1458 ocount = com->obufq.l_tail - ioptr; 1459 if (ocount > CD1400_TX_FIFO_SIZE) 1460 ocount = CD1400_TX_FIFO_SIZE; 1461 com->bytes_out += ocount; 1462 do 1463 cd_outb(iobase, CD1400_TDR, cy_align, 1464 *ioptr++); 1465 while (--ocount != 0); 1466 com->obufq.l_head = ioptr; 1467 if (ioptr >= com->obufq.l_tail) { 1468 struct lbq *qp; 1469 1470 qp = com->obufq.l_next; 1471 qp->l_queued = FALSE; 1472 qp = qp->l_next; 1473 if (qp != NULL) { 1474 com->obufq.l_head = qp->l_head; 1475 com->obufq.l_tail = qp->l_tail; 1476 com->obufq.l_next = qp; 1477 } else { 1478 /* output just completed */ 1479 com->state &= ~CS_BUSY; 1480 1481 /* 1482 * The setting of CSE_ODONE may be 1483 * stale here. We currently only 1484 * use it when CS_BUSY is set, and 1485 * fixing it when we clear CS_BUSY 1486 * is easiest. 1487 */ 1488 if (com->extra_state & CSE_ODONE) { 1489 com_events -= LOTS_OF_EVENTS; 1490 com->extra_state &= ~CSE_ODONE; 1491 } 1492 1493 cd_outb(iobase, CD1400_SRER, cy_align, 1494 com->intr_enable 1495 = (com->intr_enable 1496 & ~CD1400_SRER_TXRDY) 1497 | CD1400_SRER_TXMPTY); 1498 } 1499 if (!(com->state & CS_ODONE)) { 1500 com_events += LOTS_OF_EVENTS; 1501 com->state |= CS_ODONE; 1502 1503 /* handle at high level ASAP */ 1504 swi_sched(sio_fast_ih, 0); 1505 } 1506 } 1507 } 1508 1509 /* terminate service context */ 1510terminate_tx_service: 1511#ifdef PollMode 1512 cd_outb(iobase, CD1400_TIR, cy_align, 1513 save_tir 1514 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1515#else 1516 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1517#endif 1518 } 1519 } 1520 1521 /* ensure an edge for the next interrupt */ 1522 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1523 1524 swi_sched(sio_slow_ih, SWI_DELAY); 1525 1526 COM_UNLOCK(); 1527} 1528 1529static int 1530sioioctl(dev, cmd, data, flag, td) 1531 struct cdev *dev; 1532 u_long cmd; 1533 caddr_t data; 1534 int flag; 1535 struct thread *td; 1536{ 1537 struct com_s *com; 1538 int error; 1539 int mynor; 1540 int s; 1541 struct tty *tp; 1542#if defined(COMPAT_43) 1543 int oldcmd; 1544 struct termios term; 1545#endif 1546 1547 mynor = minor(dev); 1548 com = com_addr(MINOR_TO_UNIT(mynor)); 1549 if (mynor & CONTROL_MASK) { 1550 struct termios *ct; 1551 1552 switch (mynor & CONTROL_MASK) { 1553 case CONTROL_INIT_STATE: 1554 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1555 break; 1556 case CONTROL_LOCK_STATE: 1557 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1558 break; 1559 default: 1560 return (ENODEV); /* /dev/nodev */ 1561 } 1562 switch (cmd) { 1563 case TIOCSETA: 1564 error = suser(td); 1565 if (error != 0) 1566 return (error); 1567 *ct = *(struct termios *)data; 1568 return (0); 1569 case TIOCGETA: 1570 *(struct termios *)data = *ct; 1571 return (0); 1572 case TIOCGETD: 1573 *(int *)data = TTYDISC; 1574 return (0); 1575 case TIOCGWINSZ: 1576 bzero(data, sizeof(struct winsize)); 1577 return (0); 1578 default: 1579 return (ENOTTY); 1580 } 1581 } 1582 tp = com->tp; 1583#if defined(COMPAT_43) 1584 term = tp->t_termios; 1585 oldcmd = cmd; 1586 error = ttsetcompat(tp, &cmd, data, &term); 1587 if (error != 0) 1588 return (error); 1589 if (cmd != oldcmd) 1590 data = (caddr_t)&term; 1591#endif 1592 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1593 int cc; 1594 struct termios *dt = (struct termios *)data; 1595 struct termios *lt = mynor & CALLOUT_MASK 1596 ? &com->lt_out : &com->lt_in; 1597 1598 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1599 | (dt->c_iflag & ~lt->c_iflag); 1600 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1601 | (dt->c_oflag & ~lt->c_oflag); 1602 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1603 | (dt->c_cflag & ~lt->c_cflag); 1604 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1605 | (dt->c_lflag & ~lt->c_lflag); 1606 for (cc = 0; cc < NCCS; ++cc) 1607 if (lt->c_cc[cc] != 0) 1608 dt->c_cc[cc] = tp->t_cc[cc]; 1609 if (lt->c_ispeed != 0) 1610 dt->c_ispeed = tp->t_ispeed; 1611 if (lt->c_ospeed != 0) 1612 dt->c_ospeed = tp->t_ospeed; 1613 } 1614 error = ttyioctl(dev, cmd, data, flag, td); 1615 disc_optim(tp, &tp->t_termios, com); 1616 if (error != ENOTTY) 1617 return (error); 1618 s = spltty(); 1619 switch (cmd) { 1620 case TIOCSBRK: 1621#if 0 1622 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1623#else 1624 cd_etc(com, CD1400_ETC_SENDBREAK); 1625#endif 1626 break; 1627 case TIOCCBRK: 1628#if 0 1629 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1630#else 1631 cd_etc(com, CD1400_ETC_STOPBREAK); 1632#endif 1633 break; 1634 case TIOCSDTR: 1635 (void)commctl(com, TIOCM_DTR, DMBIS); 1636 break; 1637 case TIOCCDTR: 1638 (void)commctl(com, TIOCM_DTR, DMBIC); 1639 break; 1640 /* 1641 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1642 * changes get undone on the next call to comparam(). 1643 */ 1644 case TIOCMSET: 1645 (void)commctl(com, *(int *)data, DMSET); 1646 break; 1647 case TIOCMBIS: 1648 (void)commctl(com, *(int *)data, DMBIS); 1649 break; 1650 case TIOCMBIC: 1651 (void)commctl(com, *(int *)data, DMBIC); 1652 break; 1653 case TIOCMGET: 1654 *(int *)data = commctl(com, 0, DMGET); 1655 break; 1656 case TIOCMSDTRWAIT: 1657 /* must be root since the wait applies to following logins */ 1658 error = suser(td); 1659 if (error != 0) { 1660 splx(s); 1661 return (error); 1662 } 1663 com->dtr_wait = *(int *)data * hz / 100; 1664 break; 1665 case TIOCMGDTRWAIT: 1666 *(int *)data = com->dtr_wait * 100 / hz; 1667 break; 1668 case TIOCTIMESTAMP: 1669 com->do_timestamp = TRUE; 1670 *(struct timeval *)data = com->timestamp; 1671 break; 1672 case TIOCDCDTIMESTAMP: 1673 com->do_dcd_timestamp = TRUE; 1674 *(struct timeval *)data = com->dcd_timestamp; 1675 break; 1676 default: 1677 splx(s); 1678 return (ENOTTY); 1679 } 1680 splx(s); 1681 return (0); 1682} 1683 1684static void 1685siopoll(void *arg) 1686{ 1687 int unit; 1688 1689#ifdef CyDebug 1690 ++cy_timeouts; 1691#endif 1692 if (com_events == 0) 1693 return; 1694repeat: 1695 for (unit = 0; unit < NSIO; ++unit) { 1696 struct com_s *com; 1697 int incc; 1698 struct tty *tp; 1699 1700 com = com_addr(unit); 1701 if (com == NULL) 1702 continue; 1703 tp = com->tp; 1704 if (tp == NULL) { 1705 /* 1706 * XXX forget any events related to closed devices 1707 * (actually never opened devices) so that we don't 1708 * loop. 1709 */ 1710 critical_enter(); 1711 COM_LOCK(); 1712 incc = com->iptr - com->ibuf; 1713 com->iptr = com->ibuf; 1714 if (com->state & CS_CHECKMSR) { 1715 incc += LOTS_OF_EVENTS; 1716 com->state &= ~CS_CHECKMSR; 1717 } 1718 com_events -= incc; 1719 COM_UNLOCK(); 1720 critical_exit(); 1721 if (incc != 0) 1722 log(LOG_DEBUG, 1723 "sio%d: %d events for device with no tp\n", 1724 unit, incc); 1725 continue; 1726 } 1727 if (com->iptr != com->ibuf) { 1728 critical_enter(); 1729 COM_LOCK(); 1730 sioinput(com); 1731 COM_UNLOCK(); 1732 critical_exit(); 1733 } 1734 if (com->state & CS_CHECKMSR) { 1735 u_char delta_modem_status; 1736 1737 critical_enter(); 1738 COM_LOCK(); 1739 sioinput(com); 1740 delta_modem_status = com->last_modem_status 1741 ^ com->prev_modem_status; 1742 com->prev_modem_status = com->last_modem_status; 1743 com_events -= LOTS_OF_EVENTS; 1744 com->state &= ~CS_CHECKMSR; 1745 COM_UNLOCK(); 1746 critical_exit(); 1747 if (delta_modem_status & MSR_DCD) 1748 ttyld_modem(tp, 1749 com->prev_modem_status & MSR_DCD); 1750 } 1751 if (com->extra_state & CSE_ODONE) { 1752 critical_enter(); 1753 COM_LOCK(); 1754 com_events -= LOTS_OF_EVENTS; 1755 com->extra_state &= ~CSE_ODONE; 1756 COM_UNLOCK(); 1757 critical_exit(); 1758 if (!(com->state & CS_BUSY)) { 1759 tp->t_state &= ~TS_BUSY; 1760 ttwwakeup(com->tp); 1761 } 1762 if (com->etc != ETC_NONE) { 1763 if (com->etc == ETC_BREAK_ENDED) 1764 com->etc = ETC_NONE; 1765 wakeup(&com->etc); 1766 } 1767 } 1768 if (com->state & CS_ODONE) { 1769 critical_enter(); 1770 COM_LOCK(); 1771 com_events -= LOTS_OF_EVENTS; 1772 com->state &= ~CS_ODONE; 1773 COM_UNLOCK(); 1774 critical_exit(); 1775 ttyld_start(tp); 1776 } 1777 if (com_events == 0) 1778 break; 1779 } 1780 if (com_events >= LOTS_OF_EVENTS) 1781 goto repeat; 1782} 1783 1784static int 1785comparam(tp, t) 1786 struct tty *tp; 1787 struct termios *t; 1788{ 1789 int bits; 1790 int cflag; 1791 struct com_s *com; 1792 u_char cor_change; 1793 u_long cy_clock; 1794 int idivisor; 1795 int iflag; 1796 int iprescaler; 1797 int itimeout; 1798 int odivisor; 1799 int oprescaler; 1800 u_char opt; 1801 int s; 1802 int unit; 1803 1804 unit = DEV_TO_UNIT(tp->t_dev); 1805 com = com_addr(unit); 1806 1807 /* check requested parameters */ 1808 cy_clock = CY_CLOCK(com->gfrcr_image); 1809 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1810 if (idivisor <= 0) 1811 return (EINVAL); 1812 odivisor = comspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed, 1813 cy_clock, &oprescaler); 1814 if (odivisor <= 0) 1815 return (EINVAL); 1816 1817 /* parameters are OK, convert them to the com struct and the device */ 1818 s = spltty(); 1819 if (t->c_ospeed == 0) 1820 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1821 else 1822 (void)commctl(com, TIOCM_DTR, DMBIS); 1823 1824 (void) siosetwater(com, t->c_ispeed); 1825 1826 /* XXX we don't actually change the speed atomically. */ 1827 1828 cd_setreg(com, CD1400_RBPR, idivisor); 1829 cd_setreg(com, CD1400_RCOR, iprescaler); 1830 cd_setreg(com, CD1400_TBPR, odivisor); 1831 cd_setreg(com, CD1400_TCOR, oprescaler); 1832 1833 /* 1834 * channel control 1835 * receiver enable 1836 * transmitter enable (always set) 1837 */ 1838 cflag = t->c_cflag; 1839 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1840 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1841 if (opt != com->channel_control) { 1842 com->channel_control = opt; 1843 cd1400_channel_cmd(com, opt); 1844 } 1845 1846#ifdef Smarts 1847 /* set special chars */ 1848 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1849 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1850 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1851 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1852 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1853 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1854 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1855 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1856 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1857#endif 1858 1859 /* 1860 * set channel option register 1 - 1861 * parity mode 1862 * stop bits 1863 * char length 1864 */ 1865 opt = 0; 1866 /* parity */ 1867 if (cflag & PARENB) { 1868 if (cflag & PARODD) 1869 opt |= CD1400_COR1_PARODD; 1870 opt |= CD1400_COR1_PARNORMAL; 1871 } 1872 iflag = t->c_iflag; 1873 if (!(iflag & INPCK)) 1874 opt |= CD1400_COR1_NOINPCK; 1875 bits = 1 + 1; 1876 /* stop bits */ 1877 if (cflag & CSTOPB) { 1878 ++bits; 1879 opt |= CD1400_COR1_STOP2; 1880 } 1881 /* char length */ 1882 switch (cflag & CSIZE) { 1883 case CS5: 1884 bits += 5; 1885 opt |= CD1400_COR1_CS5; 1886 break; 1887 case CS6: 1888 bits += 6; 1889 opt |= CD1400_COR1_CS6; 1890 break; 1891 case CS7: 1892 bits += 7; 1893 opt |= CD1400_COR1_CS7; 1894 break; 1895 default: 1896 bits += 8; 1897 opt |= CD1400_COR1_CS8; 1898 break; 1899 } 1900 cor_change = 0; 1901 if (opt != com->cor[0]) { 1902 cor_change |= CD1400_CCR_COR1; 1903 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1904 } 1905 1906 /* 1907 * Set receive time-out period, normally to max(one char time, 5 ms). 1908 */ 1909 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1910#ifdef SOFT_HOTCHAR 1911#define MIN_RTP 1 1912#else 1913#define MIN_RTP 5 1914#endif 1915 if (itimeout < MIN_RTP) 1916 itimeout = MIN_RTP; 1917 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1918 && t->c_cc[VTIME] * 10 > itimeout) 1919 itimeout = t->c_cc[VTIME] * 10; 1920 if (itimeout > 255) 1921 itimeout = 255; 1922 cd_setreg(com, CD1400_RTPR, itimeout); 1923 1924 /* 1925 * set channel option register 2 - 1926 * flow control 1927 */ 1928 opt = 0; 1929#ifdef Smarts 1930 if (iflag & IXANY) 1931 opt |= CD1400_COR2_IXANY; 1932 if (iflag & IXOFF) 1933 opt |= CD1400_COR2_IXOFF; 1934#endif 1935#ifndef SOFT_CTS_OFLOW 1936 if (cflag & CCTS_OFLOW) 1937 opt |= CD1400_COR2_CCTS_OFLOW; 1938#endif 1939 critical_enter(); 1940 COM_LOCK(); 1941 if (opt != com->cor[1]) { 1942 cor_change |= CD1400_CCR_COR2; 1943 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 1944 } 1945 COM_UNLOCK(); 1946 critical_exit(); 1947 1948 /* 1949 * set channel option register 3 - 1950 * receiver FIFO interrupt threshold 1951 * flow control 1952 */ 1953 opt = RxFifoThreshold; 1954#ifdef Smarts 1955 if (t->c_lflag & ICANON) 1956 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 1957 if (iflag & IXOFF) 1958 /* detect and transparently handle START and STOP chars */ 1959 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 1960#endif 1961 if (opt != com->cor[2]) { 1962 cor_change |= CD1400_CCR_COR3; 1963 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 1964 } 1965 1966 /* notify the CD1400 if COR1-3 have changed */ 1967 if (cor_change) 1968 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 1969 1970 /* 1971 * set channel option register 4 - 1972 * CR/NL processing 1973 * break processing 1974 * received exception processing 1975 */ 1976 opt = 0; 1977 if (iflag & IGNCR) 1978 opt |= CD1400_COR4_IGNCR; 1979#ifdef Smarts 1980 /* 1981 * we need a new ttyinput() for this, as we don't want to 1982 * have ICRNL && INLCR being done in both layers, or to have 1983 * synchronisation problems 1984 */ 1985 if (iflag & ICRNL) 1986 opt |= CD1400_COR4_ICRNL; 1987 if (iflag & INLCR) 1988 opt |= CD1400_COR4_INLCR; 1989#endif 1990 if (iflag & IGNBRK) 1991 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 1992 /* 1993 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 1994 * so only tell the hardware about -brkint if -parmrk. 1995 */ 1996 if (!(iflag & (BRKINT | PARMRK))) 1997 opt |= CD1400_COR4_NOBRKINT; 1998#if 0 1999 /* XXX using this "intelligence" breaks reporting of overruns. */ 2000 if (iflag & IGNPAR) 2001 opt |= CD1400_COR4_PFO_DISCARD; 2002 else { 2003 if (iflag & PARMRK) 2004 opt |= CD1400_COR4_PFO_ESC; 2005 else 2006 opt |= CD1400_COR4_PFO_NUL; 2007 } 2008#else 2009 opt |= CD1400_COR4_PFO_EXCEPTION; 2010#endif 2011 cd_setreg(com, CD1400_COR4, opt); 2012 2013 /* 2014 * set channel option register 5 - 2015 */ 2016 opt = 0; 2017 if (iflag & ISTRIP) 2018 opt |= CD1400_COR5_ISTRIP; 2019 if (t->c_iflag & IEXTEN) 2020 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2021 opt |= CD1400_COR5_LNEXT; 2022#ifdef Smarts 2023 if (t->c_oflag & ONLCR) 2024 opt |= CD1400_COR5_ONLCR; 2025 if (t->c_oflag & OCRNL) 2026 opt |= CD1400_COR5_OCRNL; 2027#endif 2028 cd_setreg(com, CD1400_COR5, opt); 2029 2030 /* 2031 * We always generate modem status change interrupts for CD changes. 2032 * Among other things, this is necessary to track TS_CARR_ON for 2033 * pstat to print even when the driver doesn't care. CD changes 2034 * should be rare so interrupts for them are not worth extra code to 2035 * avoid. We avoid interrupts for other modem status changes (except 2036 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2037 * simplest and best. 2038 */ 2039 2040 /* 2041 * set modem change option register 1 2042 * generate modem interrupts on which 1 -> 0 input transitions 2043 * also controls auto-DTR output flow-control, which we don't use 2044 */ 2045 opt = CD1400_MCOR1_CDzd; 2046#ifdef SOFT_CTS_OFLOW 2047 if (cflag & CCTS_OFLOW) 2048 opt |= CD1400_MCOR1_CTSzd; 2049#endif 2050 cd_setreg(com, CD1400_MCOR1, opt); 2051 2052 /* 2053 * set modem change option register 2 2054 * generate modem interrupts on specific 0 -> 1 input transitions 2055 */ 2056 opt = CD1400_MCOR2_CDod; 2057#ifdef SOFT_CTS_OFLOW 2058 if (cflag & CCTS_OFLOW) 2059 opt |= CD1400_MCOR2_CTSod; 2060#endif 2061 cd_setreg(com, CD1400_MCOR2, opt); 2062 2063 /* 2064 * XXX should have done this long ago, but there is too much state 2065 * to change all atomically. 2066 */ 2067 critical_enter(); 2068 COM_LOCK(); 2069 2070 com->state &= ~CS_TTGO; 2071 if (!(tp->t_state & TS_TTSTOP)) 2072 com->state |= CS_TTGO; 2073 if (cflag & CRTS_IFLOW) { 2074 com->state |= CS_RTS_IFLOW; 2075 /* 2076 * If CS_RTS_IFLOW just changed from off to on, the change 2077 * needs to be propagated to MCR_RTS. This isn't urgent, 2078 * so do it later by calling comstart() instead of repeating 2079 * a lot of code from comstart() here. 2080 */ 2081 } else if (com->state & CS_RTS_IFLOW) { 2082 com->state &= ~CS_RTS_IFLOW; 2083 /* 2084 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2085 * on here, since comstart() won't do it later. 2086 */ 2087#if 0 2088 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2089#else 2090 cd_setreg(com, com->mcr_rts_reg, 2091 com->mcr_image |= com->mcr_rts); 2092#endif 2093 } 2094 2095 /* 2096 * Set up state to handle output flow control. 2097 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2098 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2099 */ 2100 com->state |= CS_ODEVREADY; 2101#ifdef SOFT_CTS_OFLOW 2102 com->state &= ~CS_CTS_OFLOW; 2103 if (cflag & CCTS_OFLOW) { 2104 com->state |= CS_CTS_OFLOW; 2105 if (!(com->last_modem_status & MSR_CTS)) 2106 com->state &= ~CS_ODEVREADY; 2107 } 2108#endif 2109 /* XXX shouldn't call functions while intrs are disabled. */ 2110 disc_optim(tp, t, com); 2111#if 0 2112 /* 2113 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2114 * unconditionally, but that defeated the careful discarding of 2115 * stale input in sioopen(). 2116 */ 2117 if (com->state >= (CS_BUSY | CS_TTGO)) 2118 siointr1(com); 2119#endif 2120 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2121 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2122 cd_setreg(com, CD1400_SRER, 2123 com->intr_enable 2124 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2125 | CD1400_SRER_TXRDY); 2126 } else { 2127 if (com->intr_enable & CD1400_SRER_TXRDY) 2128 cd_setreg(com, CD1400_SRER, 2129 com->intr_enable 2130 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2131 | CD1400_SRER_TXMPTY); 2132 } 2133 2134 COM_UNLOCK(); 2135 critical_exit(); 2136 splx(s); 2137 comstart(tp); 2138 if (com->ibufold != NULL) { 2139 free(com->ibufold, M_DEVBUF); 2140 com->ibufold = NULL; 2141 } 2142 return (0); 2143} 2144 2145static int 2146siosetwater(com, speed) 2147 struct com_s *com; 2148 speed_t speed; 2149{ 2150 int cp4ticks; 2151 u_char *ibuf; 2152 int ibufsize; 2153 struct tty *tp; 2154 2155 /* 2156 * Make the buffer size large enough to handle a softtty interrupt 2157 * latency of about 2 ticks without loss of throughput or data 2158 * (about 3 ticks if input flow control is not used or not honoured, 2159 * but a bit less for CS5-CS7 modes). 2160 */ 2161 cp4ticks = speed / 10 / hz * 4; 2162 for (ibufsize = 128; ibufsize < cp4ticks;) 2163 ibufsize <<= 1; 2164 if (ibufsize == com->ibufsize) { 2165 return (0); 2166 } 2167 2168 /* 2169 * Allocate input buffer. The extra factor of 2 in the size is 2170 * to allow for an error byte for each input byte. 2171 */ 2172 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2173 if (ibuf == NULL) { 2174 return (ENOMEM); 2175 } 2176 2177 /* Initialize non-critical variables. */ 2178 com->ibufold = com->ibuf; 2179 com->ibufsize = ibufsize; 2180 tp = com->tp; 2181 if (tp != NULL) { 2182 tp->t_ififosize = 2 * ibufsize; 2183 tp->t_ispeedwat = (speed_t)-1; 2184 tp->t_ospeedwat = (speed_t)-1; 2185 } 2186 2187 /* 2188 * Read current input buffer, if any. Continue with interrupts 2189 * disabled. 2190 */ 2191 critical_enter(); 2192 COM_LOCK(); 2193 if (com->iptr != com->ibuf) 2194 sioinput(com); 2195 2196 /*- 2197 * Initialize critical variables, including input buffer watermarks. 2198 * The external device is asked to stop sending when the buffer 2199 * exactly reaches high water, or when the high level requests it. 2200 * The high level is notified immediately (rather than at a later 2201 * clock tick) when this watermark is reached. 2202 * The buffer size is chosen so the watermark should almost never 2203 * be reached. 2204 * The low watermark is invisibly 0 since the buffer is always 2205 * emptied all at once. 2206 */ 2207 com->iptr = com->ibuf = ibuf; 2208 com->ibufend = ibuf + ibufsize; 2209 com->ierroff = ibufsize; 2210 com->ihighwater = ibuf + 3 * ibufsize / 4; 2211 2212 COM_UNLOCK(); 2213 critical_exit(); 2214 return (0); 2215} 2216 2217static void 2218comstart(tp) 2219 struct tty *tp; 2220{ 2221 struct com_s *com; 2222 int s; 2223#ifdef CyDebug 2224 bool_t started; 2225#endif 2226 int unit; 2227 2228 unit = DEV_TO_UNIT(tp->t_dev); 2229 com = com_addr(unit); 2230 s = spltty(); 2231 2232#ifdef CyDebug 2233 ++com->start_count; 2234 started = FALSE; 2235#endif 2236 2237 critical_enter(); 2238 COM_LOCK(); 2239 if (tp->t_state & TS_TTSTOP) { 2240 com->state &= ~CS_TTGO; 2241 if (com->intr_enable & CD1400_SRER_TXRDY) 2242 cd_setreg(com, CD1400_SRER, 2243 com->intr_enable 2244 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2245 | CD1400_SRER_TXMPTY); 2246 } else { 2247 com->state |= CS_TTGO; 2248 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2249 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2250 cd_setreg(com, CD1400_SRER, 2251 com->intr_enable 2252 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2253 | CD1400_SRER_TXRDY); 2254 } 2255 if (tp->t_state & TS_TBLOCK) { 2256 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2257#if 0 2258 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2259#else 2260 cd_setreg(com, com->mcr_rts_reg, 2261 com->mcr_image &= ~com->mcr_rts); 2262#endif 2263 } else { 2264 if (!(com->mcr_image & com->mcr_rts) 2265 && com->iptr < com->ihighwater 2266 && com->state & CS_RTS_IFLOW) 2267#if 0 2268 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2269#else 2270 cd_setreg(com, com->mcr_rts_reg, 2271 com->mcr_image |= com->mcr_rts); 2272#endif 2273 } 2274 COM_UNLOCK(); 2275 critical_exit(); 2276 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2277 ttwwakeup(tp); 2278 splx(s); 2279 return; 2280 } 2281 if (tp->t_outq.c_cc != 0) { 2282 struct lbq *qp; 2283 struct lbq *next; 2284 2285 if (!com->obufs[0].l_queued) { 2286#ifdef CyDebug 2287 started = TRUE; 2288#endif 2289 com->obufs[0].l_tail 2290 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2291 sizeof com->obuf1); 2292 com->obufs[0].l_next = NULL; 2293 com->obufs[0].l_queued = TRUE; 2294 critical_enter(); 2295 COM_LOCK(); 2296 if (com->state & CS_BUSY) { 2297 qp = com->obufq.l_next; 2298 while ((next = qp->l_next) != NULL) 2299 qp = next; 2300 qp->l_next = &com->obufs[0]; 2301 } else { 2302 com->obufq.l_head = com->obufs[0].l_head; 2303 com->obufq.l_tail = com->obufs[0].l_tail; 2304 com->obufq.l_next = &com->obufs[0]; 2305 com->state |= CS_BUSY; 2306 if (com->state >= (CS_BUSY | CS_TTGO 2307 | CS_ODEVREADY)) 2308 cd_setreg(com, CD1400_SRER, 2309 com->intr_enable 2310 = (com->intr_enable 2311 & ~CD1400_SRER_TXMPTY) 2312 | CD1400_SRER_TXRDY); 2313 } 2314 COM_UNLOCK(); 2315 critical_exit(); 2316 } 2317 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2318#ifdef CyDebug 2319 started = TRUE; 2320#endif 2321 com->obufs[1].l_tail 2322 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2323 sizeof com->obuf2); 2324 com->obufs[1].l_next = NULL; 2325 com->obufs[1].l_queued = TRUE; 2326 critical_enter(); 2327 COM_LOCK(); 2328 if (com->state & CS_BUSY) { 2329 qp = com->obufq.l_next; 2330 while ((next = qp->l_next) != NULL) 2331 qp = next; 2332 qp->l_next = &com->obufs[1]; 2333 } else { 2334 com->obufq.l_head = com->obufs[1].l_head; 2335 com->obufq.l_tail = com->obufs[1].l_tail; 2336 com->obufq.l_next = &com->obufs[1]; 2337 com->state |= CS_BUSY; 2338 if (com->state >= (CS_BUSY | CS_TTGO 2339 | CS_ODEVREADY)) 2340 cd_setreg(com, CD1400_SRER, 2341 com->intr_enable 2342 = (com->intr_enable 2343 & ~CD1400_SRER_TXMPTY) 2344 | CD1400_SRER_TXRDY); 2345 } 2346 COM_UNLOCK(); 2347 critical_exit(); 2348 } 2349 tp->t_state |= TS_BUSY; 2350 } 2351#ifdef CyDebug 2352 if (started) 2353 ++com->start_real; 2354#endif 2355#if 0 2356 critical_enter(); 2357 COM_LOCK(); 2358 if (com->state >= (CS_BUSY | CS_TTGO)) 2359 siointr1(com); /* fake interrupt to start output */ 2360 COM_UNLOCK(); 2361 critical_exit(); 2362#endif 2363 ttwwakeup(tp); 2364 splx(s); 2365} 2366 2367static void 2368comstop(tp, rw) 2369 struct tty *tp; 2370 int rw; 2371{ 2372 struct com_s *com; 2373 bool_t wakeup_etc; 2374 2375 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2376 wakeup_etc = FALSE; 2377 critical_enter(); 2378 COM_LOCK(); 2379 if (rw & FWRITE) { 2380 com->obufs[0].l_queued = FALSE; 2381 com->obufs[1].l_queued = FALSE; 2382 if (com->extra_state & CSE_ODONE) { 2383 com_events -= LOTS_OF_EVENTS; 2384 com->extra_state &= ~CSE_ODONE; 2385 if (com->etc != ETC_NONE) { 2386 if (com->etc == ETC_BREAK_ENDED) 2387 com->etc = ETC_NONE; 2388 wakeup_etc = TRUE; 2389 } 2390 } 2391 com->tp->t_state &= ~TS_BUSY; 2392 if (com->state & CS_ODONE) 2393 com_events -= LOTS_OF_EVENTS; 2394 com->state &= ~(CS_ODONE | CS_BUSY); 2395 } 2396 if (rw & FREAD) { 2397 /* XXX no way to reset only input fifo. */ 2398 com_events -= (com->iptr - com->ibuf); 2399 com->iptr = com->ibuf; 2400 } 2401 COM_UNLOCK(); 2402 critical_exit(); 2403 if (wakeup_etc) 2404 wakeup(&com->etc); 2405 if (rw & FWRITE && com->etc == ETC_NONE) 2406 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2407 comstart(tp); 2408} 2409 2410static int 2411commctl(com, bits, how) 2412 struct com_s *com; 2413 int bits; 2414 int how; 2415{ 2416 int mcr; 2417 int msr; 2418 2419 if (how == DMGET) { 2420 if (com->channel_control & CD1400_CCR_RCVEN) 2421 bits |= TIOCM_LE; 2422 mcr = com->mcr_image; 2423 if (mcr & com->mcr_dtr) 2424 bits |= TIOCM_DTR; 2425 if (mcr & com->mcr_rts) 2426 /* XXX wired on for Cyclom-8Ys */ 2427 bits |= TIOCM_RTS; 2428 2429 /* 2430 * We must read the modem status from the hardware because 2431 * we don't generate modem status change interrupts for all 2432 * changes, so com->prev_modem_status is not guaranteed to 2433 * be up to date. This is safe, unlike for sio, because 2434 * reading the status register doesn't clear pending modem 2435 * status change interrupts. 2436 */ 2437 msr = cd_getreg(com, CD1400_MSVR2); 2438 2439 if (msr & MSR_CTS) 2440 bits |= TIOCM_CTS; 2441 if (msr & MSR_DCD) 2442 bits |= TIOCM_CD; 2443 if (msr & MSR_DSR) 2444 bits |= TIOCM_DSR; 2445 if (msr & MSR_RI) 2446 /* XXX not connected except for Cyclom-16Y? */ 2447 bits |= TIOCM_RI; 2448 return (bits); 2449 } 2450 mcr = 0; 2451 if (bits & TIOCM_DTR) 2452 mcr |= com->mcr_dtr; 2453 if (bits & TIOCM_RTS) 2454 mcr |= com->mcr_rts; 2455 critical_enter(); 2456 COM_LOCK(); 2457 switch (how) { 2458 case DMSET: 2459 com->mcr_image = mcr; 2460 cd_setreg(com, CD1400_MSVR1, mcr); 2461 cd_setreg(com, CD1400_MSVR2, mcr); 2462 break; 2463 case DMBIS: 2464 com->mcr_image = mcr = com->mcr_image | mcr; 2465 cd_setreg(com, CD1400_MSVR1, mcr); 2466 cd_setreg(com, CD1400_MSVR2, mcr); 2467 break; 2468 case DMBIC: 2469 com->mcr_image = mcr = com->mcr_image & ~mcr; 2470 cd_setreg(com, CD1400_MSVR1, mcr); 2471 cd_setreg(com, CD1400_MSVR2, mcr); 2472 break; 2473 } 2474 COM_UNLOCK(); 2475 critical_exit(); 2476 return (0); 2477} 2478 2479static void 2480siosettimeout() 2481{ 2482 struct com_s *com; 2483 bool_t someopen; 2484 int unit; 2485 2486 /* 2487 * Set our timeout period to 1 second if no polled devices are open. 2488 * Otherwise set it to max(1/200, 1/hz). 2489 * Enable timeouts iff some device is open. 2490 */ 2491 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2492 sio_timeout = hz; 2493 someopen = FALSE; 2494 for (unit = 0; unit < NSIO; ++unit) { 2495 com = com_addr(unit); 2496 if (com != NULL && com->tp != NULL 2497 && com->tp->t_state & TS_ISOPEN) { 2498 someopen = TRUE; 2499#if 0 2500 if (com->poll || com->poll_output) { 2501 sio_timeout = hz > 200 ? hz / 200 : 1; 2502 break; 2503 } 2504#endif 2505 } 2506 } 2507 if (someopen) { 2508 sio_timeouts_until_log = hz / sio_timeout; 2509 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2510 sio_timeout); 2511 } else { 2512 /* Flush error messages, if any. */ 2513 sio_timeouts_until_log = 1; 2514 comwakeup((void *)NULL); 2515 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2516 } 2517} 2518 2519static void 2520comwakeup(chan) 2521 void *chan; 2522{ 2523 struct com_s *com; 2524 int unit; 2525 2526 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2527 2528#if 0 2529 /* 2530 * Recover from lost output interrupts. 2531 * Poll any lines that don't use interrupts. 2532 */ 2533 for (unit = 0; unit < NSIO; ++unit) { 2534 com = com_addr(unit); 2535 if (com != NULL 2536 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2537 critical_enter(); 2538 COM_LOCK(); 2539 siointr1(com); 2540 COM_UNLOCK(); 2541 critical_exit(); 2542 } 2543 } 2544#endif 2545 2546 /* 2547 * Check for and log errors, but not too often. 2548 */ 2549 if (--sio_timeouts_until_log > 0) 2550 return; 2551 sio_timeouts_until_log = hz / sio_timeout; 2552 for (unit = 0; unit < NSIO; ++unit) { 2553 int errnum; 2554 2555 com = com_addr(unit); 2556 if (com == NULL) 2557 continue; 2558 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2559 u_int delta; 2560 u_long total; 2561 2562 critical_enter(); 2563 COM_LOCK(); 2564 delta = com->delta_error_counts[errnum]; 2565 com->delta_error_counts[errnum] = 0; 2566 COM_UNLOCK(); 2567 critical_exit(); 2568 if (delta == 0) 2569 continue; 2570 total = com->error_counts[errnum] += delta; 2571 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2572 unit, delta, error_desc[errnum], 2573 delta == 1 ? "" : "s", total); 2574 } 2575 } 2576} 2577 2578static void 2579disc_optim(tp, t, com) 2580 struct tty *tp; 2581 struct termios *t; 2582 struct com_s *com; 2583{ 2584#ifndef SOFT_HOTCHAR 2585 u_char opt; 2586#endif 2587 2588 com->hotchar = ttyldoptim(tp); 2589#ifndef SOFT_HOTCHAR 2590 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2591 if (com->hotchar != 0) { 2592 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2593 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2594 opt |= CD1400_COR3_SCD34; 2595 } 2596 if (opt != com->cor[2]) { 2597 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2598 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2599 } 2600#endif 2601} 2602 2603#ifdef Smarts 2604/* standard line discipline input routine */ 2605int 2606cyinput(c, tp) 2607 int c; 2608 struct tty *tp; 2609{ 2610 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2611 * bits, as they are done by the CD1400. Hardly worth the effort, 2612 * given that high-throughput sessions are raw anyhow. 2613 */ 2614} 2615#endif /* Smarts */ 2616 2617static int 2618comspeed(speed, cy_clock, prescaler_io) 2619 speed_t speed; 2620 u_long cy_clock; 2621 int *prescaler_io; 2622{ 2623 int actual; 2624 int error; 2625 int divider; 2626 int prescaler; 2627 int prescaler_unit; 2628 2629 if (speed == 0) 2630 return (0); 2631 if (speed < 0 || speed > 150000) 2632 return (-1); 2633 2634 /* determine which prescaler to use */ 2635 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2636 prescaler_unit--, prescaler >>= 2) { 2637 if (cy_clock / prescaler / speed > 63) 2638 break; 2639 } 2640 2641 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2642 if (divider > 255) 2643 divider = 255; 2644 actual = cy_clock/prescaler/divider; 2645 2646 /* 10 times error in percent: */ 2647 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2648 2649 /* 3.0% max error tolerance */ 2650 if (error < -30 || error > 30) 2651 return (-1); 2652 2653#if 0 2654 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2655 printf("divider = %d (%x)\n", divider, divider); 2656 printf("actual = %d\n", actual); 2657 printf("error = %d\n", error); 2658#endif 2659 2660 *prescaler_io = prescaler_unit; 2661 return (divider); 2662} 2663 2664static void 2665cd1400_channel_cmd(com, cmd) 2666 struct com_s *com; 2667 int cmd; 2668{ 2669 cd1400_channel_cmd_wait(com); 2670 cd_setreg(com, CD1400_CCR, cmd); 2671 cd1400_channel_cmd_wait(com); 2672} 2673 2674static void 2675cd1400_channel_cmd_wait(com) 2676 struct com_s *com; 2677{ 2678 struct timeval start; 2679 struct timeval tv; 2680 long usec; 2681 2682 if (cd_getreg(com, CD1400_CCR) == 0) 2683 return; 2684 microtime(&start); 2685 for (;;) { 2686 if (cd_getreg(com, CD1400_CCR) == 0) 2687 return; 2688 microtime(&tv); 2689 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2690 tv.tv_usec - start.tv_usec; 2691 if (usec >= 5000) { 2692 log(LOG_ERR, 2693 "cy%d: channel command timeout (%ld usec)\n", 2694 com->unit, usec); 2695 return; 2696 } 2697 } 2698} 2699 2700static void 2701cd_etc(com, etc) 2702 struct com_s *com; 2703 int etc; 2704{ 2705 2706 /* 2707 * We can't change the hardware's ETC state while there are any 2708 * characters in the tx fifo, since those characters would be 2709 * interpreted as commands! Unputting characters from the fifo 2710 * is difficult, so we wait up to 12 character times for the fifo 2711 * to drain. The command will be delayed for up to 2 character 2712 * times for the tx to become empty. Unputting characters from 2713 * the tx holding and shift registers is impossible, so we wait 2714 * for the tx to become empty so that the command is sure to be 2715 * executed soon after we issue it. 2716 */ 2717 critical_enter(); 2718 COM_LOCK(); 2719 if (com->etc == etc) 2720 goto wait; 2721 if ((etc == CD1400_ETC_SENDBREAK 2722 && (com->etc == ETC_BREAK_STARTING 2723 || com->etc == ETC_BREAK_STARTED)) 2724 || (etc == CD1400_ETC_STOPBREAK 2725 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2726 || com->etc == ETC_NONE))) { 2727 COM_UNLOCK(); 2728 critical_exit(); 2729 return; 2730 } 2731 com->etc = etc; 2732 cd_setreg(com, CD1400_SRER, 2733 com->intr_enable 2734 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2735wait: 2736 COM_UNLOCK(); 2737 critical_exit(); 2738 while (com->etc == etc 2739 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2740 continue; 2741} 2742 2743static int 2744cd_getreg(com, reg) 2745 struct com_s *com; 2746 int reg; 2747{ 2748 struct com_s *basecom; 2749 u_char car; 2750 int cy_align; 2751 cy_addr iobase; 2752#ifdef SMP 2753 int need_unlock; 2754#endif 2755 int val; 2756 2757 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2758 car = com->unit & CD1400_CAR_CHAN; 2759 cy_align = com->cy_align; 2760 iobase = com->iobase; 2761 critical_enter(); 2762#ifdef SMP 2763 need_unlock = 0; 2764 if (!mtx_owned(&sio_lock)) { 2765 COM_LOCK(); 2766 need_unlock = 1; 2767 } 2768#endif 2769 if (basecom->car != car) 2770 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2771 val = cd_inb(iobase, reg, cy_align); 2772#ifdef SMP 2773 if (need_unlock) 2774 COM_UNLOCK(); 2775#endif 2776 critical_exit(); 2777 return (val); 2778} 2779 2780static void 2781cd_setreg(com, reg, val) 2782 struct com_s *com; 2783 int reg; 2784 int val; 2785{ 2786 struct com_s *basecom; 2787 u_char car; 2788 int cy_align; 2789 cy_addr iobase; 2790#ifdef SMP 2791 int need_unlock; 2792#endif 2793 2794 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2795 car = com->unit & CD1400_CAR_CHAN; 2796 cy_align = com->cy_align; 2797 iobase = com->iobase; 2798 critical_enter(); 2799#ifdef SMP 2800 need_unlock = 0; 2801 if (!mtx_owned(&sio_lock)) { 2802 COM_LOCK(); 2803 need_unlock = 1; 2804 } 2805#endif 2806 if (basecom->car != car) 2807 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2808 cd_outb(iobase, reg, cy_align, val); 2809#ifdef SMP 2810 if (need_unlock) 2811 COM_UNLOCK(); 2812#endif 2813 critical_exit(); 2814} 2815 2816#ifdef CyDebug 2817/* useful in ddb */ 2818void 2819cystatus(unit) 2820 int unit; 2821{ 2822 struct com_s *com; 2823 cy_addr iobase; 2824 u_int ocount; 2825 struct tty *tp; 2826 2827 com = com_addr(unit); 2828 printf("info for channel %d\n", unit); 2829 printf("------------------\n"); 2830 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2831 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2832 if (com == NULL) 2833 return; 2834 iobase = com->iobase; 2835 printf("\n"); 2836 printf("cd1400 base address:\\tt%p\n", iobase); 2837 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2838 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2839 com->cor[0], com->cor[1], com->cor[2]); 2840 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2841 cd_getreg(com, CD1400_SRER), com->intr_enable); 2842 printf("service request register:\t0x%02x\n", 2843 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2844 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2845 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2846 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2847 cd_inb(iobase, CD1400_RIR, com->cy_align), 2848 cd_inb(iobase, CD1400_TIR, com->cy_align), 2849 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2850 printf("\n"); 2851 printf("com state:\t\t\t0x%02x\n", com->state); 2852 printf("calls to comstart():\t\t%d (%d useful)\n", 2853 com->start_count, com->start_real); 2854 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2855 ocount = 0; 2856 if (com->obufs[0].l_queued) 2857 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2858 if (com->obufs[1].l_queued) 2859 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2860 printf("tx buffer chars:\t\t%u\n", ocount); 2861 printf("received chars:\t\t\t%d\n", com->bytes_in); 2862 printf("received exceptions:\t\t%d\n", com->recv_exception); 2863 printf("modem signal deltas:\t\t%d\n", com->mdm); 2864 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2865 printf("\n"); 2866 tp = com->tp; 2867 if (tp != NULL) { 2868 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2869 printf( 2870 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2871 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2872 } else 2873 printf("tty state:\t\t\tclosed\n"); 2874} 2875#endif /* CyDebug */
|