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