475 /* mmap */ nommap, 476 /* strategy */ nostrategy, 477 /* name */ driver_name, 478 /* parms */ noparms, 479 /* maj */ CDEV_MAJOR, 480 /* dump */ nodump, 481 /* psize */ nopsize, 482 /* flags */ D_TTY, 483 /* maxio */ 0, 484 /* bmaj */ -1 485}; 486 487int comconsole = -1; 488static volatile speed_t comdefaultrate = CONSPEED; 489#ifdef __alpha__ 490static volatile speed_t gdbdefaultrate = CONSPEED; 491#endif 492static u_int com_events; /* input chars + weighted output completions */ 493static Port_t siocniobase; 494static int siocnunit; 495static Port_t siogdbiobase; 496static int siogdbunit = -1; 497static bool_t sio_registered; 498static int sio_timeout; 499static int sio_timeouts_until_log; 500static struct callout_handle sio_timeout_handle 501 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 502 503#ifdef PC98 504struct siodev { 505 short if_type; 506 short irq; 507 Port_t cmd, sts, ctrl, mod; 508}; 509static int sysclock; 510 511#define COM_INT_DISABLE {int previpri; previpri=spltty(); 512#define COM_INT_ENABLE splx(previpri);} 513#define IEN_TxFLAG IEN_Tx 514 515#define COM_CARRIER_DETECT_EMULATE 0 516#define PC98_CHECK_MODEM_INTERVAL (hz/10) 517#define DCD_OFF_TOLERANCE 2 518#define DCD_ON_RECOGNITION 2 519#define IS_8251(if_type) (!(if_type & 0x10)) 520#define COM1_EXT_CLOCK 0x40000 521 522static void commint __P((dev_t dev)); 523static void com_tiocm_set __P((struct com_s *com, int msr)); 524static void com_tiocm_bis __P((struct com_s *com, int msr)); 525static void com_tiocm_bic __P((struct com_s *com, int msr)); 526static int com_tiocm_get __P((struct com_s *com)); 527static int com_tiocm_get_delta __P((struct com_s *com)); 528static void pc98_msrint_start __P((dev_t dev)); 529static void com_cflag_and_speed_set __P((struct com_s *com, int cflag, int speed)); 530static int pc98_ttspeedtab __P((struct com_s *com, int speed)); 531static int pc98_get_modem_status __P((struct com_s *com)); 532static timeout_t pc98_check_msr; 533static void pc98_set_baud_rate __P((struct com_s *com, int count)); 534static void pc98_i8251_reset __P((struct com_s *com, int mode, int command)); 535static void pc98_disable_i8251_interrupt __P((struct com_s *com, int mod)); 536static void pc98_enable_i8251_interrupt __P((struct com_s *com, int mod)); 537static int pc98_check_i8251_interrupt __P((struct com_s *com)); 538static int pc98_i8251_get_cmd __P((struct com_s *com)); 539static int pc98_i8251_get_mod __P((struct com_s *com)); 540static void pc98_i8251_set_cmd __P((struct com_s *com, int x)); 541static void pc98_i8251_or_cmd __P((struct com_s *com, int x)); 542static void pc98_i8251_clear_cmd __P((struct com_s *com, int x)); 543static void pc98_i8251_clear_or_cmd __P((struct com_s *com, int clr, int x)); 544static int pc98_check_if_type __P((device_t dev, struct siodev *iod)); 545static void pc98_check_sysclock __P((void)); 546static int pc98_set_ioport __P((struct com_s *com, int id_flags)); 547 548#define com_int_Tx_disable(com) \ 549 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP) 550#define com_int_Tx_enable(com) \ 551 pc98_enable_i8251_interrupt(com,IEN_TxFLAG) 552#define com_int_Rx_disable(com) \ 553 pc98_disable_i8251_interrupt(com,IEN_Rx) 554#define com_int_Rx_enable(com) \ 555 pc98_enable_i8251_interrupt(com,IEN_Rx) 556#define com_int_TxRx_disable(com) \ 557 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx) 558#define com_int_TxRx_enable(com) \ 559 pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx) 560#define com_send_break_on(com) \ 561 pc98_i8251_or_cmd(com,CMD8251_SBRK) 562#define com_send_break_off(com) \ 563 pc98_i8251_clear_cmd(com,CMD8251_SBRK) 564 565static struct speedtab pc98speedtab[] = { /* internal RS232C interface */ 566 { 0, 0, }, 567 { 50, 50, }, 568 { 75, 75, }, 569 { 150, 150, }, 570 { 200, 200, }, 571 { 300, 300, }, 572 { 600, 600, }, 573 { 1200, 1200, }, 574 { 2400, 2400, }, 575 { 4800, 4800, }, 576 { 9600, 9600, }, 577 { 19200, 19200, }, 578 { 38400, 38400, }, 579 { 51200, 51200, }, 580 { 76800, 76800, }, 581 { 20800, 20800, }, 582 { 31200, 31200, }, 583 { 41600, 41600, }, 584 { 62400, 62400, }, 585 { -1, -1 } 586}; 587static struct speedtab pc98fast_speedtab[] = { 588 { 9600, 0x80 | COMBRD(9600), }, 589 { 19200, 0x80 | COMBRD(19200), }, 590 { 38400, 0x80 | COMBRD(38400), }, 591 { 57600, 0x80 | COMBRD(57600), }, 592 { 115200, 0x80 | COMBRD(115200), }, 593 { -1, -1 } 594}; 595static struct speedtab comspeedtab_pio9032b[] = { 596 { 300, 6, }, 597 { 600, 5, }, 598 { 1200, 4, }, 599 { 2400, 3, }, 600 { 4800, 2, }, 601 { 9600, 1, }, 602 { 19200, 0, }, 603 { 38400, 7, }, 604 { -1, -1 } 605}; 606static struct speedtab comspeedtab_b98_01[] = { 607 { 75, 11, }, 608 { 150, 10, }, 609 { 300, 9, }, 610 { 600, 8, }, 611 { 1200, 7, }, 612 { 2400, 6, }, 613 { 4800, 5, }, 614 { 9600, 4, }, 615 { 19200, 3, }, 616 { 38400, 2, }, 617 { 76800, 1, }, 618 { 153600, 0, }, 619 { -1, -1 } 620}; 621static struct speedtab comspeedtab_mc16550[] = { 622 { 300, 1536, }, 623 { 600, 768, }, 624 { 1200, 384, }, 625 { 2400, 192, }, 626 { 4800, 96, }, 627 { 9600, 48, }, 628 { 19200, 24, }, 629 { 38400, 12, }, 630 { 57600, 8, }, 631 { 115200, 4, }, 632 { 153600, 3, }, 633 { 230400, 2, }, 634 { 460800, 1, }, 635 { -1, -1 } 636}; 637static struct speedtab comspeedtab_rsb384[] = { 638 { 300, 3840, }, 639 { 600, 1920, }, 640 { 1200, 960, }, 641 { 2400, 480, }, 642 { 4800, 240, }, 643 { 9600, 120, }, 644 { 19200, 60, }, 645 { 38400, 30, }, 646 { 57600, 20, }, 647 { 115200, 10, }, 648 { 128000, 9, }, 649 { 144000, 8, }, 650 { 192000, 6, }, 651 { 230400, 5, }, 652 { 288000, 4, }, 653 { 384000, 3, }, 654 { 576000, 2, }, 655 { 1152000, 1, }, 656 { -1, -1 } 657}; 658static struct speedtab comspeedtab_rsa[] = { 659 { 0, 0 }, 660 { 50, COMBRD_RSA(50) }, 661 { 75, COMBRD_RSA(75) }, 662 { 110, COMBRD_RSA(110) }, 663 { 134, COMBRD_RSA(134) }, 664 { 150, COMBRD_RSA(150) }, 665 { 200, COMBRD_RSA(200) }, 666 { 300, COMBRD_RSA(300) }, 667 { 600, COMBRD_RSA(600) }, 668 { 1200, COMBRD_RSA(1200) }, 669 { 1800, COMBRD_RSA(1800) }, 670 { 2400, COMBRD_RSA(2400) }, 671 { 4800, COMBRD_RSA(4800) }, 672 { 9600, COMBRD_RSA(9600) }, 673 { 19200, COMBRD_RSA(19200) }, 674 { 38400, COMBRD_RSA(38400) }, 675 { 57600, COMBRD_RSA(57600) }, 676 { 115200, COMBRD_RSA(115200) }, 677 { 230400, COMBRD_RSA(230400) }, 678 { 460800, COMBRD_RSA(460800) }, 679 { 921600, COMBRD_RSA(921600) }, 680 { -1, -1 } 681}; 682#endif /* PC98 */ 683 684static struct speedtab comspeedtab[] = { 685 { 0, 0 }, 686 { 50, COMBRD(50) }, 687 { 75, COMBRD(75) }, 688 { 110, COMBRD(110) }, 689 { 134, COMBRD(134) }, 690 { 150, COMBRD(150) }, 691 { 200, COMBRD(200) }, 692 { 300, COMBRD(300) }, 693 { 600, COMBRD(600) }, 694 { 1200, COMBRD(1200) }, 695 { 1800, COMBRD(1800) }, 696 { 2400, COMBRD(2400) }, 697 { 4800, COMBRD(4800) }, 698 { 9600, COMBRD(9600) }, 699 { 19200, COMBRD(19200) }, 700 { 38400, COMBRD(38400) }, 701 { 57600, COMBRD(57600) }, 702 { 115200, COMBRD(115200) }, 703 { -1, -1 } 704}; 705 706#ifdef PC98 707struct { 708 char *name; 709 short port_table[7]; 710 short irr_mask; 711 struct speedtab *speedtab; 712 short check_irq; 713} if_8251_type[] = { 714 /* COM_IF_INTERNAL */ 715 { " (internal)", {0x30, 0x32, 0x32, 0x33, 0x35, -1, -1}, 716 -1, pc98speedtab, 1 }, 717 /* COM_IF_PC9861K_1 */ 718 { " (PC9861K)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, -1, -1}, 719 3, NULL, 1 }, 720 /* COM_IF_PC9861K_2 */ 721 { " (PC9861K)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, -1, -1}, 722 3, NULL, 1 }, 723 /* COM_IF_IND_SS_1 */ 724 { " (IND-SS)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb3, -1}, 725 3, comspeedtab_mc16550, 1 }, 726 /* COM_IF_IND_SS_2 */ 727 { " (IND-SS)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xbb, -1}, 728 3, comspeedtab_mc16550, 1 }, 729 /* COM_IF_PIO9032B_1 */ 730 { " (PIO9032B)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb8, -1}, 731 7, comspeedtab_pio9032b, 1 }, 732 /* COM_IF_PIO9032B_2 */ 733 { " (PIO9032B)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xba, -1}, 734 7, comspeedtab_pio9032b, 1 }, 735 /* COM_IF_B98_01_1 */ 736 { " (B98-01)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xd1, 0xd3}, 737 7, comspeedtab_b98_01, 0 }, 738 /* COM_IF_B98_01_2 */ 739 { " (B98-01)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xd5, 0xd7}, 740 7, comspeedtab_b98_01, 0 }, 741}; 742#define PC98SIO_data_port(type) (if_8251_type[type].port_table[0]) 743#define PC98SIO_cmd_port(type) (if_8251_type[type].port_table[1]) 744#define PC98SIO_sts_port(type) (if_8251_type[type].port_table[2]) 745#define PC98SIO_in_modem_port(type) (if_8251_type[type].port_table[3]) 746#define PC98SIO_intr_ctrl_port(type) (if_8251_type[type].port_table[4]) 747#define PC98SIO_baud_rate_port(type) (if_8251_type[type].port_table[5]) 748#define PC98SIO_func_port(type) (if_8251_type[type].port_table[6]) 749 750struct { 751 char *name; 752 short irr_read; 753 short irr_write; 754 short port_shift; 755 short io_size; 756 struct speedtab *speedtab; 757} if_16550a_type[] = { 758 /* COM_IF_RSA98 */ 759 { " (RSA-98)", -1, -1, 0, IO_COMSIZE, comspeedtab }, 760 /* COM_IF_NS16550 */ 761 { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, 762 /* COM_IF_SECOND_CCU */ 763 { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, 764 /* COM_IF_MC16550II */ 765 { " (MC16550II)", -1, 0x1000, 8, 1, comspeedtab_mc16550 }, 766 /* COM_IF_MCRS98 */ 767 { " (MC-RS98)", -1, 0x1000, 8, 1, comspeedtab_mc16550 }, 768 /* COM_IF_RSB3000 */ 769 { " (RSB-3000)", 0xbf, -1, 1, 1, comspeedtab_rsb384 }, 770 /* COM_IF_RSB384 */ 771 { " (RSB-384)", 0xbf, -1, 1, 1, comspeedtab_rsb384 }, 772 /* COM_IF_MODEM_CARD */ 773 { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, 774 /* COM_IF_RSA98III */ 775 { " (RSA-98III)", -1, -1, 0, 16, comspeedtab_rsa }, 776 /* COM_IF_ESP98 */ 777 { " (ESP98)", -1, -1, 1, 1, comspeedtab_mc16550 }, 778}; 779#endif /* PC98 */ 780 781#ifdef COM_ESP 782#ifdef PC98 783 784/* XXX configure this properly. */ 785static Port_t likely_com_ports[] = { 0, 0xb0, 0xb1, 0 }; 786static Port_t likely_esp_ports[] = { 0xc0d0, 0 }; 787 788#define ESP98_CMD1 (ESP_CMD1 * 0x100) 789#define ESP98_CMD2 (ESP_CMD2 * 0x100) 790#define ESP98_STATUS1 (ESP_STATUS1 * 0x100) 791#define ESP98_STATUS2 (ESP_STATUS2 * 0x100) 792 793#else /* PC98 */ 794 795/* XXX configure this properly. */ 796static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; 797static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; 798 799#endif /* PC98 */ 800#endif 801 802/* 803 * handle sysctl read/write requests for console speed 804 * 805 * In addition to setting comdefaultrate for I/O through /dev/console, 806 * also set the initial and lock values for the /dev/ttyXX device 807 * if there is one associated with the console. Finally, if the /dev/tty 808 * device has already been open, change the speed on the open running port 809 * itself. 810 */ 811 812static int 813sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS 814{ 815 int error, s; 816 speed_t newspeed; 817 struct com_s *com; 818 struct tty *tp; 819 820 newspeed = comdefaultrate; 821 822 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req); 823 if (error || !req->newptr) 824 return (error); 825 826 comdefaultrate = newspeed; 827 828 if (comconsole < 0) /* serial console not selected? */ 829 return (0); 830 831 com = com_addr(comconsole); 832 if (!com) 833 return (ENXIO); 834 835 /* 836 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX 837 * (note, the lock rates really are boolean -- if non-zero, disallow 838 * speed changes) 839 */ 840 com->it_in.c_ispeed = com->it_in.c_ospeed = 841 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 842 com->it_out.c_ispeed = com->it_out.c_ospeed = 843 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate; 844 845 /* 846 * if we're open, change the running rate too 847 */ 848 tp = com->tp; 849 if (tp && (tp->t_state & TS_ISOPEN)) { 850 tp->t_termios.c_ispeed = 851 tp->t_termios.c_ospeed = comdefaultrate; 852 s = spltty(); 853 error = comparam(tp, &tp->t_termios); 854 splx(s); 855 } 856 return error; 857} 858 859SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW, 860 0, 0, sysctl_machdep_comdefaultrate, "I", ""); 861 862#if NCARD > 0 863/* 864 * PC-Card (PCMCIA) specific code. 865 */ 866static int sioinit __P((struct pccard_devinfo *)); 867static void siounload __P((struct pccard_devinfo *)); 868static int card_intr __P((struct pccard_devinfo *)); 869 870PCCARD_MODULE(sio, sioinit, siounload, card_intr, 0, tty_imask); 871 872/* 873 * Initialize the device - called from Slot manager. 874 */ 875int 876sioinit(struct pccard_devinfo *devi) 877{ 878 879 /* validate unit number. */ 880 if (devi->isahd.id_unit >= (NSIOTOT)) 881 return(ENODEV); 882 /* Make sure it isn't already probed. */ 883 if (com_addr(devi->isahd.id_unit)) 884 return(EBUSY); 885 886 /* It's already probed as serial by Upper */ 887 devi->isahd.id_flags |= COM_C_NOPROBE; 888 889 /* 890 * attach the device. 891 */ 892 if (sioattach(devi->isahd.id_device) == 0) 893 return(ENXIO); 894 895 return(0); 896} 897 898/* 899 * siounload - unload the driver and clear the table. 900 * XXX TODO: 901 * This is usually called when the card is ejected, but 902 * can be caused by a modunload of a controller driver. 903 * The idea is to reset the driver's view of the device 904 * and ensure that any driver entry points such as 905 * read and write do not hang. 906 */ 907static void 908siounload(struct pccard_devinfo *devi) 909{ 910 struct com_s *com; 911 912 if (!devi) { 913 printf("NULL devi in siounload\n"); 914 return; 915 } 916 com = com_addr(devi->isahd.id_unit); 917 if (!com) { 918 printf("NULL com in siounload\n"); 919 return; 920 } 921 if (!com->iobase) { 922 printf("sio%d already unloaded!\n",devi->isahd.id_unit); 923 return; 924 } 925 if (com->tp && (com->tp->t_state & TS_ISOPEN)) { 926 com->gone = 1; 927 printf("sio%d: unload\n", devi->isahd.id_unit); 928 com->tp->t_gen++; 929 ttyclose(com->tp); 930 ttwakeup(com->tp); 931 ttwwakeup(com->tp); 932 } else { 933 if (com->ibuf != NULL) 934 free(com->ibuf, M_DEVBUF); 935 free(com, M_DEVBUF); 936 printf("sio%d: unload,gone\n", devi->isahd.id_unit); 937 } 938} 939 940/* 941 * card_intr - Shared interrupt called from 942 * front end of PC-Card handler. 943 */ 944static int 945card_intr(struct pccard_devinfo *devi) 946{ 947 struct com_s *com; 948 949 COM_LOCK(); 950 com = com_addr(devi->isahd.id_unit); 951 if (com && !com->gone) 952 siointr1(com_addr(devi->isahd.id_unit)); 953 COM_UNLOCK(); 954 return(1); 955} 956#endif /* NCARD > 0 */ 957 958#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit)) 959#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit)) 960 961static struct isa_pnp_id sio_ids[] = { 962 {0x0005d041, "Standard PC COM port"}, /* PNP0500 */ 963 {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */ 964 {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */ 965 {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */ 966 {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */ 967 {0x31307256, "USR3031"}, /* USR3031 */ 968 {0} 969}; 970 971static int 972sioprobe(dev) 973 device_t dev; 974{ 975 static bool_t already_init; 976 bool_t failures[10]; 977 int fn; 978 device_t idev; 979 Port_t iobase; 980 intrmask_t irqmap[4]; 981 intrmask_t irqs; 982 u_char mcr_image; 983 int result; 984 device_t xdev; 985 u_int flags = device_get_flags(dev); 986 int rid; 987 struct resource *port; 988#ifdef PC98 989 int irqout=0; 990 int tmp; 991 int port_shift = 0; 992 struct siodev iod; 993 Port_t rsabase = NULL; 994#endif 995 996 /* Check isapnp ids */ 997 if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO) 998 return (ENXIO); 999 1000 rid = 0; 1001#ifdef PC98 1002 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1003 0, ~0, 1, RF_ACTIVE); /* XXX */ 1004#else 1005 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1006 0, ~0, IO_COMSIZE, RF_ACTIVE); 1007#endif 1008 if (!port) 1009 return ENXIO; 1010 1011 if (!already_init) { 1012 /* 1013 * Turn off MCR_IENABLE for all likely serial ports. An unused 1014 * port with its MCR_IENABLE gate open will inhibit interrupts 1015 * from any used port that shares the interrupt vector. 1016 * XXX the gate enable is elsewhere for some multiports. 1017 */ 1018 device_t *devs; 1019 int count, i; 1020 1021 devclass_get_devices(sio_devclass, &devs, &count); 1022#ifdef PC98 1023 for (i = 0; i < count; i++) { 1024 xdev = devs[i]; 1025 if (device_is_enabled(xdev)) { 1026 tmp = (flags >> 24) & 0xff; 1027 if (IS_8251(tmp)) 1028 outb((isa_get_port(xdev) & 0xff00) | PC98SIO_cmd_port(tmp & 0x0f), 0xf2); 1029 else 1030 if (tmp == COM_IF_RSA98III) { 1031 rsabase = isa_get_port(xdev) & 0xfff0; 1032 outb(isa_get_port(xdev) + 8 + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0); 1033 } else 1034 outb(isa_get_port(xdev) + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0); 1035 } 1036 } 1037#else 1038 for (i = 0; i < count; i++) { 1039 xdev = devs[i]; 1040 if (device_is_enabled(xdev)) 1041 outb(isa_get_port(xdev) + com_mcr, 0); 1042 } 1043#endif 1044 free(devs, M_TEMP); 1045 already_init = TRUE; 1046 } 1047 1048 if (COM_LLCONSOLE(flags)) { 1049 printf("sio%d: reserved for low-level i/o\n", 1050 device_get_unit(dev)); 1051 return (ENXIO); 1052 } 1053 1054#ifdef PC98 1055 DELAY(10); 1056 1057 /* 1058 * If the port is i8251 UART (internal, B98_01) 1059 */ 1060 if (pc98_check_if_type(dev, &iod) == -1) 1061 return ENXIO; 1062 if (iod.irq > 0) 1063 isa_set_irq(dev, iod.irq); 1064 if (IS_8251(iod.if_type)) { 1065 outb(iod.cmd, 0); 1066 DELAY(10); 1067 outb(iod.cmd, 0); 1068 DELAY(10); 1069 outb(iod.cmd, 0); 1070 DELAY(10); 1071 outb(iod.cmd, CMD8251_RESET); 1072 DELAY(1000); /* for a while...*/ 1073 outb(iod.cmd, 0xf2); /* MODE (dummy) */ 1074 DELAY(10); 1075 outb(iod.cmd, 0x01); /* CMD (dummy) */ 1076 DELAY(1000); /* for a while...*/ 1077 if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) { 1078 result = ENXIO; 1079 } 1080 if (if_8251_type[iod.if_type & 0x0f].check_irq) { 1081 COM_INT_DISABLE 1082 tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx)); 1083 outb( iod.ctrl, tmp|IEN_TxEMP ); 1084 DELAY(10); 1085 result = isa_irq_pending() ? 0 : ENXIO; 1086 outb( iod.ctrl, tmp ); 1087 COM_INT_ENABLE 1088 } else { 1089 /* 1090 * B98_01 doesn't activate TxEMP interrupt line 1091 * when being reset, so we can't check irq pending. 1092 */ 1093 result = 0; 1094 } 1095 if (epson_machine_id==0x20) { /* XXX */ 1096 result = 0; 1097 } 1098 bus_release_resource(dev, SYS_RES_IOPORT, rid, port); 1099 return result; 1100 } 1101#endif /* PC98 */ 1102 /* 1103 * If the device is on a multiport card and has an AST/4 1104 * compatible interrupt control register, initialize this 1105 * register and prepare to leave MCR_IENABLE clear in the mcr. 1106 * Otherwise, prepare to set MCR_IENABLE in the mcr. 1107 * Point idev to the device struct giving the correct id_irq. 1108 * This is the struct for the master device if there is one. 1109 */ 1110 idev = dev; 1111 mcr_image = MCR_IENABLE; 1112#ifdef PC98 1113 if (iod.if_type == COM_IF_RSA98III) { 1114 mcr_image = 0; 1115 rsabase = isa_get_port(idev) & 0xfff0; 1116 if (rsabase != isa_get_port(idev)) 1117 return(0); 1118 outb(rsabase + rsa_msr, 0x04); 1119 outb(rsabase + rsa_frr, 0x00); 1120 if ((inb(rsabase + rsa_srr) & 0x36) != 0x36) 1121 return (0); 1122 outb(rsabase + rsa_ier, 0x00); 1123 outb(rsabase + rsa_frr, 0x00); 1124 outb(rsabase + rsa_tivsr, 0x00); 1125 outb(rsabase + rsa_tcr, 0x00); 1126 } 1127#endif /* PC98 */ 1128#ifdef COM_MULTIPORT 1129 if (COM_ISMULTIPORT(flags)) { 1130 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags)); 1131 if (idev == NULL) { 1132 printf("sio%d: master device %d not configured\n", 1133 device_get_unit(dev), COM_MPMASTER(flags)); 1134 idev = dev; 1135 } 1136#ifndef PC98 1137 if (!COM_NOTAST4(flags)) { 1138 outb(isa_get_port(idev) + com_scr, 1139 isa_get_irq(idev) >= 0 ? 0x80 : 0); 1140 mcr_image = 0; 1141 } 1142#endif /* !PC98 */ 1143 } 1144#endif /* COM_MULTIPORT */ 1145 if (isa_get_irq(idev) < 0) 1146 mcr_image = 0; 1147 1148#ifdef PC98 1149 tmp = if_16550a_type[iod.if_type & 0x0f].irr_write; 1150 if (tmp != -1) { 1151 /* MC16550II */ 1152 switch (isa_get_irq(idev)) { 1153 case 3: irqout = 4; break; 1154 case 5: irqout = 5; break; 1155 case 6: irqout = 6; break; 1156 case 12: irqout = 7; break; 1157 default: 1158 printf("sio%d: irq configuration error\n", 1159 device_get_unit(dev)); 1160 return (0); 1161 } 1162 outb((isa_get_port(dev) & 0x00ff) | tmp, irqout); 1163 } 1164 port_shift = if_16550a_type[iod.if_type & 0x0f].port_shift; 1165#endif 1166 bzero(failures, sizeof failures); 1167 iobase = rman_get_start(port); 1168#ifdef PC98 1169 if (iod.if_type == COM_IF_RSA98III) 1170 iobase += 8; 1171#endif 1172 1173 /* 1174 * We don't want to get actual interrupts, just masked ones. 1175 * Interrupts from this line should already be masked in the ICU, 1176 * but mask them in the processor as well in case there are some 1177 * (misconfigured) shared interrupts. 1178 */ 1179 disable_intr(); 1180/* EXTRA DELAY? */ 1181 1182 /* 1183 * Initialize the speed and the word size and wait long enough to 1184 * drain the maximum of 16 bytes of junk in device output queues. 1185 * The speed is undefined after a master reset and must be set 1186 * before relying on anything related to output. There may be 1187 * junk after a (very fast) soft reboot and (apparently) after 1188 * master reset. 1189 * XXX what about the UART bug avoided by waiting in comparam()? 1190 * We don't want to to wait long enough to drain at 2 bps. 1191 */ 1192 if (iobase == siocniobase) 1193 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); 1194 else { 1195#ifdef PC98 1196 tmp = ttspeedtab(SIO_TEST_SPEED, 1197 if_16550a_type[iod.if_type & 0x0f].speedtab); 1198 outb(iobase + (com_cfcr << port_shift), CFCR_DLAB|CFCR_8BITS); 1199 outb(iobase + (com_dlbl << port_shift), tmp & 0xff); 1200 outb(iobase + (com_dlbh << port_shift), (tmp >> 8) & 0xff); 1201 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); 1202#else 1203 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 1204 outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff); 1205 outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8); 1206 outb(iobase + com_cfcr, CFCR_8BITS); 1207#endif 1208 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); 1209 } 1210 1211 /* 1212 * Enable the interrupt gate and disable device interupts. This 1213 * should leave the device driving the interrupt line low and 1214 * guarantee an edge trigger if an interrupt can be generated. 1215 */ 1216/* EXTRA DELAY? */ 1217#ifdef PC98 1218 outb(iobase + (com_mcr << port_shift), mcr_image); 1219 outb(iobase + (com_ier << port_shift), 0); 1220#else 1221 outb(iobase + com_mcr, mcr_image); 1222 outb(iobase + com_ier, 0); 1223#endif 1224 DELAY(1000); /* XXX */ 1225 irqmap[0] = isa_irq_pending(); 1226 1227 /* 1228 * Attempt to set loopback mode so that we can send a null byte 1229 * without annoying any external device. 1230 */ 1231/* EXTRA DELAY? */ 1232#ifdef PC98 1233 outb(iobase + (com_mcr << port_shift), mcr_image | MCR_LOOPBACK); 1234#else 1235 outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK); 1236#endif 1237 1238 /* 1239 * Attempt to generate an output interrupt. On 8250's, setting 1240 * IER_ETXRDY generates an interrupt independent of the current 1241 * setting and independent of whether the THR is empty. On 16450's, 1242 * setting IER_ETXRDY generates an interrupt independent of the 1243 * current setting. On 16550A's, setting IER_ETXRDY only 1244 * generates an interrupt when IER_ETXRDY is not already set. 1245 */ 1246#ifdef PC98 1247 outb(iobase + (com_ier << port_shift), IER_ETXRDY); 1248 if (iod.if_type == COM_IF_RSA98III) 1249 outb(rsabase + rsa_ier, 0x04); 1250#else 1251 outb(iobase + com_ier, IER_ETXRDY); 1252#endif /* PC98 */ 1253 1254 /* 1255 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate 1256 * an interrupt. They'd better generate one for actually doing 1257 * output. Loopback may be broken on the same incompatibles but 1258 * it's unlikely to do more than allow the null byte out. 1259 */ 1260#ifdef PC98 1261 outb(iobase + (com_data << port_shift), 0); 1262#else 1263 outb(iobase + com_data, 0); 1264#endif 1265 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); 1266 1267 /* 1268 * Turn off loopback mode so that the interrupt gate works again 1269 * (MCR_IENABLE was hidden). This should leave the device driving 1270 * an interrupt line high. It doesn't matter if the interrupt 1271 * line oscillates while we are not looking at it, since interrupts 1272 * are disabled. 1273 */ 1274/* EXTRA DELAY? */ 1275#ifdef PC98 1276 outb(iobase + (com_mcr << port_shift), mcr_image); 1277#else 1278 outb(iobase + com_mcr, mcr_image); 1279#endif /* PC98 */ 1280 1281 /* 1282 * It's a definitly Serial PCMCIA(16550A), but still be required 1283 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... ) 1284 */ 1285 if ( COM_NOPROBE(flags) ) { 1286 /* Reading IIR register twice */ 1287 for ( fn = 0; fn < 2; fn ++ ) { 1288 DELAY(10000); 1289#ifdef PC98 1290 failures[6] = inb(iobase + (com_iir << port_shift)); 1291#else 1292 failures[6] = inb(iobase + com_iir); 1293#endif 1294 } 1295 /* Check IIR_TXRDY clear ? */ 1296 result = 0; 1297 if ( failures[6] & IIR_TXRDY ) { 1298 /* Nop, Double check with clearing IER */ 1299#ifdef PC98 1300 outb(iobase + (com_ier << port_shift), 0); 1301 if (inb(iobase + 1302 (com_iir << port_shift)) & IIR_NOPEND) { 1303#else 1304 outb(iobase + com_ier, 0); 1305 if ( inb(iobase + com_iir) & IIR_NOPEND ) { 1306#endif 1307 /* Ok. we're familia this gang */ 1308 SET_FLAG(dev, COM_C_IIR_TXRDYBUG); /* Set IIR_TXRDYBUG */ 1309 } else { 1310 /* Unknown, Just omit this chip.. XXX */ 1311 result = ENXIO; 1312 } 1313 } else { 1314 /* OK. this is well-known guys */ 1315 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG); /*Clear IIR_TXRDYBUG*/ 1316 } 1317#ifdef PC98 1318 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); 1319#else 1320 outb(iobase + com_cfcr, CFCR_8BITS); 1321#endif 1322 enable_intr(); 1323 bus_release_resource(dev, SYS_RES_IOPORT, rid, port); 1324 return (iobase == siocniobase ? 0 : result); 1325 } 1326 1327 /* 1328 * Check that 1329 * o the CFCR, IER and MCR in UART hold the values written to them 1330 * (the values happen to be all distinct - this is good for 1331 * avoiding false positive tests from bus echoes). 1332 * o an output interrupt is generated and its vector is correct. 1333 * o the interrupt goes away when the IIR in the UART is read. 1334 */ 1335/* EXTRA DELAY? */ 1336#ifdef PC98 1337 failures[0] = inb(iobase + (com_cfcr << port_shift)) - CFCR_8BITS; 1338 failures[1] = inb(iobase + (com_ier << port_shift)) - IER_ETXRDY; 1339 failures[2] = inb(iobase + (com_mcr << port_shift)) - mcr_image; 1340#else 1341 failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS; 1342 failures[1] = inb(iobase + com_ier) - IER_ETXRDY; 1343 failures[2] = inb(iobase + com_mcr) - mcr_image; 1344#endif 1345 DELAY(10000); /* Some internal modems need this time */ 1346 irqmap[1] = isa_irq_pending(); 1347#ifdef PC98 1348 failures[4] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) 1349 - IIR_TXRDY; 1350 if (iod.if_type == COM_IF_RSA98III) 1351 inb(rsabase + rsa_srr); 1352#else 1353 failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY; 1354#endif 1355 DELAY(1000); /* XXX */ 1356 irqmap[2] = isa_irq_pending(); 1357#ifdef PC98 1358 failures[6] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) 1359 - IIR_NOPEND; 1360 if (iod.if_type == COM_IF_RSA98III) 1361 inb(rsabase + rsa_srr); 1362#else 1363 failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1364#endif 1365 1366 /* 1367 * Turn off all device interrupts and check that they go off properly. 1368 * Leave MCR_IENABLE alone. For ports without a master port, it gates 1369 * the OUT2 output of the UART to 1370 * the ICU input. Closing the gate would give a floating ICU input 1371 * (unless there is another device driving it) and spurious interrupts. 1372 * (On the system that this was first tested on, the input floats high 1373 * and gives a (masked) interrupt as soon as the gate is closed.) 1374 */ 1375#ifdef PC98 1376 outb(iobase + (com_ier << port_shift), 0); 1377 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); 1378 failures[7] = inb(iobase + (com_ier << port_shift)); 1379 if (iod.if_type == COM_IF_RSA98III) 1380 outb(rsabase + rsa_ier, 0x00); 1381#else 1382 outb(iobase + com_ier, 0); 1383 outb(iobase + com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ 1384 failures[7] = inb(iobase + com_ier); 1385#endif 1386 DELAY(1000); /* XXX */ 1387 irqmap[3] = isa_irq_pending(); 1388#ifdef PC98 1389 failures[9] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) 1390 - IIR_NOPEND; 1391 if (iod.if_type == COM_IF_RSA98III) { 1392 inb(rsabase + rsa_srr); 1393 outb(rsabase + rsa_frr, 0x00); 1394 } 1395#else 1396 failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1397#endif 1398 1399 enable_intr(); 1400 1401 irqs = irqmap[1] & ~irqmap[0]; 1402 if (isa_get_irq(idev) >= 0 && ((1 << isa_get_irq(idev)) & irqs) == 0) 1403 printf( 1404 "sio%d: configured irq %d not in bitmap of probed irqs %#x\n", 1405 device_get_unit(dev), isa_get_irq(idev), irqs); 1406 if (bootverbose) 1407 printf("sio%d: irq maps: %#x %#x %#x %#x\n", 1408 device_get_unit(dev), 1409 irqmap[0], irqmap[1], irqmap[2], irqmap[3]); 1410 1411 result = 0; 1412 for (fn = 0; fn < sizeof failures; ++fn) 1413 if (failures[fn]) { 1414#ifdef PC98 1415 outb(iobase + (com_mcr << port_shift), 0); 1416#else 1417 outb(iobase + com_mcr, 0); 1418#endif 1419 result = ENXIO; 1420 if (bootverbose) { 1421 printf("sio%d: probe failed test(s):", 1422 device_get_unit(dev)); 1423 for (fn = 0; fn < sizeof failures; ++fn) 1424 if (failures[fn]) 1425 printf(" %d", fn); 1426 printf("\n"); 1427 } 1428 break; 1429 } 1430 bus_release_resource(dev, SYS_RES_IOPORT, rid, port); 1431 return (iobase == siocniobase ? 0 : result); 1432} 1433 1434#ifdef COM_ESP 1435static int 1436espattach(com, esp_port) 1437 struct com_s *com; 1438 Port_t esp_port; 1439{ 1440 u_char dips; 1441 u_char val; 1442 1443 /* 1444 * Check the ESP-specific I/O port to see if we're an ESP 1445 * card. If not, return failure immediately. 1446 */ 1447 if ((inb(esp_port) & 0xf3) == 0) { 1448 printf(" port 0x%x is not an ESP board?\n", esp_port); 1449 return (0); 1450 } 1451 1452 /* 1453 * We've got something that claims to be a Hayes ESP card. 1454 * Let's hope so. 1455 */ 1456 1457 /* Get the dip-switch configuration */ 1458#ifdef PC98 1459 outb(esp_port + ESP98_CMD1, ESP_GETDIPS); 1460 dips = inb(esp_port + ESP98_STATUS1); 1461#else 1462 outb(esp_port + ESP_CMD1, ESP_GETDIPS); 1463 dips = inb(esp_port + ESP_STATUS1); 1464#endif 1465 1466 /* 1467 * Bits 0,1 of dips say which COM port we are. 1468 */ 1469#ifdef PC98 1470 if ((com->iobase & 0xff) == likely_com_ports[dips & 0x03]) 1471#else 1472 if (com->iobase == likely_com_ports[dips & 0x03]) 1473#endif 1474 printf(" : ESP"); 1475 else { 1476 printf(" esp_port has com %d\n", dips & 0x03); 1477 return (0); 1478 } 1479 1480 /* 1481 * Check for ESP version 2.0 or later: bits 4,5,6 = 010. 1482 */ 1483#ifdef PC98 1484 outb(esp_port + ESP98_CMD1, ESP_GETTEST); 1485 val = inb(esp_port + ESP98_STATUS1); /* clear reg 1 */ 1486 val = inb(esp_port + ESP98_STATUS2); 1487#else 1488 outb(esp_port + ESP_CMD1, ESP_GETTEST); 1489 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */ 1490 val = inb(esp_port + ESP_STATUS2); 1491#endif 1492 if ((val & 0x70) < 0x20) { 1493 printf("-old (%o)", val & 0x70); 1494 return (0); 1495 } 1496 1497 /* 1498 * Check for ability to emulate 16550: bit 7 == 1 1499 */ 1500 if ((dips & 0x80) == 0) { 1501 printf(" slave"); 1502 return (0); 1503 } 1504 1505 /* 1506 * Okay, we seem to be a Hayes ESP card. Whee. 1507 */ 1508 com->esp = TRUE; 1509 com->esp_port = esp_port; 1510 return (1); 1511} 1512#endif /* COM_ESP */ 1513 1514static int 1515sioattach(dev) 1516 device_t dev; 1517{ 1518 struct com_s *com; 1519#ifdef COM_ESP 1520 Port_t *espp; 1521#endif 1522 Port_t iobase; 1523 int unit; 1524 void *ih; 1525 u_int flags = device_get_flags(dev); 1526 int rid; 1527 struct resource *port; 1528#ifdef PC98 1529 int port_shift = 0; 1530 u_char *obuf; 1531 u_long obufsize; 1532#endif 1533 1534 rid = 0; 1535#ifdef PC98 1536 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1537 0, ~0, 1, RF_ACTIVE); /* XXX */ 1538#else 1539 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1540 0, ~0, IO_COMSIZE, RF_ACTIVE); 1541#endif 1542 if (!port) 1543 return ENXIO; 1544 1545 iobase = rman_get_start(port); 1546#ifdef PC98 1547 if (((flags >> 24) & 0xff) == COM_IF_RSA98III) 1548 iobase += 8; 1549#endif 1550 unit = device_get_unit(dev); 1551 com = device_get_softc(dev); 1552#ifdef PC98 1553 obufsize = 256; 1554 if (((flags >> 24) & 0xff) == COM_IF_RSA98III) 1555 obufsize = 2048; 1556 if ((obuf = malloc(obufsize * 2, M_DEVBUF, M_NOWAIT)) == NULL) 1557 return (0); 1558 bzero(obuf, obufsize * 2); 1559#endif 1560 1561 /* 1562 * sioprobe() has initialized the device registers as follows: 1563 * o cfcr = CFCR_8BITS. 1564 * It is most important that CFCR_DLAB is off, so that the 1565 * data port is not hidden when we enable interrupts. 1566 * o ier = 0. 1567 * Interrupts are only enabled when the line is open. 1568 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible 1569 * interrupt control register or the config specifies no irq. 1570 * Keeping MCR_DTR and MCR_RTS off might stop the external 1571 * device from sending before we are ready. 1572 */ 1573 bzero(com, sizeof *com); 1574#ifdef PC98 1575 com->obufsize = obufsize; 1576 com->obuf1 = obuf; 1577 com->obuf2 = obuf + obufsize; 1578#endif 1579 com->unit = unit; 1580 com->ioportres = port; 1581 com->cfcr_image = CFCR_8BITS; 1582 com->dtr_wait = 3 * hz; 1583 com->loses_outints = COM_LOSESOUTINTS(flags) != 0; 1584 com->no_irq = isa_get_irq(dev) < 0; 1585 com->tx_fifo_size = 1; 1586 com->obufs[0].l_head = com->obuf1; 1587 com->obufs[1].l_head = com->obuf2; 1588 1589 com->iobase = iobase; 1590#ifdef PC98 1591 if (pc98_set_ioport(com, device_get_flags(dev)) == -1) { 1592 com->pc98_if_type = (device_get_flags(dev) >> 24) & 0xff; 1593 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 1594 com->data_port = iobase + (com_data << port_shift); 1595 com->int_id_port = iobase + (com_iir << port_shift); 1596 com->modem_ctl_port = iobase + (com_mcr << port_shift); 1597 com->mcr_image = inb(com->modem_ctl_port); 1598 com->line_status_port = iobase + (com_lsr << port_shift); 1599 com->modem_status_port = iobase + (com_msr << port_shift); 1600 com->intr_ctl_port = iobase + (com_ier << port_shift); 1601 } 1602#else /* not PC98 */ 1603 com->data_port = iobase + com_data; 1604 com->int_id_port = iobase + com_iir; 1605 com->modem_ctl_port = iobase + com_mcr; 1606 com->mcr_image = inb(com->modem_ctl_port); 1607 com->line_status_port = iobase + com_lsr; 1608 com->modem_status_port = iobase + com_msr; 1609 com->intr_ctl_port = iobase + com_ier; 1610#endif 1611 1612 /* 1613 * We don't use all the flags from <sys/ttydefaults.h> since they 1614 * are only relevant for logins. It's important to have echo off 1615 * initially so that the line doesn't start blathering before the 1616 * echo flag can be turned off. 1617 */ 1618 com->it_in.c_iflag = 0; 1619 com->it_in.c_oflag = 0; 1620 com->it_in.c_cflag = TTYDEF_CFLAG; 1621 com->it_in.c_lflag = 0; 1622 if (unit == comconsole) { 1623#ifdef PC98 1624 if (IS_8251(com->pc98_if_type)) 1625 DELAY(100000); 1626#endif 1627 com->it_in.c_iflag = TTYDEF_IFLAG; 1628 com->it_in.c_oflag = TTYDEF_OFLAG; 1629 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 1630 com->it_in.c_lflag = TTYDEF_LFLAG; 1631 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 1632 com->lt_out.c_ispeed = com->lt_out.c_ospeed = 1633 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 1634 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 1635 } else 1636 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; 1637 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 1638 enable_intr(); 1639 free(com, M_DEVBUF); 1640 return (0); 1641 } 1642 enable_intr(); 1643 termioschars(&com->it_in); 1644 com->it_out = com->it_in; 1645 1646 /* attempt to determine UART type */ 1647 printf("sio%d: type", unit); 1648 1649 1650#ifndef PC98 1651#ifdef COM_MULTIPORT 1652 if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags)) 1653#else 1654 if (!COM_IIR_TXRDYBUG(flags)) 1655#endif 1656 { 1657 u_char scr; 1658 u_char scr1; 1659 u_char scr2; 1660 1661 scr = inb(iobase + com_scr); 1662 outb(iobase + com_scr, 0xa5); 1663 scr1 = inb(iobase + com_scr); 1664 outb(iobase + com_scr, 0x5a); 1665 scr2 = inb(iobase + com_scr); 1666 outb(iobase + com_scr, scr); 1667 if (scr1 != 0xa5 || scr2 != 0x5a) { 1668 printf(" 8250"); 1669 goto determined_type; 1670 } 1671 } 1672#endif /* !PC98 */ 1673#ifdef PC98 1674 if (IS_8251(com->pc98_if_type)) { 1675 com_int_TxRx_disable( com ); 1676 com_cflag_and_speed_set( com, com->it_in.c_cflag, comdefaultrate ); 1677 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 1678 com_send_break_off( com ); 1679 printf(" 8251%s", if_8251_type[com->pc98_if_type & 0x0f].name); 1680 } else { 1681 outb(iobase + (com_fifo << port_shift), FIFO_ENABLE | FIFO_RX_HIGH); 1682#else 1683 outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); 1684#endif /* PC98 */ 1685 DELAY(100); 1686 com->st16650a = 0; 1687 switch (inb(com->int_id_port) & IIR_FIFO_MASK) { 1688 case FIFO_RX_LOW: 1689 printf(" 16450"); 1690 break; 1691 case FIFO_RX_MEDL: 1692 printf(" 16450?"); 1693 break; 1694 case FIFO_RX_MEDH: 1695 printf(" 16550?"); 1696 break; 1697 case FIFO_RX_HIGH: 1698 if (COM_NOFIFO(flags)) { 1699 printf(" 16550A fifo disabled"); 1700 } else { 1701 com->hasfifo = TRUE; 1702#ifdef PC98 1703 com->tx_fifo_size = 0; /* XXX flag conflicts. */ 1704 printf(" 16550A"); 1705#else 1706 if (COM_ST16650A(flags)) { 1707 com->st16650a = 1; 1708 com->tx_fifo_size = 32; 1709 printf(" ST16650A"); 1710 } else { 1711 com->tx_fifo_size = COM_FIFOSIZE(flags); 1712 printf(" 16550A"); 1713 } 1714#endif 1715 } 1716#ifdef PC98 1717 if (com->pc98_if_type == COM_IF_RSA98III) { 1718 com->tx_fifo_size = 2048; 1719 com->rsabase = isa_get_port(dev); 1720 outb(com->rsabase + rsa_ier, 0x00); 1721 outb(com->rsabase + rsa_frr, 0x00); 1722 } 1723#endif 1724 1725#ifdef COM_ESP 1726#ifdef PC98 1727 if (com->pc98_if_type == COM_IF_ESP98) 1728#endif 1729 for (espp = likely_esp_ports; *espp != 0; espp++) 1730 if (espattach(com, *espp)) { 1731 com->tx_fifo_size = 1024; 1732 break; 1733 } 1734#endif 1735 if (!com->st16650a) { 1736 if (!com->tx_fifo_size) 1737 com->tx_fifo_size = 16; 1738 else 1739 printf(" lookalike with %d bytes FIFO", 1740 com->tx_fifo_size); 1741 } 1742 1743 break; 1744 } 1745 1746#ifdef PC98 1747 if (com->pc98_if_type == COM_IF_RSB3000) { 1748 /* Set RSB-2000/3000 Extended Buffer mode. */ 1749 u_char lcr; 1750 lcr = inb(iobase + (com_cfcr << port_shift)); 1751 outb(iobase + (com_cfcr << port_shift), lcr | CFCR_DLAB); 1752 outb(iobase + (com_emr << port_shift), EMR_EXBUFF | EMR_EFMODE); 1753 outb(iobase + (com_cfcr << port_shift), lcr); 1754 } 1755#endif 1756 1757#ifdef COM_ESP 1758 if (com->esp) { 1759 /* 1760 * Set 16550 compatibility mode. 1761 * We don't use the ESP_MODE_SCALE bit to increase the 1762 * fifo trigger levels because we can't handle large 1763 * bursts of input. 1764 * XXX flow control should be set in comparam(), not here. 1765 */ 1766#ifdef PC98 1767 outb(com->esp_port + ESP98_CMD1, ESP_SETMODE); 1768 outb(com->esp_port + ESP98_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1769#else 1770 outb(com->esp_port + ESP_CMD1, ESP_SETMODE); 1771 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1772#endif 1773 1774 /* Set RTS/CTS flow control. */ 1775#ifdef PC98 1776 outb(com->esp_port + ESP98_CMD1, ESP_SETFLOWTYPE); 1777 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_RTS); 1778 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_CTS); 1779#else 1780 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); 1781 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS); 1782 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS); 1783#endif 1784 1785 /* Set flow-control levels. */ 1786#ifdef PC98 1787 outb(com->esp_port + ESP98_CMD1, ESP_SETRXFLOW); 1788 outb(com->esp_port + ESP98_CMD2, HIBYTE(768)); 1789 outb(com->esp_port + ESP98_CMD2, LOBYTE(768)); 1790 outb(com->esp_port + ESP98_CMD2, HIBYTE(512)); 1791 outb(com->esp_port + ESP98_CMD2, LOBYTE(512)); 1792#else 1793 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW); 1794 outb(com->esp_port + ESP_CMD2, HIBYTE(768)); 1795 outb(com->esp_port + ESP_CMD2, LOBYTE(768)); 1796 outb(com->esp_port + ESP_CMD2, HIBYTE(512)); 1797 outb(com->esp_port + ESP_CMD2, LOBYTE(512)); 1798#endif 1799 1800#ifdef PC98 1801 /* Set UART clock prescaler. */ 1802 outb(com->esp_port + ESP98_CMD1, ESP_SETCLOCK); 1803 outb(com->esp_port + ESP98_CMD2, 2); /* 4 times */ 1804#endif 1805 } 1806#endif /* COM_ESP */ 1807#ifdef PC98 1808 printf("%s", if_16550a_type[com->pc98_if_type & 0x0f].name); 1809 outb(iobase + (com_fifo << port_shift), 0); 1810#else 1811 outb(iobase + com_fifo, 0); 1812determined_type: ; 1813#endif 1814 1815#ifdef COM_MULTIPORT 1816 if (COM_ISMULTIPORT(flags)) { 1817 com->multiport = TRUE; 1818 printf(" (multiport"); 1819 if (unit == COM_MPMASTER(flags)) 1820 printf(" master"); 1821 printf(")"); 1822 com->no_irq = 1823 isa_get_irq(devclass_get_device 1824 (sio_devclass, COM_MPMASTER(flags))) < 0; 1825 } 1826#endif /* COM_MULTIPORT */ 1827#ifdef PC98 1828 } 1829#endif 1830 if (unit == comconsole) 1831 printf(", console"); 1832 if ( COM_IIR_TXRDYBUG(flags) ) 1833 printf(" with a bogus IIR_TXRDY register"); 1834 printf("\n"); 1835 1836 if (!sio_registered) { 1837 register_swi(SWI_TTY, siopoll); 1838 sio_registered = TRUE; 1839 } 1840 make_dev(&sio_cdevsw, unit, 1841 UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit); 1842 make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE, 1843 UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit); 1844 make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE, 1845 UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit); 1846 make_dev(&sio_cdevsw, unit | CALLOUT_MASK, 1847 UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit); 1848 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE, 1849 UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit); 1850 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE, 1851 UID_UUCP, GID_DIALER, 0660, "cuala%r", unit); 1852 com->flags = flags; 1853 com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 1854 pps_init(&com->pps); 1855 1856 rid = 0; 1857 com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, 1858 RF_SHAREABLE | RF_ACTIVE); 1859 BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres, 1860 INTR_TYPE_TTY | INTR_TYPE_FAST, 1861 siointr, com, &ih); 1862 1863 return (0); 1864} 1865 1866static int 1867sioopen(dev, flag, mode, p) 1868 dev_t dev; 1869 int flag; 1870 int mode; 1871 struct proc *p; 1872{ 1873 struct com_s *com; 1874 int error; 1875 Port_t iobase; 1876 int mynor; 1877 int s; 1878 struct tty *tp; 1879 int unit; 1880#ifdef PC98 1881 int port_shift = 0; 1882#endif 1883 1884 mynor = minor(dev); 1885 unit = MINOR_TO_UNIT(mynor); 1886 if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL) 1887 return (ENXIO); 1888 if (com->gone) 1889 return (ENXIO); 1890 if (mynor & CONTROL_MASK) 1891 return (0); 1892 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 1893 s = spltty(); 1894 1895#ifdef PC98 1896 if (!IS_8251(com->pc98_if_type)) 1897 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 1898#endif 1899 /* 1900 * We jump to this label after all non-interrupted sleeps to pick 1901 * up any changes of the device state. 1902 */ 1903open_top: 1904 while (com->state & CS_DTR_OFF) { 1905 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0); 1906 if (com_addr(unit) == NULL) 1907 return (ENXIO); 1908 if (error != 0 || com->gone) 1909 goto out; 1910 } 1911 if (tp->t_state & TS_ISOPEN) { 1912 /* 1913 * The device is open, so everything has been initialized. 1914 * Handle conflicts. 1915 */ 1916 if (mynor & CALLOUT_MASK) { 1917 if (!com->active_out) { 1918 error = EBUSY; 1919 goto out; 1920 } 1921 } else { 1922 if (com->active_out) { 1923 if (flag & O_NONBLOCK) { 1924 error = EBUSY; 1925 goto out; 1926 } 1927 error = tsleep(&com->active_out, 1928 TTIPRI | PCATCH, "siobi", 0); 1929 if (com_addr(unit) == NULL) 1930 return (ENXIO); 1931 if (error != 0 || com->gone) 1932 goto out; 1933 goto open_top; 1934 } 1935 } 1936 if (tp->t_state & TS_XCLUDE && 1937 suser(p)) { 1938 error = EBUSY; 1939 goto out; 1940 } 1941 } else { 1942 /* 1943 * The device isn't open, so there are no conflicts. 1944 * Initialize it. Initialization is done twice in many 1945 * cases: to preempt sleeping callin opens if we are 1946 * callout, and to complete a callin open after DCD rises. 1947 */ 1948 tp->t_oproc = comstart;
| 474 /* mmap */ nommap, 475 /* strategy */ nostrategy, 476 /* name */ driver_name, 477 /* parms */ noparms, 478 /* maj */ CDEV_MAJOR, 479 /* dump */ nodump, 480 /* psize */ nopsize, 481 /* flags */ D_TTY, 482 /* maxio */ 0, 483 /* bmaj */ -1 484}; 485 486int comconsole = -1; 487static volatile speed_t comdefaultrate = CONSPEED; 488#ifdef __alpha__ 489static volatile speed_t gdbdefaultrate = CONSPEED; 490#endif 491static u_int com_events; /* input chars + weighted output completions */ 492static Port_t siocniobase; 493static int siocnunit; 494static Port_t siogdbiobase; 495static int siogdbunit = -1; 496static bool_t sio_registered; 497static int sio_timeout; 498static int sio_timeouts_until_log; 499static struct callout_handle sio_timeout_handle 500 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 501 502#ifdef PC98 503struct siodev { 504 short if_type; 505 short irq; 506 Port_t cmd, sts, ctrl, mod; 507}; 508static int sysclock; 509 510#define COM_INT_DISABLE {int previpri; previpri=spltty(); 511#define COM_INT_ENABLE splx(previpri);} 512#define IEN_TxFLAG IEN_Tx 513 514#define COM_CARRIER_DETECT_EMULATE 0 515#define PC98_CHECK_MODEM_INTERVAL (hz/10) 516#define DCD_OFF_TOLERANCE 2 517#define DCD_ON_RECOGNITION 2 518#define IS_8251(if_type) (!(if_type & 0x10)) 519#define COM1_EXT_CLOCK 0x40000 520 521static void commint __P((dev_t dev)); 522static void com_tiocm_set __P((struct com_s *com, int msr)); 523static void com_tiocm_bis __P((struct com_s *com, int msr)); 524static void com_tiocm_bic __P((struct com_s *com, int msr)); 525static int com_tiocm_get __P((struct com_s *com)); 526static int com_tiocm_get_delta __P((struct com_s *com)); 527static void pc98_msrint_start __P((dev_t dev)); 528static void com_cflag_and_speed_set __P((struct com_s *com, int cflag, int speed)); 529static int pc98_ttspeedtab __P((struct com_s *com, int speed)); 530static int pc98_get_modem_status __P((struct com_s *com)); 531static timeout_t pc98_check_msr; 532static void pc98_set_baud_rate __P((struct com_s *com, int count)); 533static void pc98_i8251_reset __P((struct com_s *com, int mode, int command)); 534static void pc98_disable_i8251_interrupt __P((struct com_s *com, int mod)); 535static void pc98_enable_i8251_interrupt __P((struct com_s *com, int mod)); 536static int pc98_check_i8251_interrupt __P((struct com_s *com)); 537static int pc98_i8251_get_cmd __P((struct com_s *com)); 538static int pc98_i8251_get_mod __P((struct com_s *com)); 539static void pc98_i8251_set_cmd __P((struct com_s *com, int x)); 540static void pc98_i8251_or_cmd __P((struct com_s *com, int x)); 541static void pc98_i8251_clear_cmd __P((struct com_s *com, int x)); 542static void pc98_i8251_clear_or_cmd __P((struct com_s *com, int clr, int x)); 543static int pc98_check_if_type __P((device_t dev, struct siodev *iod)); 544static void pc98_check_sysclock __P((void)); 545static int pc98_set_ioport __P((struct com_s *com, int id_flags)); 546 547#define com_int_Tx_disable(com) \ 548 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP) 549#define com_int_Tx_enable(com) \ 550 pc98_enable_i8251_interrupt(com,IEN_TxFLAG) 551#define com_int_Rx_disable(com) \ 552 pc98_disable_i8251_interrupt(com,IEN_Rx) 553#define com_int_Rx_enable(com) \ 554 pc98_enable_i8251_interrupt(com,IEN_Rx) 555#define com_int_TxRx_disable(com) \ 556 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx) 557#define com_int_TxRx_enable(com) \ 558 pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx) 559#define com_send_break_on(com) \ 560 pc98_i8251_or_cmd(com,CMD8251_SBRK) 561#define com_send_break_off(com) \ 562 pc98_i8251_clear_cmd(com,CMD8251_SBRK) 563 564static struct speedtab pc98speedtab[] = { /* internal RS232C interface */ 565 { 0, 0, }, 566 { 50, 50, }, 567 { 75, 75, }, 568 { 150, 150, }, 569 { 200, 200, }, 570 { 300, 300, }, 571 { 600, 600, }, 572 { 1200, 1200, }, 573 { 2400, 2400, }, 574 { 4800, 4800, }, 575 { 9600, 9600, }, 576 { 19200, 19200, }, 577 { 38400, 38400, }, 578 { 51200, 51200, }, 579 { 76800, 76800, }, 580 { 20800, 20800, }, 581 { 31200, 31200, }, 582 { 41600, 41600, }, 583 { 62400, 62400, }, 584 { -1, -1 } 585}; 586static struct speedtab pc98fast_speedtab[] = { 587 { 9600, 0x80 | COMBRD(9600), }, 588 { 19200, 0x80 | COMBRD(19200), }, 589 { 38400, 0x80 | COMBRD(38400), }, 590 { 57600, 0x80 | COMBRD(57600), }, 591 { 115200, 0x80 | COMBRD(115200), }, 592 { -1, -1 } 593}; 594static struct speedtab comspeedtab_pio9032b[] = { 595 { 300, 6, }, 596 { 600, 5, }, 597 { 1200, 4, }, 598 { 2400, 3, }, 599 { 4800, 2, }, 600 { 9600, 1, }, 601 { 19200, 0, }, 602 { 38400, 7, }, 603 { -1, -1 } 604}; 605static struct speedtab comspeedtab_b98_01[] = { 606 { 75, 11, }, 607 { 150, 10, }, 608 { 300, 9, }, 609 { 600, 8, }, 610 { 1200, 7, }, 611 { 2400, 6, }, 612 { 4800, 5, }, 613 { 9600, 4, }, 614 { 19200, 3, }, 615 { 38400, 2, }, 616 { 76800, 1, }, 617 { 153600, 0, }, 618 { -1, -1 } 619}; 620static struct speedtab comspeedtab_mc16550[] = { 621 { 300, 1536, }, 622 { 600, 768, }, 623 { 1200, 384, }, 624 { 2400, 192, }, 625 { 4800, 96, }, 626 { 9600, 48, }, 627 { 19200, 24, }, 628 { 38400, 12, }, 629 { 57600, 8, }, 630 { 115200, 4, }, 631 { 153600, 3, }, 632 { 230400, 2, }, 633 { 460800, 1, }, 634 { -1, -1 } 635}; 636static struct speedtab comspeedtab_rsb384[] = { 637 { 300, 3840, }, 638 { 600, 1920, }, 639 { 1200, 960, }, 640 { 2400, 480, }, 641 { 4800, 240, }, 642 { 9600, 120, }, 643 { 19200, 60, }, 644 { 38400, 30, }, 645 { 57600, 20, }, 646 { 115200, 10, }, 647 { 128000, 9, }, 648 { 144000, 8, }, 649 { 192000, 6, }, 650 { 230400, 5, }, 651 { 288000, 4, }, 652 { 384000, 3, }, 653 { 576000, 2, }, 654 { 1152000, 1, }, 655 { -1, -1 } 656}; 657static struct speedtab comspeedtab_rsa[] = { 658 { 0, 0 }, 659 { 50, COMBRD_RSA(50) }, 660 { 75, COMBRD_RSA(75) }, 661 { 110, COMBRD_RSA(110) }, 662 { 134, COMBRD_RSA(134) }, 663 { 150, COMBRD_RSA(150) }, 664 { 200, COMBRD_RSA(200) }, 665 { 300, COMBRD_RSA(300) }, 666 { 600, COMBRD_RSA(600) }, 667 { 1200, COMBRD_RSA(1200) }, 668 { 1800, COMBRD_RSA(1800) }, 669 { 2400, COMBRD_RSA(2400) }, 670 { 4800, COMBRD_RSA(4800) }, 671 { 9600, COMBRD_RSA(9600) }, 672 { 19200, COMBRD_RSA(19200) }, 673 { 38400, COMBRD_RSA(38400) }, 674 { 57600, COMBRD_RSA(57600) }, 675 { 115200, COMBRD_RSA(115200) }, 676 { 230400, COMBRD_RSA(230400) }, 677 { 460800, COMBRD_RSA(460800) }, 678 { 921600, COMBRD_RSA(921600) }, 679 { -1, -1 } 680}; 681#endif /* PC98 */ 682 683static struct speedtab comspeedtab[] = { 684 { 0, 0 }, 685 { 50, COMBRD(50) }, 686 { 75, COMBRD(75) }, 687 { 110, COMBRD(110) }, 688 { 134, COMBRD(134) }, 689 { 150, COMBRD(150) }, 690 { 200, COMBRD(200) }, 691 { 300, COMBRD(300) }, 692 { 600, COMBRD(600) }, 693 { 1200, COMBRD(1200) }, 694 { 1800, COMBRD(1800) }, 695 { 2400, COMBRD(2400) }, 696 { 4800, COMBRD(4800) }, 697 { 9600, COMBRD(9600) }, 698 { 19200, COMBRD(19200) }, 699 { 38400, COMBRD(38400) }, 700 { 57600, COMBRD(57600) }, 701 { 115200, COMBRD(115200) }, 702 { -1, -1 } 703}; 704 705#ifdef PC98 706struct { 707 char *name; 708 short port_table[7]; 709 short irr_mask; 710 struct speedtab *speedtab; 711 short check_irq; 712} if_8251_type[] = { 713 /* COM_IF_INTERNAL */ 714 { " (internal)", {0x30, 0x32, 0x32, 0x33, 0x35, -1, -1}, 715 -1, pc98speedtab, 1 }, 716 /* COM_IF_PC9861K_1 */ 717 { " (PC9861K)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, -1, -1}, 718 3, NULL, 1 }, 719 /* COM_IF_PC9861K_2 */ 720 { " (PC9861K)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, -1, -1}, 721 3, NULL, 1 }, 722 /* COM_IF_IND_SS_1 */ 723 { " (IND-SS)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb3, -1}, 724 3, comspeedtab_mc16550, 1 }, 725 /* COM_IF_IND_SS_2 */ 726 { " (IND-SS)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xbb, -1}, 727 3, comspeedtab_mc16550, 1 }, 728 /* COM_IF_PIO9032B_1 */ 729 { " (PIO9032B)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb8, -1}, 730 7, comspeedtab_pio9032b, 1 }, 731 /* COM_IF_PIO9032B_2 */ 732 { " (PIO9032B)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xba, -1}, 733 7, comspeedtab_pio9032b, 1 }, 734 /* COM_IF_B98_01_1 */ 735 { " (B98-01)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xd1, 0xd3}, 736 7, comspeedtab_b98_01, 0 }, 737 /* COM_IF_B98_01_2 */ 738 { " (B98-01)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xd5, 0xd7}, 739 7, comspeedtab_b98_01, 0 }, 740}; 741#define PC98SIO_data_port(type) (if_8251_type[type].port_table[0]) 742#define PC98SIO_cmd_port(type) (if_8251_type[type].port_table[1]) 743#define PC98SIO_sts_port(type) (if_8251_type[type].port_table[2]) 744#define PC98SIO_in_modem_port(type) (if_8251_type[type].port_table[3]) 745#define PC98SIO_intr_ctrl_port(type) (if_8251_type[type].port_table[4]) 746#define PC98SIO_baud_rate_port(type) (if_8251_type[type].port_table[5]) 747#define PC98SIO_func_port(type) (if_8251_type[type].port_table[6]) 748 749struct { 750 char *name; 751 short irr_read; 752 short irr_write; 753 short port_shift; 754 short io_size; 755 struct speedtab *speedtab; 756} if_16550a_type[] = { 757 /* COM_IF_RSA98 */ 758 { " (RSA-98)", -1, -1, 0, IO_COMSIZE, comspeedtab }, 759 /* COM_IF_NS16550 */ 760 { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, 761 /* COM_IF_SECOND_CCU */ 762 { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, 763 /* COM_IF_MC16550II */ 764 { " (MC16550II)", -1, 0x1000, 8, 1, comspeedtab_mc16550 }, 765 /* COM_IF_MCRS98 */ 766 { " (MC-RS98)", -1, 0x1000, 8, 1, comspeedtab_mc16550 }, 767 /* COM_IF_RSB3000 */ 768 { " (RSB-3000)", 0xbf, -1, 1, 1, comspeedtab_rsb384 }, 769 /* COM_IF_RSB384 */ 770 { " (RSB-384)", 0xbf, -1, 1, 1, comspeedtab_rsb384 }, 771 /* COM_IF_MODEM_CARD */ 772 { "", -1, -1, 0, IO_COMSIZE, comspeedtab }, 773 /* COM_IF_RSA98III */ 774 { " (RSA-98III)", -1, -1, 0, 16, comspeedtab_rsa }, 775 /* COM_IF_ESP98 */ 776 { " (ESP98)", -1, -1, 1, 1, comspeedtab_mc16550 }, 777}; 778#endif /* PC98 */ 779 780#ifdef COM_ESP 781#ifdef PC98 782 783/* XXX configure this properly. */ 784static Port_t likely_com_ports[] = { 0, 0xb0, 0xb1, 0 }; 785static Port_t likely_esp_ports[] = { 0xc0d0, 0 }; 786 787#define ESP98_CMD1 (ESP_CMD1 * 0x100) 788#define ESP98_CMD2 (ESP_CMD2 * 0x100) 789#define ESP98_STATUS1 (ESP_STATUS1 * 0x100) 790#define ESP98_STATUS2 (ESP_STATUS2 * 0x100) 791 792#else /* PC98 */ 793 794/* XXX configure this properly. */ 795static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; 796static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; 797 798#endif /* PC98 */ 799#endif 800 801/* 802 * handle sysctl read/write requests for console speed 803 * 804 * In addition to setting comdefaultrate for I/O through /dev/console, 805 * also set the initial and lock values for the /dev/ttyXX device 806 * if there is one associated with the console. Finally, if the /dev/tty 807 * device has already been open, change the speed on the open running port 808 * itself. 809 */ 810 811static int 812sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS 813{ 814 int error, s; 815 speed_t newspeed; 816 struct com_s *com; 817 struct tty *tp; 818 819 newspeed = comdefaultrate; 820 821 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req); 822 if (error || !req->newptr) 823 return (error); 824 825 comdefaultrate = newspeed; 826 827 if (comconsole < 0) /* serial console not selected? */ 828 return (0); 829 830 com = com_addr(comconsole); 831 if (!com) 832 return (ENXIO); 833 834 /* 835 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX 836 * (note, the lock rates really are boolean -- if non-zero, disallow 837 * speed changes) 838 */ 839 com->it_in.c_ispeed = com->it_in.c_ospeed = 840 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 841 com->it_out.c_ispeed = com->it_out.c_ospeed = 842 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate; 843 844 /* 845 * if we're open, change the running rate too 846 */ 847 tp = com->tp; 848 if (tp && (tp->t_state & TS_ISOPEN)) { 849 tp->t_termios.c_ispeed = 850 tp->t_termios.c_ospeed = comdefaultrate; 851 s = spltty(); 852 error = comparam(tp, &tp->t_termios); 853 splx(s); 854 } 855 return error; 856} 857 858SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW, 859 0, 0, sysctl_machdep_comdefaultrate, "I", ""); 860 861#if NCARD > 0 862/* 863 * PC-Card (PCMCIA) specific code. 864 */ 865static int sioinit __P((struct pccard_devinfo *)); 866static void siounload __P((struct pccard_devinfo *)); 867static int card_intr __P((struct pccard_devinfo *)); 868 869PCCARD_MODULE(sio, sioinit, siounload, card_intr, 0, tty_imask); 870 871/* 872 * Initialize the device - called from Slot manager. 873 */ 874int 875sioinit(struct pccard_devinfo *devi) 876{ 877 878 /* validate unit number. */ 879 if (devi->isahd.id_unit >= (NSIOTOT)) 880 return(ENODEV); 881 /* Make sure it isn't already probed. */ 882 if (com_addr(devi->isahd.id_unit)) 883 return(EBUSY); 884 885 /* It's already probed as serial by Upper */ 886 devi->isahd.id_flags |= COM_C_NOPROBE; 887 888 /* 889 * attach the device. 890 */ 891 if (sioattach(devi->isahd.id_device) == 0) 892 return(ENXIO); 893 894 return(0); 895} 896 897/* 898 * siounload - unload the driver and clear the table. 899 * XXX TODO: 900 * This is usually called when the card is ejected, but 901 * can be caused by a modunload of a controller driver. 902 * The idea is to reset the driver's view of the device 903 * and ensure that any driver entry points such as 904 * read and write do not hang. 905 */ 906static void 907siounload(struct pccard_devinfo *devi) 908{ 909 struct com_s *com; 910 911 if (!devi) { 912 printf("NULL devi in siounload\n"); 913 return; 914 } 915 com = com_addr(devi->isahd.id_unit); 916 if (!com) { 917 printf("NULL com in siounload\n"); 918 return; 919 } 920 if (!com->iobase) { 921 printf("sio%d already unloaded!\n",devi->isahd.id_unit); 922 return; 923 } 924 if (com->tp && (com->tp->t_state & TS_ISOPEN)) { 925 com->gone = 1; 926 printf("sio%d: unload\n", devi->isahd.id_unit); 927 com->tp->t_gen++; 928 ttyclose(com->tp); 929 ttwakeup(com->tp); 930 ttwwakeup(com->tp); 931 } else { 932 if (com->ibuf != NULL) 933 free(com->ibuf, M_DEVBUF); 934 free(com, M_DEVBUF); 935 printf("sio%d: unload,gone\n", devi->isahd.id_unit); 936 } 937} 938 939/* 940 * card_intr - Shared interrupt called from 941 * front end of PC-Card handler. 942 */ 943static int 944card_intr(struct pccard_devinfo *devi) 945{ 946 struct com_s *com; 947 948 COM_LOCK(); 949 com = com_addr(devi->isahd.id_unit); 950 if (com && !com->gone) 951 siointr1(com_addr(devi->isahd.id_unit)); 952 COM_UNLOCK(); 953 return(1); 954} 955#endif /* NCARD > 0 */ 956 957#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit)) 958#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit)) 959 960static struct isa_pnp_id sio_ids[] = { 961 {0x0005d041, "Standard PC COM port"}, /* PNP0500 */ 962 {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */ 963 {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */ 964 {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */ 965 {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */ 966 {0x31307256, "USR3031"}, /* USR3031 */ 967 {0} 968}; 969 970static int 971sioprobe(dev) 972 device_t dev; 973{ 974 static bool_t already_init; 975 bool_t failures[10]; 976 int fn; 977 device_t idev; 978 Port_t iobase; 979 intrmask_t irqmap[4]; 980 intrmask_t irqs; 981 u_char mcr_image; 982 int result; 983 device_t xdev; 984 u_int flags = device_get_flags(dev); 985 int rid; 986 struct resource *port; 987#ifdef PC98 988 int irqout=0; 989 int tmp; 990 int port_shift = 0; 991 struct siodev iod; 992 Port_t rsabase = NULL; 993#endif 994 995 /* Check isapnp ids */ 996 if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO) 997 return (ENXIO); 998 999 rid = 0; 1000#ifdef PC98 1001 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1002 0, ~0, 1, RF_ACTIVE); /* XXX */ 1003#else 1004 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1005 0, ~0, IO_COMSIZE, RF_ACTIVE); 1006#endif 1007 if (!port) 1008 return ENXIO; 1009 1010 if (!already_init) { 1011 /* 1012 * Turn off MCR_IENABLE for all likely serial ports. An unused 1013 * port with its MCR_IENABLE gate open will inhibit interrupts 1014 * from any used port that shares the interrupt vector. 1015 * XXX the gate enable is elsewhere for some multiports. 1016 */ 1017 device_t *devs; 1018 int count, i; 1019 1020 devclass_get_devices(sio_devclass, &devs, &count); 1021#ifdef PC98 1022 for (i = 0; i < count; i++) { 1023 xdev = devs[i]; 1024 if (device_is_enabled(xdev)) { 1025 tmp = (flags >> 24) & 0xff; 1026 if (IS_8251(tmp)) 1027 outb((isa_get_port(xdev) & 0xff00) | PC98SIO_cmd_port(tmp & 0x0f), 0xf2); 1028 else 1029 if (tmp == COM_IF_RSA98III) { 1030 rsabase = isa_get_port(xdev) & 0xfff0; 1031 outb(isa_get_port(xdev) + 8 + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0); 1032 } else 1033 outb(isa_get_port(xdev) + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0); 1034 } 1035 } 1036#else 1037 for (i = 0; i < count; i++) { 1038 xdev = devs[i]; 1039 if (device_is_enabled(xdev)) 1040 outb(isa_get_port(xdev) + com_mcr, 0); 1041 } 1042#endif 1043 free(devs, M_TEMP); 1044 already_init = TRUE; 1045 } 1046 1047 if (COM_LLCONSOLE(flags)) { 1048 printf("sio%d: reserved for low-level i/o\n", 1049 device_get_unit(dev)); 1050 return (ENXIO); 1051 } 1052 1053#ifdef PC98 1054 DELAY(10); 1055 1056 /* 1057 * If the port is i8251 UART (internal, B98_01) 1058 */ 1059 if (pc98_check_if_type(dev, &iod) == -1) 1060 return ENXIO; 1061 if (iod.irq > 0) 1062 isa_set_irq(dev, iod.irq); 1063 if (IS_8251(iod.if_type)) { 1064 outb(iod.cmd, 0); 1065 DELAY(10); 1066 outb(iod.cmd, 0); 1067 DELAY(10); 1068 outb(iod.cmd, 0); 1069 DELAY(10); 1070 outb(iod.cmd, CMD8251_RESET); 1071 DELAY(1000); /* for a while...*/ 1072 outb(iod.cmd, 0xf2); /* MODE (dummy) */ 1073 DELAY(10); 1074 outb(iod.cmd, 0x01); /* CMD (dummy) */ 1075 DELAY(1000); /* for a while...*/ 1076 if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) { 1077 result = ENXIO; 1078 } 1079 if (if_8251_type[iod.if_type & 0x0f].check_irq) { 1080 COM_INT_DISABLE 1081 tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx)); 1082 outb( iod.ctrl, tmp|IEN_TxEMP ); 1083 DELAY(10); 1084 result = isa_irq_pending() ? 0 : ENXIO; 1085 outb( iod.ctrl, tmp ); 1086 COM_INT_ENABLE 1087 } else { 1088 /* 1089 * B98_01 doesn't activate TxEMP interrupt line 1090 * when being reset, so we can't check irq pending. 1091 */ 1092 result = 0; 1093 } 1094 if (epson_machine_id==0x20) { /* XXX */ 1095 result = 0; 1096 } 1097 bus_release_resource(dev, SYS_RES_IOPORT, rid, port); 1098 return result; 1099 } 1100#endif /* PC98 */ 1101 /* 1102 * If the device is on a multiport card and has an AST/4 1103 * compatible interrupt control register, initialize this 1104 * register and prepare to leave MCR_IENABLE clear in the mcr. 1105 * Otherwise, prepare to set MCR_IENABLE in the mcr. 1106 * Point idev to the device struct giving the correct id_irq. 1107 * This is the struct for the master device if there is one. 1108 */ 1109 idev = dev; 1110 mcr_image = MCR_IENABLE; 1111#ifdef PC98 1112 if (iod.if_type == COM_IF_RSA98III) { 1113 mcr_image = 0; 1114 rsabase = isa_get_port(idev) & 0xfff0; 1115 if (rsabase != isa_get_port(idev)) 1116 return(0); 1117 outb(rsabase + rsa_msr, 0x04); 1118 outb(rsabase + rsa_frr, 0x00); 1119 if ((inb(rsabase + rsa_srr) & 0x36) != 0x36) 1120 return (0); 1121 outb(rsabase + rsa_ier, 0x00); 1122 outb(rsabase + rsa_frr, 0x00); 1123 outb(rsabase + rsa_tivsr, 0x00); 1124 outb(rsabase + rsa_tcr, 0x00); 1125 } 1126#endif /* PC98 */ 1127#ifdef COM_MULTIPORT 1128 if (COM_ISMULTIPORT(flags)) { 1129 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags)); 1130 if (idev == NULL) { 1131 printf("sio%d: master device %d not configured\n", 1132 device_get_unit(dev), COM_MPMASTER(flags)); 1133 idev = dev; 1134 } 1135#ifndef PC98 1136 if (!COM_NOTAST4(flags)) { 1137 outb(isa_get_port(idev) + com_scr, 1138 isa_get_irq(idev) >= 0 ? 0x80 : 0); 1139 mcr_image = 0; 1140 } 1141#endif /* !PC98 */ 1142 } 1143#endif /* COM_MULTIPORT */ 1144 if (isa_get_irq(idev) < 0) 1145 mcr_image = 0; 1146 1147#ifdef PC98 1148 tmp = if_16550a_type[iod.if_type & 0x0f].irr_write; 1149 if (tmp != -1) { 1150 /* MC16550II */ 1151 switch (isa_get_irq(idev)) { 1152 case 3: irqout = 4; break; 1153 case 5: irqout = 5; break; 1154 case 6: irqout = 6; break; 1155 case 12: irqout = 7; break; 1156 default: 1157 printf("sio%d: irq configuration error\n", 1158 device_get_unit(dev)); 1159 return (0); 1160 } 1161 outb((isa_get_port(dev) & 0x00ff) | tmp, irqout); 1162 } 1163 port_shift = if_16550a_type[iod.if_type & 0x0f].port_shift; 1164#endif 1165 bzero(failures, sizeof failures); 1166 iobase = rman_get_start(port); 1167#ifdef PC98 1168 if (iod.if_type == COM_IF_RSA98III) 1169 iobase += 8; 1170#endif 1171 1172 /* 1173 * We don't want to get actual interrupts, just masked ones. 1174 * Interrupts from this line should already be masked in the ICU, 1175 * but mask them in the processor as well in case there are some 1176 * (misconfigured) shared interrupts. 1177 */ 1178 disable_intr(); 1179/* EXTRA DELAY? */ 1180 1181 /* 1182 * Initialize the speed and the word size and wait long enough to 1183 * drain the maximum of 16 bytes of junk in device output queues. 1184 * The speed is undefined after a master reset and must be set 1185 * before relying on anything related to output. There may be 1186 * junk after a (very fast) soft reboot and (apparently) after 1187 * master reset. 1188 * XXX what about the UART bug avoided by waiting in comparam()? 1189 * We don't want to to wait long enough to drain at 2 bps. 1190 */ 1191 if (iobase == siocniobase) 1192 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); 1193 else { 1194#ifdef PC98 1195 tmp = ttspeedtab(SIO_TEST_SPEED, 1196 if_16550a_type[iod.if_type & 0x0f].speedtab); 1197 outb(iobase + (com_cfcr << port_shift), CFCR_DLAB|CFCR_8BITS); 1198 outb(iobase + (com_dlbl << port_shift), tmp & 0xff); 1199 outb(iobase + (com_dlbh << port_shift), (tmp >> 8) & 0xff); 1200 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); 1201#else 1202 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 1203 outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff); 1204 outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8); 1205 outb(iobase + com_cfcr, CFCR_8BITS); 1206#endif 1207 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); 1208 } 1209 1210 /* 1211 * Enable the interrupt gate and disable device interupts. This 1212 * should leave the device driving the interrupt line low and 1213 * guarantee an edge trigger if an interrupt can be generated. 1214 */ 1215/* EXTRA DELAY? */ 1216#ifdef PC98 1217 outb(iobase + (com_mcr << port_shift), mcr_image); 1218 outb(iobase + (com_ier << port_shift), 0); 1219#else 1220 outb(iobase + com_mcr, mcr_image); 1221 outb(iobase + com_ier, 0); 1222#endif 1223 DELAY(1000); /* XXX */ 1224 irqmap[0] = isa_irq_pending(); 1225 1226 /* 1227 * Attempt to set loopback mode so that we can send a null byte 1228 * without annoying any external device. 1229 */ 1230/* EXTRA DELAY? */ 1231#ifdef PC98 1232 outb(iobase + (com_mcr << port_shift), mcr_image | MCR_LOOPBACK); 1233#else 1234 outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK); 1235#endif 1236 1237 /* 1238 * Attempt to generate an output interrupt. On 8250's, setting 1239 * IER_ETXRDY generates an interrupt independent of the current 1240 * setting and independent of whether the THR is empty. On 16450's, 1241 * setting IER_ETXRDY generates an interrupt independent of the 1242 * current setting. On 16550A's, setting IER_ETXRDY only 1243 * generates an interrupt when IER_ETXRDY is not already set. 1244 */ 1245#ifdef PC98 1246 outb(iobase + (com_ier << port_shift), IER_ETXRDY); 1247 if (iod.if_type == COM_IF_RSA98III) 1248 outb(rsabase + rsa_ier, 0x04); 1249#else 1250 outb(iobase + com_ier, IER_ETXRDY); 1251#endif /* PC98 */ 1252 1253 /* 1254 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate 1255 * an interrupt. They'd better generate one for actually doing 1256 * output. Loopback may be broken on the same incompatibles but 1257 * it's unlikely to do more than allow the null byte out. 1258 */ 1259#ifdef PC98 1260 outb(iobase + (com_data << port_shift), 0); 1261#else 1262 outb(iobase + com_data, 0); 1263#endif 1264 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); 1265 1266 /* 1267 * Turn off loopback mode so that the interrupt gate works again 1268 * (MCR_IENABLE was hidden). This should leave the device driving 1269 * an interrupt line high. It doesn't matter if the interrupt 1270 * line oscillates while we are not looking at it, since interrupts 1271 * are disabled. 1272 */ 1273/* EXTRA DELAY? */ 1274#ifdef PC98 1275 outb(iobase + (com_mcr << port_shift), mcr_image); 1276#else 1277 outb(iobase + com_mcr, mcr_image); 1278#endif /* PC98 */ 1279 1280 /* 1281 * It's a definitly Serial PCMCIA(16550A), but still be required 1282 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... ) 1283 */ 1284 if ( COM_NOPROBE(flags) ) { 1285 /* Reading IIR register twice */ 1286 for ( fn = 0; fn < 2; fn ++ ) { 1287 DELAY(10000); 1288#ifdef PC98 1289 failures[6] = inb(iobase + (com_iir << port_shift)); 1290#else 1291 failures[6] = inb(iobase + com_iir); 1292#endif 1293 } 1294 /* Check IIR_TXRDY clear ? */ 1295 result = 0; 1296 if ( failures[6] & IIR_TXRDY ) { 1297 /* Nop, Double check with clearing IER */ 1298#ifdef PC98 1299 outb(iobase + (com_ier << port_shift), 0); 1300 if (inb(iobase + 1301 (com_iir << port_shift)) & IIR_NOPEND) { 1302#else 1303 outb(iobase + com_ier, 0); 1304 if ( inb(iobase + com_iir) & IIR_NOPEND ) { 1305#endif 1306 /* Ok. we're familia this gang */ 1307 SET_FLAG(dev, COM_C_IIR_TXRDYBUG); /* Set IIR_TXRDYBUG */ 1308 } else { 1309 /* Unknown, Just omit this chip.. XXX */ 1310 result = ENXIO; 1311 } 1312 } else { 1313 /* OK. this is well-known guys */ 1314 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG); /*Clear IIR_TXRDYBUG*/ 1315 } 1316#ifdef PC98 1317 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); 1318#else 1319 outb(iobase + com_cfcr, CFCR_8BITS); 1320#endif 1321 enable_intr(); 1322 bus_release_resource(dev, SYS_RES_IOPORT, rid, port); 1323 return (iobase == siocniobase ? 0 : result); 1324 } 1325 1326 /* 1327 * Check that 1328 * o the CFCR, IER and MCR in UART hold the values written to them 1329 * (the values happen to be all distinct - this is good for 1330 * avoiding false positive tests from bus echoes). 1331 * o an output interrupt is generated and its vector is correct. 1332 * o the interrupt goes away when the IIR in the UART is read. 1333 */ 1334/* EXTRA DELAY? */ 1335#ifdef PC98 1336 failures[0] = inb(iobase + (com_cfcr << port_shift)) - CFCR_8BITS; 1337 failures[1] = inb(iobase + (com_ier << port_shift)) - IER_ETXRDY; 1338 failures[2] = inb(iobase + (com_mcr << port_shift)) - mcr_image; 1339#else 1340 failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS; 1341 failures[1] = inb(iobase + com_ier) - IER_ETXRDY; 1342 failures[2] = inb(iobase + com_mcr) - mcr_image; 1343#endif 1344 DELAY(10000); /* Some internal modems need this time */ 1345 irqmap[1] = isa_irq_pending(); 1346#ifdef PC98 1347 failures[4] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) 1348 - IIR_TXRDY; 1349 if (iod.if_type == COM_IF_RSA98III) 1350 inb(rsabase + rsa_srr); 1351#else 1352 failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY; 1353#endif 1354 DELAY(1000); /* XXX */ 1355 irqmap[2] = isa_irq_pending(); 1356#ifdef PC98 1357 failures[6] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) 1358 - IIR_NOPEND; 1359 if (iod.if_type == COM_IF_RSA98III) 1360 inb(rsabase + rsa_srr); 1361#else 1362 failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1363#endif 1364 1365 /* 1366 * Turn off all device interrupts and check that they go off properly. 1367 * Leave MCR_IENABLE alone. For ports without a master port, it gates 1368 * the OUT2 output of the UART to 1369 * the ICU input. Closing the gate would give a floating ICU input 1370 * (unless there is another device driving it) and spurious interrupts. 1371 * (On the system that this was first tested on, the input floats high 1372 * and gives a (masked) interrupt as soon as the gate is closed.) 1373 */ 1374#ifdef PC98 1375 outb(iobase + (com_ier << port_shift), 0); 1376 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS); 1377 failures[7] = inb(iobase + (com_ier << port_shift)); 1378 if (iod.if_type == COM_IF_RSA98III) 1379 outb(rsabase + rsa_ier, 0x00); 1380#else 1381 outb(iobase + com_ier, 0); 1382 outb(iobase + com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ 1383 failures[7] = inb(iobase + com_ier); 1384#endif 1385 DELAY(1000); /* XXX */ 1386 irqmap[3] = isa_irq_pending(); 1387#ifdef PC98 1388 failures[9] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK) 1389 - IIR_NOPEND; 1390 if (iod.if_type == COM_IF_RSA98III) { 1391 inb(rsabase + rsa_srr); 1392 outb(rsabase + rsa_frr, 0x00); 1393 } 1394#else 1395 failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1396#endif 1397 1398 enable_intr(); 1399 1400 irqs = irqmap[1] & ~irqmap[0]; 1401 if (isa_get_irq(idev) >= 0 && ((1 << isa_get_irq(idev)) & irqs) == 0) 1402 printf( 1403 "sio%d: configured irq %d not in bitmap of probed irqs %#x\n", 1404 device_get_unit(dev), isa_get_irq(idev), irqs); 1405 if (bootverbose) 1406 printf("sio%d: irq maps: %#x %#x %#x %#x\n", 1407 device_get_unit(dev), 1408 irqmap[0], irqmap[1], irqmap[2], irqmap[3]); 1409 1410 result = 0; 1411 for (fn = 0; fn < sizeof failures; ++fn) 1412 if (failures[fn]) { 1413#ifdef PC98 1414 outb(iobase + (com_mcr << port_shift), 0); 1415#else 1416 outb(iobase + com_mcr, 0); 1417#endif 1418 result = ENXIO; 1419 if (bootverbose) { 1420 printf("sio%d: probe failed test(s):", 1421 device_get_unit(dev)); 1422 for (fn = 0; fn < sizeof failures; ++fn) 1423 if (failures[fn]) 1424 printf(" %d", fn); 1425 printf("\n"); 1426 } 1427 break; 1428 } 1429 bus_release_resource(dev, SYS_RES_IOPORT, rid, port); 1430 return (iobase == siocniobase ? 0 : result); 1431} 1432 1433#ifdef COM_ESP 1434static int 1435espattach(com, esp_port) 1436 struct com_s *com; 1437 Port_t esp_port; 1438{ 1439 u_char dips; 1440 u_char val; 1441 1442 /* 1443 * Check the ESP-specific I/O port to see if we're an ESP 1444 * card. If not, return failure immediately. 1445 */ 1446 if ((inb(esp_port) & 0xf3) == 0) { 1447 printf(" port 0x%x is not an ESP board?\n", esp_port); 1448 return (0); 1449 } 1450 1451 /* 1452 * We've got something that claims to be a Hayes ESP card. 1453 * Let's hope so. 1454 */ 1455 1456 /* Get the dip-switch configuration */ 1457#ifdef PC98 1458 outb(esp_port + ESP98_CMD1, ESP_GETDIPS); 1459 dips = inb(esp_port + ESP98_STATUS1); 1460#else 1461 outb(esp_port + ESP_CMD1, ESP_GETDIPS); 1462 dips = inb(esp_port + ESP_STATUS1); 1463#endif 1464 1465 /* 1466 * Bits 0,1 of dips say which COM port we are. 1467 */ 1468#ifdef PC98 1469 if ((com->iobase & 0xff) == likely_com_ports[dips & 0x03]) 1470#else 1471 if (com->iobase == likely_com_ports[dips & 0x03]) 1472#endif 1473 printf(" : ESP"); 1474 else { 1475 printf(" esp_port has com %d\n", dips & 0x03); 1476 return (0); 1477 } 1478 1479 /* 1480 * Check for ESP version 2.0 or later: bits 4,5,6 = 010. 1481 */ 1482#ifdef PC98 1483 outb(esp_port + ESP98_CMD1, ESP_GETTEST); 1484 val = inb(esp_port + ESP98_STATUS1); /* clear reg 1 */ 1485 val = inb(esp_port + ESP98_STATUS2); 1486#else 1487 outb(esp_port + ESP_CMD1, ESP_GETTEST); 1488 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */ 1489 val = inb(esp_port + ESP_STATUS2); 1490#endif 1491 if ((val & 0x70) < 0x20) { 1492 printf("-old (%o)", val & 0x70); 1493 return (0); 1494 } 1495 1496 /* 1497 * Check for ability to emulate 16550: bit 7 == 1 1498 */ 1499 if ((dips & 0x80) == 0) { 1500 printf(" slave"); 1501 return (0); 1502 } 1503 1504 /* 1505 * Okay, we seem to be a Hayes ESP card. Whee. 1506 */ 1507 com->esp = TRUE; 1508 com->esp_port = esp_port; 1509 return (1); 1510} 1511#endif /* COM_ESP */ 1512 1513static int 1514sioattach(dev) 1515 device_t dev; 1516{ 1517 struct com_s *com; 1518#ifdef COM_ESP 1519 Port_t *espp; 1520#endif 1521 Port_t iobase; 1522 int unit; 1523 void *ih; 1524 u_int flags = device_get_flags(dev); 1525 int rid; 1526 struct resource *port; 1527#ifdef PC98 1528 int port_shift = 0; 1529 u_char *obuf; 1530 u_long obufsize; 1531#endif 1532 1533 rid = 0; 1534#ifdef PC98 1535 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1536 0, ~0, 1, RF_ACTIVE); /* XXX */ 1537#else 1538 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 1539 0, ~0, IO_COMSIZE, RF_ACTIVE); 1540#endif 1541 if (!port) 1542 return ENXIO; 1543 1544 iobase = rman_get_start(port); 1545#ifdef PC98 1546 if (((flags >> 24) & 0xff) == COM_IF_RSA98III) 1547 iobase += 8; 1548#endif 1549 unit = device_get_unit(dev); 1550 com = device_get_softc(dev); 1551#ifdef PC98 1552 obufsize = 256; 1553 if (((flags >> 24) & 0xff) == COM_IF_RSA98III) 1554 obufsize = 2048; 1555 if ((obuf = malloc(obufsize * 2, M_DEVBUF, M_NOWAIT)) == NULL) 1556 return (0); 1557 bzero(obuf, obufsize * 2); 1558#endif 1559 1560 /* 1561 * sioprobe() has initialized the device registers as follows: 1562 * o cfcr = CFCR_8BITS. 1563 * It is most important that CFCR_DLAB is off, so that the 1564 * data port is not hidden when we enable interrupts. 1565 * o ier = 0. 1566 * Interrupts are only enabled when the line is open. 1567 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible 1568 * interrupt control register or the config specifies no irq. 1569 * Keeping MCR_DTR and MCR_RTS off might stop the external 1570 * device from sending before we are ready. 1571 */ 1572 bzero(com, sizeof *com); 1573#ifdef PC98 1574 com->obufsize = obufsize; 1575 com->obuf1 = obuf; 1576 com->obuf2 = obuf + obufsize; 1577#endif 1578 com->unit = unit; 1579 com->ioportres = port; 1580 com->cfcr_image = CFCR_8BITS; 1581 com->dtr_wait = 3 * hz; 1582 com->loses_outints = COM_LOSESOUTINTS(flags) != 0; 1583 com->no_irq = isa_get_irq(dev) < 0; 1584 com->tx_fifo_size = 1; 1585 com->obufs[0].l_head = com->obuf1; 1586 com->obufs[1].l_head = com->obuf2; 1587 1588 com->iobase = iobase; 1589#ifdef PC98 1590 if (pc98_set_ioport(com, device_get_flags(dev)) == -1) { 1591 com->pc98_if_type = (device_get_flags(dev) >> 24) & 0xff; 1592 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 1593 com->data_port = iobase + (com_data << port_shift); 1594 com->int_id_port = iobase + (com_iir << port_shift); 1595 com->modem_ctl_port = iobase + (com_mcr << port_shift); 1596 com->mcr_image = inb(com->modem_ctl_port); 1597 com->line_status_port = iobase + (com_lsr << port_shift); 1598 com->modem_status_port = iobase + (com_msr << port_shift); 1599 com->intr_ctl_port = iobase + (com_ier << port_shift); 1600 } 1601#else /* not PC98 */ 1602 com->data_port = iobase + com_data; 1603 com->int_id_port = iobase + com_iir; 1604 com->modem_ctl_port = iobase + com_mcr; 1605 com->mcr_image = inb(com->modem_ctl_port); 1606 com->line_status_port = iobase + com_lsr; 1607 com->modem_status_port = iobase + com_msr; 1608 com->intr_ctl_port = iobase + com_ier; 1609#endif 1610 1611 /* 1612 * We don't use all the flags from <sys/ttydefaults.h> since they 1613 * are only relevant for logins. It's important to have echo off 1614 * initially so that the line doesn't start blathering before the 1615 * echo flag can be turned off. 1616 */ 1617 com->it_in.c_iflag = 0; 1618 com->it_in.c_oflag = 0; 1619 com->it_in.c_cflag = TTYDEF_CFLAG; 1620 com->it_in.c_lflag = 0; 1621 if (unit == comconsole) { 1622#ifdef PC98 1623 if (IS_8251(com->pc98_if_type)) 1624 DELAY(100000); 1625#endif 1626 com->it_in.c_iflag = TTYDEF_IFLAG; 1627 com->it_in.c_oflag = TTYDEF_OFLAG; 1628 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 1629 com->it_in.c_lflag = TTYDEF_LFLAG; 1630 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 1631 com->lt_out.c_ispeed = com->lt_out.c_ospeed = 1632 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 1633 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 1634 } else 1635 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; 1636 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 1637 enable_intr(); 1638 free(com, M_DEVBUF); 1639 return (0); 1640 } 1641 enable_intr(); 1642 termioschars(&com->it_in); 1643 com->it_out = com->it_in; 1644 1645 /* attempt to determine UART type */ 1646 printf("sio%d: type", unit); 1647 1648 1649#ifndef PC98 1650#ifdef COM_MULTIPORT 1651 if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags)) 1652#else 1653 if (!COM_IIR_TXRDYBUG(flags)) 1654#endif 1655 { 1656 u_char scr; 1657 u_char scr1; 1658 u_char scr2; 1659 1660 scr = inb(iobase + com_scr); 1661 outb(iobase + com_scr, 0xa5); 1662 scr1 = inb(iobase + com_scr); 1663 outb(iobase + com_scr, 0x5a); 1664 scr2 = inb(iobase + com_scr); 1665 outb(iobase + com_scr, scr); 1666 if (scr1 != 0xa5 || scr2 != 0x5a) { 1667 printf(" 8250"); 1668 goto determined_type; 1669 } 1670 } 1671#endif /* !PC98 */ 1672#ifdef PC98 1673 if (IS_8251(com->pc98_if_type)) { 1674 com_int_TxRx_disable( com ); 1675 com_cflag_and_speed_set( com, com->it_in.c_cflag, comdefaultrate ); 1676 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 1677 com_send_break_off( com ); 1678 printf(" 8251%s", if_8251_type[com->pc98_if_type & 0x0f].name); 1679 } else { 1680 outb(iobase + (com_fifo << port_shift), FIFO_ENABLE | FIFO_RX_HIGH); 1681#else 1682 outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); 1683#endif /* PC98 */ 1684 DELAY(100); 1685 com->st16650a = 0; 1686 switch (inb(com->int_id_port) & IIR_FIFO_MASK) { 1687 case FIFO_RX_LOW: 1688 printf(" 16450"); 1689 break; 1690 case FIFO_RX_MEDL: 1691 printf(" 16450?"); 1692 break; 1693 case FIFO_RX_MEDH: 1694 printf(" 16550?"); 1695 break; 1696 case FIFO_RX_HIGH: 1697 if (COM_NOFIFO(flags)) { 1698 printf(" 16550A fifo disabled"); 1699 } else { 1700 com->hasfifo = TRUE; 1701#ifdef PC98 1702 com->tx_fifo_size = 0; /* XXX flag conflicts. */ 1703 printf(" 16550A"); 1704#else 1705 if (COM_ST16650A(flags)) { 1706 com->st16650a = 1; 1707 com->tx_fifo_size = 32; 1708 printf(" ST16650A"); 1709 } else { 1710 com->tx_fifo_size = COM_FIFOSIZE(flags); 1711 printf(" 16550A"); 1712 } 1713#endif 1714 } 1715#ifdef PC98 1716 if (com->pc98_if_type == COM_IF_RSA98III) { 1717 com->tx_fifo_size = 2048; 1718 com->rsabase = isa_get_port(dev); 1719 outb(com->rsabase + rsa_ier, 0x00); 1720 outb(com->rsabase + rsa_frr, 0x00); 1721 } 1722#endif 1723 1724#ifdef COM_ESP 1725#ifdef PC98 1726 if (com->pc98_if_type == COM_IF_ESP98) 1727#endif 1728 for (espp = likely_esp_ports; *espp != 0; espp++) 1729 if (espattach(com, *espp)) { 1730 com->tx_fifo_size = 1024; 1731 break; 1732 } 1733#endif 1734 if (!com->st16650a) { 1735 if (!com->tx_fifo_size) 1736 com->tx_fifo_size = 16; 1737 else 1738 printf(" lookalike with %d bytes FIFO", 1739 com->tx_fifo_size); 1740 } 1741 1742 break; 1743 } 1744 1745#ifdef PC98 1746 if (com->pc98_if_type == COM_IF_RSB3000) { 1747 /* Set RSB-2000/3000 Extended Buffer mode. */ 1748 u_char lcr; 1749 lcr = inb(iobase + (com_cfcr << port_shift)); 1750 outb(iobase + (com_cfcr << port_shift), lcr | CFCR_DLAB); 1751 outb(iobase + (com_emr << port_shift), EMR_EXBUFF | EMR_EFMODE); 1752 outb(iobase + (com_cfcr << port_shift), lcr); 1753 } 1754#endif 1755 1756#ifdef COM_ESP 1757 if (com->esp) { 1758 /* 1759 * Set 16550 compatibility mode. 1760 * We don't use the ESP_MODE_SCALE bit to increase the 1761 * fifo trigger levels because we can't handle large 1762 * bursts of input. 1763 * XXX flow control should be set in comparam(), not here. 1764 */ 1765#ifdef PC98 1766 outb(com->esp_port + ESP98_CMD1, ESP_SETMODE); 1767 outb(com->esp_port + ESP98_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1768#else 1769 outb(com->esp_port + ESP_CMD1, ESP_SETMODE); 1770 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1771#endif 1772 1773 /* Set RTS/CTS flow control. */ 1774#ifdef PC98 1775 outb(com->esp_port + ESP98_CMD1, ESP_SETFLOWTYPE); 1776 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_RTS); 1777 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_CTS); 1778#else 1779 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); 1780 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS); 1781 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS); 1782#endif 1783 1784 /* Set flow-control levels. */ 1785#ifdef PC98 1786 outb(com->esp_port + ESP98_CMD1, ESP_SETRXFLOW); 1787 outb(com->esp_port + ESP98_CMD2, HIBYTE(768)); 1788 outb(com->esp_port + ESP98_CMD2, LOBYTE(768)); 1789 outb(com->esp_port + ESP98_CMD2, HIBYTE(512)); 1790 outb(com->esp_port + ESP98_CMD2, LOBYTE(512)); 1791#else 1792 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW); 1793 outb(com->esp_port + ESP_CMD2, HIBYTE(768)); 1794 outb(com->esp_port + ESP_CMD2, LOBYTE(768)); 1795 outb(com->esp_port + ESP_CMD2, HIBYTE(512)); 1796 outb(com->esp_port + ESP_CMD2, LOBYTE(512)); 1797#endif 1798 1799#ifdef PC98 1800 /* Set UART clock prescaler. */ 1801 outb(com->esp_port + ESP98_CMD1, ESP_SETCLOCK); 1802 outb(com->esp_port + ESP98_CMD2, 2); /* 4 times */ 1803#endif 1804 } 1805#endif /* COM_ESP */ 1806#ifdef PC98 1807 printf("%s", if_16550a_type[com->pc98_if_type & 0x0f].name); 1808 outb(iobase + (com_fifo << port_shift), 0); 1809#else 1810 outb(iobase + com_fifo, 0); 1811determined_type: ; 1812#endif 1813 1814#ifdef COM_MULTIPORT 1815 if (COM_ISMULTIPORT(flags)) { 1816 com->multiport = TRUE; 1817 printf(" (multiport"); 1818 if (unit == COM_MPMASTER(flags)) 1819 printf(" master"); 1820 printf(")"); 1821 com->no_irq = 1822 isa_get_irq(devclass_get_device 1823 (sio_devclass, COM_MPMASTER(flags))) < 0; 1824 } 1825#endif /* COM_MULTIPORT */ 1826#ifdef PC98 1827 } 1828#endif 1829 if (unit == comconsole) 1830 printf(", console"); 1831 if ( COM_IIR_TXRDYBUG(flags) ) 1832 printf(" with a bogus IIR_TXRDY register"); 1833 printf("\n"); 1834 1835 if (!sio_registered) { 1836 register_swi(SWI_TTY, siopoll); 1837 sio_registered = TRUE; 1838 } 1839 make_dev(&sio_cdevsw, unit, 1840 UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit); 1841 make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE, 1842 UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit); 1843 make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE, 1844 UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit); 1845 make_dev(&sio_cdevsw, unit | CALLOUT_MASK, 1846 UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit); 1847 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE, 1848 UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit); 1849 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE, 1850 UID_UUCP, GID_DIALER, 0660, "cuala%r", unit); 1851 com->flags = flags; 1852 com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 1853 pps_init(&com->pps); 1854 1855 rid = 0; 1856 com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, 1857 RF_SHAREABLE | RF_ACTIVE); 1858 BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres, 1859 INTR_TYPE_TTY | INTR_TYPE_FAST, 1860 siointr, com, &ih); 1861 1862 return (0); 1863} 1864 1865static int 1866sioopen(dev, flag, mode, p) 1867 dev_t dev; 1868 int flag; 1869 int mode; 1870 struct proc *p; 1871{ 1872 struct com_s *com; 1873 int error; 1874 Port_t iobase; 1875 int mynor; 1876 int s; 1877 struct tty *tp; 1878 int unit; 1879#ifdef PC98 1880 int port_shift = 0; 1881#endif 1882 1883 mynor = minor(dev); 1884 unit = MINOR_TO_UNIT(mynor); 1885 if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL) 1886 return (ENXIO); 1887 if (com->gone) 1888 return (ENXIO); 1889 if (mynor & CONTROL_MASK) 1890 return (0); 1891 tp = dev->si_tty = com->tp = ttymalloc(com->tp); 1892 s = spltty(); 1893 1894#ifdef PC98 1895 if (!IS_8251(com->pc98_if_type)) 1896 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 1897#endif 1898 /* 1899 * We jump to this label after all non-interrupted sleeps to pick 1900 * up any changes of the device state. 1901 */ 1902open_top: 1903 while (com->state & CS_DTR_OFF) { 1904 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0); 1905 if (com_addr(unit) == NULL) 1906 return (ENXIO); 1907 if (error != 0 || com->gone) 1908 goto out; 1909 } 1910 if (tp->t_state & TS_ISOPEN) { 1911 /* 1912 * The device is open, so everything has been initialized. 1913 * Handle conflicts. 1914 */ 1915 if (mynor & CALLOUT_MASK) { 1916 if (!com->active_out) { 1917 error = EBUSY; 1918 goto out; 1919 } 1920 } else { 1921 if (com->active_out) { 1922 if (flag & O_NONBLOCK) { 1923 error = EBUSY; 1924 goto out; 1925 } 1926 error = tsleep(&com->active_out, 1927 TTIPRI | PCATCH, "siobi", 0); 1928 if (com_addr(unit) == NULL) 1929 return (ENXIO); 1930 if (error != 0 || com->gone) 1931 goto out; 1932 goto open_top; 1933 } 1934 } 1935 if (tp->t_state & TS_XCLUDE && 1936 suser(p)) { 1937 error = EBUSY; 1938 goto out; 1939 } 1940 } else { 1941 /* 1942 * The device isn't open, so there are no conflicts. 1943 * Initialize it. Initialization is done twice in many 1944 * cases: to preempt sleeping callin opens if we are 1945 * callout, and to complete a callin open after DCD rises. 1946 */ 1947 tp->t_oproc = comstart;
|
2131 comhardclose(com); 2132 ttyclose(tp); 2133 siosettimeout(); 2134 splx(s); 2135 if (com->gone) { 2136 printf("sio%d: gone\n", com->unit); 2137 s = spltty(); 2138 if (com->ibuf != NULL) 2139 free(com->ibuf, M_DEVBUF); 2140 bzero(tp, sizeof *tp); 2141 free(com, M_DEVBUF); 2142 splx(s); 2143 } 2144 return (0); 2145} 2146 2147static void 2148comhardclose(com) 2149 struct com_s *com; 2150{ 2151 Port_t iobase; 2152 int s; 2153 struct tty *tp; 2154 int unit; 2155#ifdef PC98 2156 int port_shift = 0; 2157#endif 2158 2159 unit = com->unit; 2160 iobase = com->iobase; 2161 s = spltty(); 2162 com->poll = FALSE; 2163 com->poll_output = FALSE; 2164 com->do_timestamp = FALSE; 2165 com->do_dcd_timestamp = FALSE; 2166 com->pps.ppsparam.mode = 0; 2167#ifdef PC98 2168 if (IS_8251(com->pc98_if_type)) 2169 com_send_break_off(com); 2170 else { 2171 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 2172 outb(iobase + (com_cfcr << port_shift), 2173 com->cfcr_image &= ~CFCR_SBREAK); 2174 } 2175#else 2176 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2177#endif 2178 { 2179#ifdef PC98 2180 int tmp; 2181 if (IS_8251(com->pc98_if_type)) 2182 com_int_TxRx_disable(com); 2183 else 2184 outb(iobase + (com_ier << port_shift), 0); 2185 if (com->pc98_if_type == COM_IF_RSA98III) { 2186 outb(com->rsabase + rsa_ier, 0x00); 2187 } 2188#else 2189 outb(iobase + com_ier, 0); 2190#endif 2191 tp = com->tp; 2192#ifdef PC98 2193 if (IS_8251(com->pc98_if_type)) 2194 tmp = pc98_get_modem_status(com) & TIOCM_CAR; 2195 else 2196 tmp = com->prev_modem_status & MSR_DCD; 2197#endif 2198 if (tp->t_cflag & HUPCL 2199 /* 2200 * XXX we will miss any carrier drop between here and the 2201 * next open. Perhaps we should watch DCD even when the 2202 * port is closed; it is not sufficient to check it at 2203 * the next open because it might go up and down while 2204 * we're not watching. 2205 */ 2206 || (!com->active_out 2207#ifdef PC98 2208 && !(tmp) 2209#else 2210 && !(com->prev_modem_status & MSR_DCD) 2211#endif 2212 && !(com->it_in.c_cflag & CLOCAL)) 2213 || !(tp->t_state & TS_ISOPEN)) { 2214#ifdef PC98 2215 if (IS_8251(com->pc98_if_type)) 2216 com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); 2217 else 2218#endif 2219 (void)commctl(com, TIOCM_DTR, DMBIC); 2220 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 2221 timeout(siodtrwakeup, com, com->dtr_wait); 2222 com->state |= CS_DTR_OFF; 2223 } 2224 } 2225#ifdef PC98 2226 else { 2227 if (IS_8251(com->pc98_if_type)) 2228 com_tiocm_bic(com, TIOCM_LE ); 2229 } 2230#endif 2231 } 2232 if (com->hasfifo) { 2233 /* 2234 * Disable fifos so that they are off after controlled 2235 * reboots. Some BIOSes fail to detect 16550s when the 2236 * fifos are enabled. 2237 */ 2238#ifdef PC98 2239 outb(iobase + (com_fifo << port_shift), 0); 2240#else 2241 outb(iobase + com_fifo, 0); 2242#endif 2243 } 2244 com->active_out = FALSE; 2245 wakeup(&com->active_out); 2246 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 2247 splx(s); 2248} 2249 2250static int 2251sioread(dev, uio, flag) 2252 dev_t dev; 2253 struct uio *uio; 2254 int flag; 2255{ 2256 int mynor; 2257 struct com_s *com; 2258 2259 mynor = minor(dev); 2260 if (mynor & CONTROL_MASK) 2261 return (ENODEV); 2262 com = com_addr(MINOR_TO_UNIT(mynor)); 2263 if (com->gone) 2264 return (ENODEV); 2265 return ((*linesw[com->tp->t_line].l_read)(com->tp, uio, flag)); 2266} 2267 2268static int 2269siowrite(dev, uio, flag) 2270 dev_t dev; 2271 struct uio *uio; 2272 int flag; 2273{ 2274 int mynor; 2275 struct com_s *com; 2276 int unit; 2277 2278 mynor = minor(dev); 2279 if (mynor & CONTROL_MASK) 2280 return (ENODEV); 2281 2282 unit = MINOR_TO_UNIT(mynor); 2283 com = com_addr(unit); 2284 if (com->gone) 2285 return (ENODEV); 2286 /* 2287 * (XXX) We disallow virtual consoles if the physical console is 2288 * a serial port. This is in case there is a display attached that 2289 * is not the console. In that situation we don't need/want the X 2290 * server taking over the console. 2291 */ 2292 if (constty != NULL && unit == comconsole) 2293 constty = NULL; 2294 return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag)); 2295} 2296 2297static void 2298siobusycheck(chan) 2299 void *chan; 2300{ 2301 struct com_s *com; 2302 int s; 2303 2304 com = (struct com_s *)chan; 2305 2306 /* 2307 * Clear TS_BUSY if low-level output is complete. 2308 * spl locking is sufficient because siointr1() does not set CS_BUSY. 2309 * If siointr1() clears CS_BUSY after we look at it, then we'll get 2310 * called again. Reading the line status port outside of siointr1() 2311 * is safe because CS_BUSY is clear so there are no output interrupts 2312 * to lose. 2313 */ 2314 s = spltty(); 2315 if (com->state & CS_BUSY) 2316 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ 2317#ifdef PC98 2318 else if ((IS_8251(com->pc98_if_type) && 2319 (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP)) 2320 == (STS8251_TxRDY | STS8251_TxEMP)) || 2321 (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2322 == (LSR_TSRE | LSR_TXRDY)) { 2323#else 2324 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2325 == (LSR_TSRE | LSR_TXRDY)) { 2326#endif 2327 com->tp->t_state &= ~TS_BUSY; 2328 ttwwakeup(com->tp); 2329 com->extra_state &= ~CSE_BUSYCHECK; 2330 } else 2331 timeout(siobusycheck, com, hz / 100); 2332 splx(s); 2333} 2334 2335static void 2336siodtrwakeup(chan) 2337 void *chan; 2338{ 2339 struct com_s *com; 2340 2341 com = (struct com_s *)chan; 2342 com->state &= ~CS_DTR_OFF; 2343 wakeup(&com->dtr_wait); 2344} 2345 2346static void 2347sioinput(com) 2348 struct com_s *com; 2349{ 2350 u_char *buf; 2351 int incc; 2352 u_char line_status; 2353 int recv_data; 2354 struct tty *tp; 2355#ifdef PC98 2356 u_char tmp; 2357#endif 2358 2359 buf = com->ibuf; 2360 tp = com->tp; 2361 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) { 2362 com_events -= (com->iptr - com->ibuf); 2363 com->iptr = com->ibuf; 2364 return; 2365 } 2366 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2367 /* 2368 * Avoid the grotesquely inefficient lineswitch routine 2369 * (ttyinput) in "raw" mode. It usually takes about 450 2370 * instructions (that's without canonical processing or echo!). 2371 * slinput is reasonably fast (usually 40 instructions plus 2372 * call overhead). 2373 */ 2374 do { 2375 enable_intr(); 2376 incc = com->iptr - buf; 2377 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 2378 && (com->state & CS_RTS_IFLOW 2379 || tp->t_iflag & IXOFF) 2380 && !(tp->t_state & TS_TBLOCK)) 2381 ttyblock(tp); 2382 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2383 += b_to_q((char *)buf, incc, &tp->t_rawq); 2384 buf += incc; 2385 tk_nin += incc; 2386 tk_rawcc += incc; 2387 tp->t_rawcc += incc; 2388 ttwakeup(tp); 2389 if (tp->t_state & TS_TTSTOP 2390 && (tp->t_iflag & IXANY 2391 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2392 tp->t_state &= ~TS_TTSTOP; 2393 tp->t_lflag &= ~FLUSHO; 2394 comstart(tp); 2395 } 2396 disable_intr(); 2397 } while (buf < com->iptr); 2398 } else { 2399 do { 2400 enable_intr(); 2401 line_status = buf[com->ierroff]; 2402 recv_data = *buf++; 2403 if (line_status 2404 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2405 if (line_status & LSR_BI) 2406 recv_data |= TTY_BI; 2407 if (line_status & LSR_FE) 2408 recv_data |= TTY_FE; 2409 if (line_status & LSR_OE) 2410 recv_data |= TTY_OE; 2411 if (line_status & LSR_PE) 2412 recv_data |= TTY_PE; 2413 } 2414 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2415 disable_intr(); 2416 } while (buf < com->iptr); 2417 } 2418 com_events -= (com->iptr - com->ibuf); 2419 com->iptr = com->ibuf; 2420 2421 /* 2422 * There is now room for another low-level buffer full of input, 2423 * so enable RTS if it is now disabled and there is room in the 2424 * high-level buffer. 2425 */ 2426#ifdef PC98 2427 if (IS_8251(com->pc98_if_type)) 2428 tmp = com_tiocm_get(com) & TIOCM_RTS; 2429 else 2430 tmp = com->mcr_image & MCR_RTS; 2431 if ((com->state & CS_RTS_IFLOW) && !(tmp) && 2432 !(tp->t_state & TS_TBLOCK)) 2433 if (IS_8251(com->pc98_if_type)) 2434 com_tiocm_bis(com, TIOCM_RTS); 2435 else 2436 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2437#else 2438 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) && 2439 !(tp->t_state & TS_TBLOCK)) 2440 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2441#endif 2442} 2443 2444void 2445siointr(arg) 2446 void *arg; 2447{ 2448#ifndef COM_MULTIPORT 2449 COM_LOCK(); 2450 siointr1((struct com_s *) arg); 2451 COM_UNLOCK(); 2452#else /* COM_MULTIPORT */ 2453 bool_t possibly_more_intrs; 2454 int unit; 2455 struct com_s *com; 2456#ifdef PC98 2457 u_char rsa_buf_status; 2458#endif 2459 2460 /* 2461 * Loop until there is no activity on any port. This is necessary 2462 * to get an interrupt edge more than to avoid another interrupt. 2463 * If the IRQ signal is just an OR of the IRQ signals from several 2464 * devices, then the edge from one may be lost because another is 2465 * on. 2466 */ 2467 COM_LOCK(); 2468 do { 2469 possibly_more_intrs = FALSE; 2470 for (unit = 0; unit < NSIOTOT; ++unit) { 2471 com = com_addr(unit); 2472 /* 2473 * XXX COM_LOCK(); 2474 * would it work here, or be counter-productive? 2475 */ 2476#ifdef PC98 2477 if (com != NULL 2478 && !com->gone 2479 && IS_8251(com->pc98_if_type)){ 2480 siointr1(com); 2481 } else 2482#endif /* PC98 */ 2483#ifdef PC98 2484 if (com != NULL 2485 && !com->gone 2486 && com->pc98_if_type == COM_IF_RSA98III) { 2487 rsa_buf_status = inb(com->rsabase + rsa_srr) & 0xc9; 2488 if ((rsa_buf_status & 0xc8) 2489 || !(rsa_buf_status & 0x01)) { 2490 siointr1(com); 2491 if(rsa_buf_status 2492 != (inb(com->rsabase + rsa_srr) & 0xc9)) 2493 possibly_more_intrs = TRUE; 2494 } 2495 } else 2496#endif 2497 if (com != NULL 2498 && !com->gone 2499 && (inb(com->int_id_port) & IIR_IMASK) 2500 != IIR_NOPEND) { 2501 siointr1(com); 2502 possibly_more_intrs = TRUE; 2503 } 2504 /* XXX COM_UNLOCK(); */ 2505 } 2506 } while (possibly_more_intrs); 2507 COM_UNLOCK(); 2508#endif /* COM_MULTIPORT */ 2509} 2510 2511static void 2512siointr1(com) 2513 struct com_s *com; 2514{ 2515 u_char line_status; 2516 u_char modem_status; 2517 u_char *ioptr; 2518 u_char recv_data; 2519 u_char int_ctl; 2520 u_char int_ctl_new; 2521 struct timecounter *tc; 2522 u_int count; 2523 2524#ifdef PC98 2525 u_char tmp=0; 2526 u_char rsa_buf_status = 0; 2527 int rsa_tx_fifo_size=0; 2528 recv_data=0; 2529#endif /* PC98 */ 2530 2531 int_ctl = inb(com->intr_ctl_port); 2532 int_ctl_new = int_ctl; 2533 2534 while (!com->gone) { 2535#ifdef PC98 2536status_read:; 2537 if (IS_8251(com->pc98_if_type)) { 2538 tmp = inb(com->sts_port); 2539more_intr: 2540 line_status = 0; 2541 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 2542 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 2543 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 2544 if (tmp & STS8251_PE) line_status |= LSR_PE; 2545 if (tmp & STS8251_OE) line_status |= LSR_OE; 2546 if (tmp & STS8251_FE) line_status |= LSR_FE; 2547 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 2548 } else { 2549#endif /* PC98 */ 2550 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) { 2551 modem_status = inb(com->modem_status_port); 2552 if ((modem_status ^ com->last_modem_status) & MSR_DCD) { 2553 tc = timecounter; 2554 count = tc->tc_get_timecount(tc); 2555 pps_event(&com->pps, tc, count, 2556 (modem_status & MSR_DCD) ? 2557 PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 2558 } 2559 } 2560 line_status = inb(com->line_status_port); 2561#ifdef PC98 2562 } 2563 if (com->pc98_if_type == COM_IF_RSA98III) 2564 rsa_buf_status = inb(com->rsabase + rsa_srr); 2565#endif /* PC98 */ 2566 2567 /* input event? (check first to help avoid overruns) */ 2568#ifndef PC98 2569 while (line_status & LSR_RCV_MASK) { 2570#else 2571 while ((line_status & LSR_RCV_MASK) 2572 || (com->pc98_if_type == COM_IF_RSA98III 2573 && (rsa_buf_status & 0x08))) { 2574#endif /* PC98 */ 2575 /* break/unnattached error bits or real input? */ 2576#ifdef PC98 2577 if (IS_8251(com->pc98_if_type)) { 2578 recv_data = inb(com->data_port); 2579 if (tmp & 0x78) { 2580 pc98_i8251_or_cmd(com,CMD8251_ER); 2581 recv_data = 0; 2582 } 2583 } else { 2584#endif /* PC98 */ 2585#ifdef PC98 2586 if (com->pc98_if_type == COM_IF_RSA98III) { 2587 if (!(rsa_buf_status & 0x08)) 2588 recv_data = 0; 2589 else { 2590 recv_data = inb(com->data_port); 2591 } 2592 } else 2593#endif 2594 if (!(line_status & LSR_RXRDY)) 2595 recv_data = 0; 2596 else 2597 recv_data = inb(com->data_port); 2598#ifdef PC98 2599 } 2600#endif 2601 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 2602 /* 2603 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 2604 * Otherwise, push the work to a higher level 2605 * (to handle PARMRK) if we're bypassing. 2606 * Otherwise, convert BI/FE and PE+INPCK to 0. 2607 * 2608 * This makes bypassing work right in the 2609 * usual "raw" case (IGNBRK set, and IGNPAR 2610 * and INPCK clear). 2611 * 2612 * Note: BI together with FE/PE means just BI. 2613 */ 2614 if (line_status & LSR_BI) { 2615#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 2616 if (com->unit == comconsole) { 2617 breakpoint(); 2618 goto cont; 2619 } 2620#endif 2621 if (com->tp == NULL 2622 || com->tp->t_iflag & IGNBRK) 2623 goto cont; 2624 } else { 2625 if (com->tp == NULL 2626 || com->tp->t_iflag & IGNPAR) 2627 goto cont; 2628 } 2629 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 2630 && (line_status & (LSR_BI | LSR_FE) 2631 || com->tp->t_iflag & INPCK)) 2632 recv_data = 0; 2633 } 2634 ++com->bytes_in; 2635 if (com->hotchar != 0 && recv_data == com->hotchar) 2636 setsofttty(); 2637 ioptr = com->iptr; 2638 if (ioptr >= com->ibufend) 2639 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2640 else { 2641 if (com->do_timestamp) 2642 microtime(&com->timestamp); 2643 ++com_events; 2644 schedsofttty(); 2645#if 0 /* for testing input latency vs efficiency */ 2646if (com->iptr - com->ibuf == 8) 2647 setsofttty(); 2648#endif 2649 ioptr[0] = recv_data; 2650 ioptr[com->ierroff] = line_status; 2651 com->iptr = ++ioptr; 2652 if (ioptr == com->ihighwater 2653 && com->state & CS_RTS_IFLOW) 2654#ifdef PC98 2655 if (IS_8251(com->pc98_if_type)) 2656 com_tiocm_bic(com, TIOCM_RTS); 2657 else 2658#endif 2659 outb(com->modem_ctl_port, 2660 com->mcr_image &= ~MCR_RTS); 2661 if (line_status & LSR_OE) 2662 CE_RECORD(com, CE_OVERRUN); 2663 } 2664cont: 2665 /* 2666 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2667 * jump from the top of the loop to here 2668 */ 2669#ifdef PC98 2670 if (IS_8251(com->pc98_if_type)) 2671 goto status_read; 2672 else 2673#endif 2674 line_status = inb(com->line_status_port) & 0x7F; 2675#ifdef PC98 2676 if (com->pc98_if_type == COM_IF_RSA98III) 2677 rsa_buf_status = inb(com->rsabase + rsa_srr); 2678#endif /* PC98 */ 2679 } 2680 2681 /* modem status change? (always check before doing output) */ 2682#ifdef PC98 2683 if (!IS_8251(com->pc98_if_type)) { 2684#endif 2685 modem_status = inb(com->modem_status_port); 2686 if (modem_status != com->last_modem_status) { 2687 if (com->do_dcd_timestamp 2688 && !(com->last_modem_status & MSR_DCD) 2689 && modem_status & MSR_DCD) 2690 microtime(&com->dcd_timestamp); 2691 2692 /* 2693 * Schedule high level to handle DCD changes. Note 2694 * that we don't use the delta bits anywhere. Some 2695 * UARTs mess them up, and it's easy to remember the 2696 * previous bits and calculate the delta. 2697 */ 2698 com->last_modem_status = modem_status; 2699 if (!(com->state & CS_CHECKMSR)) { 2700 com_events += LOTS_OF_EVENTS; 2701 com->state |= CS_CHECKMSR; 2702 setsofttty(); 2703 } 2704 2705 /* handle CTS change immediately for crisp flow ctl */ 2706 if (com->state & CS_CTS_OFLOW) { 2707 if (modem_status & MSR_CTS) 2708 com->state |= CS_ODEVREADY; 2709 else 2710 com->state &= ~CS_ODEVREADY; 2711 } 2712 } 2713#ifdef PC98 2714 } 2715#endif 2716 2717 /* output queued and everything ready? */ 2718#ifndef PC98 2719 if (line_status & LSR_TXRDY 2720 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2721#else 2722 if (((com->pc98_if_type == COM_IF_RSA98III) 2723 ? (rsa_buf_status & 0x02) 2724 : (line_status & LSR_TXRDY)) 2725 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2726#endif 2727 ioptr = com->obufq.l_head; 2728 if (com->tx_fifo_size > 1) { 2729 u_int ocount; 2730 2731 ocount = com->obufq.l_tail - ioptr; 2732#ifdef PC98 2733 if (com->pc98_if_type == COM_IF_RSA98III) { 2734 rsa_buf_status = inb(com->rsabase + rsa_srr); 2735 rsa_tx_fifo_size = 1024; 2736 if (!(rsa_buf_status & 0x01)) 2737 rsa_tx_fifo_size = 2048; 2738 if (ocount > rsa_tx_fifo_size) 2739 ocount = rsa_tx_fifo_size; 2740 } else 2741#endif 2742 if (ocount > com->tx_fifo_size) 2743 ocount = com->tx_fifo_size; 2744 com->bytes_out += ocount; 2745 do 2746 outb(com->data_port, *ioptr++); 2747 while (--ocount != 0); 2748 } else { 2749 outb(com->data_port, *ioptr++); 2750 ++com->bytes_out; 2751 } 2752#ifdef PC98 2753 if (IS_8251(com->pc98_if_type)) 2754 if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG)) 2755 com_int_Tx_enable(com); 2756#endif 2757 com->obufq.l_head = ioptr; 2758 if (COM_IIR_TXRDYBUG(com->flags)) { 2759 int_ctl_new = int_ctl | IER_ETXRDY; 2760 } 2761 if (ioptr >= com->obufq.l_tail) { 2762 struct lbq *qp; 2763 2764 qp = com->obufq.l_next; 2765 qp->l_queued = FALSE; 2766 qp = qp->l_next; 2767 if (qp != NULL) { 2768 com->obufq.l_head = qp->l_head; 2769 com->obufq.l_tail = qp->l_tail; 2770 com->obufq.l_next = qp; 2771 } else { 2772 /* output just completed */ 2773 if ( COM_IIR_TXRDYBUG(com->flags) ) { 2774 int_ctl_new = int_ctl & ~IER_ETXRDY; 2775 } 2776 com->state &= ~CS_BUSY; 2777#if defined(PC98) 2778 if (IS_8251(com->pc98_if_type)) 2779 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2780 com_int_Tx_disable(com); 2781#endif 2782 } 2783 if (!(com->state & CS_ODONE)) { 2784 com_events += LOTS_OF_EVENTS; 2785 com->state |= CS_ODONE; 2786 setsofttty(); /* handle at high level ASAP */ 2787 } 2788 } 2789 if ( COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) { 2790#ifdef PC98 2791 if (com->pc98_if_type == COM_IF_RSA98III) { 2792 int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY); 2793 outb(com->intr_ctl_port, int_ctl_new); 2794 outb(com->rsabase + rsa_ier, 0x1d); 2795 } else 2796#endif 2797 outb(com->intr_ctl_port, int_ctl_new); 2798 } 2799 } 2800#ifdef PC98 2801 else if (line_status & LSR_TXRDY) { 2802 if (IS_8251(com->pc98_if_type)) 2803 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2804 com_int_Tx_disable(com); 2805 } 2806 if (IS_8251(com->pc98_if_type)) 2807 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2808 goto more_intr; 2809#endif 2810 2811 /* finished? */ 2812#ifndef COM_MULTIPORT 2813#ifdef PC98 2814 if (IS_8251(com->pc98_if_type)) 2815 return; 2816#endif 2817 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2818#endif /* COM_MULTIPORT */ 2819 return; 2820 } 2821} 2822 2823static int 2824sioioctl(dev, cmd, data, flag, p) 2825 dev_t dev; 2826 u_long cmd; 2827 caddr_t data; 2828 int flag; 2829 struct proc *p; 2830{ 2831 struct com_s *com; 2832 int error; 2833 Port_t iobase; 2834 int mynor; 2835 int s; 2836 struct tty *tp; 2837#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2838 u_long oldcmd; 2839 struct termios term; 2840#endif 2841 2842 mynor = minor(dev); 2843 com = com_addr(MINOR_TO_UNIT(mynor)); 2844 if (com->gone) 2845 return (ENODEV); 2846 iobase = com->iobase; 2847 if (mynor & CONTROL_MASK) { 2848 struct termios *ct; 2849 2850 switch (mynor & CONTROL_MASK) { 2851 case CONTROL_INIT_STATE: 2852 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2853 break; 2854 case CONTROL_LOCK_STATE: 2855 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2856 break; 2857 default: 2858 return (ENODEV); /* /dev/nodev */ 2859 } 2860 switch (cmd) { 2861 case TIOCSETA: 2862 error = suser(p); 2863 if (error != 0) 2864 return (error); 2865 *ct = *(struct termios *)data; 2866 return (0); 2867 case TIOCGETA: 2868 *(struct termios *)data = *ct; 2869 return (0); 2870 case TIOCGETD: 2871 *(int *)data = TTYDISC; 2872 return (0); 2873 case TIOCGWINSZ: 2874 bzero(data, sizeof(struct winsize)); 2875 return (0); 2876 default: 2877 return (ENOTTY); 2878 } 2879 } 2880 tp = com->tp; 2881#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2882 term = tp->t_termios; 2883 oldcmd = cmd; 2884 error = ttsetcompat(tp, &cmd, data, &term); 2885 if (error != 0) 2886 return (error); 2887 if (cmd != oldcmd) 2888 data = (caddr_t)&term; 2889#endif 2890 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2891 int cc; 2892 struct termios *dt = (struct termios *)data; 2893 struct termios *lt = mynor & CALLOUT_MASK 2894 ? &com->lt_out : &com->lt_in; 2895 2896 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2897 | (dt->c_iflag & ~lt->c_iflag); 2898 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2899 | (dt->c_oflag & ~lt->c_oflag); 2900 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2901 | (dt->c_cflag & ~lt->c_cflag); 2902 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2903 | (dt->c_lflag & ~lt->c_lflag); 2904 for (cc = 0; cc < NCCS; ++cc) 2905 if (lt->c_cc[cc] != 0) 2906 dt->c_cc[cc] = tp->t_cc[cc]; 2907 if (lt->c_ispeed != 0) 2908 dt->c_ispeed = tp->t_ispeed; 2909 if (lt->c_ospeed != 0) 2910 dt->c_ospeed = tp->t_ospeed; 2911 } 2912 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2913 if (error != ENOIOCTL) 2914 return (error); 2915 s = spltty(); 2916 error = ttioctl(tp, cmd, data, flag); 2917 disc_optim(tp, &tp->t_termios, com); 2918 if (error != ENOIOCTL) { 2919 splx(s); 2920 return (error); 2921 } 2922#ifdef PC98 2923 if (IS_8251(com->pc98_if_type)) { 2924 switch (cmd) { 2925 case TIOCSBRK: 2926 com_send_break_on( com ); 2927 break; 2928 case TIOCCBRK: 2929 com_send_break_off( com ); 2930 break; 2931 case TIOCSDTR: 2932 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2933 break; 2934 case TIOCCDTR: 2935 com_tiocm_bic(com, TIOCM_DTR); 2936 break; 2937 /* 2938 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2939 * changes get undone on the next call to comparam(). 2940 */ 2941 case TIOCMSET: 2942 com_tiocm_set( com, *(int *)data ); 2943 break; 2944 case TIOCMBIS: 2945 com_tiocm_bis( com, *(int *)data ); 2946 break; 2947 case TIOCMBIC: 2948 com_tiocm_bic( com, *(int *)data ); 2949 break; 2950 case TIOCMGET: 2951 *(int *)data = com_tiocm_get(com); 2952 break; 2953 case TIOCMSDTRWAIT: 2954 /* must be root since the wait applies to following logins */ 2955 error = suser(p); 2956 if (error != 0) { 2957 splx(s); 2958 return (error); 2959 } 2960 com->dtr_wait = *(int *)data * hz / 100; 2961 break; 2962 case TIOCMGDTRWAIT: 2963 *(int *)data = com->dtr_wait * 100 / hz; 2964 break; 2965 case TIOCTIMESTAMP: 2966 com->do_timestamp = TRUE; 2967 *(struct timeval *)data = com->timestamp; 2968 break; 2969 case TIOCDCDTIMESTAMP: 2970 com->do_dcd_timestamp = TRUE; 2971 *(struct timeval *)data = com->dcd_timestamp; 2972 break; 2973 default: 2974 splx(s); 2975 return (ENOTTY); 2976 } 2977 } else { 2978 int port_shift; 2979 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 2980#endif 2981 switch (cmd) { 2982 case TIOCSBRK: 2983#ifdef PC98 2984 outb(iobase + (com_cfcr << port_shift), 2985 com->cfcr_image |= CFCR_SBREAK); 2986#else 2987 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2988#endif 2989 break; 2990 case TIOCCBRK: 2991#ifdef PC98 2992 outb(iobase + (com_cfcr << port_shift), 2993 com->cfcr_image &= ~CFCR_SBREAK); 2994#else 2995 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2996#endif 2997 break; 2998 case TIOCSDTR: 2999 (void)commctl(com, TIOCM_DTR, DMBIS); 3000 break; 3001 case TIOCCDTR: 3002 (void)commctl(com, TIOCM_DTR, DMBIC); 3003 break; 3004 /* 3005 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 3006 * changes get undone on the next call to comparam(). 3007 */ 3008 case TIOCMSET: 3009 (void)commctl(com, *(int *)data, DMSET); 3010 break; 3011 case TIOCMBIS: 3012 (void)commctl(com, *(int *)data, DMBIS); 3013 break; 3014 case TIOCMBIC: 3015 (void)commctl(com, *(int *)data, DMBIC); 3016 break; 3017 case TIOCMGET: 3018 *(int *)data = commctl(com, 0, DMGET); 3019 break; 3020 case TIOCMSDTRWAIT: 3021 /* must be root since the wait applies to following logins */ 3022 error = suser(p); 3023 if (error != 0) { 3024 splx(s); 3025 return (error); 3026 } 3027 com->dtr_wait = *(int *)data * hz / 100; 3028 break; 3029 case TIOCMGDTRWAIT: 3030 *(int *)data = com->dtr_wait * 100 / hz; 3031 break; 3032 case TIOCTIMESTAMP: 3033 com->do_timestamp = TRUE; 3034 *(struct timeval *)data = com->timestamp; 3035 break; 3036 case TIOCDCDTIMESTAMP: 3037 com->do_dcd_timestamp = TRUE; 3038 *(struct timeval *)data = com->dcd_timestamp; 3039 break; 3040 default: 3041 splx(s); 3042 error = pps_ioctl(cmd, data, &com->pps); 3043 if (error == ENODEV) 3044 error = ENOTTY; 3045 return (error); 3046 } 3047#ifdef PC98 3048 } 3049#endif 3050 splx(s); 3051 return (0); 3052} 3053 3054static void 3055siopoll() 3056{ 3057 int unit; 3058 3059 if (com_events == 0) 3060 return; 3061repeat: 3062 for (unit = 0; unit < NSIOTOT; ++unit) { 3063 struct com_s *com; 3064 int incc; 3065 struct tty *tp; 3066 3067 com = com_addr(unit); 3068 if (com == NULL) 3069 continue; 3070 tp = com->tp; 3071 if (tp == NULL || com->gone) { 3072 /* 3073 * Discard any events related to never-opened or 3074 * going-away devices. 3075 */ 3076 disable_intr(); 3077 incc = com->iptr - com->ibuf; 3078 com->iptr = com->ibuf; 3079 if (com->state & CS_CHECKMSR) { 3080 incc += LOTS_OF_EVENTS; 3081 com->state &= ~CS_CHECKMSR; 3082 } 3083 com_events -= incc; 3084 enable_intr(); 3085 continue; 3086 } 3087 if (com->iptr != com->ibuf) { 3088 disable_intr(); 3089 sioinput(com); 3090 enable_intr(); 3091 } 3092 if (com->state & CS_CHECKMSR) { 3093 u_char delta_modem_status; 3094 3095#ifdef PC98 3096 if (!IS_8251(com->pc98_if_type)) { 3097#endif 3098 disable_intr(); 3099 delta_modem_status = com->last_modem_status 3100 ^ com->prev_modem_status; 3101 com->prev_modem_status = com->last_modem_status; 3102 com_events -= LOTS_OF_EVENTS; 3103 com->state &= ~CS_CHECKMSR; 3104 enable_intr(); 3105 if (delta_modem_status & MSR_DCD) 3106 (*linesw[tp->t_line].l_modem) 3107 (tp, com->prev_modem_status & MSR_DCD); 3108#ifdef PC98 3109 } 3110#endif 3111 } 3112 if (com->state & CS_ODONE) { 3113 disable_intr(); 3114 com_events -= LOTS_OF_EVENTS; 3115 com->state &= ~CS_ODONE; 3116 enable_intr(); 3117 if (!(com->state & CS_BUSY) 3118 && !(com->extra_state & CSE_BUSYCHECK)) { 3119 timeout(siobusycheck, com, hz / 100); 3120 com->extra_state |= CSE_BUSYCHECK; 3121 } 3122 (*linesw[tp->t_line].l_start)(tp); 3123 } 3124 if (com_events == 0) 3125 break; 3126 } 3127 if (com_events >= LOTS_OF_EVENTS) 3128 goto repeat; 3129} 3130 3131static int 3132comparam(tp, t) 3133 struct tty *tp; 3134 struct termios *t; 3135{ 3136 u_int cfcr; 3137 int cflag; 3138 struct com_s *com; 3139 int divisor; 3140 u_char dlbh; 3141 u_char dlbl; 3142 Port_t iobase; 3143 int s; 3144 int unit; 3145#ifdef PC98 3146 int port_shift = 0; 3147 u_char param = 0; 3148#endif 3149 3150#ifdef PC98 3151 cfcr = 0; 3152 unit = DEV_TO_UNIT(tp->t_dev); 3153 com = com_addr(unit); 3154 iobase = com->iobase; 3155 if (IS_8251(com->pc98_if_type)) { 3156 divisor = pc98_ttspeedtab(com, t->c_ospeed); 3157 } else { 3158 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 3159 3160 /* do historical conversions */ 3161 if (t->c_ispeed == 0) 3162 t->c_ispeed = t->c_ospeed; 3163 3164 /* check requested parameters */ 3165 divisor = ttspeedtab(t->c_ospeed, 3166 if_16550a_type[com->pc98_if_type & 0x0f].speedtab); 3167 } 3168#else 3169 /* do historical conversions */ 3170 if (t->c_ispeed == 0) 3171 t->c_ispeed = t->c_ospeed; 3172 3173 /* check requested parameters */ 3174 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 3175#endif 3176 if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed)) 3177 return (EINVAL); 3178 3179 /* parameters are OK, convert them to the com struct and the device */ 3180#ifndef PC98 3181 unit = DEV_TO_UNIT(tp->t_dev); 3182 com = com_addr(unit); 3183 iobase = com->iobase; 3184#endif 3185 s = spltty(); 3186#ifdef PC98 3187 if (IS_8251(com->pc98_if_type)) { 3188 if (divisor == 0) 3189 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3190 else 3191 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3192 } else { 3193#endif 3194 if (divisor == 0) 3195 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 3196 else 3197 (void)commctl(com, TIOCM_DTR, DMBIS); 3198#ifdef PC98 3199 } 3200#endif 3201 cflag = t->c_cflag; 3202#ifdef PC98 3203 if (!IS_8251(com->pc98_if_type)) { 3204#endif 3205 switch (cflag & CSIZE) { 3206 case CS5: 3207 cfcr = CFCR_5BITS; 3208 break; 3209 case CS6: 3210 cfcr = CFCR_6BITS; 3211 break; 3212 case CS7: 3213 cfcr = CFCR_7BITS; 3214 break; 3215 default: 3216 cfcr = CFCR_8BITS; 3217 break; 3218 } 3219 if (cflag & PARENB) { 3220 cfcr |= CFCR_PENAB; 3221 if (!(cflag & PARODD)) 3222 cfcr |= CFCR_PEVEN; 3223 } 3224 if (cflag & CSTOPB) 3225 cfcr |= CFCR_STOPB; 3226 3227 if (com->hasfifo && divisor != 0) { 3228 /* 3229 * Use a fifo trigger level low enough so that the input 3230 * latency from the fifo is less than about 16 msec and 3231 * the total latency is less than about 30 msec. These 3232 * latencies are reasonable for humans. Serial comms 3233 * protocols shouldn't expect anything better since modem 3234 * latencies are larger. 3235 */ 3236 com->fifo_image = t->c_ospeed <= 4800 3237 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 3238#ifdef COM_ESP 3239 /* 3240 * The Hayes ESP card needs the fifo DMA mode bit set 3241 * in compatibility mode. If not, it will interrupt 3242 * for each character received. 3243 */ 3244 if (com->esp) 3245 com->fifo_image |= FIFO_DMA_MODE; 3246#endif 3247#ifdef PC98 3248 outb(iobase + (com_fifo << port_shift), com->fifo_image); 3249#else 3250 outb(iobase + com_fifo, com->fifo_image); 3251#endif 3252 } 3253#ifdef PC98 3254 } 3255#endif 3256 3257 /* 3258 * This returns with interrupts disabled so that we can complete 3259 * the speed change atomically. Keeping interrupts disabled is 3260 * especially important while com_data is hidden. 3261 */ 3262 (void) siosetwater(com, t->c_ispeed); 3263 3264#ifdef PC98 3265 if (IS_8251(com->pc98_if_type)) 3266 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 3267 else { 3268#endif 3269 if (divisor != 0) { 3270#ifdef PC98 3271 outb(iobase + (com_cfcr << port_shift), cfcr | CFCR_DLAB); 3272#else 3273 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 3274#endif 3275 /* 3276 * Only set the divisor registers if they would change, 3277 * since on some 16550 incompatibles (UMC8669F), setting 3278 * them while input is arriving them loses sync until 3279 * data stops arriving. 3280 */ 3281 dlbl = divisor & 0xFF; 3282#ifdef PC98 3283 if (inb(iobase + (com_dlbl << port_shift)) != dlbl) 3284 outb(iobase + (com_dlbl << port_shift), dlbl); 3285 dlbh = (u_int) divisor >> 8; 3286 if (inb(iobase + (com_dlbh << port_shift)) != dlbh) 3287 outb(iobase + (com_dlbh << port_shift), dlbh); 3288#else 3289 if (inb(iobase + com_dlbl) != dlbl) 3290 outb(iobase + com_dlbl, dlbl); 3291 dlbh = (u_int) divisor >> 8; 3292 if (inb(iobase + com_dlbh) != dlbh) 3293 outb(iobase + com_dlbh, dlbh); 3294#endif 3295 } 3296 3297 3298#ifdef PC98 3299 } 3300 outb(iobase + (com_cfcr << port_shift), com->cfcr_image = cfcr); 3301#else 3302 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 3303#endif 3304 3305 if (!(tp->t_state & TS_TTSTOP)) 3306 com->state |= CS_TTGO; 3307 3308 if (cflag & CRTS_IFLOW) { 3309 if (com->st16650a) { 3310 outb(iobase + com_cfcr, 0xbf); 3311 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 3312 } 3313 com->state |= CS_RTS_IFLOW; 3314 /* 3315 * If CS_RTS_IFLOW just changed from off to on, the change 3316 * needs to be propagated to MCR_RTS. This isn't urgent, 3317 * so do it later by calling comstart() instead of repeating 3318 * a lot of code from comstart() here. 3319 */ 3320 } else if (com->state & CS_RTS_IFLOW) { 3321 com->state &= ~CS_RTS_IFLOW; 3322 /* 3323 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 3324 * on here, since comstart() won't do it later. 3325 */ 3326#ifdef PC98 3327 if (IS_8251(com->pc98_if_type)) 3328 com_tiocm_bis(com, TIOCM_RTS); 3329 else 3330#endif 3331 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3332 if (com->st16650a) { 3333 outb(iobase + com_cfcr, 0xbf); 3334 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 3335 } 3336 } 3337 3338 3339 /* 3340 * Set up state to handle output flow control. 3341 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 3342 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 3343 */ 3344 com->state |= CS_ODEVREADY; 3345 com->state &= ~CS_CTS_OFLOW; 3346#ifdef PC98 3347 if (com->pc98_if_type == COM_IF_RSA98III) { 3348 param = inb(com->rsabase + rsa_msr); 3349 outb(com->rsabase + rsa_msr, param & 0x14); 3350 } 3351#endif 3352 if (cflag & CCTS_OFLOW) { 3353 com->state |= CS_CTS_OFLOW; 3354#ifdef PC98 3355 if (IS_8251(com->pc98_if_type)) { 3356 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 3357 com->state &= ~CS_ODEVREADY; 3358 } else { 3359#endif 3360#ifdef PC98 3361 if (com->pc98_if_type == COM_IF_RSA98III) { 3362 /* Set automatic flow control mode */ 3363 outb(com->rsabase + rsa_msr, param | 0x08); 3364 } else 3365#endif 3366 if (!(com->last_modem_status & MSR_CTS)) 3367 com->state &= ~CS_ODEVREADY; 3368 if (com->st16650a) { 3369 outb(iobase + com_cfcr, 0xbf); 3370 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 3371 } 3372#ifdef PC98 3373 } 3374#endif 3375 } else { 3376 if (com->st16650a) { 3377 outb(iobase + com_cfcr, 0xbf); 3378 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 3379 } 3380 } 3381 3382 3383#ifdef PC98 3384 outb(iobase + (com_cfcr << port_shift), com->cfcr_image); 3385#else 3386 outb(iobase + com_cfcr, com->cfcr_image); 3387#endif 3388 3389 3390 /* XXX shouldn't call functions while intrs are disabled. */ 3391 disc_optim(tp, t, com); 3392 /* 3393 * Recover from fiddling with CS_TTGO. We used to call siointr1() 3394 * unconditionally, but that defeated the careful discarding of 3395 * stale input in sioopen(). 3396 */ 3397 if (com->state >= (CS_BUSY | CS_TTGO)) 3398 siointr1(com); 3399 3400 enable_intr(); 3401 splx(s); 3402 comstart(tp); 3403 if (com->ibufold != NULL) { 3404 free(com->ibufold, M_DEVBUF); 3405 com->ibufold = NULL; 3406 } 3407 return (0); 3408} 3409 3410static int 3411siosetwater(com, speed) 3412 struct com_s *com; 3413 speed_t speed; 3414{ 3415 int cp4ticks; 3416 u_char *ibuf; 3417 int ibufsize; 3418 struct tty *tp; 3419 3420 /* 3421 * Make the buffer size large enough to handle a softtty interrupt 3422 * latency of about 2 ticks without loss of throughput or data 3423 * (about 3 ticks if input flow control is not used or not honoured, 3424 * but a bit less for CS5-CS7 modes). 3425 */ 3426 cp4ticks = speed / 10 / hz * 4; 3427 for (ibufsize = 128; ibufsize < cp4ticks;) 3428 ibufsize <<= 1; 3429#ifdef PC98 3430 if (com->pc98_if_type == COM_IF_RSA98III) 3431 ibufsize = 2048; 3432#endif 3433 if (ibufsize == com->ibufsize) { 3434 disable_intr(); 3435 return (0); 3436 } 3437 3438 /* 3439 * Allocate input buffer. The extra factor of 2 in the size is 3440 * to allow for an error byte for each input byte. 3441 */ 3442 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 3443 if (ibuf == NULL) { 3444 disable_intr(); 3445 return (ENOMEM); 3446 } 3447 3448 /* Initialize non-critical variables. */ 3449 com->ibufold = com->ibuf; 3450 com->ibufsize = ibufsize; 3451 tp = com->tp; 3452 if (tp != NULL) { 3453 tp->t_ififosize = 2 * ibufsize; 3454 tp->t_ispeedwat = (speed_t)-1; 3455 tp->t_ospeedwat = (speed_t)-1; 3456 } 3457 3458 /* 3459 * Read current input buffer, if any. Continue with interrupts 3460 * disabled. 3461 */ 3462 disable_intr(); 3463 if (com->iptr != com->ibuf) 3464 sioinput(com); 3465 3466 /*- 3467 * Initialize critical variables, including input buffer watermarks. 3468 * The external device is asked to stop sending when the buffer 3469 * exactly reaches high water, or when the high level requests it. 3470 * The high level is notified immediately (rather than at a later 3471 * clock tick) when this watermark is reached. 3472 * The buffer size is chosen so the watermark should almost never 3473 * be reached. 3474 * The low watermark is invisibly 0 since the buffer is always 3475 * emptied all at once. 3476 */ 3477 com->iptr = com->ibuf = ibuf; 3478 com->ibufend = ibuf + ibufsize; 3479 com->ierroff = ibufsize; 3480 com->ihighwater = ibuf + 3 * ibufsize / 4; 3481 return (0); 3482} 3483 3484static void 3485comstart(tp) 3486 struct tty *tp; 3487{ 3488 struct com_s *com; 3489 int s; 3490 int unit; 3491#ifdef PC98 3492 int tmp; 3493#endif 3494 3495 unit = DEV_TO_UNIT(tp->t_dev); 3496 com = com_addr(unit); 3497 s = spltty(); 3498 disable_intr(); 3499 if (tp->t_state & TS_TTSTOP) 3500 com->state &= ~CS_TTGO; 3501 else 3502 com->state |= CS_TTGO; 3503 if (tp->t_state & TS_TBLOCK) { 3504#ifdef PC98 3505 if (IS_8251(com->pc98_if_type)) 3506 tmp = com_tiocm_get(com) & TIOCM_RTS; 3507 else 3508 tmp = com->mcr_image & MCR_RTS; 3509 if (tmp && (com->state & CS_RTS_IFLOW)) 3510#else 3511 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 3512#endif 3513#ifdef PC98 3514 if (IS_8251(com->pc98_if_type)) 3515 com_tiocm_bic(com, TIOCM_RTS); 3516 else 3517#endif 3518 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 3519 } else { 3520#ifdef PC98 3521 if (IS_8251(com->pc98_if_type)) 3522 tmp = com_tiocm_get(com) & TIOCM_RTS; 3523 else 3524 tmp = com->mcr_image & MCR_RTS; 3525 if (!(tmp) && com->iptr < com->ihighwater 3526 && com->state & CS_RTS_IFLOW) 3527#else 3528 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 3529 && com->state & CS_RTS_IFLOW) 3530#endif 3531#ifdef PC98 3532 if (IS_8251(com->pc98_if_type)) 3533 com_tiocm_bis(com, TIOCM_RTS); 3534 else 3535#endif 3536 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3537 } 3538 enable_intr(); 3539 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 3540 ttwwakeup(tp); 3541#ifdef PC98 3542/* if(IS_8251(com->pc98_if_type)) 3543 com_int_Tx_enable(com); */ 3544#endif 3545 splx(s); 3546 return; 3547 } 3548 if (tp->t_outq.c_cc != 0) { 3549 struct lbq *qp; 3550 struct lbq *next; 3551 3552 if (!com->obufs[0].l_queued) { 3553 com->obufs[0].l_tail 3554 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 3555#ifndef PC98 3556 sizeof com->obuf1); 3557#else 3558 com->obufsize); 3559#endif 3560 com->obufs[0].l_next = NULL; 3561 com->obufs[0].l_queued = TRUE; 3562 disable_intr(); 3563 if (com->state & CS_BUSY) { 3564 qp = com->obufq.l_next; 3565 while ((next = qp->l_next) != NULL) 3566 qp = next; 3567 qp->l_next = &com->obufs[0]; 3568 } else { 3569 com->obufq.l_head = com->obufs[0].l_head; 3570 com->obufq.l_tail = com->obufs[0].l_tail; 3571 com->obufq.l_next = &com->obufs[0]; 3572 com->state |= CS_BUSY; 3573 } 3574 enable_intr(); 3575 } 3576 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 3577 com->obufs[1].l_tail 3578 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 3579#ifndef PC98 3580 sizeof com->obuf2); 3581#else 3582 com->obufsize); 3583#endif 3584 com->obufs[1].l_next = NULL; 3585 com->obufs[1].l_queued = TRUE; 3586 disable_intr(); 3587 if (com->state & CS_BUSY) { 3588 qp = com->obufq.l_next; 3589 while ((next = qp->l_next) != NULL) 3590 qp = next; 3591 qp->l_next = &com->obufs[1]; 3592 } else { 3593 com->obufq.l_head = com->obufs[1].l_head; 3594 com->obufq.l_tail = com->obufs[1].l_tail; 3595 com->obufq.l_next = &com->obufs[1]; 3596 com->state |= CS_BUSY; 3597 } 3598 enable_intr(); 3599 } 3600 tp->t_state |= TS_BUSY; 3601 } 3602 disable_intr(); 3603 if (com->state >= (CS_BUSY | CS_TTGO)) 3604 siointr1(com); /* fake interrupt to start output */ 3605 enable_intr(); 3606#ifdef PC98 3607/* if(IS_8251(com->pc98_if_type)) 3608 com_int_Tx_enable(com); */ 3609#endif 3610 ttwwakeup(tp); 3611 splx(s); 3612} 3613 3614static void
| 2131 comhardclose(com); 2132 ttyclose(tp); 2133 siosettimeout(); 2134 splx(s); 2135 if (com->gone) { 2136 printf("sio%d: gone\n", com->unit); 2137 s = spltty(); 2138 if (com->ibuf != NULL) 2139 free(com->ibuf, M_DEVBUF); 2140 bzero(tp, sizeof *tp); 2141 free(com, M_DEVBUF); 2142 splx(s); 2143 } 2144 return (0); 2145} 2146 2147static void 2148comhardclose(com) 2149 struct com_s *com; 2150{ 2151 Port_t iobase; 2152 int s; 2153 struct tty *tp; 2154 int unit; 2155#ifdef PC98 2156 int port_shift = 0; 2157#endif 2158 2159 unit = com->unit; 2160 iobase = com->iobase; 2161 s = spltty(); 2162 com->poll = FALSE; 2163 com->poll_output = FALSE; 2164 com->do_timestamp = FALSE; 2165 com->do_dcd_timestamp = FALSE; 2166 com->pps.ppsparam.mode = 0; 2167#ifdef PC98 2168 if (IS_8251(com->pc98_if_type)) 2169 com_send_break_off(com); 2170 else { 2171 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 2172 outb(iobase + (com_cfcr << port_shift), 2173 com->cfcr_image &= ~CFCR_SBREAK); 2174 } 2175#else 2176 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2177#endif 2178 { 2179#ifdef PC98 2180 int tmp; 2181 if (IS_8251(com->pc98_if_type)) 2182 com_int_TxRx_disable(com); 2183 else 2184 outb(iobase + (com_ier << port_shift), 0); 2185 if (com->pc98_if_type == COM_IF_RSA98III) { 2186 outb(com->rsabase + rsa_ier, 0x00); 2187 } 2188#else 2189 outb(iobase + com_ier, 0); 2190#endif 2191 tp = com->tp; 2192#ifdef PC98 2193 if (IS_8251(com->pc98_if_type)) 2194 tmp = pc98_get_modem_status(com) & TIOCM_CAR; 2195 else 2196 tmp = com->prev_modem_status & MSR_DCD; 2197#endif 2198 if (tp->t_cflag & HUPCL 2199 /* 2200 * XXX we will miss any carrier drop between here and the 2201 * next open. Perhaps we should watch DCD even when the 2202 * port is closed; it is not sufficient to check it at 2203 * the next open because it might go up and down while 2204 * we're not watching. 2205 */ 2206 || (!com->active_out 2207#ifdef PC98 2208 && !(tmp) 2209#else 2210 && !(com->prev_modem_status & MSR_DCD) 2211#endif 2212 && !(com->it_in.c_cflag & CLOCAL)) 2213 || !(tp->t_state & TS_ISOPEN)) { 2214#ifdef PC98 2215 if (IS_8251(com->pc98_if_type)) 2216 com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); 2217 else 2218#endif 2219 (void)commctl(com, TIOCM_DTR, DMBIC); 2220 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 2221 timeout(siodtrwakeup, com, com->dtr_wait); 2222 com->state |= CS_DTR_OFF; 2223 } 2224 } 2225#ifdef PC98 2226 else { 2227 if (IS_8251(com->pc98_if_type)) 2228 com_tiocm_bic(com, TIOCM_LE ); 2229 } 2230#endif 2231 } 2232 if (com->hasfifo) { 2233 /* 2234 * Disable fifos so that they are off after controlled 2235 * reboots. Some BIOSes fail to detect 16550s when the 2236 * fifos are enabled. 2237 */ 2238#ifdef PC98 2239 outb(iobase + (com_fifo << port_shift), 0); 2240#else 2241 outb(iobase + com_fifo, 0); 2242#endif 2243 } 2244 com->active_out = FALSE; 2245 wakeup(&com->active_out); 2246 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 2247 splx(s); 2248} 2249 2250static int 2251sioread(dev, uio, flag) 2252 dev_t dev; 2253 struct uio *uio; 2254 int flag; 2255{ 2256 int mynor; 2257 struct com_s *com; 2258 2259 mynor = minor(dev); 2260 if (mynor & CONTROL_MASK) 2261 return (ENODEV); 2262 com = com_addr(MINOR_TO_UNIT(mynor)); 2263 if (com->gone) 2264 return (ENODEV); 2265 return ((*linesw[com->tp->t_line].l_read)(com->tp, uio, flag)); 2266} 2267 2268static int 2269siowrite(dev, uio, flag) 2270 dev_t dev; 2271 struct uio *uio; 2272 int flag; 2273{ 2274 int mynor; 2275 struct com_s *com; 2276 int unit; 2277 2278 mynor = minor(dev); 2279 if (mynor & CONTROL_MASK) 2280 return (ENODEV); 2281 2282 unit = MINOR_TO_UNIT(mynor); 2283 com = com_addr(unit); 2284 if (com->gone) 2285 return (ENODEV); 2286 /* 2287 * (XXX) We disallow virtual consoles if the physical console is 2288 * a serial port. This is in case there is a display attached that 2289 * is not the console. In that situation we don't need/want the X 2290 * server taking over the console. 2291 */ 2292 if (constty != NULL && unit == comconsole) 2293 constty = NULL; 2294 return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag)); 2295} 2296 2297static void 2298siobusycheck(chan) 2299 void *chan; 2300{ 2301 struct com_s *com; 2302 int s; 2303 2304 com = (struct com_s *)chan; 2305 2306 /* 2307 * Clear TS_BUSY if low-level output is complete. 2308 * spl locking is sufficient because siointr1() does not set CS_BUSY. 2309 * If siointr1() clears CS_BUSY after we look at it, then we'll get 2310 * called again. Reading the line status port outside of siointr1() 2311 * is safe because CS_BUSY is clear so there are no output interrupts 2312 * to lose. 2313 */ 2314 s = spltty(); 2315 if (com->state & CS_BUSY) 2316 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ 2317#ifdef PC98 2318 else if ((IS_8251(com->pc98_if_type) && 2319 (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP)) 2320 == (STS8251_TxRDY | STS8251_TxEMP)) || 2321 (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2322 == (LSR_TSRE | LSR_TXRDY)) { 2323#else 2324 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2325 == (LSR_TSRE | LSR_TXRDY)) { 2326#endif 2327 com->tp->t_state &= ~TS_BUSY; 2328 ttwwakeup(com->tp); 2329 com->extra_state &= ~CSE_BUSYCHECK; 2330 } else 2331 timeout(siobusycheck, com, hz / 100); 2332 splx(s); 2333} 2334 2335static void 2336siodtrwakeup(chan) 2337 void *chan; 2338{ 2339 struct com_s *com; 2340 2341 com = (struct com_s *)chan; 2342 com->state &= ~CS_DTR_OFF; 2343 wakeup(&com->dtr_wait); 2344} 2345 2346static void 2347sioinput(com) 2348 struct com_s *com; 2349{ 2350 u_char *buf; 2351 int incc; 2352 u_char line_status; 2353 int recv_data; 2354 struct tty *tp; 2355#ifdef PC98 2356 u_char tmp; 2357#endif 2358 2359 buf = com->ibuf; 2360 tp = com->tp; 2361 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) { 2362 com_events -= (com->iptr - com->ibuf); 2363 com->iptr = com->ibuf; 2364 return; 2365 } 2366 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2367 /* 2368 * Avoid the grotesquely inefficient lineswitch routine 2369 * (ttyinput) in "raw" mode. It usually takes about 450 2370 * instructions (that's without canonical processing or echo!). 2371 * slinput is reasonably fast (usually 40 instructions plus 2372 * call overhead). 2373 */ 2374 do { 2375 enable_intr(); 2376 incc = com->iptr - buf; 2377 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 2378 && (com->state & CS_RTS_IFLOW 2379 || tp->t_iflag & IXOFF) 2380 && !(tp->t_state & TS_TBLOCK)) 2381 ttyblock(tp); 2382 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2383 += b_to_q((char *)buf, incc, &tp->t_rawq); 2384 buf += incc; 2385 tk_nin += incc; 2386 tk_rawcc += incc; 2387 tp->t_rawcc += incc; 2388 ttwakeup(tp); 2389 if (tp->t_state & TS_TTSTOP 2390 && (tp->t_iflag & IXANY 2391 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2392 tp->t_state &= ~TS_TTSTOP; 2393 tp->t_lflag &= ~FLUSHO; 2394 comstart(tp); 2395 } 2396 disable_intr(); 2397 } while (buf < com->iptr); 2398 } else { 2399 do { 2400 enable_intr(); 2401 line_status = buf[com->ierroff]; 2402 recv_data = *buf++; 2403 if (line_status 2404 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2405 if (line_status & LSR_BI) 2406 recv_data |= TTY_BI; 2407 if (line_status & LSR_FE) 2408 recv_data |= TTY_FE; 2409 if (line_status & LSR_OE) 2410 recv_data |= TTY_OE; 2411 if (line_status & LSR_PE) 2412 recv_data |= TTY_PE; 2413 } 2414 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2415 disable_intr(); 2416 } while (buf < com->iptr); 2417 } 2418 com_events -= (com->iptr - com->ibuf); 2419 com->iptr = com->ibuf; 2420 2421 /* 2422 * There is now room for another low-level buffer full of input, 2423 * so enable RTS if it is now disabled and there is room in the 2424 * high-level buffer. 2425 */ 2426#ifdef PC98 2427 if (IS_8251(com->pc98_if_type)) 2428 tmp = com_tiocm_get(com) & TIOCM_RTS; 2429 else 2430 tmp = com->mcr_image & MCR_RTS; 2431 if ((com->state & CS_RTS_IFLOW) && !(tmp) && 2432 !(tp->t_state & TS_TBLOCK)) 2433 if (IS_8251(com->pc98_if_type)) 2434 com_tiocm_bis(com, TIOCM_RTS); 2435 else 2436 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2437#else 2438 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) && 2439 !(tp->t_state & TS_TBLOCK)) 2440 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2441#endif 2442} 2443 2444void 2445siointr(arg) 2446 void *arg; 2447{ 2448#ifndef COM_MULTIPORT 2449 COM_LOCK(); 2450 siointr1((struct com_s *) arg); 2451 COM_UNLOCK(); 2452#else /* COM_MULTIPORT */ 2453 bool_t possibly_more_intrs; 2454 int unit; 2455 struct com_s *com; 2456#ifdef PC98 2457 u_char rsa_buf_status; 2458#endif 2459 2460 /* 2461 * Loop until there is no activity on any port. This is necessary 2462 * to get an interrupt edge more than to avoid another interrupt. 2463 * If the IRQ signal is just an OR of the IRQ signals from several 2464 * devices, then the edge from one may be lost because another is 2465 * on. 2466 */ 2467 COM_LOCK(); 2468 do { 2469 possibly_more_intrs = FALSE; 2470 for (unit = 0; unit < NSIOTOT; ++unit) { 2471 com = com_addr(unit); 2472 /* 2473 * XXX COM_LOCK(); 2474 * would it work here, or be counter-productive? 2475 */ 2476#ifdef PC98 2477 if (com != NULL 2478 && !com->gone 2479 && IS_8251(com->pc98_if_type)){ 2480 siointr1(com); 2481 } else 2482#endif /* PC98 */ 2483#ifdef PC98 2484 if (com != NULL 2485 && !com->gone 2486 && com->pc98_if_type == COM_IF_RSA98III) { 2487 rsa_buf_status = inb(com->rsabase + rsa_srr) & 0xc9; 2488 if ((rsa_buf_status & 0xc8) 2489 || !(rsa_buf_status & 0x01)) { 2490 siointr1(com); 2491 if(rsa_buf_status 2492 != (inb(com->rsabase + rsa_srr) & 0xc9)) 2493 possibly_more_intrs = TRUE; 2494 } 2495 } else 2496#endif 2497 if (com != NULL 2498 && !com->gone 2499 && (inb(com->int_id_port) & IIR_IMASK) 2500 != IIR_NOPEND) { 2501 siointr1(com); 2502 possibly_more_intrs = TRUE; 2503 } 2504 /* XXX COM_UNLOCK(); */ 2505 } 2506 } while (possibly_more_intrs); 2507 COM_UNLOCK(); 2508#endif /* COM_MULTIPORT */ 2509} 2510 2511static void 2512siointr1(com) 2513 struct com_s *com; 2514{ 2515 u_char line_status; 2516 u_char modem_status; 2517 u_char *ioptr; 2518 u_char recv_data; 2519 u_char int_ctl; 2520 u_char int_ctl_new; 2521 struct timecounter *tc; 2522 u_int count; 2523 2524#ifdef PC98 2525 u_char tmp=0; 2526 u_char rsa_buf_status = 0; 2527 int rsa_tx_fifo_size=0; 2528 recv_data=0; 2529#endif /* PC98 */ 2530 2531 int_ctl = inb(com->intr_ctl_port); 2532 int_ctl_new = int_ctl; 2533 2534 while (!com->gone) { 2535#ifdef PC98 2536status_read:; 2537 if (IS_8251(com->pc98_if_type)) { 2538 tmp = inb(com->sts_port); 2539more_intr: 2540 line_status = 0; 2541 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 2542 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 2543 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 2544 if (tmp & STS8251_PE) line_status |= LSR_PE; 2545 if (tmp & STS8251_OE) line_status |= LSR_OE; 2546 if (tmp & STS8251_FE) line_status |= LSR_FE; 2547 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 2548 } else { 2549#endif /* PC98 */ 2550 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) { 2551 modem_status = inb(com->modem_status_port); 2552 if ((modem_status ^ com->last_modem_status) & MSR_DCD) { 2553 tc = timecounter; 2554 count = tc->tc_get_timecount(tc); 2555 pps_event(&com->pps, tc, count, 2556 (modem_status & MSR_DCD) ? 2557 PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 2558 } 2559 } 2560 line_status = inb(com->line_status_port); 2561#ifdef PC98 2562 } 2563 if (com->pc98_if_type == COM_IF_RSA98III) 2564 rsa_buf_status = inb(com->rsabase + rsa_srr); 2565#endif /* PC98 */ 2566 2567 /* input event? (check first to help avoid overruns) */ 2568#ifndef PC98 2569 while (line_status & LSR_RCV_MASK) { 2570#else 2571 while ((line_status & LSR_RCV_MASK) 2572 || (com->pc98_if_type == COM_IF_RSA98III 2573 && (rsa_buf_status & 0x08))) { 2574#endif /* PC98 */ 2575 /* break/unnattached error bits or real input? */ 2576#ifdef PC98 2577 if (IS_8251(com->pc98_if_type)) { 2578 recv_data = inb(com->data_port); 2579 if (tmp & 0x78) { 2580 pc98_i8251_or_cmd(com,CMD8251_ER); 2581 recv_data = 0; 2582 } 2583 } else { 2584#endif /* PC98 */ 2585#ifdef PC98 2586 if (com->pc98_if_type == COM_IF_RSA98III) { 2587 if (!(rsa_buf_status & 0x08)) 2588 recv_data = 0; 2589 else { 2590 recv_data = inb(com->data_port); 2591 } 2592 } else 2593#endif 2594 if (!(line_status & LSR_RXRDY)) 2595 recv_data = 0; 2596 else 2597 recv_data = inb(com->data_port); 2598#ifdef PC98 2599 } 2600#endif 2601 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 2602 /* 2603 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 2604 * Otherwise, push the work to a higher level 2605 * (to handle PARMRK) if we're bypassing. 2606 * Otherwise, convert BI/FE and PE+INPCK to 0. 2607 * 2608 * This makes bypassing work right in the 2609 * usual "raw" case (IGNBRK set, and IGNPAR 2610 * and INPCK clear). 2611 * 2612 * Note: BI together with FE/PE means just BI. 2613 */ 2614 if (line_status & LSR_BI) { 2615#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 2616 if (com->unit == comconsole) { 2617 breakpoint(); 2618 goto cont; 2619 } 2620#endif 2621 if (com->tp == NULL 2622 || com->tp->t_iflag & IGNBRK) 2623 goto cont; 2624 } else { 2625 if (com->tp == NULL 2626 || com->tp->t_iflag & IGNPAR) 2627 goto cont; 2628 } 2629 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 2630 && (line_status & (LSR_BI | LSR_FE) 2631 || com->tp->t_iflag & INPCK)) 2632 recv_data = 0; 2633 } 2634 ++com->bytes_in; 2635 if (com->hotchar != 0 && recv_data == com->hotchar) 2636 setsofttty(); 2637 ioptr = com->iptr; 2638 if (ioptr >= com->ibufend) 2639 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2640 else { 2641 if (com->do_timestamp) 2642 microtime(&com->timestamp); 2643 ++com_events; 2644 schedsofttty(); 2645#if 0 /* for testing input latency vs efficiency */ 2646if (com->iptr - com->ibuf == 8) 2647 setsofttty(); 2648#endif 2649 ioptr[0] = recv_data; 2650 ioptr[com->ierroff] = line_status; 2651 com->iptr = ++ioptr; 2652 if (ioptr == com->ihighwater 2653 && com->state & CS_RTS_IFLOW) 2654#ifdef PC98 2655 if (IS_8251(com->pc98_if_type)) 2656 com_tiocm_bic(com, TIOCM_RTS); 2657 else 2658#endif 2659 outb(com->modem_ctl_port, 2660 com->mcr_image &= ~MCR_RTS); 2661 if (line_status & LSR_OE) 2662 CE_RECORD(com, CE_OVERRUN); 2663 } 2664cont: 2665 /* 2666 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2667 * jump from the top of the loop to here 2668 */ 2669#ifdef PC98 2670 if (IS_8251(com->pc98_if_type)) 2671 goto status_read; 2672 else 2673#endif 2674 line_status = inb(com->line_status_port) & 0x7F; 2675#ifdef PC98 2676 if (com->pc98_if_type == COM_IF_RSA98III) 2677 rsa_buf_status = inb(com->rsabase + rsa_srr); 2678#endif /* PC98 */ 2679 } 2680 2681 /* modem status change? (always check before doing output) */ 2682#ifdef PC98 2683 if (!IS_8251(com->pc98_if_type)) { 2684#endif 2685 modem_status = inb(com->modem_status_port); 2686 if (modem_status != com->last_modem_status) { 2687 if (com->do_dcd_timestamp 2688 && !(com->last_modem_status & MSR_DCD) 2689 && modem_status & MSR_DCD) 2690 microtime(&com->dcd_timestamp); 2691 2692 /* 2693 * Schedule high level to handle DCD changes. Note 2694 * that we don't use the delta bits anywhere. Some 2695 * UARTs mess them up, and it's easy to remember the 2696 * previous bits and calculate the delta. 2697 */ 2698 com->last_modem_status = modem_status; 2699 if (!(com->state & CS_CHECKMSR)) { 2700 com_events += LOTS_OF_EVENTS; 2701 com->state |= CS_CHECKMSR; 2702 setsofttty(); 2703 } 2704 2705 /* handle CTS change immediately for crisp flow ctl */ 2706 if (com->state & CS_CTS_OFLOW) { 2707 if (modem_status & MSR_CTS) 2708 com->state |= CS_ODEVREADY; 2709 else 2710 com->state &= ~CS_ODEVREADY; 2711 } 2712 } 2713#ifdef PC98 2714 } 2715#endif 2716 2717 /* output queued and everything ready? */ 2718#ifndef PC98 2719 if (line_status & LSR_TXRDY 2720 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2721#else 2722 if (((com->pc98_if_type == COM_IF_RSA98III) 2723 ? (rsa_buf_status & 0x02) 2724 : (line_status & LSR_TXRDY)) 2725 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2726#endif 2727 ioptr = com->obufq.l_head; 2728 if (com->tx_fifo_size > 1) { 2729 u_int ocount; 2730 2731 ocount = com->obufq.l_tail - ioptr; 2732#ifdef PC98 2733 if (com->pc98_if_type == COM_IF_RSA98III) { 2734 rsa_buf_status = inb(com->rsabase + rsa_srr); 2735 rsa_tx_fifo_size = 1024; 2736 if (!(rsa_buf_status & 0x01)) 2737 rsa_tx_fifo_size = 2048; 2738 if (ocount > rsa_tx_fifo_size) 2739 ocount = rsa_tx_fifo_size; 2740 } else 2741#endif 2742 if (ocount > com->tx_fifo_size) 2743 ocount = com->tx_fifo_size; 2744 com->bytes_out += ocount; 2745 do 2746 outb(com->data_port, *ioptr++); 2747 while (--ocount != 0); 2748 } else { 2749 outb(com->data_port, *ioptr++); 2750 ++com->bytes_out; 2751 } 2752#ifdef PC98 2753 if (IS_8251(com->pc98_if_type)) 2754 if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG)) 2755 com_int_Tx_enable(com); 2756#endif 2757 com->obufq.l_head = ioptr; 2758 if (COM_IIR_TXRDYBUG(com->flags)) { 2759 int_ctl_new = int_ctl | IER_ETXRDY; 2760 } 2761 if (ioptr >= com->obufq.l_tail) { 2762 struct lbq *qp; 2763 2764 qp = com->obufq.l_next; 2765 qp->l_queued = FALSE; 2766 qp = qp->l_next; 2767 if (qp != NULL) { 2768 com->obufq.l_head = qp->l_head; 2769 com->obufq.l_tail = qp->l_tail; 2770 com->obufq.l_next = qp; 2771 } else { 2772 /* output just completed */ 2773 if ( COM_IIR_TXRDYBUG(com->flags) ) { 2774 int_ctl_new = int_ctl & ~IER_ETXRDY; 2775 } 2776 com->state &= ~CS_BUSY; 2777#if defined(PC98) 2778 if (IS_8251(com->pc98_if_type)) 2779 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2780 com_int_Tx_disable(com); 2781#endif 2782 } 2783 if (!(com->state & CS_ODONE)) { 2784 com_events += LOTS_OF_EVENTS; 2785 com->state |= CS_ODONE; 2786 setsofttty(); /* handle at high level ASAP */ 2787 } 2788 } 2789 if ( COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) { 2790#ifdef PC98 2791 if (com->pc98_if_type == COM_IF_RSA98III) { 2792 int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY); 2793 outb(com->intr_ctl_port, int_ctl_new); 2794 outb(com->rsabase + rsa_ier, 0x1d); 2795 } else 2796#endif 2797 outb(com->intr_ctl_port, int_ctl_new); 2798 } 2799 } 2800#ifdef PC98 2801 else if (line_status & LSR_TXRDY) { 2802 if (IS_8251(com->pc98_if_type)) 2803 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2804 com_int_Tx_disable(com); 2805 } 2806 if (IS_8251(com->pc98_if_type)) 2807 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2808 goto more_intr; 2809#endif 2810 2811 /* finished? */ 2812#ifndef COM_MULTIPORT 2813#ifdef PC98 2814 if (IS_8251(com->pc98_if_type)) 2815 return; 2816#endif 2817 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2818#endif /* COM_MULTIPORT */ 2819 return; 2820 } 2821} 2822 2823static int 2824sioioctl(dev, cmd, data, flag, p) 2825 dev_t dev; 2826 u_long cmd; 2827 caddr_t data; 2828 int flag; 2829 struct proc *p; 2830{ 2831 struct com_s *com; 2832 int error; 2833 Port_t iobase; 2834 int mynor; 2835 int s; 2836 struct tty *tp; 2837#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2838 u_long oldcmd; 2839 struct termios term; 2840#endif 2841 2842 mynor = minor(dev); 2843 com = com_addr(MINOR_TO_UNIT(mynor)); 2844 if (com->gone) 2845 return (ENODEV); 2846 iobase = com->iobase; 2847 if (mynor & CONTROL_MASK) { 2848 struct termios *ct; 2849 2850 switch (mynor & CONTROL_MASK) { 2851 case CONTROL_INIT_STATE: 2852 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2853 break; 2854 case CONTROL_LOCK_STATE: 2855 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2856 break; 2857 default: 2858 return (ENODEV); /* /dev/nodev */ 2859 } 2860 switch (cmd) { 2861 case TIOCSETA: 2862 error = suser(p); 2863 if (error != 0) 2864 return (error); 2865 *ct = *(struct termios *)data; 2866 return (0); 2867 case TIOCGETA: 2868 *(struct termios *)data = *ct; 2869 return (0); 2870 case TIOCGETD: 2871 *(int *)data = TTYDISC; 2872 return (0); 2873 case TIOCGWINSZ: 2874 bzero(data, sizeof(struct winsize)); 2875 return (0); 2876 default: 2877 return (ENOTTY); 2878 } 2879 } 2880 tp = com->tp; 2881#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2882 term = tp->t_termios; 2883 oldcmd = cmd; 2884 error = ttsetcompat(tp, &cmd, data, &term); 2885 if (error != 0) 2886 return (error); 2887 if (cmd != oldcmd) 2888 data = (caddr_t)&term; 2889#endif 2890 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2891 int cc; 2892 struct termios *dt = (struct termios *)data; 2893 struct termios *lt = mynor & CALLOUT_MASK 2894 ? &com->lt_out : &com->lt_in; 2895 2896 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2897 | (dt->c_iflag & ~lt->c_iflag); 2898 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2899 | (dt->c_oflag & ~lt->c_oflag); 2900 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2901 | (dt->c_cflag & ~lt->c_cflag); 2902 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2903 | (dt->c_lflag & ~lt->c_lflag); 2904 for (cc = 0; cc < NCCS; ++cc) 2905 if (lt->c_cc[cc] != 0) 2906 dt->c_cc[cc] = tp->t_cc[cc]; 2907 if (lt->c_ispeed != 0) 2908 dt->c_ispeed = tp->t_ispeed; 2909 if (lt->c_ospeed != 0) 2910 dt->c_ospeed = tp->t_ospeed; 2911 } 2912 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2913 if (error != ENOIOCTL) 2914 return (error); 2915 s = spltty(); 2916 error = ttioctl(tp, cmd, data, flag); 2917 disc_optim(tp, &tp->t_termios, com); 2918 if (error != ENOIOCTL) { 2919 splx(s); 2920 return (error); 2921 } 2922#ifdef PC98 2923 if (IS_8251(com->pc98_if_type)) { 2924 switch (cmd) { 2925 case TIOCSBRK: 2926 com_send_break_on( com ); 2927 break; 2928 case TIOCCBRK: 2929 com_send_break_off( com ); 2930 break; 2931 case TIOCSDTR: 2932 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2933 break; 2934 case TIOCCDTR: 2935 com_tiocm_bic(com, TIOCM_DTR); 2936 break; 2937 /* 2938 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2939 * changes get undone on the next call to comparam(). 2940 */ 2941 case TIOCMSET: 2942 com_tiocm_set( com, *(int *)data ); 2943 break; 2944 case TIOCMBIS: 2945 com_tiocm_bis( com, *(int *)data ); 2946 break; 2947 case TIOCMBIC: 2948 com_tiocm_bic( com, *(int *)data ); 2949 break; 2950 case TIOCMGET: 2951 *(int *)data = com_tiocm_get(com); 2952 break; 2953 case TIOCMSDTRWAIT: 2954 /* must be root since the wait applies to following logins */ 2955 error = suser(p); 2956 if (error != 0) { 2957 splx(s); 2958 return (error); 2959 } 2960 com->dtr_wait = *(int *)data * hz / 100; 2961 break; 2962 case TIOCMGDTRWAIT: 2963 *(int *)data = com->dtr_wait * 100 / hz; 2964 break; 2965 case TIOCTIMESTAMP: 2966 com->do_timestamp = TRUE; 2967 *(struct timeval *)data = com->timestamp; 2968 break; 2969 case TIOCDCDTIMESTAMP: 2970 com->do_dcd_timestamp = TRUE; 2971 *(struct timeval *)data = com->dcd_timestamp; 2972 break; 2973 default: 2974 splx(s); 2975 return (ENOTTY); 2976 } 2977 } else { 2978 int port_shift; 2979 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 2980#endif 2981 switch (cmd) { 2982 case TIOCSBRK: 2983#ifdef PC98 2984 outb(iobase + (com_cfcr << port_shift), 2985 com->cfcr_image |= CFCR_SBREAK); 2986#else 2987 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2988#endif 2989 break; 2990 case TIOCCBRK: 2991#ifdef PC98 2992 outb(iobase + (com_cfcr << port_shift), 2993 com->cfcr_image &= ~CFCR_SBREAK); 2994#else 2995 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2996#endif 2997 break; 2998 case TIOCSDTR: 2999 (void)commctl(com, TIOCM_DTR, DMBIS); 3000 break; 3001 case TIOCCDTR: 3002 (void)commctl(com, TIOCM_DTR, DMBIC); 3003 break; 3004 /* 3005 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 3006 * changes get undone on the next call to comparam(). 3007 */ 3008 case TIOCMSET: 3009 (void)commctl(com, *(int *)data, DMSET); 3010 break; 3011 case TIOCMBIS: 3012 (void)commctl(com, *(int *)data, DMBIS); 3013 break; 3014 case TIOCMBIC: 3015 (void)commctl(com, *(int *)data, DMBIC); 3016 break; 3017 case TIOCMGET: 3018 *(int *)data = commctl(com, 0, DMGET); 3019 break; 3020 case TIOCMSDTRWAIT: 3021 /* must be root since the wait applies to following logins */ 3022 error = suser(p); 3023 if (error != 0) { 3024 splx(s); 3025 return (error); 3026 } 3027 com->dtr_wait = *(int *)data * hz / 100; 3028 break; 3029 case TIOCMGDTRWAIT: 3030 *(int *)data = com->dtr_wait * 100 / hz; 3031 break; 3032 case TIOCTIMESTAMP: 3033 com->do_timestamp = TRUE; 3034 *(struct timeval *)data = com->timestamp; 3035 break; 3036 case TIOCDCDTIMESTAMP: 3037 com->do_dcd_timestamp = TRUE; 3038 *(struct timeval *)data = com->dcd_timestamp; 3039 break; 3040 default: 3041 splx(s); 3042 error = pps_ioctl(cmd, data, &com->pps); 3043 if (error == ENODEV) 3044 error = ENOTTY; 3045 return (error); 3046 } 3047#ifdef PC98 3048 } 3049#endif 3050 splx(s); 3051 return (0); 3052} 3053 3054static void 3055siopoll() 3056{ 3057 int unit; 3058 3059 if (com_events == 0) 3060 return; 3061repeat: 3062 for (unit = 0; unit < NSIOTOT; ++unit) { 3063 struct com_s *com; 3064 int incc; 3065 struct tty *tp; 3066 3067 com = com_addr(unit); 3068 if (com == NULL) 3069 continue; 3070 tp = com->tp; 3071 if (tp == NULL || com->gone) { 3072 /* 3073 * Discard any events related to never-opened or 3074 * going-away devices. 3075 */ 3076 disable_intr(); 3077 incc = com->iptr - com->ibuf; 3078 com->iptr = com->ibuf; 3079 if (com->state & CS_CHECKMSR) { 3080 incc += LOTS_OF_EVENTS; 3081 com->state &= ~CS_CHECKMSR; 3082 } 3083 com_events -= incc; 3084 enable_intr(); 3085 continue; 3086 } 3087 if (com->iptr != com->ibuf) { 3088 disable_intr(); 3089 sioinput(com); 3090 enable_intr(); 3091 } 3092 if (com->state & CS_CHECKMSR) { 3093 u_char delta_modem_status; 3094 3095#ifdef PC98 3096 if (!IS_8251(com->pc98_if_type)) { 3097#endif 3098 disable_intr(); 3099 delta_modem_status = com->last_modem_status 3100 ^ com->prev_modem_status; 3101 com->prev_modem_status = com->last_modem_status; 3102 com_events -= LOTS_OF_EVENTS; 3103 com->state &= ~CS_CHECKMSR; 3104 enable_intr(); 3105 if (delta_modem_status & MSR_DCD) 3106 (*linesw[tp->t_line].l_modem) 3107 (tp, com->prev_modem_status & MSR_DCD); 3108#ifdef PC98 3109 } 3110#endif 3111 } 3112 if (com->state & CS_ODONE) { 3113 disable_intr(); 3114 com_events -= LOTS_OF_EVENTS; 3115 com->state &= ~CS_ODONE; 3116 enable_intr(); 3117 if (!(com->state & CS_BUSY) 3118 && !(com->extra_state & CSE_BUSYCHECK)) { 3119 timeout(siobusycheck, com, hz / 100); 3120 com->extra_state |= CSE_BUSYCHECK; 3121 } 3122 (*linesw[tp->t_line].l_start)(tp); 3123 } 3124 if (com_events == 0) 3125 break; 3126 } 3127 if (com_events >= LOTS_OF_EVENTS) 3128 goto repeat; 3129} 3130 3131static int 3132comparam(tp, t) 3133 struct tty *tp; 3134 struct termios *t; 3135{ 3136 u_int cfcr; 3137 int cflag; 3138 struct com_s *com; 3139 int divisor; 3140 u_char dlbh; 3141 u_char dlbl; 3142 Port_t iobase; 3143 int s; 3144 int unit; 3145#ifdef PC98 3146 int port_shift = 0; 3147 u_char param = 0; 3148#endif 3149 3150#ifdef PC98 3151 cfcr = 0; 3152 unit = DEV_TO_UNIT(tp->t_dev); 3153 com = com_addr(unit); 3154 iobase = com->iobase; 3155 if (IS_8251(com->pc98_if_type)) { 3156 divisor = pc98_ttspeedtab(com, t->c_ospeed); 3157 } else { 3158 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 3159 3160 /* do historical conversions */ 3161 if (t->c_ispeed == 0) 3162 t->c_ispeed = t->c_ospeed; 3163 3164 /* check requested parameters */ 3165 divisor = ttspeedtab(t->c_ospeed, 3166 if_16550a_type[com->pc98_if_type & 0x0f].speedtab); 3167 } 3168#else 3169 /* do historical conversions */ 3170 if (t->c_ispeed == 0) 3171 t->c_ispeed = t->c_ospeed; 3172 3173 /* check requested parameters */ 3174 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 3175#endif 3176 if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed)) 3177 return (EINVAL); 3178 3179 /* parameters are OK, convert them to the com struct and the device */ 3180#ifndef PC98 3181 unit = DEV_TO_UNIT(tp->t_dev); 3182 com = com_addr(unit); 3183 iobase = com->iobase; 3184#endif 3185 s = spltty(); 3186#ifdef PC98 3187 if (IS_8251(com->pc98_if_type)) { 3188 if (divisor == 0) 3189 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3190 else 3191 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3192 } else { 3193#endif 3194 if (divisor == 0) 3195 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 3196 else 3197 (void)commctl(com, TIOCM_DTR, DMBIS); 3198#ifdef PC98 3199 } 3200#endif 3201 cflag = t->c_cflag; 3202#ifdef PC98 3203 if (!IS_8251(com->pc98_if_type)) { 3204#endif 3205 switch (cflag & CSIZE) { 3206 case CS5: 3207 cfcr = CFCR_5BITS; 3208 break; 3209 case CS6: 3210 cfcr = CFCR_6BITS; 3211 break; 3212 case CS7: 3213 cfcr = CFCR_7BITS; 3214 break; 3215 default: 3216 cfcr = CFCR_8BITS; 3217 break; 3218 } 3219 if (cflag & PARENB) { 3220 cfcr |= CFCR_PENAB; 3221 if (!(cflag & PARODD)) 3222 cfcr |= CFCR_PEVEN; 3223 } 3224 if (cflag & CSTOPB) 3225 cfcr |= CFCR_STOPB; 3226 3227 if (com->hasfifo && divisor != 0) { 3228 /* 3229 * Use a fifo trigger level low enough so that the input 3230 * latency from the fifo is less than about 16 msec and 3231 * the total latency is less than about 30 msec. These 3232 * latencies are reasonable for humans. Serial comms 3233 * protocols shouldn't expect anything better since modem 3234 * latencies are larger. 3235 */ 3236 com->fifo_image = t->c_ospeed <= 4800 3237 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 3238#ifdef COM_ESP 3239 /* 3240 * The Hayes ESP card needs the fifo DMA mode bit set 3241 * in compatibility mode. If not, it will interrupt 3242 * for each character received. 3243 */ 3244 if (com->esp) 3245 com->fifo_image |= FIFO_DMA_MODE; 3246#endif 3247#ifdef PC98 3248 outb(iobase + (com_fifo << port_shift), com->fifo_image); 3249#else 3250 outb(iobase + com_fifo, com->fifo_image); 3251#endif 3252 } 3253#ifdef PC98 3254 } 3255#endif 3256 3257 /* 3258 * This returns with interrupts disabled so that we can complete 3259 * the speed change atomically. Keeping interrupts disabled is 3260 * especially important while com_data is hidden. 3261 */ 3262 (void) siosetwater(com, t->c_ispeed); 3263 3264#ifdef PC98 3265 if (IS_8251(com->pc98_if_type)) 3266 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 3267 else { 3268#endif 3269 if (divisor != 0) { 3270#ifdef PC98 3271 outb(iobase + (com_cfcr << port_shift), cfcr | CFCR_DLAB); 3272#else 3273 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 3274#endif 3275 /* 3276 * Only set the divisor registers if they would change, 3277 * since on some 16550 incompatibles (UMC8669F), setting 3278 * them while input is arriving them loses sync until 3279 * data stops arriving. 3280 */ 3281 dlbl = divisor & 0xFF; 3282#ifdef PC98 3283 if (inb(iobase + (com_dlbl << port_shift)) != dlbl) 3284 outb(iobase + (com_dlbl << port_shift), dlbl); 3285 dlbh = (u_int) divisor >> 8; 3286 if (inb(iobase + (com_dlbh << port_shift)) != dlbh) 3287 outb(iobase + (com_dlbh << port_shift), dlbh); 3288#else 3289 if (inb(iobase + com_dlbl) != dlbl) 3290 outb(iobase + com_dlbl, dlbl); 3291 dlbh = (u_int) divisor >> 8; 3292 if (inb(iobase + com_dlbh) != dlbh) 3293 outb(iobase + com_dlbh, dlbh); 3294#endif 3295 } 3296 3297 3298#ifdef PC98 3299 } 3300 outb(iobase + (com_cfcr << port_shift), com->cfcr_image = cfcr); 3301#else 3302 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 3303#endif 3304 3305 if (!(tp->t_state & TS_TTSTOP)) 3306 com->state |= CS_TTGO; 3307 3308 if (cflag & CRTS_IFLOW) { 3309 if (com->st16650a) { 3310 outb(iobase + com_cfcr, 0xbf); 3311 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 3312 } 3313 com->state |= CS_RTS_IFLOW; 3314 /* 3315 * If CS_RTS_IFLOW just changed from off to on, the change 3316 * needs to be propagated to MCR_RTS. This isn't urgent, 3317 * so do it later by calling comstart() instead of repeating 3318 * a lot of code from comstart() here. 3319 */ 3320 } else if (com->state & CS_RTS_IFLOW) { 3321 com->state &= ~CS_RTS_IFLOW; 3322 /* 3323 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 3324 * on here, since comstart() won't do it later. 3325 */ 3326#ifdef PC98 3327 if (IS_8251(com->pc98_if_type)) 3328 com_tiocm_bis(com, TIOCM_RTS); 3329 else 3330#endif 3331 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3332 if (com->st16650a) { 3333 outb(iobase + com_cfcr, 0xbf); 3334 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 3335 } 3336 } 3337 3338 3339 /* 3340 * Set up state to handle output flow control. 3341 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 3342 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 3343 */ 3344 com->state |= CS_ODEVREADY; 3345 com->state &= ~CS_CTS_OFLOW; 3346#ifdef PC98 3347 if (com->pc98_if_type == COM_IF_RSA98III) { 3348 param = inb(com->rsabase + rsa_msr); 3349 outb(com->rsabase + rsa_msr, param & 0x14); 3350 } 3351#endif 3352 if (cflag & CCTS_OFLOW) { 3353 com->state |= CS_CTS_OFLOW; 3354#ifdef PC98 3355 if (IS_8251(com->pc98_if_type)) { 3356 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 3357 com->state &= ~CS_ODEVREADY; 3358 } else { 3359#endif 3360#ifdef PC98 3361 if (com->pc98_if_type == COM_IF_RSA98III) { 3362 /* Set automatic flow control mode */ 3363 outb(com->rsabase + rsa_msr, param | 0x08); 3364 } else 3365#endif 3366 if (!(com->last_modem_status & MSR_CTS)) 3367 com->state &= ~CS_ODEVREADY; 3368 if (com->st16650a) { 3369 outb(iobase + com_cfcr, 0xbf); 3370 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 3371 } 3372#ifdef PC98 3373 } 3374#endif 3375 } else { 3376 if (com->st16650a) { 3377 outb(iobase + com_cfcr, 0xbf); 3378 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 3379 } 3380 } 3381 3382 3383#ifdef PC98 3384 outb(iobase + (com_cfcr << port_shift), com->cfcr_image); 3385#else 3386 outb(iobase + com_cfcr, com->cfcr_image); 3387#endif 3388 3389 3390 /* XXX shouldn't call functions while intrs are disabled. */ 3391 disc_optim(tp, t, com); 3392 /* 3393 * Recover from fiddling with CS_TTGO. We used to call siointr1() 3394 * unconditionally, but that defeated the careful discarding of 3395 * stale input in sioopen(). 3396 */ 3397 if (com->state >= (CS_BUSY | CS_TTGO)) 3398 siointr1(com); 3399 3400 enable_intr(); 3401 splx(s); 3402 comstart(tp); 3403 if (com->ibufold != NULL) { 3404 free(com->ibufold, M_DEVBUF); 3405 com->ibufold = NULL; 3406 } 3407 return (0); 3408} 3409 3410static int 3411siosetwater(com, speed) 3412 struct com_s *com; 3413 speed_t speed; 3414{ 3415 int cp4ticks; 3416 u_char *ibuf; 3417 int ibufsize; 3418 struct tty *tp; 3419 3420 /* 3421 * Make the buffer size large enough to handle a softtty interrupt 3422 * latency of about 2 ticks without loss of throughput or data 3423 * (about 3 ticks if input flow control is not used or not honoured, 3424 * but a bit less for CS5-CS7 modes). 3425 */ 3426 cp4ticks = speed / 10 / hz * 4; 3427 for (ibufsize = 128; ibufsize < cp4ticks;) 3428 ibufsize <<= 1; 3429#ifdef PC98 3430 if (com->pc98_if_type == COM_IF_RSA98III) 3431 ibufsize = 2048; 3432#endif 3433 if (ibufsize == com->ibufsize) { 3434 disable_intr(); 3435 return (0); 3436 } 3437 3438 /* 3439 * Allocate input buffer. The extra factor of 2 in the size is 3440 * to allow for an error byte for each input byte. 3441 */ 3442 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 3443 if (ibuf == NULL) { 3444 disable_intr(); 3445 return (ENOMEM); 3446 } 3447 3448 /* Initialize non-critical variables. */ 3449 com->ibufold = com->ibuf; 3450 com->ibufsize = ibufsize; 3451 tp = com->tp; 3452 if (tp != NULL) { 3453 tp->t_ififosize = 2 * ibufsize; 3454 tp->t_ispeedwat = (speed_t)-1; 3455 tp->t_ospeedwat = (speed_t)-1; 3456 } 3457 3458 /* 3459 * Read current input buffer, if any. Continue with interrupts 3460 * disabled. 3461 */ 3462 disable_intr(); 3463 if (com->iptr != com->ibuf) 3464 sioinput(com); 3465 3466 /*- 3467 * Initialize critical variables, including input buffer watermarks. 3468 * The external device is asked to stop sending when the buffer 3469 * exactly reaches high water, or when the high level requests it. 3470 * The high level is notified immediately (rather than at a later 3471 * clock tick) when this watermark is reached. 3472 * The buffer size is chosen so the watermark should almost never 3473 * be reached. 3474 * The low watermark is invisibly 0 since the buffer is always 3475 * emptied all at once. 3476 */ 3477 com->iptr = com->ibuf = ibuf; 3478 com->ibufend = ibuf + ibufsize; 3479 com->ierroff = ibufsize; 3480 com->ihighwater = ibuf + 3 * ibufsize / 4; 3481 return (0); 3482} 3483 3484static void 3485comstart(tp) 3486 struct tty *tp; 3487{ 3488 struct com_s *com; 3489 int s; 3490 int unit; 3491#ifdef PC98 3492 int tmp; 3493#endif 3494 3495 unit = DEV_TO_UNIT(tp->t_dev); 3496 com = com_addr(unit); 3497 s = spltty(); 3498 disable_intr(); 3499 if (tp->t_state & TS_TTSTOP) 3500 com->state &= ~CS_TTGO; 3501 else 3502 com->state |= CS_TTGO; 3503 if (tp->t_state & TS_TBLOCK) { 3504#ifdef PC98 3505 if (IS_8251(com->pc98_if_type)) 3506 tmp = com_tiocm_get(com) & TIOCM_RTS; 3507 else 3508 tmp = com->mcr_image & MCR_RTS; 3509 if (tmp && (com->state & CS_RTS_IFLOW)) 3510#else 3511 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 3512#endif 3513#ifdef PC98 3514 if (IS_8251(com->pc98_if_type)) 3515 com_tiocm_bic(com, TIOCM_RTS); 3516 else 3517#endif 3518 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 3519 } else { 3520#ifdef PC98 3521 if (IS_8251(com->pc98_if_type)) 3522 tmp = com_tiocm_get(com) & TIOCM_RTS; 3523 else 3524 tmp = com->mcr_image & MCR_RTS; 3525 if (!(tmp) && com->iptr < com->ihighwater 3526 && com->state & CS_RTS_IFLOW) 3527#else 3528 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 3529 && com->state & CS_RTS_IFLOW) 3530#endif 3531#ifdef PC98 3532 if (IS_8251(com->pc98_if_type)) 3533 com_tiocm_bis(com, TIOCM_RTS); 3534 else 3535#endif 3536 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3537 } 3538 enable_intr(); 3539 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 3540 ttwwakeup(tp); 3541#ifdef PC98 3542/* if(IS_8251(com->pc98_if_type)) 3543 com_int_Tx_enable(com); */ 3544#endif 3545 splx(s); 3546 return; 3547 } 3548 if (tp->t_outq.c_cc != 0) { 3549 struct lbq *qp; 3550 struct lbq *next; 3551 3552 if (!com->obufs[0].l_queued) { 3553 com->obufs[0].l_tail 3554 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 3555#ifndef PC98 3556 sizeof com->obuf1); 3557#else 3558 com->obufsize); 3559#endif 3560 com->obufs[0].l_next = NULL; 3561 com->obufs[0].l_queued = TRUE; 3562 disable_intr(); 3563 if (com->state & CS_BUSY) { 3564 qp = com->obufq.l_next; 3565 while ((next = qp->l_next) != NULL) 3566 qp = next; 3567 qp->l_next = &com->obufs[0]; 3568 } else { 3569 com->obufq.l_head = com->obufs[0].l_head; 3570 com->obufq.l_tail = com->obufs[0].l_tail; 3571 com->obufq.l_next = &com->obufs[0]; 3572 com->state |= CS_BUSY; 3573 } 3574 enable_intr(); 3575 } 3576 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 3577 com->obufs[1].l_tail 3578 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 3579#ifndef PC98 3580 sizeof com->obuf2); 3581#else 3582 com->obufsize); 3583#endif 3584 com->obufs[1].l_next = NULL; 3585 com->obufs[1].l_queued = TRUE; 3586 disable_intr(); 3587 if (com->state & CS_BUSY) { 3588 qp = com->obufq.l_next; 3589 while ((next = qp->l_next) != NULL) 3590 qp = next; 3591 qp->l_next = &com->obufs[1]; 3592 } else { 3593 com->obufq.l_head = com->obufs[1].l_head; 3594 com->obufq.l_tail = com->obufs[1].l_tail; 3595 com->obufq.l_next = &com->obufs[1]; 3596 com->state |= CS_BUSY; 3597 } 3598 enable_intr(); 3599 } 3600 tp->t_state |= TS_BUSY; 3601 } 3602 disable_intr(); 3603 if (com->state >= (CS_BUSY | CS_TTGO)) 3604 siointr1(com); /* fake interrupt to start output */ 3605 enable_intr(); 3606#ifdef PC98 3607/* if(IS_8251(com->pc98_if_type)) 3608 com_int_Tx_enable(com); */ 3609#endif 3610 ttwwakeup(tp); 3611 splx(s); 3612} 3613 3614static void
|
3697static int 3698commctl(com, bits, how) 3699 struct com_s *com; 3700 int bits; 3701 int how; 3702{ 3703 int mcr; 3704 int msr; 3705 3706 if (how == DMGET) { 3707 bits = TIOCM_LE; /* XXX - always enabled while open */ 3708 mcr = com->mcr_image; 3709 if (mcr & MCR_DTR) 3710 bits |= TIOCM_DTR; 3711 if (mcr & MCR_RTS) 3712 bits |= TIOCM_RTS; 3713 msr = com->prev_modem_status; 3714 if (msr & MSR_CTS) 3715 bits |= TIOCM_CTS; 3716 if (msr & MSR_DCD) 3717 bits |= TIOCM_CD; 3718 if (msr & MSR_DSR) 3719 bits |= TIOCM_DSR; 3720 /* 3721 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3722 * more volatile by reading the modem status a lot. Perhaps 3723 * we should latch both bits until the status is read here. 3724 */ 3725 if (msr & (MSR_RI | MSR_TERI)) 3726 bits |= TIOCM_RI; 3727 return (bits); 3728 } 3729 mcr = 0; 3730 if (bits & TIOCM_DTR) 3731 mcr |= MCR_DTR; 3732 if (bits & TIOCM_RTS) 3733 mcr |= MCR_RTS; 3734 if (com->gone) 3735 return(0); 3736 disable_intr(); 3737 switch (how) { 3738 case DMSET: 3739 outb(com->modem_ctl_port, 3740 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3741 break; 3742 case DMBIS: 3743 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3744 break; 3745 case DMBIC: 3746 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3747 break; 3748 } 3749 enable_intr(); 3750 return (0); 3751} 3752 3753static void 3754siosettimeout() 3755{ 3756 struct com_s *com; 3757 bool_t someopen; 3758 int unit; 3759 3760 /* 3761 * Set our timeout period to 1 second if no polled devices are open. 3762 * Otherwise set it to max(1/200, 1/hz). 3763 * Enable timeouts iff some device is open. 3764 */ 3765 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3766 sio_timeout = hz; 3767 someopen = FALSE; 3768 for (unit = 0; unit < NSIOTOT; ++unit) { 3769 com = com_addr(unit); 3770 if (com != NULL && com->tp != NULL 3771 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3772 someopen = TRUE; 3773 if (com->poll || com->poll_output) { 3774 sio_timeout = hz > 200 ? hz / 200 : 1; 3775 break; 3776 } 3777 } 3778 } 3779 if (someopen) { 3780 sio_timeouts_until_log = hz / sio_timeout; 3781 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3782 sio_timeout); 3783 } else { 3784 /* Flush error messages, if any. */ 3785 sio_timeouts_until_log = 1; 3786 comwakeup((void *)NULL); 3787 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3788 } 3789} 3790 3791static void 3792comwakeup(chan) 3793 void *chan; 3794{ 3795 struct com_s *com; 3796 int unit; 3797 3798 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3799 3800 /* 3801 * Recover from lost output interrupts. 3802 * Poll any lines that don't use interrupts. 3803 */ 3804 for (unit = 0; unit < NSIOTOT; ++unit) { 3805 com = com_addr(unit); 3806 if (com != NULL && !com->gone 3807 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3808 disable_intr(); 3809 siointr1(com); 3810 enable_intr(); 3811 } 3812 } 3813 3814 /* 3815 * Check for and log errors, but not too often. 3816 */ 3817 if (--sio_timeouts_until_log > 0) 3818 return; 3819 sio_timeouts_until_log = hz / sio_timeout; 3820 for (unit = 0; unit < NSIOTOT; ++unit) { 3821 int errnum; 3822 3823 com = com_addr(unit); 3824 if (com == NULL) 3825 continue; 3826 if (com->gone) 3827 continue; 3828 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3829 u_int delta; 3830 u_long total; 3831 3832 disable_intr(); 3833 delta = com->delta_error_counts[errnum]; 3834 com->delta_error_counts[errnum] = 0; 3835 enable_intr(); 3836 if (delta == 0) 3837 continue; 3838 total = com->error_counts[errnum] += delta; 3839 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3840 unit, delta, error_desc[errnum], 3841 delta == 1 ? "" : "s", total); 3842 } 3843 } 3844} 3845 3846#ifdef PC98 3847/* commint is called when modem control line changes */ 3848static void 3849commint(dev_t dev) 3850{ 3851 register struct tty *tp; 3852 int stat,delta; 3853 struct com_s *com; 3854 int mynor,unit; 3855 3856 mynor = minor(dev); 3857 unit = MINOR_TO_UNIT(mynor); 3858 com = com_addr(unit); 3859 tp = com->tp; 3860 3861 stat = com_tiocm_get(com); 3862 delta = com_tiocm_get_delta(com); 3863 3864 if (com->state & CS_CTS_OFLOW) { 3865 if (stat & TIOCM_CTS) 3866 com->state |= CS_ODEVREADY; 3867 else 3868 com->state &= ~CS_ODEVREADY; 3869 } 3870 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3871 if (stat & TIOCM_CAR ) 3872 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3873 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3874 /* negate DTR, RTS */ 3875 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3876 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3877 /* disable IENABLE */ 3878 com_int_TxRx_disable( com ); 3879 } 3880 } 3881} 3882#endif 3883 3884static void 3885disc_optim(tp, t, com) 3886 struct tty *tp; 3887 struct termios *t; 3888 struct com_s *com; 3889{ 3890 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3891 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3892 && (!(t->c_iflag & PARMRK) 3893 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3894 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3895 && linesw[tp->t_line].l_rint == ttyinput) 3896 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3897 else 3898 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3899 com->hotchar = linesw[tp->t_line].l_hotchar; 3900} 3901 3902/* 3903 * Following are all routines needed for SIO to act as console 3904 */ 3905#include <sys/cons.h> 3906 3907struct siocnstate { 3908 u_char dlbl; 3909 u_char dlbh; 3910 u_char ier; 3911 u_char cfcr; 3912 u_char mcr; 3913}; 3914 3915static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3916static void siocnclose __P((struct siocnstate *sp, Port_t iobase)); 3917static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed)); 3918static void siocntxwait __P((Port_t iobase)); 3919 3920static cn_probe_t siocnprobe; 3921static cn_init_t siocninit; 3922static cn_checkc_t siocncheckc; 3923static cn_getc_t siocngetc; 3924static cn_putc_t siocnputc; 3925 3926#ifdef __i386__ 3927CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc, siocnputc); 3928 3929#endif 3930 3931/* To get the GDB related variables */ 3932#if DDB > 0 3933#include <ddb/ddb.h> 3934#endif 3935 3936static void 3937siocntxwait(iobase) 3938 Port_t iobase; 3939{ 3940 int timo; 3941 3942 /* 3943 * Wait for any pending transmission to finish. Required to avoid 3944 * the UART lockup bug when the speed is changed, and for normal 3945 * transmits. 3946 */ 3947 timo = 100000; 3948 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3949 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3950 ; 3951} 3952 3953/* 3954 * Read the serial port specified and try to figure out what speed 3955 * it's currently running at. We're assuming the serial port has 3956 * been initialized and is basicly idle. This routine is only intended 3957 * to be run at system startup. 3958 * 3959 * If the value read from the serial port doesn't make sense, return 0. 3960 */ 3961 3962static speed_t 3963siocngetspeed(iobase, table) 3964 Port_t iobase; 3965 struct speedtab *table; 3966{ 3967 int code; 3968 u_char dlbh; 3969 u_char dlbl; 3970 u_char cfcr; 3971 3972 cfcr = inb(iobase + com_cfcr); 3973 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3974 3975 dlbl = inb(iobase + com_dlbl); 3976 dlbh = inb(iobase + com_dlbh); 3977 3978 outb(iobase + com_cfcr, cfcr); 3979 3980 code = dlbh << 8 | dlbl; 3981 3982 for ( ; table->sp_speed != -1; table++) 3983 if (table->sp_code == code) 3984 return (table->sp_speed); 3985 3986 return 0; /* didn't match anything sane */ 3987} 3988 3989static void 3990siocnopen(sp, iobase, speed) 3991 struct siocnstate *sp; 3992 Port_t iobase; 3993 int speed; 3994{ 3995 int divisor; 3996 u_char dlbh; 3997 u_char dlbl; 3998 3999 /* 4000 * Save all the device control registers except the fifo register 4001 * and set our default ones (cs8 -parenb speed=comdefaultrate). 4002 * We can't save the fifo register since it is read-only. 4003 */ 4004 sp->ier = inb(iobase + com_ier); 4005 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 4006 siocntxwait(iobase); 4007 sp->cfcr = inb(iobase + com_cfcr); 4008 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 4009 sp->dlbl = inb(iobase + com_dlbl); 4010 sp->dlbh = inb(iobase + com_dlbh); 4011 /* 4012 * Only set the divisor registers if they would change, since on 4013 * some 16550 incompatibles (Startech), setting them clears the 4014 * data input register. This also reduces the effects of the 4015 * UMC8669F bug. 4016 */ 4017 divisor = ttspeedtab(speed, comspeedtab); 4018 dlbl = divisor & 0xFF; 4019 if (sp->dlbl != dlbl) 4020 outb(iobase + com_dlbl, dlbl); 4021 dlbh = (u_int) divisor >> 8; 4022 if (sp->dlbh != dlbh) 4023 outb(iobase + com_dlbh, dlbh); 4024 outb(iobase + com_cfcr, CFCR_8BITS); 4025 sp->mcr = inb(iobase + com_mcr); 4026 /* 4027 * We don't want interrupts, but must be careful not to "disable" 4028 * them by clearing the MCR_IENABLE bit, since that might cause 4029 * an interrupt by floating the IRQ line. 4030 */ 4031 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 4032} 4033 4034static void 4035siocnclose(sp, iobase) 4036 struct siocnstate *sp; 4037 Port_t iobase; 4038{ 4039 /* 4040 * Restore the device control registers. 4041 */ 4042 siocntxwait(iobase); 4043 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 4044 if (sp->dlbl != inb(iobase + com_dlbl)) 4045 outb(iobase + com_dlbl, sp->dlbl); 4046 if (sp->dlbh != inb(iobase + com_dlbh)) 4047 outb(iobase + com_dlbh, sp->dlbh); 4048 outb(iobase + com_cfcr, sp->cfcr); 4049 /* 4050 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 4051 */ 4052 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 4053 outb(iobase + com_ier, sp->ier); 4054} 4055 4056static void 4057siocnprobe(cp) 4058 struct consdev *cp; 4059{ 4060 speed_t boot_speed; 4061 u_char cfcr; 4062 int s, unit; 4063 struct siocnstate sp; 4064 4065 /* 4066 * Find our first enabled console, if any. If it is a high-level 4067 * console device, then initialize it and return successfully. 4068 * If it is a low-level console device, then initialize it and 4069 * return unsuccessfully. It must be initialized in both cases 4070 * for early use by console drivers and debuggers. Initializing 4071 * the hardware is not necessary in all cases, since the i/o 4072 * routines initialize it on the fly, but it is necessary if 4073 * input might arrive while the hardware is switched back to an 4074 * uninitialized state. We can't handle multiple console devices 4075 * yet because our low-level routines don't take a device arg. 4076 * We trust the user to set the console flags properly so that we 4077 * don't need to probe. 4078 */ 4079 cp->cn_pri = CN_DEAD; 4080 4081 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ 4082 int flags; 4083 int disabled; 4084 if (resource_int_value("sio", unit, "disabled", &disabled) == 0) { 4085 if (disabled) 4086 continue; 4087 } 4088 if (resource_int_value("sio", unit, "flags", &flags)) 4089 continue; 4090 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) { 4091 int port; 4092 Port_t iobase; 4093 4094 if (resource_int_value("sio", unit, "port", &port)) 4095 continue; 4096 iobase = port; 4097 s = spltty(); 4098 if (boothowto & RB_SERIAL) { 4099 boot_speed = siocngetspeed(iobase, comspeedtab); 4100 if (boot_speed) 4101 comdefaultrate = boot_speed; 4102 } 4103 4104 /* 4105 * Initialize the divisor latch. We can't rely on 4106 * siocnopen() to do this the first time, since it 4107 * avoids writing to the latch if the latch appears 4108 * to have the correct value. Also, if we didn't 4109 * just read the speed from the hardware, then we 4110 * need to set the speed in hardware so that 4111 * switching it later is null. 4112 */ 4113 cfcr = inb(iobase + com_cfcr); 4114 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 4115 outb(iobase + com_dlbl, 4116 COMBRD(comdefaultrate) & 0xff); 4117 outb(iobase + com_dlbh, 4118 (u_int) COMBRD(comdefaultrate) >> 8); 4119 outb(iobase + com_cfcr, cfcr); 4120 4121 siocnopen(&sp, iobase, comdefaultrate); 4122 4123 splx(s); 4124 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) { 4125 cp->cn_dev = makedev(CDEV_MAJOR, unit); 4126 cp->cn_pri = COM_FORCECONSOLE(flags) 4127 || boothowto & RB_SERIAL 4128 ? CN_REMOTE : CN_NORMAL; 4129 siocniobase = iobase; 4130 siocnunit = unit; 4131 } 4132 if (COM_DEBUGGER(flags)) { 4133 printf("sio%d: gdb debugging port\n", unit); 4134 siogdbiobase = iobase; 4135 siogdbunit = unit; 4136#if DDB > 0 4137 gdbdev = makedev(CDEV_MAJOR, unit); 4138 gdb_getc = siocngetc; 4139 gdb_putc = siocnputc; 4140#endif 4141 } 4142 } 4143 } 4144#ifdef __i386__ 4145#if DDB > 0 4146 /* 4147 * XXX Ugly Compatability. 4148 * If no gdb port has been specified, set it to be the console 4149 * as some configuration files don't specify the gdb port. 4150 */ 4151 if (gdbdev == NODEV && (boothowto & RB_GDB)) { 4152 printf("Warning: no GDB port specified. Defaulting to sio%d.\n", 4153 siocnunit); 4154 printf("Set flag 0x80 on desired GDB port in your\n"); 4155 printf("configuration file (currently sio only).\n"); 4156 siogdbiobase = siocniobase; 4157 siogdbunit = siocnunit; 4158 gdbdev = makedev(CDEV_MAJOR, siocnunit); 4159 gdb_getc = siocngetc; 4160 gdb_putc = siocnputc; 4161 } 4162#endif 4163#endif 4164} 4165 4166#ifdef __alpha__ 4167 4168CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc); 4169 4170int 4171siocnattach(port, speed) 4172 int port; 4173 int speed; 4174{ 4175 int s; 4176 u_char cfcr; 4177 struct siocnstate sp; 4178 4179 siocniobase = port; 4180 comdefaultrate = speed; 4181 sio_consdev.cn_pri = CN_NORMAL; 4182 sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0); 4183 4184 s = spltty(); 4185 4186 /* 4187 * Initialize the divisor latch. We can't rely on 4188 * siocnopen() to do this the first time, since it 4189 * avoids writing to the latch if the latch appears 4190 * to have the correct value. Also, if we didn't 4191 * just read the speed from the hardware, then we 4192 * need to set the speed in hardware so that 4193 * switching it later is null. 4194 */ 4195 cfcr = inb(siocniobase + com_cfcr); 4196 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 4197 outb(siocniobase + com_dlbl, 4198 COMBRD(comdefaultrate) & 0xff); 4199 outb(siocniobase + com_dlbh, 4200 (u_int) COMBRD(comdefaultrate) >> 8); 4201 outb(siocniobase + com_cfcr, cfcr); 4202 4203 siocnopen(&sp, siocniobase, comdefaultrate); 4204 splx(s); 4205 4206 cn_tab = &sio_consdev; 4207 return 0; 4208} 4209 4210int 4211siogdbattach(port, speed) 4212 int port; 4213 int speed; 4214{ 4215 int s; 4216 u_char cfcr; 4217 struct siocnstate sp; 4218 4219 siogdbiobase = port; 4220 gdbdefaultrate = speed; 4221 4222 s = spltty(); 4223 4224 /* 4225 * Initialize the divisor latch. We can't rely on 4226 * siocnopen() to do this the first time, since it 4227 * avoids writing to the latch if the latch appears 4228 * to have the correct value. Also, if we didn't 4229 * just read the speed from the hardware, then we 4230 * need to set the speed in hardware so that 4231 * switching it later is null. 4232 */ 4233 cfcr = inb(siogdbiobase + com_cfcr); 4234 outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr); 4235 outb(siogdbiobase + com_dlbl, 4236 COMBRD(gdbdefaultrate) & 0xff); 4237 outb(siogdbiobase + com_dlbh, 4238 (u_int) COMBRD(gdbdefaultrate) >> 8); 4239 outb(siogdbiobase + com_cfcr, cfcr); 4240 4241 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 4242 splx(s); 4243 4244 return 0; 4245} 4246 4247#endif 4248 4249static void 4250siocninit(cp) 4251 struct consdev *cp; 4252{ 4253 comconsole = DEV_TO_UNIT(cp->cn_dev); 4254} 4255 4256static int 4257siocncheckc(dev) 4258 dev_t dev; 4259{ 4260 int c; 4261 Port_t iobase; 4262 int s; 4263 struct siocnstate sp; 4264 4265 if (minor(dev) == siogdbunit) 4266 iobase = siogdbiobase; 4267 else 4268 iobase = siocniobase; 4269 s = spltty(); 4270 siocnopen(&sp, iobase, comdefaultrate); 4271 if (inb(iobase + com_lsr) & LSR_RXRDY) 4272 c = inb(iobase + com_data); 4273 else 4274 c = -1; 4275 siocnclose(&sp, iobase); 4276 splx(s); 4277 return (c); 4278} 4279 4280 4281int 4282siocngetc(dev) 4283 dev_t dev; 4284{ 4285 int c; 4286 Port_t iobase; 4287 int s; 4288 struct siocnstate sp; 4289 4290 if (minor(dev) == siogdbunit) 4291 iobase = siogdbiobase; 4292 else 4293 iobase = siocniobase; 4294 s = spltty(); 4295 siocnopen(&sp, iobase, comdefaultrate); 4296 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 4297 ; 4298 c = inb(iobase + com_data); 4299 siocnclose(&sp, iobase); 4300 splx(s); 4301 return (c); 4302} 4303 4304void 4305siocnputc(dev, c) 4306 dev_t dev; 4307 int c; 4308{ 4309 int s; 4310 struct siocnstate sp; 4311 Port_t iobase; 4312 4313 if (minor(dev) == siogdbunit) 4314 iobase = siogdbiobase; 4315 else 4316 iobase = siocniobase; 4317 s = spltty(); 4318 siocnopen(&sp, iobase, comdefaultrate); 4319 siocntxwait(iobase); 4320 outb(iobase + com_data, c); 4321 siocnclose(&sp, iobase); 4322 splx(s); 4323} 4324 4325#ifdef __alpha__ 4326int 4327siogdbgetc() 4328{ 4329 int c; 4330 Port_t iobase; 4331 int s; 4332 struct siocnstate sp; 4333 4334 iobase = siogdbiobase; 4335 s = spltty(); 4336 siocnopen(&sp, iobase, gdbdefaultrate); 4337 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 4338 ; 4339 c = inb(iobase + com_data); 4340 siocnclose(&sp, iobase); 4341 splx(s); 4342 return (c); 4343} 4344 4345void 4346siogdbputc(c) 4347 int c; 4348{ 4349 int s; 4350 struct siocnstate sp; 4351 4352 s = spltty(); 4353 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 4354 siocntxwait(siogdbiobase); 4355 outb(siogdbiobase + com_data, c); 4356 siocnclose(&sp, siogdbiobase); 4357 splx(s); 4358} 4359#endif 4360 4361DEV_DRIVER_MODULE(sio, isa, sio_driver, sio_devclass, sio_cdevsw, 0, 0); 4362 4363#ifdef PC98 4364/* 4365 * pc98 local function 4366 */ 4367 4368static void 4369com_tiocm_set(struct com_s *com, int msr) 4370{ 4371 int s; 4372 int tmp = 0; 4373 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 4374 4375 s=spltty(); 4376 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 4377 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4378 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 4379 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4380 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4381 pc98_i8251_clear_or_cmd( com, mask, tmp ); 4382 splx(s); 4383} 4384 4385static void 4386com_tiocm_bis(struct com_s *com, int msr) 4387{ 4388 int s; 4389 int tmp = 0; 4390 4391 s=spltty(); 4392 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4393 tmp |= CMD8251_TxEN|CMD8251_RxEN; 4394 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4395 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4396 4397 pc98_i8251_or_cmd( com, tmp ); 4398 splx(s); 4399} 4400 4401static void 4402com_tiocm_bic(struct com_s *com, int msr) 4403{ 4404 int s; 4405 int tmp = msr; 4406 4407 s=spltty(); 4408 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4409 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4410 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4411 4412 pc98_i8251_clear_cmd( com, tmp ); 4413 splx(s); 4414} 4415 4416static int 4417com_tiocm_get(struct com_s *com) 4418{ 4419 return( com->pc98_prev_modem_status ); 4420} 4421 4422static int 4423com_tiocm_get_delta(struct com_s *com) 4424{ 4425 int tmp; 4426 4427 tmp = com->pc98_modem_delta; 4428 com->pc98_modem_delta = 0; 4429 return( tmp ); 4430} 4431 4432/* convert to TIOCM_?? ( ioctl.h ) */ 4433static int 4434pc98_get_modem_status(struct com_s *com) 4435{ 4436 int stat, stat2; 4437 register int msr; 4438 4439 stat = inb(com->sts_port); 4440 stat2 = inb(com->in_modem_port); 4441 msr = com->pc98_prev_modem_status 4442 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4443 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 4444 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 4445 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 4446 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 4447#if COM_CARRIER_DETECT_EMULATE 4448 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 4449 msr |= TIOCM_CAR; 4450 } 4451#endif 4452 return(msr); 4453} 4454 4455static void 4456pc98_check_msr(void* chan) 4457{ 4458 int msr, delta; 4459 int s; 4460 register struct tty *tp; 4461 struct com_s *com; 4462 int mynor; 4463 int unit; 4464 dev_t dev; 4465 4466 dev=(dev_t)chan; 4467 mynor = minor(dev); 4468 unit = MINOR_TO_UNIT(mynor); 4469 com = com_addr(unit); 4470 tp = com->tp; 4471 4472 s = spltty(); 4473 msr = pc98_get_modem_status(com); 4474 /* make change flag */ 4475 delta = msr ^ com->pc98_prev_modem_status; 4476 if ( delta & TIOCM_CAR ) { 4477 if ( com->modem_car_chg_timer ) { 4478 if ( -- com->modem_car_chg_timer ) 4479 msr ^= TIOCM_CAR; 4480 } else { 4481 if ((com->modem_car_chg_timer = (msr & TIOCM_CAR) ? 4482 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE) != 0) 4483 msr ^= TIOCM_CAR; 4484 } 4485 } else 4486 com->modem_car_chg_timer = 0; 4487 delta = ( msr ^ com->pc98_prev_modem_status ) & 4488 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4489 com->pc98_prev_modem_status = msr; 4490 delta = ( com->pc98_modem_delta |= delta ); 4491 splx(s); 4492 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 4493 if ( delta ) { 4494 commint(dev); 4495 } 4496 timeout(pc98_check_msr, (caddr_t)dev, 4497 PC98_CHECK_MODEM_INTERVAL); 4498 } else { 4499 com->modem_checking = 0; 4500 } 4501} 4502 4503static void 4504pc98_msrint_start(dev_t dev) 4505{ 4506 struct com_s *com; 4507 int mynor; 4508 int unit; 4509 int s = spltty(); 4510 4511 mynor = minor(dev); 4512 unit = MINOR_TO_UNIT(mynor); 4513 com = com_addr(unit); 4514 /* modem control line check routine envoke interval is 1/10 sec */ 4515 if ( com->modem_checking == 0 ) { 4516 com->pc98_prev_modem_status = pc98_get_modem_status(com); 4517 com->pc98_modem_delta = 0; 4518 timeout(pc98_check_msr, (caddr_t)dev, 4519 PC98_CHECK_MODEM_INTERVAL); 4520 com->modem_checking = 1; 4521 } 4522 splx(s); 4523} 4524 4525static void 4526pc98_disable_i8251_interrupt(struct com_s *com, int mod) 4527{ 4528 /* disable interrupt */ 4529 register int tmp; 4530 4531 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4532 COM_INT_DISABLE 4533 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4534 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 4535 COM_INT_ENABLE 4536} 4537 4538static void 4539pc98_enable_i8251_interrupt(struct com_s *com, int mod) 4540{ 4541 register int tmp; 4542 4543 COM_INT_DISABLE 4544 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4545 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 4546 COM_INT_ENABLE 4547} 4548 4549static int 4550pc98_check_i8251_interrupt(struct com_s *com) 4551{ 4552 return ( com->intr_enable & 0x07 ); 4553} 4554 4555static void 4556pc98_i8251_clear_cmd(struct com_s *com, int x) 4557{ 4558 int tmp; 4559 4560 COM_INT_DISABLE 4561 tmp = com->pc98_prev_siocmd & ~(x); 4562 outb(com->cmd_port, tmp); 4563 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4564 COM_INT_ENABLE 4565} 4566 4567static void 4568pc98_i8251_or_cmd(struct com_s *com, int x) 4569{ 4570 int tmp; 4571 4572 COM_INT_DISABLE 4573 tmp = com->pc98_prev_siocmd | (x); 4574 outb(com->cmd_port, tmp); 4575 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4576 COM_INT_ENABLE 4577} 4578 4579static void 4580pc98_i8251_set_cmd(struct com_s *com, int x) 4581{ 4582 int tmp; 4583 4584 COM_INT_DISABLE 4585 tmp = (x); 4586 outb(com->cmd_port, tmp); 4587 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4588 COM_INT_ENABLE 4589} 4590 4591static void 4592pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4593{ 4594 int tmp; 4595 COM_INT_DISABLE 4596 tmp = com->pc98_prev_siocmd & ~(clr); 4597 tmp |= (x); 4598 outb(com->cmd_port, tmp); 4599 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4600 COM_INT_ENABLE 4601} 4602 4603static int 4604pc98_i8251_get_cmd(struct com_s *com) 4605{ 4606 return com->pc98_prev_siocmd; 4607} 4608 4609static int 4610pc98_i8251_get_mod(struct com_s *com) 4611{ 4612 return com->pc98_prev_siomod; 4613} 4614 4615static void 4616pc98_i8251_reset(struct com_s *com, int mode, int command) 4617{ 4618 outb(com->cmd_port, 0); /* dummy */ 4619 DELAY(2); 4620 outb(com->cmd_port, 0); /* dummy */ 4621 DELAY(2); 4622 outb(com->cmd_port, 0); /* dummy */ 4623 DELAY(2); 4624 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4625 DELAY(2); 4626 outb(com->cmd_port, mode ); /* mode register */ 4627 com->pc98_prev_siomod = mode; 4628 DELAY(2); 4629 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4630} 4631 4632static void 4633pc98_check_sysclock(void) 4634{ 4635 /* get system clock from port */ 4636 if ( pc98_machine_type & M_8M ) { 4637 /* 8 MHz system & H98 */ 4638 sysclock = 8; 4639 } else { 4640 /* 5 MHz system */ 4641 sysclock = 5; 4642 } 4643} 4644 4645static void 4646com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4647{ 4648 int cfcr=0, count; 4649 int previnterrupt; 4650 4651 count = pc98_ttspeedtab( com, speed ); 4652 if ( count < 0 ) return; 4653 4654 previnterrupt = pc98_check_i8251_interrupt(com); 4655 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4656 4657 switch ( cflag&CSIZE ) { 4658 case CS5: 4659 cfcr = MOD8251_5BITS; break; 4660 case CS6: 4661 cfcr = MOD8251_6BITS; break; 4662 case CS7: 4663 cfcr = MOD8251_7BITS; break; 4664 case CS8: 4665 cfcr = MOD8251_8BITS; break; 4666 } 4667 if ( cflag&PARENB ) { 4668 if ( cflag&PARODD ) 4669 cfcr |= MOD8251_PODD; 4670 else 4671 cfcr |= MOD8251_PEVEN; 4672 } else 4673 cfcr |= MOD8251_PDISAB; 4674 4675 if ( cflag&CSTOPB ) 4676 cfcr |= MOD8251_STOP2; 4677 else 4678 cfcr |= MOD8251_STOP1; 4679 4680 if ( count & 0x10000 ) 4681 cfcr |= MOD8251_CLKX1; 4682 else 4683 cfcr |= MOD8251_CLKX16; 4684 4685 if (epson_machine_id != 0x20) { /* XXX */ 4686 int tmp; 4687 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4688 ; 4689 } 4690 /* set baud rate from ospeed */ 4691 pc98_set_baud_rate( com, count ); 4692 4693 if ( cfcr != pc98_i8251_get_mod(com) ) 4694 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4695 4696 pc98_enable_i8251_interrupt( com, previnterrupt ); 4697} 4698 4699static int 4700pc98_ttspeedtab(struct com_s *com, int speed) 4701{ 4702 int if_type, effect_sp, count = -1, mod; 4703 4704 if_type = com->pc98_if_type & 0x0f; 4705 4706 switch (com->pc98_if_type) { 4707 case COM_IF_INTERNAL: 4708 if (PC98SIO_baud_rate_port(if_type) != -1) { 4709 count = ttspeedtab(speed, if_8251_type[if_type].speedtab); 4710 if (count > 0) { 4711 count |= COM1_EXT_CLOCK; 4712 break; 4713 } 4714 } 4715 4716 /* for *1CLK asynchronous! mode, TEFUTEFU */ 4717 mod = (sysclock == 5) ? 2457600 : 1996800; 4718 effect_sp = ttspeedtab( speed, pc98speedtab ); 4719 if ( effect_sp < 0 ) /* XXX */ 4720 effect_sp = ttspeedtab( (speed - 1), pc98speedtab ); 4721 if ( effect_sp <= 0 ) 4722 return effect_sp; 4723 if ( effect_sp == speed ) 4724 mod /= 16; 4725 if ( mod % effect_sp ) 4726 return(-1); 4727 count = mod / effect_sp; 4728 if ( count > 65535 ) 4729 return(-1); 4730 if ( effect_sp != speed ) 4731 count |= 0x10000; 4732 break; 4733 case COM_IF_PC9861K_1: 4734 case COM_IF_PC9861K_2: 4735 count = 1; 4736 break; 4737 case COM_IF_IND_SS_1: 4738 case COM_IF_IND_SS_2: 4739 case COM_IF_PIO9032B_1: 4740 case COM_IF_PIO9032B_2: 4741 if ( speed == 0 ) return 0; 4742 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4743 break; 4744 case COM_IF_B98_01_1: 4745 case COM_IF_B98_01_2: 4746 if ( speed == 0 ) return 0; 4747 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4748#ifdef B98_01_OLD 4749 if (count == 0 || count == 1) { 4750 count += 4; 4751 count |= 0x20000; /* x1 mode for 76800 and 153600 */ 4752 } 4753#endif 4754 break; 4755 } 4756 4757 return count; 4758} 4759 4760static void 4761pc98_set_baud_rate( struct com_s *com, int count ) 4762{ 4763 int if_type, io, s; 4764 4765 if_type = com->pc98_if_type & 0x0f; 4766 io = com->iobase & 0xff00; 4767 4768 switch (com->pc98_if_type) { 4769 case COM_IF_INTERNAL: 4770 if (PC98SIO_baud_rate_port(if_type) != -1) { 4771 if (count & COM1_EXT_CLOCK) { 4772 outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff); 4773 break; 4774 } else { 4775 outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09); 4776 } 4777 } 4778 4779 if ( count < 0 ) { 4780 printf( "[ Illegal count : %d ]", count ); 4781 return; 4782 } else if ( count == 0 ) 4783 return; 4784 /* set i8253 */ 4785 s = splclock(); 4786 if (count != 3) 4787 outb( 0x77, 0xb6 ); 4788 else 4789 outb( 0x77, 0xb4 ); 4790 outb( 0x5f, 0); 4791 outb( 0x75, count & 0xff ); 4792 outb( 0x5f, 0); 4793 outb( 0x75, (count >> 8) & 0xff ); 4794 splx(s); 4795 break; 4796 case COM_IF_IND_SS_1: 4797 case COM_IF_IND_SS_2: 4798 outb(io | PC98SIO_intr_ctrl_port(if_type), 0); 4799 outb(io | PC98SIO_baud_rate_port(if_type), 0); 4800 outb(io | PC98SIO_baud_rate_port(if_type), 0xc0); 4801 outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80); 4802 outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff); 4803 break; 4804 case COM_IF_PIO9032B_1: 4805 case COM_IF_PIO9032B_2: 4806 outb(io | PC98SIO_baud_rate_port(if_type), count); 4807 break; 4808 case COM_IF_B98_01_1: 4809 case COM_IF_B98_01_2: 4810 outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f); 4811#ifdef B98_01_OLD 4812 /* 4813 * Some old B98_01 board should be controlled 4814 * in different way, but this hasn't been tested yet. 4815 */ 4816 outb(io | PC98SIO_func_port(if_type), 4817 (count & 0x20000) ? 0xf0 : 0xf2); 4818#endif 4819 break; 4820 } 4821} 4822static int 4823pc98_check_if_type(device_t dev, struct siodev *iod) 4824{ 4825 int irr, io, if_type, tmp; 4826 static short irq_tab[2][8] = { 4827 { 3, 5, 6, 9, 10, 12, 13, -1}, 4828 { 3, 10, 12, 13, 5, 6, 9, -1} 4829 }; 4830 4831 iod->if_type = if_type = (device_get_flags(dev) >> 24) & 0xff; 4832 if ((if_type < 0 || if_type > COM_IF_END1) && 4833 (if_type < 0x10 || if_type > COM_IF_END2)) 4834 return(-1); 4835 if_type &= 0x0f; 4836 iod->irq = 0; 4837 io = isa_get_port(dev) & 0xff00; 4838 4839 if (IS_8251(iod->if_type)) { 4840 if (PC98SIO_func_port(if_type) != -1) { 4841 outb(io | PC98SIO_func_port(if_type), 0xf2); 4842 tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab); 4843 if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1) 4844 outb(io | PC98SIO_baud_rate_port(if_type), tmp); 4845 } 4846 4847 iod->cmd = io | PC98SIO_cmd_port(if_type); 4848 iod->sts = io | PC98SIO_sts_port(if_type); 4849 iod->mod = io | PC98SIO_in_modem_port(if_type); 4850 iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type); 4851 4852 if (iod->if_type == COM_IF_INTERNAL) { 4853 iod->irq = 4; 4854 4855 /* XXX check new internal port. */ 4856 outb(0x13a, 0); 4857 DELAY(10); 4858 for (tmp = 0; tmp < 100; tmp++) { 4859 if ((inb(0x13a) & 0x80) == 0) { 4860 PC98SIO_baud_rate_port(if_type) = 0x13a; 4861 if_8251_type[if_type].name = " (internal fast)"; 4862 if_8251_type[if_type].speedtab = pc98fast_speedtab; 4863 break; 4864 } 4865 DELAY(1); 4866 } 4867 } else { 4868 tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask; 4869 if ((isa_get_port(dev) & 0xff) == IO_COM2) 4870 iod->irq = irq_tab[0][tmp]; 4871 else 4872 iod->irq = irq_tab[1][tmp]; 4873 } 4874 } else { 4875 irr = if_16550a_type[if_type].irr_read; 4876#ifdef COM_MULTIPORT 4877 if (!COM_ISMULTIPORT(device_get_flags(dev)) || 4878 device_get_unit(dev) == COM_MPMASTER(device_get_flags(dev))) 4879#endif 4880 if (irr != -1) { 4881 tmp = inb(io | irr); 4882 if (isa_get_port(dev) & 0x01) /* XXX depend on RSB-384 */ 4883 iod->irq = irq_tab[1][tmp >> 3]; 4884 else 4885 iod->irq = irq_tab[0][tmp & 0x07]; 4886 } 4887 } 4888 if ( iod->irq == -1 ) return -1; 4889 4890 return 0; 4891} 4892static int 4893pc98_set_ioport( struct com_s *com, int id_flags ) 4894{ 4895 int io, if_type; 4896 4897 if_type = (id_flags >> 24) & 0xff; 4898 if (IS_8251(if_type)) { 4899 pc98_check_sysclock(); 4900 io = com->iobase & 0xff00; 4901 com->pc98_if_type = if_type; 4902 if_type &= 0x0f; 4903 com->data_port = io | PC98SIO_data_port(if_type); 4904 com->cmd_port = io | PC98SIO_cmd_port(if_type); 4905 com->sts_port = io | PC98SIO_sts_port(if_type); 4906 com->in_modem_port = io | PC98SIO_in_modem_port(if_type); 4907 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(if_type); 4908 return 0; 4909 } 4910 4911 return -1; 4912} 4913#endif /* PC98 defined */
| 3681static int 3682commctl(com, bits, how) 3683 struct com_s *com; 3684 int bits; 3685 int how; 3686{ 3687 int mcr; 3688 int msr; 3689 3690 if (how == DMGET) { 3691 bits = TIOCM_LE; /* XXX - always enabled while open */ 3692 mcr = com->mcr_image; 3693 if (mcr & MCR_DTR) 3694 bits |= TIOCM_DTR; 3695 if (mcr & MCR_RTS) 3696 bits |= TIOCM_RTS; 3697 msr = com->prev_modem_status; 3698 if (msr & MSR_CTS) 3699 bits |= TIOCM_CTS; 3700 if (msr & MSR_DCD) 3701 bits |= TIOCM_CD; 3702 if (msr & MSR_DSR) 3703 bits |= TIOCM_DSR; 3704 /* 3705 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3706 * more volatile by reading the modem status a lot. Perhaps 3707 * we should latch both bits until the status is read here. 3708 */ 3709 if (msr & (MSR_RI | MSR_TERI)) 3710 bits |= TIOCM_RI; 3711 return (bits); 3712 } 3713 mcr = 0; 3714 if (bits & TIOCM_DTR) 3715 mcr |= MCR_DTR; 3716 if (bits & TIOCM_RTS) 3717 mcr |= MCR_RTS; 3718 if (com->gone) 3719 return(0); 3720 disable_intr(); 3721 switch (how) { 3722 case DMSET: 3723 outb(com->modem_ctl_port, 3724 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3725 break; 3726 case DMBIS: 3727 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3728 break; 3729 case DMBIC: 3730 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3731 break; 3732 } 3733 enable_intr(); 3734 return (0); 3735} 3736 3737static void 3738siosettimeout() 3739{ 3740 struct com_s *com; 3741 bool_t someopen; 3742 int unit; 3743 3744 /* 3745 * Set our timeout period to 1 second if no polled devices are open. 3746 * Otherwise set it to max(1/200, 1/hz). 3747 * Enable timeouts iff some device is open. 3748 */ 3749 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3750 sio_timeout = hz; 3751 someopen = FALSE; 3752 for (unit = 0; unit < NSIOTOT; ++unit) { 3753 com = com_addr(unit); 3754 if (com != NULL && com->tp != NULL 3755 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3756 someopen = TRUE; 3757 if (com->poll || com->poll_output) { 3758 sio_timeout = hz > 200 ? hz / 200 : 1; 3759 break; 3760 } 3761 } 3762 } 3763 if (someopen) { 3764 sio_timeouts_until_log = hz / sio_timeout; 3765 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3766 sio_timeout); 3767 } else { 3768 /* Flush error messages, if any. */ 3769 sio_timeouts_until_log = 1; 3770 comwakeup((void *)NULL); 3771 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3772 } 3773} 3774 3775static void 3776comwakeup(chan) 3777 void *chan; 3778{ 3779 struct com_s *com; 3780 int unit; 3781 3782 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3783 3784 /* 3785 * Recover from lost output interrupts. 3786 * Poll any lines that don't use interrupts. 3787 */ 3788 for (unit = 0; unit < NSIOTOT; ++unit) { 3789 com = com_addr(unit); 3790 if (com != NULL && !com->gone 3791 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3792 disable_intr(); 3793 siointr1(com); 3794 enable_intr(); 3795 } 3796 } 3797 3798 /* 3799 * Check for and log errors, but not too often. 3800 */ 3801 if (--sio_timeouts_until_log > 0) 3802 return; 3803 sio_timeouts_until_log = hz / sio_timeout; 3804 for (unit = 0; unit < NSIOTOT; ++unit) { 3805 int errnum; 3806 3807 com = com_addr(unit); 3808 if (com == NULL) 3809 continue; 3810 if (com->gone) 3811 continue; 3812 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3813 u_int delta; 3814 u_long total; 3815 3816 disable_intr(); 3817 delta = com->delta_error_counts[errnum]; 3818 com->delta_error_counts[errnum] = 0; 3819 enable_intr(); 3820 if (delta == 0) 3821 continue; 3822 total = com->error_counts[errnum] += delta; 3823 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3824 unit, delta, error_desc[errnum], 3825 delta == 1 ? "" : "s", total); 3826 } 3827 } 3828} 3829 3830#ifdef PC98 3831/* commint is called when modem control line changes */ 3832static void 3833commint(dev_t dev) 3834{ 3835 register struct tty *tp; 3836 int stat,delta; 3837 struct com_s *com; 3838 int mynor,unit; 3839 3840 mynor = minor(dev); 3841 unit = MINOR_TO_UNIT(mynor); 3842 com = com_addr(unit); 3843 tp = com->tp; 3844 3845 stat = com_tiocm_get(com); 3846 delta = com_tiocm_get_delta(com); 3847 3848 if (com->state & CS_CTS_OFLOW) { 3849 if (stat & TIOCM_CTS) 3850 com->state |= CS_ODEVREADY; 3851 else 3852 com->state &= ~CS_ODEVREADY; 3853 } 3854 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3855 if (stat & TIOCM_CAR ) 3856 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3857 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3858 /* negate DTR, RTS */ 3859 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3860 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3861 /* disable IENABLE */ 3862 com_int_TxRx_disable( com ); 3863 } 3864 } 3865} 3866#endif 3867 3868static void 3869disc_optim(tp, t, com) 3870 struct tty *tp; 3871 struct termios *t; 3872 struct com_s *com; 3873{ 3874 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3875 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3876 && (!(t->c_iflag & PARMRK) 3877 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3878 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3879 && linesw[tp->t_line].l_rint == ttyinput) 3880 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3881 else 3882 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3883 com->hotchar = linesw[tp->t_line].l_hotchar; 3884} 3885 3886/* 3887 * Following are all routines needed for SIO to act as console 3888 */ 3889#include <sys/cons.h> 3890 3891struct siocnstate { 3892 u_char dlbl; 3893 u_char dlbh; 3894 u_char ier; 3895 u_char cfcr; 3896 u_char mcr; 3897}; 3898 3899static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3900static void siocnclose __P((struct siocnstate *sp, Port_t iobase)); 3901static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed)); 3902static void siocntxwait __P((Port_t iobase)); 3903 3904static cn_probe_t siocnprobe; 3905static cn_init_t siocninit; 3906static cn_checkc_t siocncheckc; 3907static cn_getc_t siocngetc; 3908static cn_putc_t siocnputc; 3909 3910#ifdef __i386__ 3911CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc, siocnputc); 3912 3913#endif 3914 3915/* To get the GDB related variables */ 3916#if DDB > 0 3917#include <ddb/ddb.h> 3918#endif 3919 3920static void 3921siocntxwait(iobase) 3922 Port_t iobase; 3923{ 3924 int timo; 3925 3926 /* 3927 * Wait for any pending transmission to finish. Required to avoid 3928 * the UART lockup bug when the speed is changed, and for normal 3929 * transmits. 3930 */ 3931 timo = 100000; 3932 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3933 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3934 ; 3935} 3936 3937/* 3938 * Read the serial port specified and try to figure out what speed 3939 * it's currently running at. We're assuming the serial port has 3940 * been initialized and is basicly idle. This routine is only intended 3941 * to be run at system startup. 3942 * 3943 * If the value read from the serial port doesn't make sense, return 0. 3944 */ 3945 3946static speed_t 3947siocngetspeed(iobase, table) 3948 Port_t iobase; 3949 struct speedtab *table; 3950{ 3951 int code; 3952 u_char dlbh; 3953 u_char dlbl; 3954 u_char cfcr; 3955 3956 cfcr = inb(iobase + com_cfcr); 3957 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3958 3959 dlbl = inb(iobase + com_dlbl); 3960 dlbh = inb(iobase + com_dlbh); 3961 3962 outb(iobase + com_cfcr, cfcr); 3963 3964 code = dlbh << 8 | dlbl; 3965 3966 for ( ; table->sp_speed != -1; table++) 3967 if (table->sp_code == code) 3968 return (table->sp_speed); 3969 3970 return 0; /* didn't match anything sane */ 3971} 3972 3973static void 3974siocnopen(sp, iobase, speed) 3975 struct siocnstate *sp; 3976 Port_t iobase; 3977 int speed; 3978{ 3979 int divisor; 3980 u_char dlbh; 3981 u_char dlbl; 3982 3983 /* 3984 * Save all the device control registers except the fifo register 3985 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3986 * We can't save the fifo register since it is read-only. 3987 */ 3988 sp->ier = inb(iobase + com_ier); 3989 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3990 siocntxwait(iobase); 3991 sp->cfcr = inb(iobase + com_cfcr); 3992 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3993 sp->dlbl = inb(iobase + com_dlbl); 3994 sp->dlbh = inb(iobase + com_dlbh); 3995 /* 3996 * Only set the divisor registers if they would change, since on 3997 * some 16550 incompatibles (Startech), setting them clears the 3998 * data input register. This also reduces the effects of the 3999 * UMC8669F bug. 4000 */ 4001 divisor = ttspeedtab(speed, comspeedtab); 4002 dlbl = divisor & 0xFF; 4003 if (sp->dlbl != dlbl) 4004 outb(iobase + com_dlbl, dlbl); 4005 dlbh = (u_int) divisor >> 8; 4006 if (sp->dlbh != dlbh) 4007 outb(iobase + com_dlbh, dlbh); 4008 outb(iobase + com_cfcr, CFCR_8BITS); 4009 sp->mcr = inb(iobase + com_mcr); 4010 /* 4011 * We don't want interrupts, but must be careful not to "disable" 4012 * them by clearing the MCR_IENABLE bit, since that might cause 4013 * an interrupt by floating the IRQ line. 4014 */ 4015 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 4016} 4017 4018static void 4019siocnclose(sp, iobase) 4020 struct siocnstate *sp; 4021 Port_t iobase; 4022{ 4023 /* 4024 * Restore the device control registers. 4025 */ 4026 siocntxwait(iobase); 4027 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 4028 if (sp->dlbl != inb(iobase + com_dlbl)) 4029 outb(iobase + com_dlbl, sp->dlbl); 4030 if (sp->dlbh != inb(iobase + com_dlbh)) 4031 outb(iobase + com_dlbh, sp->dlbh); 4032 outb(iobase + com_cfcr, sp->cfcr); 4033 /* 4034 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 4035 */ 4036 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 4037 outb(iobase + com_ier, sp->ier); 4038} 4039 4040static void 4041siocnprobe(cp) 4042 struct consdev *cp; 4043{ 4044 speed_t boot_speed; 4045 u_char cfcr; 4046 int s, unit; 4047 struct siocnstate sp; 4048 4049 /* 4050 * Find our first enabled console, if any. If it is a high-level 4051 * console device, then initialize it and return successfully. 4052 * If it is a low-level console device, then initialize it and 4053 * return unsuccessfully. It must be initialized in both cases 4054 * for early use by console drivers and debuggers. Initializing 4055 * the hardware is not necessary in all cases, since the i/o 4056 * routines initialize it on the fly, but it is necessary if 4057 * input might arrive while the hardware is switched back to an 4058 * uninitialized state. We can't handle multiple console devices 4059 * yet because our low-level routines don't take a device arg. 4060 * We trust the user to set the console flags properly so that we 4061 * don't need to probe. 4062 */ 4063 cp->cn_pri = CN_DEAD; 4064 4065 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ 4066 int flags; 4067 int disabled; 4068 if (resource_int_value("sio", unit, "disabled", &disabled) == 0) { 4069 if (disabled) 4070 continue; 4071 } 4072 if (resource_int_value("sio", unit, "flags", &flags)) 4073 continue; 4074 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) { 4075 int port; 4076 Port_t iobase; 4077 4078 if (resource_int_value("sio", unit, "port", &port)) 4079 continue; 4080 iobase = port; 4081 s = spltty(); 4082 if (boothowto & RB_SERIAL) { 4083 boot_speed = siocngetspeed(iobase, comspeedtab); 4084 if (boot_speed) 4085 comdefaultrate = boot_speed; 4086 } 4087 4088 /* 4089 * Initialize the divisor latch. We can't rely on 4090 * siocnopen() to do this the first time, since it 4091 * avoids writing to the latch if the latch appears 4092 * to have the correct value. Also, if we didn't 4093 * just read the speed from the hardware, then we 4094 * need to set the speed in hardware so that 4095 * switching it later is null. 4096 */ 4097 cfcr = inb(iobase + com_cfcr); 4098 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 4099 outb(iobase + com_dlbl, 4100 COMBRD(comdefaultrate) & 0xff); 4101 outb(iobase + com_dlbh, 4102 (u_int) COMBRD(comdefaultrate) >> 8); 4103 outb(iobase + com_cfcr, cfcr); 4104 4105 siocnopen(&sp, iobase, comdefaultrate); 4106 4107 splx(s); 4108 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) { 4109 cp->cn_dev = makedev(CDEV_MAJOR, unit); 4110 cp->cn_pri = COM_FORCECONSOLE(flags) 4111 || boothowto & RB_SERIAL 4112 ? CN_REMOTE : CN_NORMAL; 4113 siocniobase = iobase; 4114 siocnunit = unit; 4115 } 4116 if (COM_DEBUGGER(flags)) { 4117 printf("sio%d: gdb debugging port\n", unit); 4118 siogdbiobase = iobase; 4119 siogdbunit = unit; 4120#if DDB > 0 4121 gdbdev = makedev(CDEV_MAJOR, unit); 4122 gdb_getc = siocngetc; 4123 gdb_putc = siocnputc; 4124#endif 4125 } 4126 } 4127 } 4128#ifdef __i386__ 4129#if DDB > 0 4130 /* 4131 * XXX Ugly Compatability. 4132 * If no gdb port has been specified, set it to be the console 4133 * as some configuration files don't specify the gdb port. 4134 */ 4135 if (gdbdev == NODEV && (boothowto & RB_GDB)) { 4136 printf("Warning: no GDB port specified. Defaulting to sio%d.\n", 4137 siocnunit); 4138 printf("Set flag 0x80 on desired GDB port in your\n"); 4139 printf("configuration file (currently sio only).\n"); 4140 siogdbiobase = siocniobase; 4141 siogdbunit = siocnunit; 4142 gdbdev = makedev(CDEV_MAJOR, siocnunit); 4143 gdb_getc = siocngetc; 4144 gdb_putc = siocnputc; 4145 } 4146#endif 4147#endif 4148} 4149 4150#ifdef __alpha__ 4151 4152CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc); 4153 4154int 4155siocnattach(port, speed) 4156 int port; 4157 int speed; 4158{ 4159 int s; 4160 u_char cfcr; 4161 struct siocnstate sp; 4162 4163 siocniobase = port; 4164 comdefaultrate = speed; 4165 sio_consdev.cn_pri = CN_NORMAL; 4166 sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0); 4167 4168 s = spltty(); 4169 4170 /* 4171 * Initialize the divisor latch. We can't rely on 4172 * siocnopen() to do this the first time, since it 4173 * avoids writing to the latch if the latch appears 4174 * to have the correct value. Also, if we didn't 4175 * just read the speed from the hardware, then we 4176 * need to set the speed in hardware so that 4177 * switching it later is null. 4178 */ 4179 cfcr = inb(siocniobase + com_cfcr); 4180 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 4181 outb(siocniobase + com_dlbl, 4182 COMBRD(comdefaultrate) & 0xff); 4183 outb(siocniobase + com_dlbh, 4184 (u_int) COMBRD(comdefaultrate) >> 8); 4185 outb(siocniobase + com_cfcr, cfcr); 4186 4187 siocnopen(&sp, siocniobase, comdefaultrate); 4188 splx(s); 4189 4190 cn_tab = &sio_consdev; 4191 return 0; 4192} 4193 4194int 4195siogdbattach(port, speed) 4196 int port; 4197 int speed; 4198{ 4199 int s; 4200 u_char cfcr; 4201 struct siocnstate sp; 4202 4203 siogdbiobase = port; 4204 gdbdefaultrate = speed; 4205 4206 s = spltty(); 4207 4208 /* 4209 * Initialize the divisor latch. We can't rely on 4210 * siocnopen() to do this the first time, since it 4211 * avoids writing to the latch if the latch appears 4212 * to have the correct value. Also, if we didn't 4213 * just read the speed from the hardware, then we 4214 * need to set the speed in hardware so that 4215 * switching it later is null. 4216 */ 4217 cfcr = inb(siogdbiobase + com_cfcr); 4218 outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr); 4219 outb(siogdbiobase + com_dlbl, 4220 COMBRD(gdbdefaultrate) & 0xff); 4221 outb(siogdbiobase + com_dlbh, 4222 (u_int) COMBRD(gdbdefaultrate) >> 8); 4223 outb(siogdbiobase + com_cfcr, cfcr); 4224 4225 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 4226 splx(s); 4227 4228 return 0; 4229} 4230 4231#endif 4232 4233static void 4234siocninit(cp) 4235 struct consdev *cp; 4236{ 4237 comconsole = DEV_TO_UNIT(cp->cn_dev); 4238} 4239 4240static int 4241siocncheckc(dev) 4242 dev_t dev; 4243{ 4244 int c; 4245 Port_t iobase; 4246 int s; 4247 struct siocnstate sp; 4248 4249 if (minor(dev) == siogdbunit) 4250 iobase = siogdbiobase; 4251 else 4252 iobase = siocniobase; 4253 s = spltty(); 4254 siocnopen(&sp, iobase, comdefaultrate); 4255 if (inb(iobase + com_lsr) & LSR_RXRDY) 4256 c = inb(iobase + com_data); 4257 else 4258 c = -1; 4259 siocnclose(&sp, iobase); 4260 splx(s); 4261 return (c); 4262} 4263 4264 4265int 4266siocngetc(dev) 4267 dev_t dev; 4268{ 4269 int c; 4270 Port_t iobase; 4271 int s; 4272 struct siocnstate sp; 4273 4274 if (minor(dev) == siogdbunit) 4275 iobase = siogdbiobase; 4276 else 4277 iobase = siocniobase; 4278 s = spltty(); 4279 siocnopen(&sp, iobase, comdefaultrate); 4280 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 4281 ; 4282 c = inb(iobase + com_data); 4283 siocnclose(&sp, iobase); 4284 splx(s); 4285 return (c); 4286} 4287 4288void 4289siocnputc(dev, c) 4290 dev_t dev; 4291 int c; 4292{ 4293 int s; 4294 struct siocnstate sp; 4295 Port_t iobase; 4296 4297 if (minor(dev) == siogdbunit) 4298 iobase = siogdbiobase; 4299 else 4300 iobase = siocniobase; 4301 s = spltty(); 4302 siocnopen(&sp, iobase, comdefaultrate); 4303 siocntxwait(iobase); 4304 outb(iobase + com_data, c); 4305 siocnclose(&sp, iobase); 4306 splx(s); 4307} 4308 4309#ifdef __alpha__ 4310int 4311siogdbgetc() 4312{ 4313 int c; 4314 Port_t iobase; 4315 int s; 4316 struct siocnstate sp; 4317 4318 iobase = siogdbiobase; 4319 s = spltty(); 4320 siocnopen(&sp, iobase, gdbdefaultrate); 4321 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 4322 ; 4323 c = inb(iobase + com_data); 4324 siocnclose(&sp, iobase); 4325 splx(s); 4326 return (c); 4327} 4328 4329void 4330siogdbputc(c) 4331 int c; 4332{ 4333 int s; 4334 struct siocnstate sp; 4335 4336 s = spltty(); 4337 siocnopen(&sp, siogdbiobase, gdbdefaultrate); 4338 siocntxwait(siogdbiobase); 4339 outb(siogdbiobase + com_data, c); 4340 siocnclose(&sp, siogdbiobase); 4341 splx(s); 4342} 4343#endif 4344 4345DEV_DRIVER_MODULE(sio, isa, sio_driver, sio_devclass, sio_cdevsw, 0, 0); 4346 4347#ifdef PC98 4348/* 4349 * pc98 local function 4350 */ 4351 4352static void 4353com_tiocm_set(struct com_s *com, int msr) 4354{ 4355 int s; 4356 int tmp = 0; 4357 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 4358 4359 s=spltty(); 4360 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 4361 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4362 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 4363 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4364 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4365 pc98_i8251_clear_or_cmd( com, mask, tmp ); 4366 splx(s); 4367} 4368 4369static void 4370com_tiocm_bis(struct com_s *com, int msr) 4371{ 4372 int s; 4373 int tmp = 0; 4374 4375 s=spltty(); 4376 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4377 tmp |= CMD8251_TxEN|CMD8251_RxEN; 4378 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4379 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4380 4381 pc98_i8251_or_cmd( com, tmp ); 4382 splx(s); 4383} 4384 4385static void 4386com_tiocm_bic(struct com_s *com, int msr) 4387{ 4388 int s; 4389 int tmp = msr; 4390 4391 s=spltty(); 4392 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4393 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4394 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4395 4396 pc98_i8251_clear_cmd( com, tmp ); 4397 splx(s); 4398} 4399 4400static int 4401com_tiocm_get(struct com_s *com) 4402{ 4403 return( com->pc98_prev_modem_status ); 4404} 4405 4406static int 4407com_tiocm_get_delta(struct com_s *com) 4408{ 4409 int tmp; 4410 4411 tmp = com->pc98_modem_delta; 4412 com->pc98_modem_delta = 0; 4413 return( tmp ); 4414} 4415 4416/* convert to TIOCM_?? ( ioctl.h ) */ 4417static int 4418pc98_get_modem_status(struct com_s *com) 4419{ 4420 int stat, stat2; 4421 register int msr; 4422 4423 stat = inb(com->sts_port); 4424 stat2 = inb(com->in_modem_port); 4425 msr = com->pc98_prev_modem_status 4426 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4427 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 4428 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 4429 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 4430 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 4431#if COM_CARRIER_DETECT_EMULATE 4432 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 4433 msr |= TIOCM_CAR; 4434 } 4435#endif 4436 return(msr); 4437} 4438 4439static void 4440pc98_check_msr(void* chan) 4441{ 4442 int msr, delta; 4443 int s; 4444 register struct tty *tp; 4445 struct com_s *com; 4446 int mynor; 4447 int unit; 4448 dev_t dev; 4449 4450 dev=(dev_t)chan; 4451 mynor = minor(dev); 4452 unit = MINOR_TO_UNIT(mynor); 4453 com = com_addr(unit); 4454 tp = com->tp; 4455 4456 s = spltty(); 4457 msr = pc98_get_modem_status(com); 4458 /* make change flag */ 4459 delta = msr ^ com->pc98_prev_modem_status; 4460 if ( delta & TIOCM_CAR ) { 4461 if ( com->modem_car_chg_timer ) { 4462 if ( -- com->modem_car_chg_timer ) 4463 msr ^= TIOCM_CAR; 4464 } else { 4465 if ((com->modem_car_chg_timer = (msr & TIOCM_CAR) ? 4466 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE) != 0) 4467 msr ^= TIOCM_CAR; 4468 } 4469 } else 4470 com->modem_car_chg_timer = 0; 4471 delta = ( msr ^ com->pc98_prev_modem_status ) & 4472 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4473 com->pc98_prev_modem_status = msr; 4474 delta = ( com->pc98_modem_delta |= delta ); 4475 splx(s); 4476 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 4477 if ( delta ) { 4478 commint(dev); 4479 } 4480 timeout(pc98_check_msr, (caddr_t)dev, 4481 PC98_CHECK_MODEM_INTERVAL); 4482 } else { 4483 com->modem_checking = 0; 4484 } 4485} 4486 4487static void 4488pc98_msrint_start(dev_t dev) 4489{ 4490 struct com_s *com; 4491 int mynor; 4492 int unit; 4493 int s = spltty(); 4494 4495 mynor = minor(dev); 4496 unit = MINOR_TO_UNIT(mynor); 4497 com = com_addr(unit); 4498 /* modem control line check routine envoke interval is 1/10 sec */ 4499 if ( com->modem_checking == 0 ) { 4500 com->pc98_prev_modem_status = pc98_get_modem_status(com); 4501 com->pc98_modem_delta = 0; 4502 timeout(pc98_check_msr, (caddr_t)dev, 4503 PC98_CHECK_MODEM_INTERVAL); 4504 com->modem_checking = 1; 4505 } 4506 splx(s); 4507} 4508 4509static void 4510pc98_disable_i8251_interrupt(struct com_s *com, int mod) 4511{ 4512 /* disable interrupt */ 4513 register int tmp; 4514 4515 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4516 COM_INT_DISABLE 4517 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4518 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 4519 COM_INT_ENABLE 4520} 4521 4522static void 4523pc98_enable_i8251_interrupt(struct com_s *com, int mod) 4524{ 4525 register int tmp; 4526 4527 COM_INT_DISABLE 4528 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4529 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 4530 COM_INT_ENABLE 4531} 4532 4533static int 4534pc98_check_i8251_interrupt(struct com_s *com) 4535{ 4536 return ( com->intr_enable & 0x07 ); 4537} 4538 4539static void 4540pc98_i8251_clear_cmd(struct com_s *com, int x) 4541{ 4542 int tmp; 4543 4544 COM_INT_DISABLE 4545 tmp = com->pc98_prev_siocmd & ~(x); 4546 outb(com->cmd_port, tmp); 4547 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4548 COM_INT_ENABLE 4549} 4550 4551static void 4552pc98_i8251_or_cmd(struct com_s *com, int x) 4553{ 4554 int tmp; 4555 4556 COM_INT_DISABLE 4557 tmp = com->pc98_prev_siocmd | (x); 4558 outb(com->cmd_port, tmp); 4559 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4560 COM_INT_ENABLE 4561} 4562 4563static void 4564pc98_i8251_set_cmd(struct com_s *com, int x) 4565{ 4566 int tmp; 4567 4568 COM_INT_DISABLE 4569 tmp = (x); 4570 outb(com->cmd_port, tmp); 4571 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4572 COM_INT_ENABLE 4573} 4574 4575static void 4576pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4577{ 4578 int tmp; 4579 COM_INT_DISABLE 4580 tmp = com->pc98_prev_siocmd & ~(clr); 4581 tmp |= (x); 4582 outb(com->cmd_port, tmp); 4583 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4584 COM_INT_ENABLE 4585} 4586 4587static int 4588pc98_i8251_get_cmd(struct com_s *com) 4589{ 4590 return com->pc98_prev_siocmd; 4591} 4592 4593static int 4594pc98_i8251_get_mod(struct com_s *com) 4595{ 4596 return com->pc98_prev_siomod; 4597} 4598 4599static void 4600pc98_i8251_reset(struct com_s *com, int mode, int command) 4601{ 4602 outb(com->cmd_port, 0); /* dummy */ 4603 DELAY(2); 4604 outb(com->cmd_port, 0); /* dummy */ 4605 DELAY(2); 4606 outb(com->cmd_port, 0); /* dummy */ 4607 DELAY(2); 4608 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4609 DELAY(2); 4610 outb(com->cmd_port, mode ); /* mode register */ 4611 com->pc98_prev_siomod = mode; 4612 DELAY(2); 4613 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4614} 4615 4616static void 4617pc98_check_sysclock(void) 4618{ 4619 /* get system clock from port */ 4620 if ( pc98_machine_type & M_8M ) { 4621 /* 8 MHz system & H98 */ 4622 sysclock = 8; 4623 } else { 4624 /* 5 MHz system */ 4625 sysclock = 5; 4626 } 4627} 4628 4629static void 4630com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4631{ 4632 int cfcr=0, count; 4633 int previnterrupt; 4634 4635 count = pc98_ttspeedtab( com, speed ); 4636 if ( count < 0 ) return; 4637 4638 previnterrupt = pc98_check_i8251_interrupt(com); 4639 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4640 4641 switch ( cflag&CSIZE ) { 4642 case CS5: 4643 cfcr = MOD8251_5BITS; break; 4644 case CS6: 4645 cfcr = MOD8251_6BITS; break; 4646 case CS7: 4647 cfcr = MOD8251_7BITS; break; 4648 case CS8: 4649 cfcr = MOD8251_8BITS; break; 4650 } 4651 if ( cflag&PARENB ) { 4652 if ( cflag&PARODD ) 4653 cfcr |= MOD8251_PODD; 4654 else 4655 cfcr |= MOD8251_PEVEN; 4656 } else 4657 cfcr |= MOD8251_PDISAB; 4658 4659 if ( cflag&CSTOPB ) 4660 cfcr |= MOD8251_STOP2; 4661 else 4662 cfcr |= MOD8251_STOP1; 4663 4664 if ( count & 0x10000 ) 4665 cfcr |= MOD8251_CLKX1; 4666 else 4667 cfcr |= MOD8251_CLKX16; 4668 4669 if (epson_machine_id != 0x20) { /* XXX */ 4670 int tmp; 4671 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4672 ; 4673 } 4674 /* set baud rate from ospeed */ 4675 pc98_set_baud_rate( com, count ); 4676 4677 if ( cfcr != pc98_i8251_get_mod(com) ) 4678 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4679 4680 pc98_enable_i8251_interrupt( com, previnterrupt ); 4681} 4682 4683static int 4684pc98_ttspeedtab(struct com_s *com, int speed) 4685{ 4686 int if_type, effect_sp, count = -1, mod; 4687 4688 if_type = com->pc98_if_type & 0x0f; 4689 4690 switch (com->pc98_if_type) { 4691 case COM_IF_INTERNAL: 4692 if (PC98SIO_baud_rate_port(if_type) != -1) { 4693 count = ttspeedtab(speed, if_8251_type[if_type].speedtab); 4694 if (count > 0) { 4695 count |= COM1_EXT_CLOCK; 4696 break; 4697 } 4698 } 4699 4700 /* for *1CLK asynchronous! mode, TEFUTEFU */ 4701 mod = (sysclock == 5) ? 2457600 : 1996800; 4702 effect_sp = ttspeedtab( speed, pc98speedtab ); 4703 if ( effect_sp < 0 ) /* XXX */ 4704 effect_sp = ttspeedtab( (speed - 1), pc98speedtab ); 4705 if ( effect_sp <= 0 ) 4706 return effect_sp; 4707 if ( effect_sp == speed ) 4708 mod /= 16; 4709 if ( mod % effect_sp ) 4710 return(-1); 4711 count = mod / effect_sp; 4712 if ( count > 65535 ) 4713 return(-1); 4714 if ( effect_sp != speed ) 4715 count |= 0x10000; 4716 break; 4717 case COM_IF_PC9861K_1: 4718 case COM_IF_PC9861K_2: 4719 count = 1; 4720 break; 4721 case COM_IF_IND_SS_1: 4722 case COM_IF_IND_SS_2: 4723 case COM_IF_PIO9032B_1: 4724 case COM_IF_PIO9032B_2: 4725 if ( speed == 0 ) return 0; 4726 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4727 break; 4728 case COM_IF_B98_01_1: 4729 case COM_IF_B98_01_2: 4730 if ( speed == 0 ) return 0; 4731 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4732#ifdef B98_01_OLD 4733 if (count == 0 || count == 1) { 4734 count += 4; 4735 count |= 0x20000; /* x1 mode for 76800 and 153600 */ 4736 } 4737#endif 4738 break; 4739 } 4740 4741 return count; 4742} 4743 4744static void 4745pc98_set_baud_rate( struct com_s *com, int count ) 4746{ 4747 int if_type, io, s; 4748 4749 if_type = com->pc98_if_type & 0x0f; 4750 io = com->iobase & 0xff00; 4751 4752 switch (com->pc98_if_type) { 4753 case COM_IF_INTERNAL: 4754 if (PC98SIO_baud_rate_port(if_type) != -1) { 4755 if (count & COM1_EXT_CLOCK) { 4756 outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff); 4757 break; 4758 } else { 4759 outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09); 4760 } 4761 } 4762 4763 if ( count < 0 ) { 4764 printf( "[ Illegal count : %d ]", count ); 4765 return; 4766 } else if ( count == 0 ) 4767 return; 4768 /* set i8253 */ 4769 s = splclock(); 4770 if (count != 3) 4771 outb( 0x77, 0xb6 ); 4772 else 4773 outb( 0x77, 0xb4 ); 4774 outb( 0x5f, 0); 4775 outb( 0x75, count & 0xff ); 4776 outb( 0x5f, 0); 4777 outb( 0x75, (count >> 8) & 0xff ); 4778 splx(s); 4779 break; 4780 case COM_IF_IND_SS_1: 4781 case COM_IF_IND_SS_2: 4782 outb(io | PC98SIO_intr_ctrl_port(if_type), 0); 4783 outb(io | PC98SIO_baud_rate_port(if_type), 0); 4784 outb(io | PC98SIO_baud_rate_port(if_type), 0xc0); 4785 outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80); 4786 outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff); 4787 break; 4788 case COM_IF_PIO9032B_1: 4789 case COM_IF_PIO9032B_2: 4790 outb(io | PC98SIO_baud_rate_port(if_type), count); 4791 break; 4792 case COM_IF_B98_01_1: 4793 case COM_IF_B98_01_2: 4794 outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f); 4795#ifdef B98_01_OLD 4796 /* 4797 * Some old B98_01 board should be controlled 4798 * in different way, but this hasn't been tested yet. 4799 */ 4800 outb(io | PC98SIO_func_port(if_type), 4801 (count & 0x20000) ? 0xf0 : 0xf2); 4802#endif 4803 break; 4804 } 4805} 4806static int 4807pc98_check_if_type(device_t dev, struct siodev *iod) 4808{ 4809 int irr, io, if_type, tmp; 4810 static short irq_tab[2][8] = { 4811 { 3, 5, 6, 9, 10, 12, 13, -1}, 4812 { 3, 10, 12, 13, 5, 6, 9, -1} 4813 }; 4814 4815 iod->if_type = if_type = (device_get_flags(dev) >> 24) & 0xff; 4816 if ((if_type < 0 || if_type > COM_IF_END1) && 4817 (if_type < 0x10 || if_type > COM_IF_END2)) 4818 return(-1); 4819 if_type &= 0x0f; 4820 iod->irq = 0; 4821 io = isa_get_port(dev) & 0xff00; 4822 4823 if (IS_8251(iod->if_type)) { 4824 if (PC98SIO_func_port(if_type) != -1) { 4825 outb(io | PC98SIO_func_port(if_type), 0xf2); 4826 tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab); 4827 if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1) 4828 outb(io | PC98SIO_baud_rate_port(if_type), tmp); 4829 } 4830 4831 iod->cmd = io | PC98SIO_cmd_port(if_type); 4832 iod->sts = io | PC98SIO_sts_port(if_type); 4833 iod->mod = io | PC98SIO_in_modem_port(if_type); 4834 iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type); 4835 4836 if (iod->if_type == COM_IF_INTERNAL) { 4837 iod->irq = 4; 4838 4839 /* XXX check new internal port. */ 4840 outb(0x13a, 0); 4841 DELAY(10); 4842 for (tmp = 0; tmp < 100; tmp++) { 4843 if ((inb(0x13a) & 0x80) == 0) { 4844 PC98SIO_baud_rate_port(if_type) = 0x13a; 4845 if_8251_type[if_type].name = " (internal fast)"; 4846 if_8251_type[if_type].speedtab = pc98fast_speedtab; 4847 break; 4848 } 4849 DELAY(1); 4850 } 4851 } else { 4852 tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask; 4853 if ((isa_get_port(dev) & 0xff) == IO_COM2) 4854 iod->irq = irq_tab[0][tmp]; 4855 else 4856 iod->irq = irq_tab[1][tmp]; 4857 } 4858 } else { 4859 irr = if_16550a_type[if_type].irr_read; 4860#ifdef COM_MULTIPORT 4861 if (!COM_ISMULTIPORT(device_get_flags(dev)) || 4862 device_get_unit(dev) == COM_MPMASTER(device_get_flags(dev))) 4863#endif 4864 if (irr != -1) { 4865 tmp = inb(io | irr); 4866 if (isa_get_port(dev) & 0x01) /* XXX depend on RSB-384 */ 4867 iod->irq = irq_tab[1][tmp >> 3]; 4868 else 4869 iod->irq = irq_tab[0][tmp & 0x07]; 4870 } 4871 } 4872 if ( iod->irq == -1 ) return -1; 4873 4874 return 0; 4875} 4876static int 4877pc98_set_ioport( struct com_s *com, int id_flags ) 4878{ 4879 int io, if_type; 4880 4881 if_type = (id_flags >> 24) & 0xff; 4882 if (IS_8251(if_type)) { 4883 pc98_check_sysclock(); 4884 io = com->iobase & 0xff00; 4885 com->pc98_if_type = if_type; 4886 if_type &= 0x0f; 4887 com->data_port = io | PC98SIO_data_port(if_type); 4888 com->cmd_port = io | PC98SIO_cmd_port(if_type); 4889 com->sts_port = io | PC98SIO_sts_port(if_type); 4890 com->in_modem_port = io | PC98SIO_in_modem_port(if_type); 4891 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(if_type); 4892 return 0; 4893 } 4894 4895 return -1; 4896} 4897#endif /* PC98 defined */
|