sio.c revision 32726
1/*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)com.c 7.5 (Berkeley) 5/16/91 34 * $Id: sio.c,v 1.49 1998/01/22 03:52:55 kato Exp $ 35 */ 36 37#include "opt_comconsole.h" 38#include "opt_compat.h" 39#include "opt_ddb.h" 40#include "opt_devfs.h" 41#include "opt_sio.h" 42#include "sio.h" 43#include "pnp.h" 44 45#ifndef EXTRA_SIO 46#if NPNP > 0 47#define EXTRA_SIO 2 48#else 49#define EXTRA_SIO 0 50#endif 51#endif 52 53#define NSIOTOT (NSIO + EXTRA_SIO) 54 55/* 56 * Serial driver, based on 386BSD-0.1 com driver. 57 * Mostly rewritten to use pseudo-DMA. 58 * Works for National Semiconductor NS8250-NS16550AF UARTs. 59 * COM driver, based on HP dca driver. 60 * 61 * Changes for PC-Card integration: 62 * - Added PC-Card driver table and handlers 63 */ 64/*=============================================================== 65 * 386BSD(98),FreeBSD-1.1x(98) com driver. 66 * ----- 67 * modified for PC9801 by M.Ishii 68 * Kyoto University Microcomputer Club (KMC) 69 * Chou "TEFUTEFU" Hirotomi 70 * Kyoto Univ. the faculty of medicine 71 *=============================================================== 72 * FreeBSD-2.0.1(98) sio driver. 73 * ----- 74 * modified for pc98 Internal i8251 and MICRO CORE MC16550II 75 * T.Koike(hfc01340@niftyserve.or.jp) 76 * implement kernel device configuration 77 * aizu@orient.center.nitech.ac.jp 78 * 79 * Notes. 80 * ----- 81 * PC98 localization based on 386BSD(98) com driver. Using its PC98 local 82 * functions. 83 * This driver is under debugging,has bugs. 84 * 85 * 1) config 86 * options COM_MULTIPORT #if using MC16550II 87 * device sio0 at nec? port 0x30 tty irq 4 vector siointr #internal 88 * device sio1 at nec? port 0xd2 tty irq 5 flags 0x101 vector siointr #mc1 89 * device sio2 at nec? port 0x8d2 tty flags 0x101 vector siointr #mc2 90 * # ~~~~~iobase ~~multi port flag 91 * # ~ master device is sio1 92 * 2) device 93 * cd /dev; MAKEDEV ttyd0 ttyd1 .. 94 * 3) /etc/rc.serial 95 * 57600bps is too fast for sio0(internal8251) 96 * my ex. 97 * #set default speed 9600 98 * modem() 99 * : 100 * stty </dev/ttyid$i crtscts 9600 101 * : # ~~~~ default speed(can change after init.) 102 * modem 0 1 2 103 * 4) COMCONSOLE 104 * not changed. 105 * 5) PC9861K,PIO9032B,B98_01 106 * not tested. 107 */ 108/* 109 * modified for AIWA B98-01 110 * by T.Hatanou <hatanou@yasuda.comm.waseda.ac.jp> last update: 15 Sep.1995 111 * 112 * How to configure... 113 * # options COM_MULTIPORT # support for MICROCORE MC16550II 114 * ... comment-out this line, which will conflict with B98_01. 115 * options "B98_01" # support for AIWA B98-01 116 * device sio1 at nec? port 0x00d1 tty irq ? vector siointr 117 * device sio2 at nec? port 0x00d5 tty irq ? vector siointr 118 * ... you can leave these lines `irq ?', irq will be autodetected. 119 */ 120#ifdef PC98 121#define MC16550 0 122#define COM_IF_INTERNAL 1 123#if 0 124#define COM_IF_PC9861K 2 125#define COM_IF_PIO9032B 3 126#endif 127#ifdef B98_01 128#undef COM_MULTIPORT /* COM_MULTIPORT will conflict with B98_01 */ 129#define COM_IF_B98_01 4 130#endif /* B98_01 */ 131#endif /* PC98 */ 132 133#include <sys/param.h> 134#include <sys/systm.h> 135#include <sys/reboot.h> 136#include <sys/malloc.h> 137#include <sys/tty.h> 138#include <sys/proc.h> 139#include <sys/conf.h> 140#include <sys/dkstat.h> 141#include <sys/fcntl.h> 142#include <sys/kernel.h> 143#include <sys/syslog.h> 144#include <sys/sysctl.h> 145#ifdef DEVFS 146#include <sys/devfsext.h> 147#endif 148 149#include <machine/clock.h> 150 151#ifdef PC98 152#include <pc98/pc98/pc98.h> 153#include <pc98/pc98/pc98_machdep.h> 154#include <i386/isa/icu.h> 155#include <i386/isa/isa_device.h> 156#include <pc98/pc98/sioreg.h> 157#include <i386/isa/ic/i8251.h> 158#else 159#include <i386/isa/isa.h> 160#include <i386/isa/isa_device.h> 161#include <i386/isa/sioreg.h> 162#endif 163#include <i386/isa/intr_machdep.h> 164 165#ifdef COM_ESP 166#include <i386/isa/ic/esp.h> 167#endif 168#include <i386/isa/ic/ns16550.h> 169 170#include "card.h" 171#if NCARD > 0 172#include <pccard/cardinfo.h> 173#include <pccard/driver.h> 174#include <pccard/slot.h> 175#endif 176 177#if NPNP > 0 178#include <i386/isa/pnp.h> 179#endif 180 181#ifdef SMP 182#define disable_intr() COM_DISABLE_INTR() 183#define enable_intr() COM_ENABLE_INTR() 184#endif /* SMP */ 185 186#ifdef APIC_IO 187/* 188 * INTs are masked in the (global) IO APIC, 189 * but the IRR register is in each LOCAL APIC, 190 * so we would have to unmask the INT to be able to "see INT pending". 191 * So instead we just look in the 8259 ICU. 192 */ 193#define isa_irq_pending icu_irq_pending 194#endif /* APIC_IO */ 195 196#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 197#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) 198#define RS_IBUFSIZE 256 199 200#define CALLOUT_MASK 0x80 201#define CONTROL_MASK 0x60 202#define CONTROL_INIT_STATE 0x20 203#define CONTROL_LOCK_STATE 0x40 204#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 205#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 206#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) 207 208#ifdef COM_MULTIPORT 209/* checks in flags for multiport and which is multiport "master chip" 210 * for a given card 211 */ 212#define COM_ISMULTIPORT(dev) ((dev)->id_flags & 0x01) 213#define COM_MPMASTER(dev) (((dev)->id_flags >> 8) & 0x0ff) 214#define COM_NOTAST4(dev) ((dev)->id_flags & 0x04) 215#endif /* COM_MULTIPORT */ 216 217#define COM_CONSOLE(dev) ((dev)->id_flags & 0x10) 218#define COM_FORCECONSOLE(dev) ((dev)->id_flags & 0x20) 219#define COM_LLCONSOLE(dev) ((dev)->id_flags & 0x40) 220#define COM_LOSESOUTINTS(dev) ((dev)->id_flags & 0x08) 221#define COM_NOFIFO(dev) ((dev)->id_flags & 0x02) 222#define COM_VERBOSE(dev) ((dev)->id_flags & 0x80) 223#define COM_NOTST3(dev) ((dev)->id_flags & 0x10000) 224#define COM_ST16650A(dev) ((dev)->id_flags & 0x20000) 225#define COM_C_NOPROBE (0x40000) 226#define COM_NOPROBE(dev) ((dev)->id_flags & COM_C_NOPROBE) 227#define COM_C_IIR_TXRDYBUG (0x80000) 228#define COM_IIR_TXRDYBUG(dev) ((dev)->id_flags & COM_C_IIR_TXRDYBUG) 229#define COM_FIFOSIZE(dev) (((dev)->id_flags & 0xff000000) >> 24) 230 231#ifndef PC98 232#define com_scr 7 /* scratch register for 16450-16550 (R/W) */ 233#endif /* !PC98 */ 234 235/* 236 * Input buffer watermarks. 237 * The external device is asked to stop sending when the buffer exactly reaches 238 * high water, or when the high level requests it. 239 * The high level is notified immediately (rather than at a later clock tick) 240 * when this watermark is reached. 241 * The buffer size is chosen so the watermark should almost never be reached. 242 * The low watermark is invisibly 0 since the buffer is always emptied all at 243 * once. 244 */ 245#define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4) 246 247/* 248 * com state bits. 249 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 250 * than the other bits so that they can be tested as a group without masking 251 * off the low bits. 252 * 253 * The following com and tty flags correspond closely: 254 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 255 * siostop()) 256 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 257 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 258 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 259 * TS_FLUSH is not used. 260 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 261 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 262 */ 263#define CS_BUSY 0x80 /* output in progress */ 264#define CS_TTGO 0x40 /* output not stopped by XOFF */ 265#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 266#define CS_CHECKMSR 1 /* check of MSR scheduled */ 267#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 268#define CS_DTR_OFF 0x10 /* DTR held off */ 269#define CS_ODONE 4 /* output completed */ 270#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 271#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ 272 273static char const * const error_desc[] = { 274#define CE_OVERRUN 0 275 "silo overflow", 276#define CE_INTERRUPT_BUF_OVERFLOW 1 277 "interrupt-level buffer overflow", 278#define CE_TTY_BUF_OVERFLOW 2 279 "tty-level buffer overflow", 280}; 281 282#define CE_NTYPES 3 283#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 284 285/* types. XXX - should be elsewhere */ 286typedef u_int Port_t; /* hardware port */ 287typedef u_char bool_t; /* boolean */ 288 289/* queue of linear buffers */ 290struct lbq { 291 u_char *l_head; /* next char to process */ 292 u_char *l_tail; /* one past the last char to process */ 293 struct lbq *l_next; /* next in queue */ 294 bool_t l_queued; /* nonzero if queued */ 295}; 296 297/* com device structure */ 298struct com_s { 299 u_int id_flags; /* Copy isa device falgas */ 300 u_char state; /* miscellaneous flag bits */ 301 bool_t active_out; /* nonzero if the callout device is open */ 302 u_char cfcr_image; /* copy of value written to CFCR */ 303#ifdef COM_ESP 304 bool_t esp; /* is this unit a hayes esp board? */ 305#endif 306 u_char extra_state; /* more flag bits, separate for order trick */ 307 u_char fifo_image; /* copy of value written to FIFO */ 308 bool_t hasfifo; /* nonzero for 16550 UARTs */ 309 bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ 310 bool_t loses_outints; /* nonzero if device loses output interrupts */ 311 u_char mcr_image; /* copy of value written to MCR */ 312#ifdef COM_MULTIPORT 313 bool_t multiport; /* is this unit part of a multiport device? */ 314#endif /* COM_MULTIPORT */ 315 bool_t no_irq; /* nonzero if irq is not attached */ 316 bool_t gone; /* hardware disappeared */ 317 bool_t poll; /* nonzero if polling is required */ 318 bool_t poll_output; /* nonzero if polling for output is required */ 319 int unit; /* unit number */ 320 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 321 u_int tx_fifo_size; 322 u_int wopeners; /* # processes waiting for DCD in open() */ 323 324 /* 325 * The high level of the driver never reads status registers directly 326 * because there would be too many side effects to handle conveniently. 327 * Instead, it reads copies of the registers stored here by the 328 * interrupt handler. 329 */ 330 u_char last_modem_status; /* last MSR read by intr handler */ 331 u_char prev_modem_status; /* last MSR handled by high level */ 332 333 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 334 u_char *ibuf; /* start of input buffer */ 335 u_char *ibufend; /* end of input buffer */ 336 u_char *ihighwater; /* threshold in input buffer */ 337 u_char *iptr; /* next free spot in input buffer */ 338 339 struct lbq obufq; /* head of queue of output buffers */ 340 struct lbq obufs[2]; /* output buffers */ 341 342#ifdef PC98 343 Port_t cmd_port; 344 Port_t sts_port; 345 Port_t in_modem_port; 346 Port_t intr_ctrl_port; 347 int intr_enable; 348 int pc98_prev_modem_status; 349 int pc98_modem_delta; 350 int modem_car_chg_timer; 351 int pc98_prev_siocmd; 352 int pc98_prev_siomod; 353 int modem_checking; 354 int pc98_if_type; 355#endif /* PC98 */ 356 Port_t data_port; /* i/o ports */ 357#ifdef COM_ESP 358 Port_t esp_port; 359#endif 360 Port_t int_id_port; 361 Port_t iobase; 362 Port_t modem_ctl_port; 363 Port_t line_status_port; 364 Port_t modem_status_port; 365 Port_t intr_ctl_port; /* Ports of IIR register */ 366 367 struct tty *tp; /* cross reference */ 368 369 /* Initial state. */ 370 struct termios it_in; /* should be in struct tty */ 371 struct termios it_out; 372 373 /* Lock state. */ 374 struct termios lt_in; /* should be in struct tty */ 375 struct termios lt_out; 376 377 bool_t do_timestamp; 378 bool_t do_dcd_timestamp; 379 struct timeval timestamp; 380 struct timeval dcd_timestamp; 381 382 u_long bytes_in; /* statistics */ 383 u_long bytes_out; 384 u_int delta_error_counts[CE_NTYPES]; 385 u_long error_counts[CE_NTYPES]; 386 387 /* 388 * Ping-pong input buffers. The extra factor of 2 in the sizes is 389 * to allow for an error byte for each input byte. 390 */ 391#define CE_INPUT_OFFSET RS_IBUFSIZE 392 u_char ibuf1[2 * RS_IBUFSIZE]; 393 u_char ibuf2[2 * RS_IBUFSIZE]; 394 395 /* 396 * Data area for output buffers. Someday we should build the output 397 * buffer queue without copying data. 398 */ 399 u_char obuf1[256]; 400 u_char obuf2[256]; 401#ifdef DEVFS 402 void *devfs_token_ttyd; 403 void *devfs_token_ttyl; 404 void *devfs_token_ttyi; 405 void *devfs_token_cuaa; 406 void *devfs_token_cual; 407 void *devfs_token_cuai; 408#endif 409}; 410 411/* 412 * XXX public functions in drivers should be declared in headers produced 413 * by `config', not here. 414 */ 415 416/* Interrupt handling entry point. */ 417void siopoll __P((void)); 418 419/* Device switch entry points. */ 420#define sioreset noreset 421#define siommap nommap 422#define siostrategy nostrategy 423 424#ifdef COM_ESP 425static int espattach __P((struct isa_device *isdp, struct com_s *com, 426 Port_t esp_port)); 427#endif 428static int sioattach __P((struct isa_device *dev)); 429static timeout_t siobusycheck; 430static timeout_t siodtrwakeup; 431static void comhardclose __P((struct com_s *com)); 432static void siointr1 __P((struct com_s *com)); 433static int commctl __P((struct com_s *com, int bits, int how)); 434static int comparam __P((struct tty *tp, struct termios *t)); 435static int sioprobe __P((struct isa_device *dev)); 436static void siosettimeout __P((void)); 437static void comstart __P((struct tty *tp)); 438static timeout_t comwakeup; 439static void disc_optim __P((struct tty *tp, struct termios *t, 440 struct com_s *com)); 441 442#ifdef DSI_SOFT_MODEM 443static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr)); 444#endif /* DSI_SOFT_MODEM */ 445 446static char driver_name[] = "sio"; 447 448/* table and macro for fast conversion from a unit number to its com struct */ 449static struct com_s *p_com_addr[NSIOTOT]; 450#define com_addr(unit) (p_com_addr[unit]) 451 452struct isa_driver siodriver = { 453 sioprobe, sioattach, driver_name 454}; 455 456static d_open_t sioopen; 457static d_close_t sioclose; 458static d_read_t sioread; 459static d_write_t siowrite; 460static d_ioctl_t sioioctl; 461static d_stop_t siostop; 462static d_devtotty_t siodevtotty; 463 464#define CDEV_MAJOR 28 465static struct cdevsw sio_cdevsw = { 466 sioopen, sioclose, sioread, siowrite, 467 sioioctl, siostop, noreset, siodevtotty, 468 ttpoll, nommap, NULL, driver_name, 469 NULL, -1, 470}; 471 472static int comconsole = -1; 473static volatile speed_t comdefaultrate = CONSPEED; 474static u_int com_events; /* input chars + weighted output completions */ 475static Port_t siocniobase; 476static int sio_timeout; 477static int sio_timeouts_until_log; 478static struct callout_handle sio_timeout_handle 479 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 480#if 0 /* XXX */ 481static struct tty *sio_tty[NSIOTOT]; 482#else 483static struct tty sio_tty[NSIOTOT]; 484#endif 485static const int nsio_tty = NSIOTOT; 486 487#ifdef PC98 488struct siodev { 489 short if_type; 490 short irq; 491 Port_t cmd, sts, ctrl, mod; 492 }; 493static int sysclock; 494static short port_table[5][3] = { 495 {0x30, 0xb1, 0xb9}, 496 {0x32, 0xb3, 0xbb}, 497 {0x32, 0xb3, 0xbb}, 498 {0x33, 0xb0, 0xb2}, 499 {0x35, 0xb0, 0xb2} 500 }; 501#define PC98SIO_data_port(ch) port_table[0][ch] 502#define PC98SIO_cmd_port(ch) port_table[1][ch] 503#define PC98SIO_sts_port(ch) port_table[2][ch] 504#define PC98SIO_in_modem_port(ch) port_table[3][ch] 505#define PC98SIO_intr_ctrl_port(ch) port_table[4][ch] 506#ifdef COM_IF_PIO9032B 507#define IO_COM_PIO9032B_2 0x0b8 508#define IO_COM_PIO9032B_3 0x0ba 509#endif /* COM_IF_PIO9032B */ 510#ifdef COM_IF_B98_01 511#define IO_COM_B98_01_2 0x0d1 512#define IO_COM_B98_01_3 0x0d5 513#endif /* COM_IF_B98_01 */ 514#define COM_INT_DISABLE {int previpri; previpri=spltty(); 515#define COM_INT_ENABLE splx(previpri);} 516#define IEN_TxFLAG IEN_Tx 517 518#define COM_CARRIER_DETECT_EMULATE 0 519#define PC98_CHECK_MODEM_INTERVAL (hz/10) 520#define DCD_OFF_TOLERANCE 2 521#define DCD_ON_RECOGNITION 2 522#define IS_8251(type) (type != MC16550) 523#define IS_PC98IN(adr) (adr == 0x30) 524 525static void commint __P((dev_t dev)); 526static void com_tiocm_set __P((struct com_s *com, int msr)); 527static void com_tiocm_bis __P((struct com_s *com, int msr)); 528static void com_tiocm_bic __P((struct com_s *com, int msr)); 529static int com_tiocm_get __P((struct com_s *com)); 530static int com_tiocm_get_delta __P((struct com_s *com)); 531static void pc98_msrint_start __P((dev_t dev)); 532static void com_cflag_and_speed_set __P((struct com_s *com, int cflag, int speed)); 533static int pc98_ttspeedtab __P((struct com_s *com, int speed)); 534static int pc98_get_modem_status __P((struct com_s *com)); 535static timeout_t pc98_check_msr; 536static void pc98_set_baud_rate __P((struct com_s *com, int count)); 537static void pc98_i8251_reset __P((struct com_s *com, int mode, int command)); 538static void pc98_disable_i8251_interrupt __P((struct com_s *com, int mod)); 539static void pc98_enable_i8251_interrupt __P((struct com_s *com, int mod)); 540static int pc98_check_i8251_interrupt __P((struct com_s *com)); 541static int pc98_i8251_get_cmd __P((struct com_s *com)); 542static int pc98_i8251_get_mod __P((struct com_s *com)); 543static void pc98_i8251_set_cmd __P((struct com_s *com, int x)); 544static void pc98_i8251_or_cmd __P((struct com_s *com, int x)); 545static void pc98_i8251_clear_cmd __P((struct com_s *com, int x)); 546static void pc98_i8251_clear_or_cmd __P((struct com_s *com, int clr, int x)); 547static int pc98_check_if_type __P((int iobase, struct siodev *iod)); 548static void pc98_check_sysclock __P((void)); 549static int pc98_set_ioport __P((struct com_s *com, int io_base)); 550 551#define com_int_Tx_disable(com) \ 552 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP) 553#define com_int_Tx_enable(com) \ 554 pc98_enable_i8251_interrupt(com,IEN_TxFLAG) 555#define com_int_Rx_disable(com) \ 556 pc98_disable_i8251_interrupt(com,IEN_Rx) 557#define com_int_Rx_enable(com) \ 558 pc98_enable_i8251_interrupt(com,IEN_Rx) 559#define com_int_TxRx_disable(com) \ 560 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx) 561#define com_int_TxRx_enable(com) \ 562 pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx) 563#define com_send_break_on(com) \ 564 pc98_i8251_or_cmd(com,CMD8251_SBRK) 565#define com_send_break_off(com) \ 566 pc98_i8251_clear_cmd(com,CMD8251_SBRK) 567 568struct speedtab pc98speedtab[] = { /* internal RS232C interface */ 569 0, 0, 570 50, 50, 571 75, 75, 572 150, 150, 573 200, 200, 574 300, 300, 575 600, 600, 576 1200, 1200, 577 2400, 2400, 578 4800, 4800, 579 9600, 9600, 580 19200, 19200, 581 38400, 38400, 582 76800, 76800, 583 20800, 20800, 584 41600, 41600, 585 15600, 15600, 586 31200, 31200, 587 62400, 62400, 588 -1, -1 589}; 590#ifdef COM_IF_PIO9032B 591struct speedtab comspeedtab_pio9032b[] = { 592 300, 6, 593 600, 5, 594 1200, 4, 595 2400, 3, 596 4800, 2, 597 9600, 1, 598 19200, 0, 599 38400, 7, 600 -1, -1 601}; 602#endif 603 604#ifdef COM_IF_B98_01 605struct speedtab comspeedtab_b98_01[] = { 606 0, 0, 607 75, 15, 608 150, 14, 609 300, 13, 610 600, 12, 611 1200, 11, 612 2400, 10, 613 4800, 9, 614 9600, 8, 615 19200, 7, 616 38400, 6, 617 76800, 5, 618 153600, 4, 619 -1, -1 620}; 621#endif 622#endif /* PC98 */ 623 624static struct speedtab comspeedtab[] = { 625 { 0, 0 }, 626 { 50, COMBRD(50) }, 627 { 75, COMBRD(75) }, 628 { 110, COMBRD(110) }, 629 { 134, COMBRD(134) }, 630 { 150, COMBRD(150) }, 631 { 200, COMBRD(200) }, 632 { 300, COMBRD(300) }, 633 { 600, COMBRD(600) }, 634 { 1200, COMBRD(1200) }, 635 { 1800, COMBRD(1800) }, 636 { 2400, COMBRD(2400) }, 637 { 4800, COMBRD(4800) }, 638 { 9600, COMBRD(9600) }, 639 { 19200, COMBRD(19200) }, 640 { 38400, COMBRD(38400) }, 641 { 57600, COMBRD(57600) }, 642 { 115200, COMBRD(115200) }, 643 { -1, -1 } 644}; 645 646#ifdef COM_ESP 647/* XXX configure this properly. */ 648static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, }; 649static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 }; 650#endif 651 652/* 653 * handle sysctl read/write requests for console speed 654 * 655 * In addition to setting comdefaultrate for I/O through /dev/console, 656 * also set the initial and lock values for the /dev/ttyXX device 657 * if there is one associated with the console. Finally, if the /dev/tty 658 * device has already been open, change the speed on the open running port 659 * itself. 660 */ 661 662static int 663sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS 664{ 665 int error, s; 666 speed_t newspeed; 667 struct com_s *com; 668 struct tty *tp; 669 670 newspeed = comdefaultrate; 671 672 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req); 673 if (error || !req->newptr) 674 return (error); 675 676 comdefaultrate = newspeed; 677 678 if (comconsole < 0) /* serial console not selected? */ 679 return (0); 680 681 com = com_addr(comconsole); 682 if (!com) 683 return (ENXIO); 684 685 /* 686 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX 687 * (note, the lock rates really are boolean -- if non-zero, disallow 688 * speed changes) 689 */ 690 com->it_in.c_ispeed = com->it_in.c_ospeed = 691 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 692 com->it_out.c_ispeed = com->it_out.c_ospeed = 693 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate; 694 695 /* 696 * if we're open, change the running rate too 697 */ 698 tp = com->tp; 699 if (tp && (tp->t_state & TS_ISOPEN)) { 700 tp->t_termios.c_ispeed = 701 tp->t_termios.c_ospeed = comdefaultrate; 702 s = spltty(); 703 error = comparam(tp, &tp->t_termios); 704 splx(s); 705 } 706 return error; 707} 708 709SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW, 710 0, 0, sysctl_machdep_comdefaultrate, "I", ""); 711 712#if NCARD > 0 713/* 714 * PC-Card (PCMCIA) specific code. 715 */ 716static int sioinit(struct pccard_devinfo *); /* init device */ 717static void siounload(struct pccard_devinfo *); /* Disable driver */ 718static int card_intr(struct pccard_devinfo *); /* Interrupt handler */ 719 720static struct pccard_device sio_info = { 721 driver_name, 722 sioinit, 723 siounload, 724 card_intr, 725 0, /* Attributes - presently unused */ 726 &tty_imask /* Interrupt mask for device */ 727 /* XXX - Should this also include net_imask? */ 728}; 729 730DATA_SET(pccarddrv_set, sio_info); 731 732/* 733 * Initialize the device - called from Slot manager. 734 */ 735int 736sioinit(struct pccard_devinfo *devi) 737{ 738 739 /* validate unit number. */ 740 if (devi->isahd.id_unit >= (NSIOTOT)) 741 return(ENODEV); 742 /* Make sure it isn't already probed. */ 743 if (com_addr(devi->isahd.id_unit)) 744 return(EBUSY); 745 746 /* It's already probed as serial by Upper */ 747 devi->isahd.id_flags |= COM_C_NOPROBE; 748 749 /* 750 * Probe the device. If a value is returned, the 751 * device was found at the location. 752 */ 753 if (sioprobe(&devi->isahd) == 0) 754 return(ENXIO); 755 if (sioattach(&devi->isahd) == 0) 756 return(ENXIO); 757 758 return(0); 759} 760 761/* 762 * siounload - unload the driver and clear the table. 763 * XXX TODO: 764 * This is usually called when the card is ejected, but 765 * can be caused by a modunload of a controller driver. 766 * The idea is to reset the driver's view of the device 767 * and ensure that any driver entry points such as 768 * read and write do not hang. 769 */ 770static void 771siounload(struct pccard_devinfo *devi) 772{ 773 struct com_s *com; 774 775 com = com_addr(devi->isahd.id_unit); 776 if (!com->iobase) { 777 printf("sio%d already unloaded!\n",devi->isahd.id_unit); 778 return; 779 } 780 if (com->tp && (com->tp->t_state & TS_ISOPEN)) { 781 com->gone = 1; 782 printf("sio%d: unload\n", devi->isahd.id_unit); 783 com->tp->t_gen++; 784 ttyclose(com->tp); 785 ttwakeup(com->tp); 786 ttwwakeup(com->tp); 787 } else { 788 com_addr(com->unit) = NULL; 789 bzero(com, sizeof *com); 790 free(com,M_TTYS); 791 printf("sio%d: unload,gone\n", devi->isahd.id_unit); 792 } 793} 794 795/* 796 * card_intr - Shared interrupt called from 797 * front end of PC-Card handler. 798 */ 799static int 800card_intr(struct pccard_devinfo *devi) 801{ 802 struct com_s *com; 803 804 COM_LOCK(); 805 com = com_addr(devi->isahd.id_unit); 806 if (com && !com->gone) 807 siointr1(com_addr(devi->isahd.id_unit)); 808 COM_UNLOCK(); 809 return(1); 810} 811#endif /* NCARD > 0 */ 812 813static int 814sioprobe(dev) 815 struct isa_device *dev; 816{ 817 static bool_t already_init; 818 bool_t failures[10]; 819 int fn; 820 struct isa_device *idev; 821 Port_t iobase; 822 u_char mcr_image; 823 int result; 824 struct isa_device *xdev; 825#ifdef PC98 826 int irqout=0; 827 int ret = 0; 828 int tmp; 829 struct siodev iod; 830#endif 831 832 if (!already_init) { 833 /* 834 * Turn off MCR_IENABLE for all likely serial ports. An unused 835 * port with its MCR_IENABLE gate open will inhibit interrupts 836 * from any used port that shares the interrupt vector. 837 * XXX the gate enable is elsewhere for some multiports. 838 */ 839 for (xdev = isa_devtab_tty; xdev->id_driver != NULL; xdev++) 840 if (xdev->id_driver == &siodriver && xdev->id_enabled) 841#ifdef PC98 842 if (IS_PC98IN(xdev->id_iobase)) 843 outb(xdev->id_iobase + 2, 0xf2); 844 else 845#endif 846 outb(xdev->id_iobase + com_mcr, 0); 847 already_init = TRUE; 848 } 849 850 if (COM_LLCONSOLE(dev)) { 851 printf("sio%d: reserved for low-level i/o\n", dev->id_unit); 852 return (0); 853 } 854 855#ifdef PC98 856 DELAY(10); 857 /* 858 * If the port is i8251 UART (internal, B98_01) 859 */ 860 if(pc98_check_if_type(dev->id_iobase, &iod) == -1) 861 return 0; 862 if(IS_8251(iod.if_type)){ 863 if ( iod.irq > 0 ) 864 dev->id_irq = (1 << iod.irq); 865 outb(iod.cmd, 0); 866 DELAY(10); 867 outb(iod.cmd, 0); 868 DELAY(10); 869 outb(iod.cmd, 0); 870 DELAY(10); 871 outb(iod.cmd, CMD8251_RESET); 872 DELAY(1000); /* for a while...*/ 873 outb(iod.cmd, 0xf2); /* MODE (dummy) */ 874 DELAY(10); 875 outb(iod.cmd, 0x01); /* CMD (dummy) */ 876 DELAY(1000); /* for a while...*/ 877 if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) { 878 ret = 0; 879 } 880 switch (iod.if_type) { 881 case COM_IF_INTERNAL: 882 COM_INT_DISABLE 883 tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx)); 884 outb( iod.ctrl, tmp|IEN_TxEMP ); 885 DELAY(10); 886 ret = isa_irq_pending(dev) ? 4 : 0; 887 outb( iod.ctrl, tmp ); 888 COM_INT_ENABLE 889 break; 890#ifdef COM_IF_B98_01 891 case COM_IF_B98_01: 892 /* B98_01 doesn't activate TxEMP interrupt line 893 when being reset, so we can't check irq pending.*/ 894 ret = 4; 895 break; 896#endif 897 } 898 if (epson_machine_id==0x20) { /* XXX */ 899 ret = 4; 900 } 901 return ret; 902 } 903#endif /* PC98 */ 904 /* 905 * If the device is on a multiport card and has an AST/4 906 * compatible interrupt control register, initialize this 907 * register and prepare to leave MCR_IENABLE clear in the mcr. 908 * Otherwise, prepare to set MCR_IENABLE in the mcr. 909 * Point idev to the device struct giving the correct id_irq. 910 * This is the struct for the master device if there is one. 911 */ 912 idev = dev; 913 mcr_image = MCR_IENABLE; 914#ifdef COM_MULTIPORT 915 if (COM_ISMULTIPORT(dev)) { 916 idev = find_isadev(isa_devtab_tty, &siodriver, 917 COM_MPMASTER(dev)); 918 if (idev == NULL) { 919 printf("sio%d: master device %d not configured\n", 920 dev->id_unit, COM_MPMASTER(dev)); 921 return (0); 922 } 923#ifndef PC98 924 if (!COM_NOTAST4(dev)) { 925 outb(idev->id_iobase + com_scr, 926 idev->id_irq ? 0x80 : 0); 927 mcr_image = 0; 928 } 929#endif /* !PC98 */ 930 } 931#endif /* COM_MULTIPORT */ 932 if (idev->id_irq == 0) 933 mcr_image = 0; 934 935#ifdef PC98 936 switch(idev->id_irq){ 937 case IRQ3: irqout = 4; break; 938 case IRQ5: irqout = 5; break; 939 case IRQ6: irqout = 6; break; 940 case IRQ12: irqout = 7; break; 941 default: 942 printf("sio%d: irq configuration error\n",dev->id_unit); 943 return (0); 944 } 945 outb(dev->id_iobase+0x1000, irqout); 946#endif 947 bzero(failures, sizeof failures); 948 iobase = dev->id_iobase; 949 950 /* 951 * We don't want to get actual interrupts, just masked ones. 952 * Interrupts from this line should already be masked in the ICU, 953 * but mask them in the processor as well in case there are some 954 * (misconfigured) shared interrupts. 955 */ 956 disable_intr(); 957/* EXTRA DELAY? */ 958 959 /* 960 * Initialize the speed and the word size and wait long enough to 961 * drain the maximum of 16 bytes of junk in device output queues. 962 * The speed is undefined after a master reset and must be set 963 * before relying on anything related to output. There may be 964 * junk after a (very fast) soft reboot and (apparently) after 965 * master reset. 966 * XXX what about the UART bug avoided by waiting in comparam()? 967 * We don't want to to wait long enough to drain at 2 bps. 968 */ 969 if (iobase == siocniobase) 970 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); 971 else { 972 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 973 outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff); 974 outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8); 975 outb(iobase + com_cfcr, CFCR_8BITS); 976 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); 977 } 978 979 /* 980 * Enable the interrupt gate and disable device interupts. This 981 * should leave the device driving the interrupt line low and 982 * guarantee an edge trigger if an interrupt can be generated. 983 */ 984/* EXTRA DELAY? */ 985 outb(iobase + com_mcr, mcr_image); 986 outb(iobase + com_ier, 0); 987 988 /* 989 * Attempt to set loopback mode so that we can send a null byte 990 * without annoying any external device. 991 */ 992/* EXTRA DELAY? */ 993 outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK); 994 995 /* 996 * Attempt to generate an output interrupt. On 8250's, setting 997 * IER_ETXRDY generates an interrupt independent of the current 998 * setting and independent of whether the THR is empty. On 16450's, 999 * setting IER_ETXRDY generates an interrupt independent of the 1000 * current setting. On 16550A's, setting IER_ETXRDY only 1001 * generates an interrupt when IER_ETXRDY is not already set. 1002 */ 1003 outb(iobase + com_ier, IER_ETXRDY); 1004 1005 /* 1006 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate 1007 * an interrupt. They'd better generate one for actually doing 1008 * output. Loopback may be broken on the same incompatibles but 1009 * it's unlikely to do more than allow the null byte out. 1010 */ 1011 outb(iobase + com_data, 0); 1012 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10)); 1013 1014 /* 1015 * Turn off loopback mode so that the interrupt gate works again 1016 * (MCR_IENABLE was hidden). This should leave the device driving 1017 * an interrupt line high. It doesn't matter if the interrupt 1018 * line oscillates while we are not looking at it, since interrupts 1019 * are disabled. 1020 */ 1021/* EXTRA DELAY? */ 1022 outb(iobase + com_mcr, mcr_image); 1023 1024 /* 1025 * It's a definitly Serial PCMCIA(16550A), but still be required 1026 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... ) 1027 */ 1028 if ( COM_NOPROBE(dev) ) { 1029 /* Reading IIR register twice */ 1030 for ( fn = 0; fn < 2; fn ++ ) { 1031 DELAY(10000); 1032 failures[6] = inb(iobase + com_iir); 1033 } 1034 /* Check IIR_TXRDY clear ? */ 1035 result = IO_COMSIZE; 1036 if ( failures[6] & IIR_TXRDY ) { 1037 /* Nop, Double check with clearing IER */ 1038 outb(iobase + com_ier, 0); 1039 if ( inb(iobase + com_iir) & IIR_NOPEND ) { 1040 /* Ok. we're familia this gang */ 1041 dev->id_flags |= COM_C_IIR_TXRDYBUG; /* Set IIR_TXRDYBUG */ 1042 } else { 1043 /* Unknow, Just omit this chip.. XXX*/ 1044 result = 0; 1045 } 1046 } else { 1047 /* OK. this is well-known guys */ 1048 dev->id_flags &= ~COM_C_IIR_TXRDYBUG; /*Clear IIR_TXRDYBUG*/ 1049 } 1050 outb(iobase + com_cfcr, CFCR_8BITS); 1051 enable_intr(); 1052 return( result ); 1053 } 1054 1055 /* 1056 * Check that 1057 * o the CFCR, IER and MCR in UART hold the values written to them 1058 * (the values happen to be all distinct - this is good for 1059 * avoiding false positive tests from bus echoes). 1060 * o an output interrupt is generated and its vector is correct. 1061 * o the interrupt goes away when the IIR in the UART is read. 1062 */ 1063/* EXTRA DELAY? */ 1064 failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS; 1065 failures[1] = inb(iobase + com_ier) - IER_ETXRDY; 1066 failures[2] = inb(iobase + com_mcr) - mcr_image; 1067 DELAY(10000); /* Some internal modems need this time */ 1068 if (idev->id_irq != 0 && !COM_NOTST3(idev)) 1069 failures[3] = isa_irq_pending(idev) ? 0 : 1; 1070 failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY; 1071 DELAY(1000); /* XXX */ 1072 if (idev->id_irq != 0) 1073 failures[5] = isa_irq_pending(idev) ? 1 : 0; 1074 failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1075 1076 /* 1077 * Turn off all device interrupts and check that they go off properly. 1078 * Leave MCR_IENABLE alone. For ports without a master port, it gates 1079 * the OUT2 output of the UART to 1080 * the ICU input. Closing the gate would give a floating ICU input 1081 * (unless there is another device driving at) and spurious interrupts. 1082 * (On the system that this was first tested on, the input floats high 1083 * and gives a (masked) interrupt as soon as the gate is closed.) 1084 */ 1085 outb(iobase + com_ier, 0); 1086 outb(iobase + com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ 1087 failures[7] = inb(iobase + com_ier); 1088 DELAY(1000); /* XXX */ 1089 if (idev->id_irq != 0) 1090 failures[8] = isa_irq_pending(idev) ? 1 : 0; 1091 failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND; 1092 1093 enable_intr(); 1094 1095 result = IO_COMSIZE; 1096 for (fn = 0; fn < sizeof failures; ++fn) 1097 if (failures[fn]) { 1098 outb(iobase + com_mcr, 0); 1099 result = 0; 1100 if (COM_VERBOSE(dev)) 1101 printf("sio%d: probe test %d failed\n", 1102 dev->id_unit, fn); 1103 } 1104 return (result); 1105} 1106 1107#ifdef COM_ESP 1108static int 1109espattach(isdp, com, esp_port) 1110 struct isa_device *isdp; 1111 struct com_s *com; 1112 Port_t esp_port; 1113{ 1114 u_char dips; 1115 u_char val; 1116 1117 /* 1118 * Check the ESP-specific I/O port to see if we're an ESP 1119 * card. If not, return failure immediately. 1120 */ 1121 if ((inb(esp_port) & 0xf3) == 0) { 1122 printf(" port 0x%x is not an ESP board?\n", esp_port); 1123 return (0); 1124 } 1125 1126 /* 1127 * We've got something that claims to be a Hayes ESP card. 1128 * Let's hope so. 1129 */ 1130 1131 /* Get the dip-switch configuration */ 1132 outb(esp_port + ESP_CMD1, ESP_GETDIPS); 1133 dips = inb(esp_port + ESP_STATUS1); 1134 1135 /* 1136 * Bits 0,1 of dips say which COM port we are. 1137 */ 1138 if (com->iobase == likely_com_ports[dips & 0x03]) 1139 printf(" : ESP"); 1140 else { 1141 printf(" esp_port has com %d\n", dips & 0x03); 1142 return (0); 1143 } 1144 1145 /* 1146 * Check for ESP version 2.0 or later: bits 4,5,6 = 010. 1147 */ 1148 outb(esp_port + ESP_CMD1, ESP_GETTEST); 1149 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */ 1150 val = inb(esp_port + ESP_STATUS2); 1151 if ((val & 0x70) < 0x20) { 1152 printf("-old (%o)", val & 0x70); 1153 return (0); 1154 } 1155 1156 /* 1157 * Check for ability to emulate 16550: bit 7 == 1 1158 */ 1159 if ((dips & 0x80) == 0) { 1160 printf(" slave"); 1161 return (0); 1162 } 1163 1164 /* 1165 * Okay, we seem to be a Hayes ESP card. Whee. 1166 */ 1167 com->esp = TRUE; 1168 com->esp_port = esp_port; 1169 return (1); 1170} 1171#endif /* COM_ESP */ 1172 1173static int 1174sioattach(isdp) 1175 struct isa_device *isdp; 1176{ 1177 struct com_s *com; 1178 dev_t dev; 1179#ifdef COM_ESP 1180 Port_t *espp; 1181#endif 1182 Port_t iobase; 1183 int s; 1184 int unit; 1185 1186 isdp->id_ri_flags |= RI_FAST; 1187 iobase = isdp->id_iobase; 1188 unit = isdp->id_unit; 1189 com = malloc(sizeof *com, M_TTYS, M_NOWAIT); 1190 if (com == NULL) 1191 return (0); 1192 1193 /* 1194 * sioprobe() has initialized the device registers as follows: 1195 * o cfcr = CFCR_8BITS. 1196 * It is most important that CFCR_DLAB is off, so that the 1197 * data port is not hidden when we enable interrupts. 1198 * o ier = 0. 1199 * Interrupts are only enabled when the line is open. 1200 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible 1201 * interrupt control register or the config specifies no irq. 1202 * Keeping MCR_DTR and MCR_RTS off might stop the external 1203 * device from sending before we are ready. 1204 */ 1205 bzero(com, sizeof *com); 1206 com->unit = unit; 1207 com->cfcr_image = CFCR_8BITS; 1208 com->dtr_wait = 3 * hz; 1209 com->loses_outints = COM_LOSESOUTINTS(isdp) != 0; 1210 com->no_irq = isdp->id_irq == 0; 1211 com->tx_fifo_size = 1; 1212 com->iptr = com->ibuf = com->ibuf1; 1213 com->ibufend = com->ibuf1 + RS_IBUFSIZE; 1214 com->ihighwater = com->ibuf1 + RS_IHIGHWATER; 1215 com->obufs[0].l_head = com->obuf1; 1216 com->obufs[1].l_head = com->obuf2; 1217 1218 com->iobase = iobase; 1219#ifdef PC98 1220 if(pc98_set_ioport(com, iobase) == -1) 1221 if((iobase & 0x0f0) == 0xd0) { 1222 com->pc98_if_type = MC16550; 1223 com->data_port = iobase + com_data; 1224 com->int_id_port = iobase + com_iir; 1225 com->modem_ctl_port = iobase + com_mcr; 1226 com->mcr_image = inb(com->modem_ctl_port); 1227 com->line_status_port = iobase + com_lsr; 1228 com->modem_status_port = iobase + com_msr; 1229 com->intr_ctl_port = iobase + com_ier; 1230 } 1231#else /* not PC98 */ 1232 com->data_port = iobase + com_data; 1233 com->int_id_port = iobase + com_iir; 1234 com->modem_ctl_port = iobase + com_mcr; 1235 com->mcr_image = inb(com->modem_ctl_port); 1236 com->line_status_port = iobase + com_lsr; 1237 com->modem_status_port = iobase + com_msr; 1238 com->intr_ctl_port = iobase + com_ier; 1239#endif 1240 1241 /* 1242 * We don't use all the flags from <sys/ttydefaults.h> since they 1243 * are only relevant for logins. It's important to have echo off 1244 * initially so that the line doesn't start blathering before the 1245 * echo flag can be turned off. 1246 */ 1247 com->it_in.c_iflag = 0; 1248 com->it_in.c_oflag = 0; 1249 com->it_in.c_cflag = TTYDEF_CFLAG; 1250 com->it_in.c_lflag = 0; 1251 if (unit == comconsole) { 1252#ifdef PC98 1253 if(IS_8251(com->pc98_if_type)) 1254 DELAY(100000); 1255#endif 1256 com->it_in.c_iflag = TTYDEF_IFLAG; 1257 com->it_in.c_oflag = TTYDEF_OFLAG; 1258 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 1259 com->it_in.c_lflag = TTYDEF_LFLAG; 1260 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 1261 com->lt_out.c_ispeed = com->lt_out.c_ospeed = 1262 com->lt_in.c_ispeed = com->lt_in.c_ospeed = 1263 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 1264 } else 1265 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; 1266 termioschars(&com->it_in); 1267 com->it_out = com->it_in; 1268 1269 /* attempt to determine UART type */ 1270 printf("sio%d: type", unit); 1271 1272#ifdef DSI_SOFT_MODEM 1273 if((inb(iobase+7) ^ inb(iobase+7)) & 0x80) { 1274 printf(" Digicom Systems, Inc. SoftModem"); 1275 goto determined_type; 1276 } 1277#endif /* DSI_SOFT_MODEM */ 1278 1279#ifndef PC98 1280#ifdef COM_MULTIPORT 1281 if (!COM_ISMULTIPORT(isdp) && !COM_IIR_TXRDYBUG(isdp)) 1282#else 1283 if (!COM_IIR_TXRDYBUG(isdp)) 1284#endif 1285 { 1286 u_char scr; 1287 u_char scr1; 1288 u_char scr2; 1289 1290 scr = inb(iobase + com_scr); 1291 outb(iobase + com_scr, 0xa5); 1292 scr1 = inb(iobase + com_scr); 1293 outb(iobase + com_scr, 0x5a); 1294 scr2 = inb(iobase + com_scr); 1295 outb(iobase + com_scr, scr); 1296 if (scr1 != 0xa5 || scr2 != 0x5a) { 1297 printf(" 8250"); 1298 goto determined_type; 1299 } 1300 } 1301#endif /* !PC98 */ 1302#ifdef PC98 1303 if(IS_8251(com->pc98_if_type)){ 1304 com_int_TxRx_disable( com ); 1305 com_cflag_and_speed_set( com, com->it_in.c_cflag, 1306 comdefaultrate ); 1307 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 1308 com_send_break_off( com ); 1309 switch(com->pc98_if_type){ 1310 case COM_IF_INTERNAL: 1311 printf(" 8251 (internal)"); 1312 break; 1313#ifdef COM_IF_PC9861K 1314 case COM_IF_PC9861K: 1315 printf(" 8251 (PC9861K)"); 1316 break; 1317#endif 1318#ifdef COM_IF_PIO9032B 1319 case COM_IF_PIO9032B: 1320 printf(" 8251 (PIO9032B)"); 1321 break; 1322#endif 1323#ifdef COM_IF_B98_01 1324 case COM_IF_B98_01: 1325 printf(" 8251 (B98_01)"); 1326 break; 1327#endif 1328 } 1329 } else { 1330#endif /* PC98 */ 1331 outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); 1332 DELAY(100); 1333 com->st16650a = 0; 1334 switch (inb(com->int_id_port) & IIR_FIFO_MASK) { 1335 case FIFO_RX_LOW: 1336 printf(" 16450"); 1337 break; 1338 case FIFO_RX_MEDL: 1339 printf(" 16450?"); 1340 break; 1341 case FIFO_RX_MEDH: 1342 printf(" 16550?"); 1343 break; 1344 case FIFO_RX_HIGH: 1345 if (COM_NOFIFO(isdp)) { 1346 printf(" 16550A fifo disabled"); 1347 } else { 1348 com->hasfifo = TRUE; 1349 if (COM_ST16650A(isdp)) { 1350 com->st16650a = 1; 1351 com->tx_fifo_size = 32; 1352 printf(" ST16650A"); 1353 } else { 1354 com->tx_fifo_size = COM_FIFOSIZE(isdp); 1355 printf(" 16550A"); 1356 } 1357 } 1358#ifdef COM_ESP 1359 for (espp = likely_esp_ports; *espp != 0; espp++) 1360 if (espattach(isdp, com, *espp)) { 1361 com->tx_fifo_size = 1024; 1362 break; 1363 } 1364#endif 1365 if (!com->st16650a) { 1366 if (!com->tx_fifo_size) 1367 com->tx_fifo_size = 16; 1368 else 1369 printf(" lookalike with %d bytes FIFO", 1370 com->tx_fifo_size); 1371 } 1372 1373 break; 1374 } 1375 1376#ifdef COM_ESP 1377 if (com->esp) { 1378 /* 1379 * Set 16550 compatibility mode. 1380 * We don't use the ESP_MODE_SCALE bit to increase the 1381 * fifo trigger levels because we can't handle large 1382 * bursts of input. 1383 * XXX flow control should be set in comparam(), not here. 1384 */ 1385 outb(com->esp_port + ESP_CMD1, ESP_SETMODE); 1386 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); 1387 1388 /* Set RTS/CTS flow control. */ 1389 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); 1390 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS); 1391 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS); 1392 1393 /* Set flow-control levels. */ 1394 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW); 1395 outb(com->esp_port + ESP_CMD2, HIBYTE(768)); 1396 outb(com->esp_port + ESP_CMD2, LOBYTE(768)); 1397 outb(com->esp_port + ESP_CMD2, HIBYTE(512)); 1398 outb(com->esp_port + ESP_CMD2, LOBYTE(512)); 1399 } 1400#endif /* COM_ESP */ 1401 outb(iobase + com_fifo, 0); 1402determined_type: ; 1403 1404#ifdef COM_MULTIPORT 1405 if (COM_ISMULTIPORT(isdp)) { 1406 com->multiport = TRUE; 1407 printf(" (multiport"); 1408 if (unit == COM_MPMASTER(isdp)) 1409 printf(" master"); 1410 printf(")"); 1411 com->no_irq = find_isadev(isa_devtab_tty, &siodriver, 1412 COM_MPMASTER(isdp))->id_irq == 0; 1413 } 1414#endif /* COM_MULTIPORT */ 1415#ifdef PC98 1416 } 1417#endif 1418 if (unit == comconsole) 1419 printf(", console"); 1420 if ( COM_IIR_TXRDYBUG(isdp) ) 1421 printf(" with a bogus IIR_TXRDY register"); 1422 printf("\n"); 1423 1424 s = spltty(); 1425 com_addr(unit) = com; 1426 splx(s); 1427 1428 dev = makedev(CDEV_MAJOR, 0); 1429 cdevsw_add(&dev, &sio_cdevsw, NULL); 1430#ifdef DEVFS 1431 com->devfs_token_ttyd = devfs_add_devswf(&sio_cdevsw, 1432 unit, DV_CHR, 1433 UID_ROOT, GID_WHEEL, 0600, "ttyd%n", unit); 1434 com->devfs_token_ttyi = devfs_add_devswf(&sio_cdevsw, 1435 unit | CONTROL_INIT_STATE, DV_CHR, 1436 UID_ROOT, GID_WHEEL, 0600, "ttyid%n", unit); 1437 com->devfs_token_ttyl = devfs_add_devswf(&sio_cdevsw, 1438 unit | CONTROL_LOCK_STATE, DV_CHR, 1439 UID_ROOT, GID_WHEEL, 0600, "ttyld%n", unit); 1440 com->devfs_token_cuaa = devfs_add_devswf(&sio_cdevsw, 1441 unit | CALLOUT_MASK, DV_CHR, 1442 UID_UUCP, GID_DIALER, 0660, "cuaa%n", unit); 1443 com->devfs_token_cuai = devfs_add_devswf(&sio_cdevsw, 1444 unit | CALLOUT_MASK | CONTROL_INIT_STATE, DV_CHR, 1445 UID_UUCP, GID_DIALER, 0660, "cuaia%n", unit); 1446 com->devfs_token_cual = devfs_add_devswf(&sio_cdevsw, 1447 unit | CALLOUT_MASK | CONTROL_LOCK_STATE, DV_CHR, 1448 UID_UUCP, GID_DIALER, 0660, "cuala%n", unit); 1449#endif 1450 com->id_flags = isdp->id_flags; /* Heritate id_flags for later */ 1451 return (1); 1452} 1453 1454static int 1455sioopen(dev, flag, mode, p) 1456 dev_t dev; 1457 int flag; 1458 int mode; 1459 struct proc *p; 1460{ 1461 struct com_s *com; 1462 int error; 1463 Port_t iobase; 1464 int mynor; 1465 int s; 1466 struct tty *tp; 1467 int unit; 1468 1469 mynor = minor(dev); 1470 unit = MINOR_TO_UNIT(mynor); 1471 if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL) 1472 return (ENXIO); 1473 if (com->gone) 1474 return (ENXIO); 1475 if (mynor & CONTROL_MASK) 1476 return (0); 1477#if 0 /* XXX */ 1478 tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); 1479#else 1480 tp = com->tp = &sio_tty[unit]; 1481#endif 1482 s = spltty(); 1483 /* 1484 * We jump to this label after all non-interrupted sleeps to pick 1485 * up any changes of the device state. 1486 */ 1487open_top: 1488 while (com->state & CS_DTR_OFF) { 1489 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0); 1490 if (com_addr(unit) == NULL) 1491 return (ENXIO); 1492 if (error != 0 || com->gone) 1493 goto out; 1494 } 1495 if (tp->t_state & TS_ISOPEN) { 1496 /* 1497 * The device is open, so everything has been initialized. 1498 * Handle conflicts. 1499 */ 1500 if (mynor & CALLOUT_MASK) { 1501 if (!com->active_out) { 1502 error = EBUSY; 1503 goto out; 1504 } 1505 } else { 1506 if (com->active_out) { 1507 if (flag & O_NONBLOCK) { 1508 error = EBUSY; 1509 goto out; 1510 } 1511 error = tsleep(&com->active_out, 1512 TTIPRI | PCATCH, "siobi", 0); 1513 if (com_addr(unit) == NULL) 1514 return (ENXIO); 1515 if (error != 0 || com->gone) 1516 goto out; 1517 goto open_top; 1518 } 1519 } 1520 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 1521 error = EBUSY; 1522 goto out; 1523 } 1524 } else { 1525 /* 1526 * The device isn't open, so there are no conflicts. 1527 * Initialize it. Initialization is done twice in many 1528 * cases: to preempt sleeping callin opens if we are 1529 * callout, and to complete a callin open after DCD rises. 1530 */ 1531 tp->t_oproc = comstart; 1532 tp->t_param = comparam; 1533 tp->t_dev = dev; 1534 tp->t_termios = mynor & CALLOUT_MASK 1535 ? com->it_out : com->it_in; 1536#ifdef PC98 1537 if(!IS_8251(com->pc98_if_type)) 1538#endif 1539 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 1540 com->poll = com->no_irq; 1541 com->poll_output = com->loses_outints; 1542 ++com->wopeners; 1543 error = comparam(tp, &tp->t_termios); 1544 --com->wopeners; 1545 if (error != 0) 1546 goto out; 1547#ifdef PC98 1548 if(IS_8251(com->pc98_if_type)){ 1549 com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS); 1550 pc98_msrint_start(dev); 1551 } 1552#endif 1553 /* 1554 * XXX we should goto open_top if comparam() slept. 1555 */ 1556 ttsetwater(tp); 1557 iobase = com->iobase; 1558 if (com->hasfifo) { 1559 /* 1560 * (Re)enable and drain fifos. 1561 * 1562 * Certain SMC chips cause problems if the fifos 1563 * are enabled while input is ready. Turn off the 1564 * fifo if necessary to clear the input. We test 1565 * the input ready bit after enabling the fifos 1566 * since we've already enabled them in comparam() 1567 * and to handle races between enabling and fresh 1568 * input. 1569 */ 1570 while (TRUE) { 1571 outb(iobase + com_fifo, 1572 FIFO_RCV_RST | FIFO_XMT_RST 1573 | com->fifo_image); 1574 /* 1575 * XXX the delays are for superstitious 1576 * historical reasons. It must be less than 1577 * the character time at the maximum 1578 * supported speed (87 usec at 115200 bps 1579 * 8N1). Otherwise we might loop endlessly 1580 * if data is streaming in. We used to use 1581 * delays of 100. That usually worked 1582 * because DELAY(100) used to usually delay 1583 * for about 85 usec instead of 100. 1584 */ 1585 DELAY(50); 1586 if (!(inb(com->line_status_port) & LSR_RXRDY)) 1587 break; 1588 outb(iobase + com_fifo, 0); 1589 DELAY(50); 1590 (void) inb(com->data_port); 1591 } 1592 } 1593 1594 disable_intr(); 1595#ifdef PC98 1596 if(IS_8251(com->pc98_if_type)){ 1597 com_tiocm_bis(com, TIOCM_LE); 1598 com->pc98_prev_modem_status = 1599 pc98_get_modem_status(com); 1600 com_int_Rx_enable(com); 1601 } else { 1602#endif 1603 (void) inb(com->line_status_port); 1604 (void) inb(com->data_port); 1605 com->prev_modem_status = com->last_modem_status 1606 = inb(com->modem_status_port); 1607 if (COM_IIR_TXRDYBUG(com)) { 1608 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS 1609 | IER_EMSC); 1610 } else { 1611 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY 1612 | IER_ERLS | IER_EMSC); 1613 } 1614#ifdef PC98 1615 } 1616#endif 1617 enable_intr(); 1618 /* 1619 * Handle initial DCD. Callout devices get a fake initial 1620 * DCD (trapdoor DCD). If we are callout, then any sleeping 1621 * callin opens get woken up and resume sleeping on "siobi" 1622 * instead of "siodcd". 1623 */ 1624 /* 1625 * XXX `mynor & CALLOUT_MASK' should be 1626 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 1627 * TRAPDOOR_CARRIER is the default initial state for callout 1628 * devices and SOFT_CARRIER is like CLOCAL except it hides 1629 * the true carrier. 1630 */ 1631#ifdef PC98 1632 if ((IS_8251(com->pc98_if_type) && 1633 (pc98_get_modem_status(com) & TIOCM_CAR)) || 1634 (!IS_8251(com->pc98_if_type) && 1635 (com->prev_modem_status & MSR_DCD)) || 1636 mynor & CALLOUT_MASK) 1637#else 1638 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 1639#endif 1640 (*linesw[tp->t_line].l_modem)(tp, 1); 1641 } 1642 /* 1643 * Wait for DCD if necessary. 1644 */ 1645 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 1646 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 1647 ++com->wopeners; 1648 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0); 1649 if (com_addr(unit) == NULL) 1650 return (ENXIO); 1651 --com->wopeners; 1652 if (error != 0 || com->gone) 1653 goto out; 1654 goto open_top; 1655 } 1656 error = (*linesw[tp->t_line].l_open)(dev, tp); 1657 disc_optim(tp, &tp->t_termios, com); 1658 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 1659 com->active_out = TRUE; 1660 siosettimeout(); 1661out: 1662 splx(s); 1663 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 1664 comhardclose(com); 1665 return (error); 1666} 1667 1668static int 1669sioclose(dev, flag, mode, p) 1670 dev_t dev; 1671 int flag; 1672 int mode; 1673 struct proc *p; 1674{ 1675 struct com_s *com; 1676 int mynor; 1677 int s; 1678 struct tty *tp; 1679 1680 mynor = minor(dev); 1681 if (mynor & CONTROL_MASK) 1682 return (0); 1683 com = com_addr(MINOR_TO_UNIT(mynor)); 1684 tp = com->tp; 1685 s = spltty(); 1686 (*linesw[tp->t_line].l_close)(tp, flag); 1687#ifdef PC98 1688 com->modem_checking = 0; 1689#endif 1690 disc_optim(tp, &tp->t_termios, com); 1691 siostop(tp, FREAD | FWRITE); 1692 comhardclose(com); 1693 ttyclose(tp); 1694 siosettimeout(); 1695 splx(s); 1696 if (com->gone) { 1697 printf("sio%d: gone\n", com->unit); 1698 s = spltty(); 1699 com_addr(com->unit) = 0; 1700 bzero(tp,sizeof *tp); 1701 bzero(com,sizeof *com); 1702 free(com,M_TTYS); 1703 splx(s); 1704 } 1705 return (0); 1706} 1707 1708static void 1709comhardclose(com) 1710 struct com_s *com; 1711{ 1712 Port_t iobase; 1713 int s; 1714 struct tty *tp; 1715 int unit; 1716 1717 unit = com->unit; 1718 iobase = com->iobase; 1719 s = spltty(); 1720 com->poll = FALSE; 1721 com->poll_output = FALSE; 1722 com->do_timestamp = FALSE; 1723 com->do_dcd_timestamp = FALSE; 1724#ifdef PC98 1725 if(IS_8251(com->pc98_if_type)) 1726 com_send_break_off(com); 1727 else 1728#endif 1729 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1730 { 1731#ifdef PC98 1732 int tmp; 1733 if(IS_8251(com->pc98_if_type)) 1734 com_int_TxRx_disable(com); 1735 else 1736#endif 1737 outb(iobase + com_ier, 0); 1738 tp = com->tp; 1739#ifdef PC98 1740 if(IS_8251(com->pc98_if_type)) 1741 tmp = pc98_get_modem_status(com) & TIOCM_CAR; 1742 else 1743 tmp = com->prev_modem_status & MSR_DCD; 1744#endif 1745 if (tp->t_cflag & HUPCL 1746 /* 1747 * XXX we will miss any carrier drop between here and the 1748 * next open. Perhaps we should watch DCD even when the 1749 * port is closed; it is not sufficient to check it at 1750 * the next open because it might go up and down while 1751 * we're not watching. 1752 */ 1753 || !com->active_out 1754#ifdef PC98 1755 && !(tmp) 1756#else 1757 && !(com->prev_modem_status & MSR_DCD) 1758#endif 1759 && !(com->it_in.c_cflag & CLOCAL) 1760 || !(tp->t_state & TS_ISOPEN)) { 1761#ifdef PC98 1762 if(IS_8251(com->pc98_if_type)) 1763 com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); 1764 else 1765#endif 1766 (void)commctl(com, TIOCM_DTR, DMBIC); 1767 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 1768 timeout(siodtrwakeup, com, com->dtr_wait); 1769 com->state |= CS_DTR_OFF; 1770 } 1771 } 1772#ifdef PC98 1773 else { 1774 if(IS_8251(com->pc98_if_type)) 1775 com_tiocm_bic(com, TIOCM_LE ); 1776 } 1777#endif 1778 } 1779 if (com->hasfifo) { 1780 /* 1781 * Disable fifos so that they are off after controlled 1782 * reboots. Some BIOSes fail to detect 16550s when the 1783 * fifos are enabled. 1784 */ 1785 outb(iobase + com_fifo, 0); 1786 } 1787 com->active_out = FALSE; 1788 wakeup(&com->active_out); 1789 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 1790 splx(s); 1791} 1792 1793static int 1794sioread(dev, uio, flag) 1795 dev_t dev; 1796 struct uio *uio; 1797 int flag; 1798{ 1799 int mynor; 1800 int unit; 1801 struct tty *tp; 1802 1803 mynor = minor(dev); 1804 if (mynor & CONTROL_MASK) 1805 return (ENODEV); 1806 unit = MINOR_TO_UNIT(mynor); 1807 if (com_addr(unit)->gone) 1808 return (ENODEV); 1809 tp = com_addr(unit)->tp; 1810 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 1811} 1812 1813static int 1814siowrite(dev, uio, flag) 1815 dev_t dev; 1816 struct uio *uio; 1817 int flag; 1818{ 1819 int mynor; 1820 struct tty *tp; 1821 int unit; 1822 1823 mynor = minor(dev); 1824 if (mynor & CONTROL_MASK) 1825 return (ENODEV); 1826 1827 unit = MINOR_TO_UNIT(mynor); 1828 if (com_addr(unit)->gone) 1829 return (ENODEV); 1830 tp = com_addr(unit)->tp; 1831 /* 1832 * (XXX) We disallow virtual consoles if the physical console is 1833 * a serial port. This is in case there is a display attached that 1834 * is not the console. In that situation we don't need/want the X 1835 * server taking over the console. 1836 */ 1837 if (constty != NULL && unit == comconsole) 1838 constty = NULL; 1839 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 1840} 1841 1842static void 1843siobusycheck(chan) 1844 void *chan; 1845{ 1846 struct com_s *com; 1847 int s; 1848 1849 com = (struct com_s *)chan; 1850 1851 /* 1852 * Clear TS_BUSY if low-level output is complete. 1853 * spl locking is sufficient because siointr1() does not set CS_BUSY. 1854 * If siointr1() clears CS_BUSY after we look at it, then we'll get 1855 * called again. Reading the line status port outside of siointr1() 1856 * is safe because CS_BUSY is clear so there are no output interrupts 1857 * to lose. 1858 */ 1859 s = spltty(); 1860 if (com->state & CS_BUSY) 1861 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ 1862#ifdef PC98 1863 else if (IS_8251(com->pc98_if_type) && 1864 (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP)) 1865 == (STS8251_TxRDY | STS8251_TxEMP) || 1866 (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 1867 == (LSR_TSRE | LSR_TXRDY)) { 1868#else 1869 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 1870 == (LSR_TSRE | LSR_TXRDY)) { 1871#endif 1872 com->tp->t_state &= ~TS_BUSY; 1873 ttwwakeup(com->tp); 1874 com->extra_state &= ~CSE_BUSYCHECK; 1875 } else 1876 timeout(siobusycheck, com, hz / 100); 1877 splx(s); 1878} 1879 1880static void 1881siodtrwakeup(chan) 1882 void *chan; 1883{ 1884 struct com_s *com; 1885 1886 com = (struct com_s *)chan; 1887 com->state &= ~CS_DTR_OFF; 1888 wakeup(&com->dtr_wait); 1889} 1890 1891void 1892siointr(unit) 1893 int unit; 1894{ 1895#ifndef COM_MULTIPORT 1896 COM_LOCK(); 1897 siointr1(com_addr(unit)); 1898 COM_UNLOCK(); 1899#else /* COM_MULTIPORT */ 1900 struct com_s *com; 1901 bool_t possibly_more_intrs; 1902 1903 /* 1904 * Loop until there is no activity on any port. This is necessary 1905 * to get an interrupt edge more than to avoid another interrupt. 1906 * If the IRQ signal is just an OR of the IRQ signals from several 1907 * devices, then the edge from one may be lost because another is 1908 * on. 1909 */ 1910 COM_LOCK(); 1911 do { 1912 possibly_more_intrs = FALSE; 1913 for (unit = 0; unit < NSIOTOT; ++unit) { 1914 com = com_addr(unit); 1915 /* 1916 * XXX COM_LOCK(); 1917 * would it work here, or be counter-productive? 1918 */ 1919#ifdef PC98 1920 if (com != NULL 1921 && !com->gone 1922 && IS_8251(com->pc98_if_type)){ 1923 siointr1(com); 1924 } else 1925#endif /* PC98 */ 1926 if (com != NULL 1927 && !com->gone 1928 && (inb(com->int_id_port) & IIR_IMASK) 1929 != IIR_NOPEND) { 1930 siointr1(com); 1931 possibly_more_intrs = TRUE; 1932 } 1933 /* XXX COM_UNLOCK(); */ 1934 } 1935 } while (possibly_more_intrs); 1936 COM_UNLOCK(); 1937#endif /* COM_MULTIPORT */ 1938} 1939 1940static void 1941siointr1(com) 1942 struct com_s *com; 1943{ 1944 u_char line_status; 1945 u_char modem_status; 1946 u_char *ioptr; 1947 u_char recv_data; 1948 u_char int_ident; 1949 u_char int_ctl; 1950 u_char int_ctl_new; 1951 1952#ifdef PC98 1953 u_char tmp=0; 1954recv_data=0; 1955#endif /* PC98 */ 1956 1957 int_ctl = inb(com->intr_ctl_port); 1958 int_ctl_new = int_ctl; 1959 1960 while (TRUE) { 1961#ifdef PC98 1962status_read:; 1963 if (IS_8251(com->pc98_if_type)) { 1964 tmp = inb(com->sts_port); 1965more_intr: 1966 line_status = 0; 1967 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 1968 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 1969 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 1970 if (tmp & STS8251_PE) line_status |= LSR_PE; 1971 if (tmp & STS8251_OE) line_status |= LSR_OE; 1972 if (tmp & STS8251_FE) line_status |= LSR_FE; 1973 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 1974 } else 1975#endif /* PC98 */ 1976 line_status = inb(com->line_status_port); 1977 1978 /* input event? (check first to help avoid overruns) */ 1979 while (line_status & LSR_RCV_MASK) { 1980 /* break/unnattached error bits or real input? */ 1981#ifdef PC98 1982 if(IS_8251(com->pc98_if_type)){ 1983 recv_data = inb(com->data_port); 1984 if(tmp & 0x78){ 1985 pc98_i8251_or_cmd(com,CMD8251_ER); 1986 recv_data = 0; 1987 } 1988 } else { 1989#endif /* PC98 */ 1990 if (!(line_status & LSR_RXRDY)) 1991 recv_data = 0; 1992 else 1993 recv_data = inb(com->data_port); 1994#ifdef PC98 1995 } 1996#endif 1997 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 1998 /* 1999 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 2000 * Otherwise, push the work to a higher level 2001 * (to handle PARMRK) if we're bypassing. 2002 * Otherwise, convert BI/FE and PE+INPCK to 0. 2003 * 2004 * This makes bypassing work right in the 2005 * usual "raw" case (IGNBRK set, and IGNPAR 2006 * and INPCK clear). 2007 * 2008 * Note: BI together with FE/PE means just BI. 2009 */ 2010 if (line_status & LSR_BI) { 2011#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 2012 if (com->unit == comconsole) { 2013 breakpoint(); 2014 goto cont; 2015 } 2016#endif 2017 if (com->tp == NULL 2018 || com->tp->t_iflag & IGNBRK) 2019 goto cont; 2020 } else { 2021 if (com->tp == NULL 2022 || com->tp->t_iflag & IGNPAR) 2023 goto cont; 2024 } 2025 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 2026 && (line_status & (LSR_BI | LSR_FE) 2027 || com->tp->t_iflag & INPCK)) 2028 recv_data = 0; 2029 } 2030 ++com->bytes_in; 2031 if (com->hotchar != 0 && recv_data == com->hotchar) 2032 setsofttty(); 2033 ioptr = com->iptr; 2034 if (ioptr >= com->ibufend) 2035 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2036 else { 2037 if (com->do_timestamp) 2038 microtime(&com->timestamp); 2039 ++com_events; 2040 schedsofttty(); 2041#if 0 /* for testing input latency vs efficiency */ 2042if (com->iptr - com->ibuf == 8) 2043 setsofttty(); 2044#endif 2045 ioptr[0] = recv_data; 2046 ioptr[CE_INPUT_OFFSET] = line_status; 2047 com->iptr = ++ioptr; 2048 if (ioptr == com->ihighwater 2049 && com->state & CS_RTS_IFLOW) 2050#ifdef PC98 2051 if(IS_8251(com->pc98_if_type)) 2052 com_tiocm_bic(com, TIOCM_RTS); 2053 else 2054#endif 2055 outb(com->modem_ctl_port, 2056 com->mcr_image &= ~MCR_RTS); 2057 if (line_status & LSR_OE) 2058 CE_RECORD(com, CE_OVERRUN); 2059 } 2060cont: 2061 /* 2062 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2063 * jump from the top of the loop to here 2064 */ 2065#ifdef PC98 2066 if(IS_8251(com->pc98_if_type)) 2067 goto status_read; 2068 else 2069#endif 2070 line_status = inb(com->line_status_port) & 0x7F; 2071 } 2072 2073 /* modem status change? (always check before doing output) */ 2074#ifdef PC98 2075 if(!IS_8251(com->pc98_if_type)){ 2076#endif 2077 modem_status = inb(com->modem_status_port); 2078 if (modem_status != com->last_modem_status) { 2079 if (com->do_dcd_timestamp 2080 && !(com->last_modem_status & MSR_DCD) 2081 && modem_status & MSR_DCD) 2082 microtime(&com->dcd_timestamp); 2083 2084 /* 2085 * Schedule high level to handle DCD changes. Note 2086 * that we don't use the delta bits anywhere. Some 2087 * UARTs mess them up, and it's easy to remember the 2088 * previous bits and calculate the delta. 2089 */ 2090 com->last_modem_status = modem_status; 2091 if (!(com->state & CS_CHECKMSR)) { 2092 com_events += LOTS_OF_EVENTS; 2093 com->state |= CS_CHECKMSR; 2094 setsofttty(); 2095 } 2096 2097 /* handle CTS change immediately for crisp flow ctl */ 2098 if (com->state & CS_CTS_OFLOW) { 2099 if (modem_status & MSR_CTS) 2100 com->state |= CS_ODEVREADY; 2101 else 2102 com->state &= ~CS_ODEVREADY; 2103 } 2104 } 2105#ifdef PC98 2106 } 2107#endif 2108 2109 /* output queued and everything ready? */ 2110 if (line_status & LSR_TXRDY 2111 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2112 ioptr = com->obufq.l_head; 2113 if (com->tx_fifo_size > 1) { 2114 u_int ocount; 2115 2116 ocount = com->obufq.l_tail - ioptr; 2117 if (ocount > com->tx_fifo_size) 2118 ocount = com->tx_fifo_size; 2119 com->bytes_out += ocount; 2120 do 2121 outb(com->data_port, *ioptr++); 2122 while (--ocount != 0); 2123 } else { 2124 outb(com->data_port, *ioptr++); 2125 ++com->bytes_out; 2126 } 2127#ifdef PC98 2128 if(IS_8251(com->pc98_if_type)) 2129 if ( !(pc98_check_i8251_interrupt(com) & IEN_TxFLAG) ) 2130 com_int_Tx_enable(com); 2131#endif 2132 com->obufq.l_head = ioptr; 2133 if (COM_IIR_TXRDYBUG(com)) { 2134 int_ctl_new = int_ctl | IER_ETXRDY; 2135 } 2136 if (ioptr >= com->obufq.l_tail) { 2137 struct lbq *qp; 2138 2139 qp = com->obufq.l_next; 2140 qp->l_queued = FALSE; 2141 qp = qp->l_next; 2142 if (qp != NULL) { 2143 com->obufq.l_head = qp->l_head; 2144 com->obufq.l_tail = qp->l_tail; 2145 com->obufq.l_next = qp; 2146 } else { 2147 /* output just completed */ 2148 if ( COM_IIR_TXRDYBUG(com) ) { 2149 int_ctl_new = int_ctl & ~IER_ETXRDY; 2150 } 2151 com->state &= ~CS_BUSY; 2152#if defined(PC98) 2153 if(IS_8251(com->pc98_if_type)) 2154 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2155 com_int_Tx_disable(com); 2156#endif 2157 } 2158 if (!(com->state & CS_ODONE)) { 2159 com_events += LOTS_OF_EVENTS; 2160 com->state |= CS_ODONE; 2161 setsofttty(); /* handle at high level ASAP */ 2162 } 2163 } 2164 if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { 2165 outb(com->intr_ctl_port, int_ctl_new); 2166 } 2167 } 2168#ifdef PC98 2169 else if (line_status & LSR_TXRDY) { 2170 if(IS_8251(com->pc98_if_type)) 2171 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2172 com_int_Tx_disable(com); 2173 } 2174 if(IS_8251(com->pc98_if_type)) 2175 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2176 goto more_intr; 2177#endif 2178 2179 /* finished? */ 2180#ifndef COM_MULTIPORT 2181#ifdef PC98 2182 if(IS_8251(com->pc98_if_type)) 2183 return; 2184#endif 2185 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2186#endif /* COM_MULTIPORT */ 2187 return; 2188 } 2189} 2190 2191static int 2192sioioctl(dev, cmd, data, flag, p) 2193 dev_t dev; 2194 int cmd; 2195 caddr_t data; 2196 int flag; 2197 struct proc *p; 2198{ 2199 struct com_s *com; 2200 int error; 2201 Port_t iobase; 2202 int mynor; 2203 int s; 2204 struct tty *tp; 2205#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2206 int oldcmd; 2207 struct termios term; 2208#endif 2209 2210 mynor = minor(dev); 2211 com = com_addr(MINOR_TO_UNIT(mynor)); 2212 if (com->gone) 2213 return (ENODEV); 2214 iobase = com->iobase; 2215 if (mynor & CONTROL_MASK) { 2216 struct termios *ct; 2217 2218 switch (mynor & CONTROL_MASK) { 2219 case CONTROL_INIT_STATE: 2220 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2221 break; 2222 case CONTROL_LOCK_STATE: 2223 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2224 break; 2225 default: 2226 return (ENODEV); /* /dev/nodev */ 2227 } 2228 switch (cmd) { 2229 case TIOCSETA: 2230 error = suser(p->p_ucred, &p->p_acflag); 2231 if (error != 0) 2232 return (error); 2233 *ct = *(struct termios *)data; 2234 return (0); 2235 case TIOCGETA: 2236 *(struct termios *)data = *ct; 2237 return (0); 2238 case TIOCGETD: 2239 *(int *)data = TTYDISC; 2240 return (0); 2241 case TIOCGWINSZ: 2242 bzero(data, sizeof(struct winsize)); 2243 return (0); 2244#ifdef DSI_SOFT_MODEM 2245 /* 2246 * Download micro-code to Digicom modem. 2247 */ 2248 case TIOCDSIMICROCODE: 2249 { 2250 u_long l; 2251 u_char *p,*pi; 2252 2253 pi = (u_char*)(*(caddr_t*)data); 2254 error = copyin(pi,&l,sizeof l); 2255 if(error) 2256 {return error;}; 2257 pi += sizeof l; 2258 2259 p = malloc(l,M_TEMP,M_NOWAIT); 2260 if(!p) 2261 {return ENOBUFS;} 2262 error = copyin(pi,p,l); 2263 if(error) 2264 {free(p,M_TEMP); return error;}; 2265 if(error = LoadSoftModem( 2266 MINOR_TO_UNIT(mynor),iobase,l,p)) 2267 {free(p,M_TEMP); return error;} 2268 free(p,M_TEMP); 2269 return(0); 2270 } 2271#endif /* DSI_SOFT_MODEM */ 2272 default: 2273 return (ENOTTY); 2274 } 2275 } 2276 tp = com->tp; 2277#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2278 term = tp->t_termios; 2279 oldcmd = cmd; 2280 error = ttsetcompat(tp, &cmd, data, &term); 2281 if (error != 0) 2282 return (error); 2283 if (cmd != oldcmd) 2284 data = (caddr_t)&term; 2285#endif 2286 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2287 int cc; 2288 struct termios *dt = (struct termios *)data; 2289 struct termios *lt = mynor & CALLOUT_MASK 2290 ? &com->lt_out : &com->lt_in; 2291 2292 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2293 | (dt->c_iflag & ~lt->c_iflag); 2294 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2295 | (dt->c_oflag & ~lt->c_oflag); 2296 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2297 | (dt->c_cflag & ~lt->c_cflag); 2298 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2299 | (dt->c_lflag & ~lt->c_lflag); 2300 for (cc = 0; cc < NCCS; ++cc) 2301 if (lt->c_cc[cc] != 0) 2302 dt->c_cc[cc] = tp->t_cc[cc]; 2303 if (lt->c_ispeed != 0) 2304 dt->c_ispeed = tp->t_ispeed; 2305 if (lt->c_ospeed != 0) 2306 dt->c_ospeed = tp->t_ospeed; 2307 } 2308 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2309 if (error != ENOIOCTL) 2310 return (error); 2311 s = spltty(); 2312 error = ttioctl(tp, cmd, data, flag); 2313 disc_optim(tp, &tp->t_termios, com); 2314 if (error != ENOIOCTL) { 2315 splx(s); 2316 return (error); 2317 } 2318#ifdef PC98 2319 if(IS_8251(com->pc98_if_type)){ 2320 switch (cmd) { 2321 case TIOCSBRK: 2322 com_send_break_on( com ); 2323 break; 2324 case TIOCCBRK: 2325 com_send_break_off( com ); 2326 break; 2327 case TIOCSDTR: 2328 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2329 break; 2330 case TIOCCDTR: 2331 com_tiocm_bic(com, TIOCM_DTR); 2332 break; 2333 /* 2334 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2335 * changes get undone on the next call to comparam(). 2336 */ 2337 case TIOCMSET: 2338 com_tiocm_set( com, *(int *)data ); 2339 break; 2340 case TIOCMBIS: 2341 com_tiocm_bis( com, *(int *)data ); 2342 break; 2343 case TIOCMBIC: 2344 com_tiocm_bic( com, *(int *)data ); 2345 break; 2346 case TIOCMGET: 2347 *(int *)data = com_tiocm_get(com); 2348 break; 2349 case TIOCMSDTRWAIT: 2350 /* must be root since the wait applies to following logins */ 2351 error = suser(p->p_ucred, &p->p_acflag); 2352 if (error != 0) { 2353 splx(s); 2354 return (error); 2355 } 2356 com->dtr_wait = *(int *)data * hz / 100; 2357 break; 2358 case TIOCMGDTRWAIT: 2359 *(int *)data = com->dtr_wait * 100 / hz; 2360 break; 2361 case TIOCTIMESTAMP: 2362 com->do_timestamp = TRUE; 2363 *(struct timeval *)data = com->timestamp; 2364 break; 2365 case TIOCDCDTIMESTAMP: 2366 com->do_dcd_timestamp = TRUE; 2367 *(struct timeval *)data = com->dcd_timestamp; 2368 break; 2369 default: 2370 splx(s); 2371 return (ENOTTY); 2372 } 2373 } else { 2374#endif 2375 switch (cmd) { 2376 case TIOCSBRK: 2377 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2378 break; 2379 case TIOCCBRK: 2380 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2381 break; 2382 case TIOCSDTR: 2383 (void)commctl(com, TIOCM_DTR, DMBIS); 2384 break; 2385 case TIOCCDTR: 2386 (void)commctl(com, TIOCM_DTR, DMBIC); 2387 break; 2388 case TIOCMSET: 2389 (void)commctl(com, *(int *)data, DMSET); 2390 break; 2391 case TIOCMBIS: 2392 (void)commctl(com, *(int *)data, DMBIS); 2393 break; 2394 case TIOCMBIC: 2395 (void)commctl(com, *(int *)data, DMBIC); 2396 break; 2397 case TIOCMGET: 2398 *(int *)data = commctl(com, 0, DMGET); 2399 break; 2400 case TIOCMSDTRWAIT: 2401 /* must be root since the wait applies to following logins */ 2402 error = suser(p->p_ucred, &p->p_acflag); 2403 if (error != 0) { 2404 splx(s); 2405 return (error); 2406 } 2407 com->dtr_wait = *(int *)data * hz / 100; 2408 break; 2409 case TIOCMGDTRWAIT: 2410 *(int *)data = com->dtr_wait * 100 / hz; 2411 break; 2412 case TIOCTIMESTAMP: 2413 com->do_timestamp = TRUE; 2414 *(struct timeval *)data = com->timestamp; 2415 break; 2416 default: 2417 splx(s); 2418 return (ENOTTY); 2419 } 2420#ifdef PC98 2421 } 2422#endif 2423 splx(s); 2424 return (0); 2425} 2426 2427void 2428siopoll() 2429{ 2430 int unit; 2431 2432 if (com_events == 0) 2433 return; 2434repeat: 2435 for (unit = 0; unit < NSIOTOT; ++unit) { 2436 u_char *buf; 2437 struct com_s *com; 2438 u_char *ibuf; 2439 int incc; 2440 struct tty *tp; 2441#ifdef PC98 2442 int tmp; 2443#endif 2444 2445 com = com_addr(unit); 2446 if (com == NULL) 2447 continue; 2448 if (com->gone) 2449 continue; 2450 tp = com->tp; 2451 if (tp == NULL) { 2452 /* 2453 * XXX forget any events related to closed devices 2454 * (actually never opened devices) so that we don't 2455 * loop. 2456 */ 2457 disable_intr(); 2458 incc = com->iptr - com->ibuf; 2459 com->iptr = com->ibuf; 2460 if (com->state & CS_CHECKMSR) { 2461 incc += LOTS_OF_EVENTS; 2462 com->state &= ~CS_CHECKMSR; 2463 } 2464 com_events -= incc; 2465 enable_intr(); 2466 if (incc != 0) 2467 log(LOG_DEBUG, 2468 "sio%d: %d events for device with no tp\n", 2469 unit, incc); 2470 continue; 2471 } 2472 2473 /* switch the role of the low-level input buffers */ 2474 if (com->iptr == (ibuf = com->ibuf)) { 2475 buf = NULL; /* not used, but compiler can't tell */ 2476 incc = 0; 2477 } else { 2478 buf = ibuf; 2479 disable_intr(); 2480 incc = com->iptr - buf; 2481 com_events -= incc; 2482 if (ibuf == com->ibuf1) 2483 ibuf = com->ibuf2; 2484 else 2485 ibuf = com->ibuf1; 2486 com->ibufend = ibuf + RS_IBUFSIZE; 2487 com->ihighwater = ibuf + RS_IHIGHWATER; 2488 com->iptr = ibuf; 2489 2490 /* 2491 * There is now room for another low-level buffer full 2492 * of input, so enable RTS if it is now disabled and 2493 * there is room in the high-level buffer. 2494 */ 2495#ifdef PC98 2496 if(IS_8251(com->pc98_if_type)) 2497 tmp = com_tiocm_get(com) & TIOCM_RTS; 2498 else 2499 tmp = com->mcr_image & MCR_RTS; 2500#endif 2501 if ((com->state & CS_RTS_IFLOW) 2502#ifdef PC98 2503 && !(tmp) 2504#else 2505 && !(com->mcr_image & MCR_RTS) 2506#endif 2507 && !(tp->t_state & TS_TBLOCK)) 2508#ifdef PC98 2509 if(IS_8251(com->pc98_if_type)) 2510 com_tiocm_bis(com, TIOCM_RTS); 2511 else 2512#endif 2513 outb(com->modem_ctl_port, 2514 com->mcr_image |= MCR_RTS); 2515 enable_intr(); 2516 com->ibuf = ibuf; 2517 } 2518 2519 if (com->state & CS_CHECKMSR) { 2520 u_char delta_modem_status; 2521 2522#ifdef PC98 2523 if(!IS_8251(com->pc98_if_type)){ 2524#endif 2525 disable_intr(); 2526 delta_modem_status = com->last_modem_status 2527 ^ com->prev_modem_status; 2528 com->prev_modem_status = com->last_modem_status; 2529 com_events -= LOTS_OF_EVENTS; 2530 com->state &= ~CS_CHECKMSR; 2531 enable_intr(); 2532 if (delta_modem_status & MSR_DCD) 2533 (*linesw[tp->t_line].l_modem) 2534 (tp, com->prev_modem_status & MSR_DCD); 2535#ifdef PC98 2536 } 2537#endif 2538 } 2539 if (com->state & CS_ODONE) { 2540 disable_intr(); 2541 com_events -= LOTS_OF_EVENTS; 2542 com->state &= ~CS_ODONE; 2543 enable_intr(); 2544 if (!(com->state & CS_BUSY) 2545 && !(com->extra_state & CSE_BUSYCHECK)) { 2546 timeout(siobusycheck, com, hz / 100); 2547 com->extra_state |= CSE_BUSYCHECK; 2548 } 2549 (*linesw[tp->t_line].l_start)(tp); 2550 } 2551 if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || 2552 !(tp->t_cflag & CREAD)) 2553 continue; 2554 /* 2555 * Avoid the grotesquely inefficient lineswitch routine 2556 * (ttyinput) in "raw" mode. It usually takes about 450 2557 * instructions (that's without canonical processing or echo!). 2558 * slinput is reasonably fast (usually 40 instructions plus 2559 * call overhead). 2560 */ 2561 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2562 if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER 2563 && (com->state & CS_RTS_IFLOW 2564 || tp->t_iflag & IXOFF) 2565 && !(tp->t_state & TS_TBLOCK)) 2566 ttyblock(tp); 2567 tk_nin += incc; 2568 tk_rawcc += incc; 2569 tp->t_rawcc += incc; 2570 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2571 += b_to_q((char *)buf, incc, &tp->t_rawq); 2572 ttwakeup(tp); 2573 if (tp->t_state & TS_TTSTOP 2574 && (tp->t_iflag & IXANY 2575 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2576 tp->t_state &= ~TS_TTSTOP; 2577 tp->t_lflag &= ~FLUSHO; 2578 comstart(tp); 2579 } 2580 } else { 2581 do { 2582 u_char line_status; 2583 int recv_data; 2584 2585 line_status = (u_char) buf[CE_INPUT_OFFSET]; 2586 recv_data = (u_char) *buf++; 2587 if (line_status 2588 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2589 if (line_status & LSR_BI) 2590 recv_data |= TTY_BI; 2591 if (line_status & LSR_FE) 2592 recv_data |= TTY_FE; 2593 if (line_status & LSR_OE) 2594 recv_data |= TTY_OE; 2595 if (line_status & LSR_PE) 2596 recv_data |= TTY_PE; 2597 } 2598 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2599 } while (--incc > 0); 2600 } 2601 if (com_events == 0) 2602 break; 2603 } 2604 if (com_events >= LOTS_OF_EVENTS) 2605 goto repeat; 2606} 2607 2608static int 2609comparam(tp, t) 2610 struct tty *tp; 2611 struct termios *t; 2612{ 2613 u_int cfcr; 2614 int cflag; 2615 struct com_s *com; 2616 int divisor; 2617 u_char dlbh; 2618 u_char dlbl; 2619 int error; 2620 Port_t iobase; 2621 int s; 2622 int unit; 2623 int txtimeout; 2624#ifdef PC98 2625 Port_t tmp_port; 2626 int tmp_flg; 2627#endif 2628 2629#ifdef PC98 2630 cfcr = 0; 2631 unit = DEV_TO_UNIT(tp->t_dev); 2632 com = com_addr(unit); 2633 iobase = com->iobase; 2634 if(IS_8251(com->pc98_if_type)) { 2635 divisor = pc98_ttspeedtab(com, t->c_ospeed); 2636 } else 2637#endif 2638 /* do historical conversions */ 2639 if (t->c_ispeed == 0) 2640 t->c_ispeed = t->c_ospeed; 2641 2642 /* check requested parameters */ 2643 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 2644 if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed) 2645 return (EINVAL); 2646 2647 /* parameters are OK, convert them to the com struct and the device */ 2648#ifndef PC98 2649 unit = DEV_TO_UNIT(tp->t_dev); 2650 com = com_addr(unit); 2651 iobase = com->iobase; 2652#endif 2653 s = spltty(); 2654#ifdef PC98 2655 if(IS_8251(com->pc98_if_type)){ 2656 if(divisor == 0) 2657 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2658 else 2659 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2660 } else { 2661#endif 2662 if (divisor == 0) 2663 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 2664 else 2665 (void)commctl(com, TIOCM_DTR, DMBIS); 2666#ifdef PC98 2667 } 2668#endif 2669 cflag = t->c_cflag; 2670#ifdef PC98 2671 if(!IS_8251(com->pc98_if_type)){ 2672#endif 2673 switch (cflag & CSIZE) { 2674 case CS5: 2675 cfcr = CFCR_5BITS; 2676 break; 2677 case CS6: 2678 cfcr = CFCR_6BITS; 2679 break; 2680 case CS7: 2681 cfcr = CFCR_7BITS; 2682 break; 2683 default: 2684 cfcr = CFCR_8BITS; 2685 break; 2686 } 2687 if (cflag & PARENB) { 2688 cfcr |= CFCR_PENAB; 2689 if (!(cflag & PARODD)) 2690 cfcr |= CFCR_PEVEN; 2691 } 2692 if (cflag & CSTOPB) 2693 cfcr |= CFCR_STOPB; 2694 2695 if (com->hasfifo && divisor != 0) { 2696 /* 2697 * Use a fifo trigger level low enough so that the input 2698 * latency from the fifo is less than about 16 msec and 2699 * the total latency is less than about 30 msec. These 2700 * latencies are reasonable for humans. Serial comms 2701 * protocols shouldn't expect anything better since modem 2702 * latencies are larger. 2703 */ 2704 com->fifo_image = t->c_ospeed <= 4800 2705 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 2706#ifdef COM_ESP 2707 /* 2708 * The Hayes ESP card needs the fifo DMA mode bit set 2709 * in compatibility mode. If not, it will interrupt 2710 * for each character received. 2711 */ 2712 if (com->esp) 2713 com->fifo_image |= FIFO_DMA_MODE; 2714#endif 2715 outb(iobase + com_fifo, com->fifo_image); 2716 } 2717 2718 /* 2719 * Some UARTs lock up if the divisor latch registers are selected 2720 * while the UART is doing output (they refuse to transmit anything 2721 * more until given a hard reset). Fix this by stopping filling 2722 * the device buffers and waiting for them to drain. Reading the 2723 * line status port outside of siointr1() might lose some receiver 2724 * error bits, but that is acceptable here. 2725 */ 2726#ifdef PC98 2727 } 2728#endif 2729 disable_intr(); 2730retry: 2731 com->state &= ~CS_TTGO; 2732 txtimeout = tp->t_timeout; 2733 enable_intr(); 2734#ifdef PC98 2735 if(IS_8251(com->pc98_if_type)){ 2736 tmp_port = com->sts_port; 2737 tmp_flg = (STS8251_TxRDY|STS8251_TxEMP); 2738 } else { 2739 tmp_port = com->line_status_port; 2740 tmp_flg = (LSR_TSRE|LSR_TXRDY); 2741 } 2742 while ((inb(tmp_port) & tmp_flg) != tmp_flg) { 2743#else 2744 while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2745 != (LSR_TSRE | LSR_TXRDY)) { 2746#endif 2747 tp->t_state |= TS_SO_OCOMPLETE; 2748 error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH, 2749 "siotx", hz / 100); 2750 if ( txtimeout != 0 2751 && (!error || error == EAGAIN) 2752 && (txtimeout -= hz / 100) <= 0 2753 ) 2754 error = EIO; 2755 if (com->gone) 2756 error = ENODEV; 2757 if (error != 0 && error != EAGAIN) { 2758 if (!(tp->t_state & TS_TTSTOP)) { 2759 disable_intr(); 2760 com->state |= CS_TTGO; 2761 enable_intr(); 2762 } 2763 splx(s); 2764 return (error); 2765 } 2766 } 2767 2768 disable_intr(); /* very important while com_data is hidden */ 2769 2770 /* 2771 * XXX - clearing CS_TTGO is not sufficient to stop further output, 2772 * because siopoll() calls comstart() which usually sets it again 2773 * because TS_TTSTOP is clear. Setting TS_TTSTOP would not be 2774 * sufficient, for similar reasons. 2775 */ 2776#ifdef PC98 2777 if ((inb(tmp_port) & tmp_flg) != tmp_flg) 2778#else 2779 if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2780 != (LSR_TSRE | LSR_TXRDY)) 2781#endif 2782 goto retry; 2783 2784#ifdef PC98 2785 if(!IS_8251(com->pc98_if_type)){ 2786#endif 2787 if (divisor != 0) { 2788 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 2789 /* 2790 * Only set the divisor registers if they would change, 2791 * since on some 16550 incompatibles (UMC8669F), setting 2792 * them while input is arriving them loses sync until 2793 * data stops arriving. 2794 */ 2795 dlbl = divisor & 0xFF; 2796 if (inb(iobase + com_dlbl) != dlbl) 2797 outb(iobase + com_dlbl, dlbl); 2798 dlbh = (u_int) divisor >> 8; 2799 if (inb(iobase + com_dlbh) != dlbh) 2800 outb(iobase + com_dlbh, dlbh); 2801 } 2802 2803 2804 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 2805 2806#ifdef PC98 2807 } else 2808 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 2809#endif 2810 if (!(tp->t_state & TS_TTSTOP)) 2811 com->state |= CS_TTGO; 2812 2813 if (cflag & CRTS_IFLOW) { 2814 if (com->st16650a) { 2815 outb(iobase + com_cfcr, 0xbf); 2816 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 2817 } 2818 com->state |= CS_RTS_IFLOW; 2819 /* 2820 * If CS_RTS_IFLOW just changed from off to on, the change 2821 * needs to be propagated to MCR_RTS. This isn't urgent, 2822 * so do it later by calling comstart() instead of repeating 2823 * a lot of code from comstart() here. 2824 */ 2825 } else if (com->state & CS_RTS_IFLOW) { 2826 com->state &= ~CS_RTS_IFLOW; 2827 /* 2828 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2829 * on here, since comstart() won't do it later. 2830 */ 2831#ifdef PC98 2832 if(IS_8251(com->pc98_if_type)) 2833 com_tiocm_bis(com, TIOCM_RTS); 2834 else 2835#endif 2836 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2837 if (com->st16650a) { 2838 outb(iobase + com_cfcr, 0xbf); 2839 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 2840 } 2841 } 2842 2843 2844 /* 2845 * Set up state to handle output flow control. 2846 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2847 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2848 */ 2849 com->state |= CS_ODEVREADY; 2850 com->state &= ~CS_CTS_OFLOW; 2851 if (cflag & CCTS_OFLOW) { 2852 com->state |= CS_CTS_OFLOW; 2853#ifdef PC98 2854 if(IS_8251(com->pc98_if_type)){ 2855 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 2856 com->state &= ~CS_ODEVREADY; 2857 } else { 2858#endif 2859 if (!(com->last_modem_status & MSR_CTS)) 2860 com->state &= ~CS_ODEVREADY; 2861 if (com->st16650a) { 2862 outb(iobase + com_cfcr, 0xbf); 2863 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 2864 } 2865#ifdef PC98 2866 } 2867#endif 2868 } else { 2869 if (com->st16650a) { 2870 outb(iobase + com_cfcr, 0xbf); 2871 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 2872 } 2873 } 2874 2875 2876 outb(iobase + com_cfcr, com->cfcr_image); 2877 2878 2879 /* XXX shouldn't call functions while intrs are disabled. */ 2880 disc_optim(tp, t, com); 2881 /* 2882 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2883 * unconditionally, but that defeated the careful discarding of 2884 * stale input in sioopen(). 2885 */ 2886 if (com->state >= (CS_BUSY | CS_TTGO)) 2887 siointr1(com); 2888 2889 enable_intr(); 2890 splx(s); 2891 comstart(tp); 2892 return (0); 2893} 2894 2895static void 2896comstart(tp) 2897 struct tty *tp; 2898{ 2899 struct com_s *com; 2900 int s; 2901 int unit; 2902#ifdef PC98 2903 int tmp; 2904#endif 2905 2906 unit = DEV_TO_UNIT(tp->t_dev); 2907 com = com_addr(unit); 2908 s = spltty(); 2909 disable_intr(); 2910 if (tp->t_state & TS_TTSTOP) 2911 com->state &= ~CS_TTGO; 2912 else 2913 com->state |= CS_TTGO; 2914 if (tp->t_state & TS_TBLOCK) { 2915#ifdef PC98 2916 if(IS_8251(com->pc98_if_type)) 2917 tmp = com_tiocm_get(com) & TIOCM_RTS; 2918 else 2919 tmp = com->mcr_image & MCR_RTS; 2920 if (tmp && (com->state & CS_RTS_IFLOW)) 2921#else 2922 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2923#endif 2924#ifdef PC98 2925 if(IS_8251(com->pc98_if_type)) 2926 com_tiocm_bic(com, TIOCM_RTS); 2927 else 2928#endif 2929 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2930 } else { 2931#ifdef PC98 2932 if(IS_8251(com->pc98_if_type)) 2933 tmp = com_tiocm_get(com) & TIOCM_RTS; 2934 else 2935 tmp = com->mcr_image & MCR_RTS; 2936 if (!(tmp) && com->iptr < com->ihighwater 2937 && com->state & CS_RTS_IFLOW) 2938#else 2939 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 2940 && com->state & CS_RTS_IFLOW) 2941#endif 2942#ifdef PC98 2943 if(IS_8251(com->pc98_if_type)) 2944 com_tiocm_bis(com, TIOCM_RTS); 2945 else 2946#endif 2947 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2948 } 2949 enable_intr(); 2950 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2951 ttwwakeup(tp); 2952#ifdef PC98 2953/* if(IS_8251(com->pc98_if_type)) 2954 com_int_Tx_enable(com); */ 2955#endif 2956 splx(s); 2957 return; 2958 } 2959 if (tp->t_outq.c_cc != 0) { 2960 struct lbq *qp; 2961 struct lbq *next; 2962 2963 if (!com->obufs[0].l_queued) { 2964 com->obufs[0].l_tail 2965 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2966 sizeof com->obuf1); 2967 com->obufs[0].l_next = NULL; 2968 com->obufs[0].l_queued = TRUE; 2969 disable_intr(); 2970 if (com->state & CS_BUSY) { 2971 qp = com->obufq.l_next; 2972 while ((next = qp->l_next) != NULL) 2973 qp = next; 2974 qp->l_next = &com->obufs[0]; 2975 } else { 2976 com->obufq.l_head = com->obufs[0].l_head; 2977 com->obufq.l_tail = com->obufs[0].l_tail; 2978 com->obufq.l_next = &com->obufs[0]; 2979 com->state |= CS_BUSY; 2980 } 2981 enable_intr(); 2982 } 2983 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2984 com->obufs[1].l_tail 2985 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2986 sizeof com->obuf2); 2987 com->obufs[1].l_next = NULL; 2988 com->obufs[1].l_queued = TRUE; 2989 disable_intr(); 2990 if (com->state & CS_BUSY) { 2991 qp = com->obufq.l_next; 2992 while ((next = qp->l_next) != NULL) 2993 qp = next; 2994 qp->l_next = &com->obufs[1]; 2995 } else { 2996 com->obufq.l_head = com->obufs[1].l_head; 2997 com->obufq.l_tail = com->obufs[1].l_tail; 2998 com->obufq.l_next = &com->obufs[1]; 2999 com->state |= CS_BUSY; 3000 } 3001 enable_intr(); 3002 } 3003 tp->t_state |= TS_BUSY; 3004 } 3005 disable_intr(); 3006 if (com->state >= (CS_BUSY | CS_TTGO)) 3007 siointr1(com); /* fake interrupt to start output */ 3008 enable_intr(); 3009#ifdef PC98 3010/* if(IS_8251(com->pc98_if_type)) 3011 com_int_Tx_enable(com); */ 3012#endif 3013 ttwwakeup(tp); 3014 splx(s); 3015} 3016 3017static void 3018siostop(tp, rw) 3019 struct tty *tp; 3020 int rw; 3021{ 3022 struct com_s *com; 3023 3024 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 3025 if (com->gone) 3026 return; 3027 disable_intr(); 3028 if (rw & FWRITE) { 3029 if (com->hasfifo) 3030#ifdef COM_ESP 3031 /* XXX avoid h/w bug. */ 3032 if (!com->esp) 3033#endif 3034 /* XXX does this flush everything? */ 3035 outb(com->iobase + com_fifo, 3036 FIFO_XMT_RST | com->fifo_image); 3037 com->obufs[0].l_queued = FALSE; 3038 com->obufs[1].l_queued = FALSE; 3039 if (com->state & CS_ODONE) 3040 com_events -= LOTS_OF_EVENTS; 3041 com->state &= ~(CS_ODONE | CS_BUSY); 3042 com->tp->t_state &= ~TS_BUSY; 3043 } 3044 if (rw & FREAD) { 3045 if (com->hasfifo) 3046#ifdef COM_ESP 3047 /* XXX avoid h/w bug. */ 3048 if (!com->esp) 3049#endif 3050 /* XXX does this flush everything? */ 3051 outb(com->iobase + com_fifo, 3052 FIFO_RCV_RST | com->fifo_image); 3053 com_events -= (com->iptr - com->ibuf); 3054 com->iptr = com->ibuf; 3055 } 3056 enable_intr(); 3057 comstart(tp); 3058} 3059 3060static struct tty * 3061siodevtotty(dev) 3062 dev_t dev; 3063{ 3064 int mynor; 3065 int unit; 3066 3067 mynor = minor(dev); 3068 if (mynor & CONTROL_MASK) 3069 return (NULL); 3070 unit = MINOR_TO_UNIT(mynor); 3071 if ((u_int) unit >= NSIOTOT) 3072 return (NULL); 3073 return (&sio_tty[unit]); 3074} 3075 3076static int 3077commctl(com, bits, how) 3078 struct com_s *com; 3079 int bits; 3080 int how; 3081{ 3082 int mcr; 3083 int msr; 3084 3085 if (how == DMGET) { 3086 bits = TIOCM_LE; /* XXX - always enabled while open */ 3087 mcr = com->mcr_image; 3088 if (mcr & MCR_DTR) 3089 bits |= TIOCM_DTR; 3090 if (mcr & MCR_RTS) 3091 bits |= TIOCM_RTS; 3092 msr = com->prev_modem_status; 3093 if (msr & MSR_CTS) 3094 bits |= TIOCM_CTS; 3095 if (msr & MSR_DCD) 3096 bits |= TIOCM_CD; 3097 if (msr & MSR_DSR) 3098 bits |= TIOCM_DSR; 3099 /* 3100 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3101 * more volatile by reading the modem status a lot. Perhaps 3102 * we should latch both bits until the status is read here. 3103 */ 3104 if (msr & (MSR_RI | MSR_TERI)) 3105 bits |= TIOCM_RI; 3106 return (bits); 3107 } 3108 mcr = 0; 3109 if (bits & TIOCM_DTR) 3110 mcr |= MCR_DTR; 3111 if (bits & TIOCM_RTS) 3112 mcr |= MCR_RTS; 3113 if (com->gone) 3114 return(0); 3115 disable_intr(); 3116 switch (how) { 3117 case DMSET: 3118 outb(com->modem_ctl_port, 3119 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3120 break; 3121 case DMBIS: 3122 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3123 break; 3124 case DMBIC: 3125 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3126 break; 3127 } 3128 enable_intr(); 3129 return (0); 3130} 3131 3132static void 3133siosettimeout() 3134{ 3135 struct com_s *com; 3136 bool_t someopen; 3137 int unit; 3138 3139 /* 3140 * Set our timeout period to 1 second if no polled devices are open. 3141 * Otherwise set it to max(1/200, 1/hz). 3142 * Enable timeouts iff some device is open. 3143 */ 3144 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3145 sio_timeout = hz; 3146 someopen = FALSE; 3147 for (unit = 0; unit < NSIOTOT; ++unit) { 3148 com = com_addr(unit); 3149 if (com != NULL && com->tp != NULL 3150 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3151 someopen = TRUE; 3152 if (com->poll || com->poll_output) { 3153 sio_timeout = hz > 200 ? hz / 200 : 1; 3154 break; 3155 } 3156 } 3157 } 3158 if (someopen) { 3159 sio_timeouts_until_log = hz / sio_timeout; 3160 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3161 sio_timeout); 3162 } else { 3163 /* Flush error messages, if any. */ 3164 sio_timeouts_until_log = 1; 3165 comwakeup((void *)NULL); 3166 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3167 } 3168} 3169 3170static void 3171comwakeup(chan) 3172 void *chan; 3173{ 3174 struct com_s *com; 3175 int unit; 3176 3177 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3178 3179 /* 3180 * Recover from lost output interrupts. 3181 * Poll any lines that don't use interrupts. 3182 */ 3183 for (unit = 0; unit < NSIOTOT; ++unit) { 3184 com = com_addr(unit); 3185 if (com != NULL && !com->gone 3186 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3187 disable_intr(); 3188 siointr1(com); 3189 enable_intr(); 3190 } 3191 } 3192 3193 /* 3194 * Check for and log errors, but not too often. 3195 */ 3196 if (--sio_timeouts_until_log > 0) 3197 return; 3198 sio_timeouts_until_log = hz / sio_timeout; 3199 for (unit = 0; unit < NSIOTOT; ++unit) { 3200 int errnum; 3201 3202 com = com_addr(unit); 3203 if (com == NULL) 3204 continue; 3205 if (com->gone) 3206 continue; 3207 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3208 u_int delta; 3209 u_long total; 3210 3211 disable_intr(); 3212 delta = com->delta_error_counts[errnum]; 3213 com->delta_error_counts[errnum] = 0; 3214 enable_intr(); 3215 if (delta == 0) 3216 continue; 3217 total = com->error_counts[errnum] += delta; 3218 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3219 unit, delta, error_desc[errnum], 3220 delta == 1 ? "" : "s", total); 3221 } 3222 } 3223} 3224 3225#ifdef PC98 3226/* commint is called when modem control line changes */ 3227static void 3228commint(dev_t dev) 3229{ 3230 register struct tty *tp; 3231 int stat,delta; 3232 struct com_s *com; 3233 int mynor,unit; 3234 3235 mynor = minor(dev); 3236 unit = MINOR_TO_UNIT(mynor); 3237 com = com_addr(unit); 3238 tp = com->tp; 3239 3240 stat = com_tiocm_get(com); 3241 delta = com_tiocm_get_delta(com); 3242 3243 if (com->state & CS_CTS_OFLOW) { 3244 if (stat & TIOCM_CTS) 3245 com->state |= CS_ODEVREADY; 3246 else 3247 com->state &= ~CS_ODEVREADY; 3248 } 3249 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3250 if (stat & TIOCM_CAR ) 3251 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3252 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3253 /* negate DTR, RTS */ 3254 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3255 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3256 /* disable IENABLE */ 3257 com_int_TxRx_disable( com ); 3258 } 3259 } 3260} 3261#endif 3262 3263static void 3264disc_optim(tp, t, com) 3265 struct tty *tp; 3266 struct termios *t; 3267 struct com_s *com; 3268{ 3269 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3270 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3271 && (!(t->c_iflag & PARMRK) 3272 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3273 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3274 && linesw[tp->t_line].l_rint == ttyinput) 3275 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3276 else 3277 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3278 /* 3279 * Prepare to reduce input latency for packet 3280 * discplines with a end of packet character. 3281 */ 3282 if (tp->t_line == SLIPDISC) 3283 com->hotchar = 0xc0; 3284 else if (tp->t_line == PPPDISC) 3285 com->hotchar = 0x7e; 3286 else 3287 com->hotchar = 0; 3288} 3289 3290/* 3291 * Following are all routines needed for SIO to act as console 3292 */ 3293#include <machine/cons.h> 3294 3295struct siocnstate { 3296 u_char dlbl; 3297 u_char dlbh; 3298 u_char ier; 3299 u_char cfcr; 3300 u_char mcr; 3301}; 3302 3303static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3304static void siocnclose __P((struct siocnstate *sp)); 3305static void siocnopen __P((struct siocnstate *sp)); 3306static void siocntxwait __P((void)); 3307 3308static void 3309siocntxwait() 3310{ 3311 int timo; 3312 3313 /* 3314 * Wait for any pending transmission to finish. Required to avoid 3315 * the UART lockup bug when the speed is changed, and for normal 3316 * transmits. 3317 */ 3318 timo = 100000; 3319 while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3320 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3321 ; 3322} 3323 3324/* 3325 * Read the serial port specified and try to figure out what speed 3326 * it's currently running at. We're assuming the serial port has 3327 * been initialized and is basicly idle. This routine is only intended 3328 * to be run at system startup. 3329 * 3330 * If the value read from the serial port doesn't make sense, return 0. 3331 */ 3332 3333static speed_t 3334siocngetspeed(iobase, table) 3335 Port_t iobase; 3336 struct speedtab *table; 3337{ 3338 int code; 3339 u_char dlbh; 3340 u_char dlbl; 3341 u_char cfcr; 3342 3343 cfcr = inb(iobase + com_cfcr); 3344 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3345 3346 dlbl = inb(iobase + com_dlbl); 3347 dlbh = inb(iobase + com_dlbh); 3348 3349 outb(iobase + com_cfcr, cfcr); 3350 3351 code = dlbh << 8 | dlbl; 3352 3353 for ( ; table->sp_speed != -1; table++) 3354 if (table->sp_code == code) 3355 return (table->sp_speed); 3356 3357 return 0; /* didn't match anything sane */ 3358} 3359 3360static void 3361siocnopen(sp) 3362 struct siocnstate *sp; 3363{ 3364 int divisor; 3365 u_char dlbh; 3366 u_char dlbl; 3367 Port_t iobase; 3368 3369 /* 3370 * Save all the device control registers except the fifo register 3371 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3372 * We can't save the fifo register since it is read-only. 3373 */ 3374 iobase = siocniobase; 3375 sp->ier = inb(iobase + com_ier); 3376 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3377 siocntxwait(); 3378 sp->cfcr = inb(iobase + com_cfcr); 3379 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3380 sp->dlbl = inb(iobase + com_dlbl); 3381 sp->dlbh = inb(iobase + com_dlbh); 3382 /* 3383 * Only set the divisor registers if they would change, since on 3384 * some 16550 incompatibles (Startech), setting them clears the 3385 * data input register. This also reduces the effects of the 3386 * UMC8669F bug. 3387 */ 3388 divisor = ttspeedtab(comdefaultrate, comspeedtab); 3389 dlbl = divisor & 0xFF; 3390 if (sp->dlbl != dlbl) 3391 outb(iobase + com_dlbl, dlbl); 3392 dlbh = (u_int) divisor >> 8; 3393 if (sp->dlbh != dlbh) 3394 outb(iobase + com_dlbh, dlbh); 3395 outb(iobase + com_cfcr, CFCR_8BITS); 3396 sp->mcr = inb(iobase + com_mcr); 3397 /* 3398 * We don't want interrupts, but must be careful not to "disable" 3399 * them by clearing the MCR_IENABLE bit, since that might cause 3400 * an interrupt by floating the IRQ line. 3401 */ 3402 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 3403} 3404 3405static void 3406siocnclose(sp) 3407 struct siocnstate *sp; 3408{ 3409 Port_t iobase; 3410 3411 /* 3412 * Restore the device control registers. 3413 */ 3414 siocntxwait(); 3415 iobase = siocniobase; 3416 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3417 if (sp->dlbl != inb(iobase + com_dlbl)) 3418 outb(iobase + com_dlbl, sp->dlbl); 3419 if (sp->dlbh != inb(iobase + com_dlbh)) 3420 outb(iobase + com_dlbh, sp->dlbh); 3421 outb(iobase + com_cfcr, sp->cfcr); 3422 /* 3423 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 3424 */ 3425 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 3426 outb(iobase + com_ier, sp->ier); 3427} 3428 3429void 3430siocnprobe(cp) 3431 struct consdev *cp; 3432{ 3433 speed_t boot_speed; 3434 u_char cfcr; 3435 struct isa_device *dvp; 3436 int s; 3437 struct siocnstate sp; 3438 3439 /* 3440 * Find our first enabled console, if any. If it is a high-level 3441 * console device, then initialize it and return successfully. 3442 * If it is a low-level console device, then initialize it and 3443 * return unsuccessfully. It must be initialized in both cases 3444 * for early use by console drivers and debuggers. Initializing 3445 * the hardware is not necessary in all cases, since the i/o 3446 * routines initialize it on the fly, but it is necessary if 3447 * input might arrive while the hardware is switched back to an 3448 * uninitialized state. We can't handle multiple console devices 3449 * yet because our low-level routines don't take a device arg. 3450 * We trust the user to set the console flags properly so that we 3451 * don't need to probe. 3452 */ 3453 cp->cn_pri = CN_DEAD; 3454 for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) 3455 if (dvp->id_driver == &siodriver && dvp->id_enabled 3456 && COM_CONSOLE(dvp)) { 3457 siocniobase = dvp->id_iobase; 3458 s = spltty(); 3459 if (boothowto & RB_SERIAL) { 3460 boot_speed = siocngetspeed(siocniobase, 3461 comspeedtab); 3462 if (boot_speed) 3463 comdefaultrate = boot_speed; 3464 } 3465 3466 /* 3467 * Initialize the divisor latch. We can't rely on 3468 * siocnopen() to do this the first time, since it 3469 * avoids writing to the latch if the latch appears 3470 * to have the correct value. Also, if we didn't 3471 * just read the speed from the hardware, then we 3472 * need to set the speed in hardware so that 3473 * switching it later is null. 3474 */ 3475 cfcr = inb(siocniobase + com_cfcr); 3476 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 3477 outb(siocniobase + com_dlbl, 3478 COMBRD(comdefaultrate) & 0xff); 3479 outb(siocniobase + com_dlbh, 3480 (u_int) COMBRD(comdefaultrate) >> 8); 3481 outb(siocniobase + com_cfcr, cfcr); 3482 3483 siocnopen(&sp); 3484 splx(s); 3485 if (!COM_LLCONSOLE(dvp)) { 3486 cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); 3487 cp->cn_pri = COM_FORCECONSOLE(dvp) 3488 || boothowto & RB_SERIAL 3489 ? CN_REMOTE : CN_NORMAL; 3490 } 3491 break; 3492 } 3493} 3494 3495void 3496siocninit(cp) 3497 struct consdev *cp; 3498{ 3499 comconsole = DEV_TO_UNIT(cp->cn_dev); 3500} 3501 3502int 3503siocncheckc(dev) 3504 dev_t dev; 3505{ 3506 int c; 3507 Port_t iobase; 3508 int s; 3509 struct siocnstate sp; 3510 3511 iobase = siocniobase; 3512 s = spltty(); 3513 siocnopen(&sp); 3514 if (inb(iobase + com_lsr) & LSR_RXRDY) 3515 c = inb(iobase + com_data); 3516 else 3517 c = -1; 3518 siocnclose(&sp); 3519 splx(s); 3520 return (c); 3521} 3522 3523 3524int 3525siocngetc(dev) 3526 dev_t dev; 3527{ 3528 int c; 3529 Port_t iobase; 3530 int s; 3531 struct siocnstate sp; 3532 3533 iobase = siocniobase; 3534 s = spltty(); 3535 siocnopen(&sp); 3536 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 3537 ; 3538 c = inb(iobase + com_data); 3539 siocnclose(&sp); 3540 splx(s); 3541 return (c); 3542} 3543 3544void 3545siocnputc(dev, c) 3546 dev_t dev; 3547 int c; 3548{ 3549 int s; 3550 struct siocnstate sp; 3551 3552 s = spltty(); 3553 siocnopen(&sp); 3554 siocntxwait(); 3555 outb(siocniobase + com_data, c); 3556 siocnclose(&sp); 3557 splx(s); 3558} 3559 3560#ifdef DSI_SOFT_MODEM 3561/* 3562 * The magic code to download microcode to a "Connection 14.4+Fax" 3563 * modem from Digicom Systems Inc. Very magic. 3564 */ 3565 3566#define DSI_ERROR(str) { ptr = str; goto error; } 3567static int 3568LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr) 3569{ 3570 int int_c,int_k; 3571 int data_0188, data_0187; 3572 3573 /* 3574 * First see if it is a DSI SoftModem 3575 */ 3576 if(!((inb(base_io+7) ^ inb(base_io+7) & 0x80))) 3577 return ENODEV; 3578 3579 data_0188 = inb(base_io+4); 3580 data_0187 = inb(base_io+3); 3581 outb(base_io+3,0x80); 3582 outb(base_io+4,0x0C); 3583 outb(base_io+0,0x31); 3584 outb(base_io+1,0x8C); 3585 outb(base_io+7,0x10); 3586 outb(base_io+7,0x19); 3587 3588 if(0x18 != (inb(base_io+7) & 0x1A)) 3589 DSI_ERROR("dsp bus not granted"); 3590 3591 if(0x01 != (inb(base_io+7) & 0x01)) { 3592 outb(base_io+7,0x18); 3593 outb(base_io+7,0x19); 3594 if(0x01 != (inb(base_io+7) & 0x01)) 3595 DSI_ERROR("program mem not granted"); 3596 } 3597 3598 int_c = 0; 3599 3600 while(1) { 3601 if(int_c >= 7 || size <= 0x1800) 3602 break; 3603 3604 for(int_k = 0 ; int_k < 0x800; int_k++) { 3605 outb(base_io+0,*ptr++); 3606 outb(base_io+1,*ptr++); 3607 outb(base_io+2,*ptr++); 3608 } 3609 3610 size -= 0x1800; 3611 int_c++; 3612 } 3613 3614 if(size > 0x1800) { 3615 outb(base_io+7,0x18); 3616 outb(base_io+7,0x19); 3617 if(0x00 != (inb(base_io+7) & 0x01)) 3618 DSI_ERROR("program data not granted"); 3619 3620 for(int_k = 0 ; int_k < 0x800; int_k++) { 3621 outb(base_io+1,*ptr++); 3622 outb(base_io+2,0); 3623 outb(base_io+1,*ptr++); 3624 outb(base_io+2,*ptr++); 3625 } 3626 3627 size -= 0x1800; 3628 3629 while(size > 0x1800) { 3630 for(int_k = 0 ; int_k < 0xC00; int_k++) { 3631 outb(base_io+1,*ptr++); 3632 outb(base_io+2,*ptr++); 3633 } 3634 size -= 0x1800; 3635 } 3636 3637 if(size < 0x1800) { 3638 for(int_k=0;int_k<size/2;int_k++) { 3639 outb(base_io+1,*ptr++); 3640 outb(base_io+2,*ptr++); 3641 } 3642 } 3643 3644 } else if (size > 0) { 3645 if(int_c == 7) { 3646 outb(base_io+7,0x18); 3647 outb(base_io+7,0x19); 3648 if(0x00 != (inb(base_io+7) & 0x01)) 3649 DSI_ERROR("program data not granted"); 3650 for(int_k = 0 ; int_k < size/3; int_k++) { 3651 outb(base_io+1,*ptr++); 3652 outb(base_io+2,0); 3653 outb(base_io+1,*ptr++); 3654 outb(base_io+2,*ptr++); 3655 } 3656 } else { 3657 for(int_k = 0 ; int_k < size/3; int_k++) { 3658 outb(base_io+0,*ptr++); 3659 outb(base_io+1,*ptr++); 3660 outb(base_io+2,*ptr++); 3661 } 3662 } 3663 } 3664 outb(base_io+7,0x11); 3665 outb(base_io+7,3); 3666 3667 outb(base_io+4,data_0188 & 0xfb); 3668 3669 outb(base_io+3,data_0187); 3670 3671 return 0; 3672error: 3673 printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr); 3674 outb(base_io+7,0x00); \ 3675 outb(base_io+3,data_0187); \ 3676 outb(base_io+4,data_0188); \ 3677 return EIO; 3678} 3679#endif /* DSI_SOFT_MODEM */ 3680 3681/* 3682 * support PnP cards if we are using 'em 3683 */ 3684 3685#if NPNP > 0 3686 3687static struct siopnp_ids { 3688 u_long vend_id; 3689 char *id_str; 3690} siopnp_ids[] = { 3691 { 0x8113b04e, "Supra1381"}, 3692 { 0x9012b04e, "Supra1290"}, 3693 { 0x11007256, "USR0011"}, 3694 { 0 } 3695}; 3696 3697static char *siopnp_probe(u_long csn, u_long vend_id); 3698static void siopnp_attach(u_long csn, u_long vend_id, char *name, 3699 struct isa_device *dev); 3700static u_long nsiopnp = NSIO; 3701 3702static struct pnp_device siopnp = { 3703 "siopnp", 3704 siopnp_probe, 3705 siopnp_attach, 3706 &nsiopnp, 3707 &tty_imask 3708}; 3709DATA_SET (pnpdevice_set, siopnp); 3710 3711static char * 3712siopnp_probe(u_long csn, u_long vend_id) 3713{ 3714 struct siopnp_ids *ids; 3715 char *s = NULL; 3716 3717 for(ids = siopnp_ids; ids->vend_id != 0; ids++) { 3718 if (vend_id == ids->vend_id) { 3719 s = ids->id_str; 3720 break; 3721 } 3722 } 3723 3724 if (s) { 3725 struct pnp_cinfo d; 3726 read_pnp_parms(&d, 0); 3727 if (d.enable == 0 || d.flags & 1) { 3728 printf("CSN %d is disabled.\n", csn); 3729 return (NULL); 3730 } 3731 3732 } 3733 3734 return (s); 3735} 3736 3737static void 3738siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) 3739{ 3740 struct pnp_cinfo d; 3741 struct isa_device *dvp; 3742 3743 if (dev->id_unit >= NSIOTOT) 3744 return; 3745 3746 if (read_pnp_parms(&d, 0) == 0) { 3747 printf("failed to read pnp parms\n"); 3748 return; 3749 } 3750 3751 write_pnp_parms(&d, 0); 3752 3753 enable_pnp_card(); 3754 3755 dev->id_iobase = d.port[0]; 3756 dev->id_irq = (1 << d.irq[0]); 3757 dev->id_intr = siointr; 3758 dev->id_ri_flags = RI_FAST; 3759 dev->id_drq = -1; 3760 3761 if (dev->id_driver == NULL) { 3762 dev->id_driver = &siodriver; 3763 dvp = find_isadev(isa_devtab_tty, &siodriver, 0); 3764 if (dvp != NULL) 3765 dev->id_id = dvp->id_id; 3766 } 3767 3768 if ((dev->id_alive = sioprobe(dev)) != 0) 3769 sioattach(dev); 3770 else 3771 printf("sio%d: probe failed\n", dev->id_unit); 3772} 3773#endif 3774#ifdef PC98 3775/* 3776 * pc98 local function 3777 */ 3778 3779static void 3780com_tiocm_set(struct com_s *com, int msr) 3781{ 3782 int s; 3783 int tmp = 0; 3784 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 3785 3786 s=spltty(); 3787 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 3788 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3789 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 3790 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3791 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3792 pc98_i8251_clear_or_cmd( com, mask, tmp ); 3793 splx(s); 3794} 3795 3796static void 3797com_tiocm_bis(struct com_s *com, int msr) 3798{ 3799 int s; 3800 int tmp = 0; 3801 3802 s=spltty(); 3803 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3804 tmp |= CMD8251_TxEN|CMD8251_RxEN; 3805 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3806 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3807 3808 pc98_i8251_or_cmd( com, tmp ); 3809 splx(s); 3810} 3811 3812static void 3813com_tiocm_bic(struct com_s *com, int msr) 3814{ 3815 int s; 3816 int tmp = msr; 3817 3818 s=spltty(); 3819 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3820 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3821 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3822 3823 pc98_i8251_clear_cmd( com, tmp ); 3824 splx(s); 3825} 3826 3827static int 3828com_tiocm_get(struct com_s *com) 3829{ 3830 return( com->pc98_prev_modem_status ); 3831} 3832 3833static int 3834com_tiocm_get_delta(struct com_s *com) 3835{ 3836 int tmp; 3837 3838 tmp = com->pc98_modem_delta; 3839 com->pc98_modem_delta = 0; 3840 return( tmp ); 3841} 3842 3843/* convert to TIOCM_?? ( ioctl.h ) */ 3844static int 3845pc98_get_modem_status(struct com_s *com) 3846{ 3847 int stat, stat2; 3848 register int msr; 3849 3850 stat = inb(com->sts_port); 3851 stat2 = inb(com->in_modem_port); 3852 msr = com->pc98_prev_modem_status 3853 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3854 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 3855 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 3856 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 3857 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 3858#if COM_CARRIER_DETECT_EMULATE 3859 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 3860 msr |= TIOCM_CAR; 3861 } 3862#endif 3863 return(msr); 3864} 3865 3866static void 3867pc98_check_msr(void* chan) 3868{ 3869 int msr, delta; 3870 int s; 3871 register struct tty *tp; 3872 struct com_s *com; 3873 int mynor; 3874 int unit; 3875 dev_t dev; 3876 3877 dev=(dev_t)chan; 3878 mynor = minor(dev); 3879 unit = MINOR_TO_UNIT(mynor); 3880 com = com_addr(unit); 3881 tp = com->tp; 3882 3883 s = spltty(); 3884 msr = pc98_get_modem_status(com); 3885 /* make change flag */ 3886 delta = msr ^ com->pc98_prev_modem_status; 3887 if ( delta & TIOCM_CAR ) { 3888 if ( com->modem_car_chg_timer ) { 3889 if ( -- com->modem_car_chg_timer ) 3890 msr ^= TIOCM_CAR; 3891 } else { 3892 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ? 3893 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE ) 3894 msr ^= TIOCM_CAR; 3895 } 3896 } else 3897 com->modem_car_chg_timer = 0; 3898 delta = ( msr ^ com->pc98_prev_modem_status ) & 3899 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3900 com->pc98_prev_modem_status = msr; 3901 delta = ( com->pc98_modem_delta |= delta ); 3902 splx(s); 3903 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 3904 if ( delta ) { 3905 commint(dev); 3906 } 3907 timeout(pc98_check_msr, (caddr_t)dev, 3908 PC98_CHECK_MODEM_INTERVAL); 3909 } else { 3910 com->modem_checking = 0; 3911 } 3912} 3913 3914static void 3915pc98_msrint_start(dev_t dev) 3916{ 3917 struct com_s *com; 3918 int mynor; 3919 int unit; 3920 int s = spltty(); 3921 3922 mynor = minor(dev); 3923 unit = MINOR_TO_UNIT(mynor); 3924 com = com_addr(unit); 3925 /* modem control line check routine envoke interval is 1/10 sec */ 3926 if ( com->modem_checking == 0 ) { 3927 com->pc98_prev_modem_status = pc98_get_modem_status(com); 3928 com->pc98_modem_delta = 0; 3929 timeout(pc98_check_msr, (caddr_t)dev, 3930 PC98_CHECK_MODEM_INTERVAL); 3931 com->modem_checking = 1; 3932 } 3933 splx(s); 3934} 3935 3936static void 3937pc98_disable_i8251_interrupt(struct com_s *com, int mod) 3938{ 3939 /* disable interrupt */ 3940 register int tmp; 3941 3942 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3943 COM_INT_DISABLE 3944 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3945 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 3946 COM_INT_ENABLE 3947} 3948 3949static void 3950pc98_enable_i8251_interrupt(struct com_s *com, int mod) 3951{ 3952 register int tmp; 3953 3954 COM_INT_DISABLE 3955 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3956 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 3957 COM_INT_ENABLE 3958} 3959 3960static int 3961pc98_check_i8251_interrupt(struct com_s *com) 3962{ 3963 return ( com->intr_enable & 0x07 ); 3964} 3965 3966static void 3967pc98_i8251_clear_cmd(struct com_s *com, int x) 3968{ 3969 int tmp; 3970 3971 COM_INT_DISABLE 3972 tmp = com->pc98_prev_siocmd & ~(x); 3973 outb(com->cmd_port, tmp); 3974 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3975 COM_INT_ENABLE 3976} 3977 3978static void 3979pc98_i8251_or_cmd(struct com_s *com, int x) 3980{ 3981 int tmp; 3982 3983 COM_INT_DISABLE 3984 tmp = com->pc98_prev_siocmd | (x); 3985 outb(com->cmd_port, tmp); 3986 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3987 COM_INT_ENABLE 3988} 3989 3990static void 3991pc98_i8251_set_cmd(struct com_s *com, int x) 3992{ 3993 int tmp; 3994 3995 COM_INT_DISABLE 3996 tmp = (x); 3997 outb(com->cmd_port, tmp); 3998 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3999 COM_INT_ENABLE 4000} 4001 4002static void 4003pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4004{ 4005 int tmp; 4006 COM_INT_DISABLE 4007 tmp = com->pc98_prev_siocmd & ~(clr); 4008 tmp |= (x); 4009 outb(com->cmd_port, tmp); 4010 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4011 COM_INT_ENABLE 4012} 4013 4014static int 4015pc98_i8251_get_cmd(struct com_s *com) 4016{ 4017 return com->pc98_prev_siocmd; 4018} 4019 4020static int 4021pc98_i8251_get_mod(struct com_s *com) 4022{ 4023 return com->pc98_prev_siomod; 4024} 4025 4026static void 4027pc98_i8251_reset(struct com_s *com, int mode, int command) 4028{ 4029 outb(com->cmd_port, 0); /* dummy */ 4030 DELAY(2); 4031 outb(com->cmd_port, 0); /* dummy */ 4032 DELAY(2); 4033 outb(com->cmd_port, 0); /* dummy */ 4034 DELAY(2); 4035 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4036 DELAY(2); 4037 outb(com->cmd_port, mode ); /* mode register */ 4038 com->pc98_prev_siomod = mode; 4039 DELAY(2); 4040 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4041} 4042 4043static void 4044pc98_check_sysclock(void) 4045{ 4046 /* get system clock from port */ 4047 if ( pc98_machine_type & M_8M ) { 4048 /* 8 MHz system & H98 */ 4049 sysclock = 8; 4050 } else { 4051 /* 5 MHz system */ 4052 sysclock = 5; 4053 } 4054} 4055 4056static void 4057com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4058{ 4059 int cfcr=0, count; 4060 int previnterrupt; 4061 4062 count = pc98_ttspeedtab( com, speed ); 4063 if ( count < 0 ) return; 4064 4065 previnterrupt = pc98_check_i8251_interrupt(com); 4066 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4067 4068 switch ( cflag&CSIZE ) { 4069 case CS5: 4070 cfcr = MOD8251_5BITS; break; 4071 case CS6: 4072 cfcr = MOD8251_6BITS; break; 4073 case CS7: 4074 cfcr = MOD8251_7BITS; break; 4075 case CS8: 4076 cfcr = MOD8251_8BITS; break; 4077 } 4078 if ( cflag&PARENB ) { 4079 if ( cflag&PARODD ) 4080 cfcr |= MOD8251_PODD; 4081 else 4082 cfcr |= MOD8251_PEVEN; 4083 } else 4084 cfcr |= MOD8251_PDISAB; 4085 4086 if ( cflag&CSTOPB ) 4087 cfcr |= MOD8251_STOP2; 4088 else 4089 cfcr |= MOD8251_STOP1; 4090 4091 if ( count & 0x10000 ) 4092 cfcr |= MOD8251_CLKX1; 4093 else 4094 cfcr |= MOD8251_CLKX16; 4095 4096 if (epson_machine_id != 0x20) { /* XXX */ 4097 { 4098 int tmp; 4099 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4100 ; 4101 } 4102 } 4103 /* set baud rate from ospeed */ 4104 pc98_set_baud_rate( com, count ); 4105 4106 if ( cfcr != pc98_i8251_get_mod(com) ) 4107 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4108 4109 pc98_enable_i8251_interrupt( com, previnterrupt ); 4110} 4111 4112static int 4113pc98_ttspeedtab(struct com_s *com, int speed) 4114{ 4115 int effect_sp, count=-1, mod; 4116 4117 switch ( com->pc98_if_type ) { 4118 case COM_IF_INTERNAL: 4119 /* for *1CLK asynchronous! mode , TEFUTEFU */ 4120 effect_sp = ttspeedtab( speed, pc98speedtab ); 4121 if ( effect_sp < 0 ) 4122 effect_sp = ttspeedtab( (speed-1), pc98speedtab ); 4123 if ( effect_sp <= 0 ) 4124 return effect_sp; 4125 mod = (sysclock == 5 ? 2457600 : 1996800); 4126 if ( effect_sp == speed ) 4127 mod /= 16; 4128 count = mod / effect_sp; 4129 if ( count > 65535 ) 4130 return(-1); 4131 if ( effect_sp >= 2400 ) 4132 if ( !(sysclock != 5 && 4133 (effect_sp == 19200 || effect_sp == 38400)) ) 4134 if ( ( mod % effect_sp ) != 0 ) 4135 return(-1); 4136 if ( effect_sp != speed ) 4137 count |= 0x10000; 4138 break; 4139#ifdef COM_IF_PC9861K 4140 case COM_IF_PC9861K: 4141 effect_sp = speed; 4142 count = 1; 4143 break; 4144#endif 4145#ifdef COM_IF_PIO9032B 4146 case COM_IF_PIO9032B: 4147 if ( speed == 0 ) return 0; 4148 count = ttspeedtab( speed, comspeedtab_pio9032b ); 4149 if ( count < 0 ) return count; 4150 effect_sp = speed; 4151 break; 4152#endif 4153#ifdef COM_IF_B98_01 4154 case COM_IF_B98_01: 4155 effect_sp=speed; 4156 count = ttspeedtab( speed, comspeedtab_b98_01 ); 4157 if ( count <= 3 ) 4158 return -1; /* invalid speed/count */ 4159 if ( count <= 5 ) 4160 count |= 0x10000; /* x1 mode for 76800 and 153600 */ 4161 else 4162 count -= 4; /* x16 mode for slower */ 4163 break; 4164#endif 4165 } 4166 return count; 4167} 4168 4169static void 4170pc98_set_baud_rate( struct com_s *com, int count) 4171{ 4172 int s; 4173 4174 switch ( com->pc98_if_type ) { 4175 case COM_IF_INTERNAL: 4176 if ( count < 0 ) { 4177 printf( "[ Illegal count : %d ]", count ); 4178 return; 4179 } else if ( count == 0) 4180 return; 4181 /* set i8253 */ 4182 s = splclock(); 4183 outb( 0x77, 0xb6 ); 4184 outb( 0x5f, 0); 4185 outb( 0x75, count & 0xff ); 4186 outb( 0x5f, 0); 4187 outb( 0x75, (count >> 8) & 0xff ); 4188 splx(s); 4189 break; 4190#if 0 4191#ifdef COM_IF_PC9861K 4192 case COM_IF_PC9861K: 4193 break; 4194 /* ext. RS232C board: speed is determined by DIP switch */ 4195#endif 4196#endif /* 0 */ 4197#ifdef COM_IF_PIO9032B 4198 case COM_IF_PIO9032B: 4199 outb( com_addr[unit], count & 0x07 ); 4200 break; 4201#endif 4202#ifdef COM_IF_B98_01 4203 case COM_IF_B98_01: 4204 outb( com->iobase, count & 0x0f ); 4205#ifdef B98_01_OLD 4206 /* some old board should be controlled in different way, 4207 but this hasn't been tested yet.*/ 4208 outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 ); 4209#endif 4210 break; 4211#endif 4212 } 4213} 4214static int 4215pc98_check_if_type( int iobase, struct siodev *iod) 4216{ 4217 int irr = 0, tmp = 0; 4218 int ret = 0; 4219 static short irq_tab[2][8] = { 4220 { 3, 5, 6, 9, 10, 12, 13, -1}, 4221 { 3, 10, 12, 13, 5, 6, 9, -1} 4222 }; 4223 iod->irq = 0; 4224 switch ( iobase & 0xff ) { 4225 case IO_COM1: 4226 iod->if_type = COM_IF_INTERNAL; 4227 ret = 0; iod->irq = 4; break; 4228#ifdef COM_IF_PC9861K 4229 case IO_COM2: 4230 iod->if_type = COM_IF_PC9861K; 4231 ret = 1; irr = 0; tmp = 3; break; 4232 case IO_COM3: 4233 iod->if_type = COM_IF_PC9861K; 4234 ret = 2; irr = 1; tmp = 3; break; 4235#endif 4236#ifdef COM_IF_PIO9032B 4237 case IO_COM_PIO9032B_2: 4238 iod->if_type = COM_IF_PIO9032B; 4239 ret = 1; irr = 0; tmp = 7; break; 4240 case IO_COM_PIO9032B_3: 4241 iod->if_type = COM_IF_PIO9032B; 4242 ret = 2; irr = 1; tmp = 7; break; 4243#endif 4244#ifdef COM_IF_B98_01 4245 case IO_COM_B98_01_2: 4246 iod->if_type = COM_IF_B98_01; 4247 ret = 1; irr = 0; tmp = 7; 4248 outb(iobase + 2, 0xf2); 4249 outb(iobase, 4); 4250 break; 4251 case IO_COM_B98_01_3: 4252 iod->if_type = COM_IF_B98_01; 4253 ret = 2; irr = 1; tmp = 7; 4254 outb(iobase + 2, 0xf2); 4255 outb(iobase , 4); 4256 break; 4257#endif 4258 default: 4259 if((iobase & 0x0f0) == 0xd0){ 4260 iod->if_type = MC16550; 4261 return 0; 4262 } 4263 return -1; 4264 } 4265 4266 iod->cmd = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret); 4267 iod->sts = ( iobase & 0xff00 )|PC98SIO_sts_port(ret); 4268 iod->mod = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret); 4269 iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret); 4270 4271 if ( iod->irq == 0 ) { 4272 tmp &= inb( iod->mod ); 4273 iod->irq = irq_tab[irr][tmp]; 4274 if ( iod->irq == -1 ) return -1; 4275 } 4276 return 0; 4277} 4278static int 4279pc98_set_ioport( struct com_s *com, int io_base ) 4280{ 4281 int a, io, type; 4282 4283 switch ( io_base & 0xff ) { 4284 case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL; 4285 pc98_check_sysclock(); break; 4286#ifdef COM_IF_PC9861K 4287 case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break; 4288 case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break; 4289#endif /* COM_IF_PC9861K */ 4290#ifdef COM_IF_PIO9032B 4291 /* PIO9032B : I/O address is changeable */ 4292 case IO_COM_PIO9032B_2: 4293 a = 1; io = io_base & 0xff00; 4294 type = COM_IF_PIO9032B; break; 4295 case IO_COM_PIO9032B_3: 4296 a = 2; io = io_base & 0xff00; 4297 type = COM_IF_PIO9032B; break; 4298#endif /* COM_IF_PIO9032B */ 4299#ifdef COM_IF_B98_01 4300 case IO_COM_B98_01_2: 4301 a = 1; io = 0; type = COM_IF_B98_01; break; 4302 case IO_COM_B98_01_3: 4303 a = 2; io = 0; type = COM_IF_B98_01; break; 4304#endif /* COM_IF_B98_01*/ 4305 default: /* i/o address not match */ 4306 return -1; 4307 } 4308 4309 com->pc98_if_type = type; 4310 com->data_port = io | PC98SIO_data_port(a); 4311 com->cmd_port = io | PC98SIO_cmd_port(a); 4312 com->sts_port = io | PC98SIO_sts_port(a); 4313 com->in_modem_port = io | PC98SIO_in_modem_port(a); 4314 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(a); 4315 return 0; 4316} 4317#endif /* PC98 defined */ 4318