sio.c revision 32332
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.46 1997/12/29 16:08:48 kato Exp $ 35 */ 36 37#include "opt_comconsole.h" 38#include "opt_compat.h" 39#include "opt_ddb.h" 40#include "opt_sio.h" 41#include "sio.h" 42#include "pnp.h" 43 44#ifndef EXTRA_SIO 45#if NPNP > 0 46#define EXTRA_SIO 2 47#else 48#define EXTRA_SIO 0 49#endif 50#endif 51 52#define NSIOTOT (NSIO + EXTRA_SIO) 53 54/* 55 * Serial driver, based on 386BSD-0.1 com driver. 56 * Mostly rewritten to use pseudo-DMA. 57 * Works for National Semiconductor NS8250-NS16550AF UARTs. 58 * COM driver, based on HP dca driver. 59 * 60 * Changes for PC-Card integration: 61 * - Added PC-Card driver table and handlers 62 */ 63/*=============================================================== 64 * 386BSD(98),FreeBSD-1.1x(98) com driver. 65 * ----- 66 * modified for PC9801 by M.Ishii 67 * Kyoto University Microcomputer Club (KMC) 68 * Chou "TEFUTEFU" Hirotomi 69 * Kyoto Univ. the faculty of medicine 70 *=============================================================== 71 * FreeBSD-2.0.1(98) sio driver. 72 * ----- 73 * modified for pc98 Internal i8251 and MICRO CORE MC16550II 74 * T.Koike(hfc01340@niftyserve.or.jp) 75 * implement kernel device configuration 76 * aizu@orient.center.nitech.ac.jp 77 * 78 * Notes. 79 * ----- 80 * PC98 localization based on 386BSD(98) com driver. Using its PC98 local 81 * functions. 82 * This driver is under debugging,has bugs. 83 * 84 * 1) config 85 * options COM_MULTIPORT #if using MC16550II 86 * device sio0 at nec? port 0x30 tty irq 4 vector siointr #internal 87 * device sio1 at nec? port 0xd2 tty irq 5 flags 0x101 vector siointr #mc1 88 * device sio2 at nec? port 0x8d2 tty flags 0x101 vector siointr #mc2 89 * # ~~~~~iobase ~~multi port flag 90 * # ~ master device is sio1 91 * 2) device 92 * cd /dev; MAKEDEV ttyd0 ttyd1 .. 93 * 3) /etc/rc.serial 94 * 57600bps is too fast for sio0(internal8251) 95 * my ex. 96 * #set default speed 9600 97 * modem() 98 * : 99 * stty </dev/ttyid$i crtscts 9600 100 * : # ~~~~ default speed(can change after init.) 101 * modem 0 1 2 102 * 4) COMCONSOLE 103 * not changed. 104 * 5) PC9861K,PIO9032B,B98_01 105 * not tested. 106 */ 107/* 108 * modified for AIWA B98-01 109 * by T.Hatanou <hatanou@yasuda.comm.waseda.ac.jp> last update: 15 Sep.1995 110 * 111 * How to configure... 112 * # options COM_MULTIPORT # support for MICROCORE MC16550II 113 * ... comment-out this line, which will conflict with B98_01. 114 * options "B98_01" # support for AIWA B98-01 115 * device sio1 at nec? port 0x00d1 tty irq ? vector siointr 116 * device sio2 at nec? port 0x00d5 tty irq ? vector siointr 117 * ... you can leave these lines `irq ?', irq will be autodetected. 118 */ 119#ifdef PC98 120#define MC16550 0 121#define COM_IF_INTERNAL 1 122#if 0 123#define COM_IF_PC9861K 2 124#define COM_IF_PIO9032B 3 125#endif 126#ifdef B98_01 127#undef COM_MULTIPORT /* COM_MULTIPORT will conflict with B98_01 */ 128#define COM_IF_B98_01 4 129#endif /* B98_01 */ 130#endif /* PC98 */ 131 132#include <sys/param.h> 133#include <sys/systm.h> 134#include <sys/reboot.h> 135#include <sys/malloc.h> 136#include <sys/tty.h> 137#include <sys/proc.h> 138#include <sys/conf.h> 139#include <sys/dkstat.h> 140#include <sys/fcntl.h> 141#include <sys/kernel.h> 142#include <sys/syslog.h> 143#include <sys/sysctl.h> 144#ifdef DEVFS 145#include <sys/devfsext.h> 146#endif 147 148#include <machine/clock.h> 149 150#ifdef PC98 151#include <pc98/pc98/pc98.h> 152#include <pc98/pc98/pc98_machdep.h> 153#include <i386/isa/icu.h> 154#include <i386/isa/isa_device.h> 155#include <pc98/pc98/sioreg.h> 156#include <i386/isa/ic/i8251.h> 157#else 158#include <i386/isa/isa.h> 159#include <i386/isa/isa_device.h> 160#include <i386/isa/sioreg.h> 161#endif 162#include <i386/isa/intr_machdep.h> 163 164#ifdef COM_ESP 165#include <i386/isa/ic/esp.h> 166#endif 167#include <i386/isa/ic/ns16550.h> 168 169#include "card.h" 170#if NCARD > 0 171#include <pccard/cardinfo.h> 172#include <pccard/driver.h> 173#include <pccard/slot.h> 174#endif 175 176#if NPNP > 0 177#include <i386/isa/pnp.h> 178#endif 179 180#ifdef SMP 181#define disable_intr() COM_DISABLE_INTR() 182#define enable_intr() COM_ENABLE_INTR() 183#endif /* SMP */ 184 185#ifdef APIC_IO 186/* 187 * INTs are masked in the (global) IO APIC, 188 * but the IRR register is in each LOCAL APIC, 189 * so we would have to unmask the INT to be able to "see INT pending". 190 * So instead we just look in the 8259 ICU. 191 */ 192#define isa_irq_pending icu_irq_pending 193#endif /* APIC_IO */ 194 195#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 196#define RB_I_HIGH_WATER (TTYHOG - 2 * RS_IBUFSIZE) 197#define RS_IBUFSIZE 256 198 199#define CALLOUT_MASK 0x80 200#define CONTROL_MASK 0x60 201#define CONTROL_INIT_STATE 0x20 202#define CONTROL_LOCK_STATE 0x40 203#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 204#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 205#define MINOR_TO_UNIT(mynor) ((mynor) & ~MINOR_MAGIC_MASK) 206 207#ifdef COM_MULTIPORT 208/* checks in flags for multiport and which is multiport "master chip" 209 * for a given card 210 */ 211#define COM_ISMULTIPORT(dev) ((dev)->id_flags & 0x01) 212#define COM_MPMASTER(dev) (((dev)->id_flags >> 8) & 0x0ff) 213#define COM_NOTAST4(dev) ((dev)->id_flags & 0x04) 214#endif /* COM_MULTIPORT */ 215 216#define COM_CONSOLE(dev) ((dev)->id_flags & 0x10) 217#define COM_FORCECONSOLE(dev) ((dev)->id_flags & 0x20) 218#define COM_LLCONSOLE(dev) ((dev)->id_flags & 0x40) 219#define COM_LOSESOUTINTS(dev) ((dev)->id_flags & 0x08) 220#define COM_NOFIFO(dev) ((dev)->id_flags & 0x02) 221#define COM_VERBOSE(dev) ((dev)->id_flags & 0x80) 222#define COM_NOTST3(dev) ((dev)->id_flags & 0x10000) 223#define COM_ST16650A(dev) ((dev)->id_flags & 0x20000) 224#define COM_C_NOPROBE (0x40000) 225#define COM_NOPROBE(dev) ((dev)->id_flags & COM_C_NOPROBE) 226#define COM_C_IIR_TXRDYBUG (0x80000) 227#define COM_IIR_TXRDYBUG(dev) ((dev)->id_flags & COM_C_IIR_TXRDYBUG) 228#define COM_FIFOSIZE(dev) (((dev)->id_flags & 0xff000000) >> 24) 229 230#ifndef PC98 231#define com_scr 7 /* scratch register for 16450-16550 (R/W) */ 232#endif /* !PC98 */ 233 234/* 235 * Input buffer watermarks. 236 * The external device is asked to stop sending when the buffer exactly reaches 237 * high water, or when the high level requests it. 238 * The high level is notified immediately (rather than at a later clock tick) 239 * when this watermark is reached. 240 * The buffer size is chosen so the watermark should almost never be reached. 241 * The low watermark is invisibly 0 since the buffer is always emptied all at 242 * once. 243 */ 244#define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4) 245 246/* 247 * com state bits. 248 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 249 * than the other bits so that they can be tested as a group without masking 250 * off the low bits. 251 * 252 * The following com and tty flags correspond closely: 253 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and 254 * siostop()) 255 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 256 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 257 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 258 * TS_FLUSH is not used. 259 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 260 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 261 */ 262#define CS_BUSY 0x80 /* output in progress */ 263#define CS_TTGO 0x40 /* output not stopped by XOFF */ 264#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 265#define CS_CHECKMSR 1 /* check of MSR scheduled */ 266#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 267#define CS_DTR_OFF 0x10 /* DTR held off */ 268#define CS_ODONE 4 /* output completed */ 269#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 270#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ 271 272static char const * const error_desc[] = { 273#define CE_OVERRUN 0 274 "silo overflow", 275#define CE_INTERRUPT_BUF_OVERFLOW 1 276 "interrupt-level buffer overflow", 277#define CE_TTY_BUF_OVERFLOW 2 278 "tty-level buffer overflow", 279}; 280 281#define CE_NTYPES 3 282#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 283 284/* types. XXX - should be elsewhere */ 285typedef u_int Port_t; /* hardware port */ 286typedef u_char bool_t; /* boolean */ 287 288/* queue of linear buffers */ 289struct lbq { 290 u_char *l_head; /* next char to process */ 291 u_char *l_tail; /* one past the last char to process */ 292 struct lbq *l_next; /* next in queue */ 293 bool_t l_queued; /* nonzero if queued */ 294}; 295 296/* com device structure */ 297struct com_s { 298 u_int id_flags; /* Copy isa device falgas */ 299 u_char state; /* miscellaneous flag bits */ 300 bool_t active_out; /* nonzero if the callout device is open */ 301 u_char cfcr_image; /* copy of value written to CFCR */ 302#ifdef COM_ESP 303 bool_t esp; /* is this unit a hayes esp board? */ 304#endif 305 u_char extra_state; /* more flag bits, separate for order trick */ 306 u_char fifo_image; /* copy of value written to FIFO */ 307 bool_t hasfifo; /* nonzero for 16550 UARTs */ 308 bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ 309 bool_t loses_outints; /* nonzero if device loses output interrupts */ 310 u_char mcr_image; /* copy of value written to MCR */ 311#ifdef COM_MULTIPORT 312 bool_t multiport; /* is this unit part of a multiport device? */ 313#endif /* COM_MULTIPORT */ 314 bool_t no_irq; /* nonzero if irq is not attached */ 315 bool_t gone; /* hardware disappeared */ 316 bool_t poll; /* nonzero if polling is required */ 317 bool_t poll_output; /* nonzero if polling for output is required */ 318 int unit; /* unit number */ 319 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 320 u_int tx_fifo_size; 321 u_int wopeners; /* # processes waiting for DCD in open() */ 322 323 /* 324 * The high level of the driver never reads status registers directly 325 * because there would be too many side effects to handle conveniently. 326 * Instead, it reads copies of the registers stored here by the 327 * interrupt handler. 328 */ 329 u_char last_modem_status; /* last MSR read by intr handler */ 330 u_char prev_modem_status; /* last MSR handled by high level */ 331 332 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 333 u_char *ibuf; /* start of input buffer */ 334 u_char *ibufend; /* end of input buffer */ 335 u_char *ihighwater; /* threshold in input buffer */ 336 u_char *iptr; /* next free spot in input buffer */ 337 338 struct lbq obufq; /* head of queue of output buffers */ 339 struct lbq obufs[2]; /* output buffers */ 340 341#ifdef PC98 342 Port_t cmd_port; 343 Port_t sts_port; 344 Port_t in_modem_port; 345 Port_t intr_ctrl_port; 346 int intr_enable; 347 int pc98_prev_modem_status; 348 int pc98_modem_delta; 349 int modem_car_chg_timer; 350 int pc98_prev_siocmd; 351 int pc98_prev_siomod; 352 int modem_checking; 353 int pc98_if_type; 354#endif /* PC98 */ 355 Port_t data_port; /* i/o ports */ 356#ifdef COM_ESP 357 Port_t esp_port; 358#endif 359 Port_t int_id_port; 360 Port_t iobase; 361 Port_t modem_ctl_port; 362 Port_t line_status_port; 363 Port_t modem_status_port; 364 Port_t intr_ctl_port; /* Ports of IIR register */ 365 366 struct tty *tp; /* cross reference */ 367 368 /* Initial state. */ 369 struct termios it_in; /* should be in struct tty */ 370 struct termios it_out; 371 372 /* Lock state. */ 373 struct termios lt_in; /* should be in struct tty */ 374 struct termios lt_out; 375 376 bool_t do_timestamp; 377 bool_t do_dcd_timestamp; 378 struct timeval timestamp; 379 struct timeval dcd_timestamp; 380 381 u_long bytes_in; /* statistics */ 382 u_long bytes_out; 383 u_int delta_error_counts[CE_NTYPES]; 384 u_long error_counts[CE_NTYPES]; 385 386 /* 387 * Ping-pong input buffers. The extra factor of 2 in the sizes is 388 * to allow for an error byte for each input byte. 389 */ 390#define CE_INPUT_OFFSET RS_IBUFSIZE 391 u_char ibuf1[2 * RS_IBUFSIZE]; 392 u_char ibuf2[2 * RS_IBUFSIZE]; 393 394 /* 395 * Data area for output buffers. Someday we should build the output 396 * buffer queue without copying data. 397 */ 398 u_char obuf1[256]; 399 u_char obuf2[256]; 400#ifdef DEVFS 401 void *devfs_token_ttyd; 402 void *devfs_token_ttyl; 403 void *devfs_token_ttyi; 404 void *devfs_token_cuaa; 405 void *devfs_token_cual; 406 void *devfs_token_cuai; 407#endif 408}; 409 410/* 411 * XXX public functions in drivers should be declared in headers produced 412 * by `config', not here. 413 */ 414 415/* Interrupt handling entry point. */ 416void siopoll __P((void)); 417 418/* Device switch entry points. */ 419#define sioreset noreset 420#define siommap nommap 421#define siostrategy nostrategy 422 423#ifdef COM_ESP 424static int espattach __P((struct isa_device *isdp, struct com_s *com, 425 Port_t esp_port)); 426#endif 427static int sioattach __P((struct isa_device *dev)); 428static timeout_t siobusycheck; 429static timeout_t siodtrwakeup; 430static void comhardclose __P((struct com_s *com)); 431static void siointr1 __P((struct com_s *com)); 432static int commctl __P((struct com_s *com, int bits, int how)); 433static int comparam __P((struct tty *tp, struct termios *t)); 434static int sioprobe __P((struct isa_device *dev)); 435static void siosettimeout __P((void)); 436static void comstart __P((struct tty *tp)); 437static timeout_t comwakeup; 438static int tiocm_xxx2mcr __P((int tiocm_xxx)); 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#ifdef PC98 825 struct isa_device *xdev; 826 int irqout=0; 827 int ret = 0; 828 int tmp; 829 struct siodev iod; 830#else 831 struct isa_device *xdev; 832#endif 833 834 if (!already_init) { 835 /* 836 * Turn off MCR_IENABLE for all likely serial ports. An unused 837 * port with its MCR_IENABLE gate open will inhibit interrupts 838 * from any used port that shares the interrupt vector. 839 * XXX the gate enable is elsewhere for some multiports. 840 */ 841 for (xdev = isa_devtab_tty; xdev->id_driver != NULL; xdev++) 842 if (xdev->id_driver == &siodriver && xdev->id_enabled) 843#ifdef PC98 844 if (IS_PC98IN(xdev->id_iobase)) 845 outb(xdev->id_iobase + 2, 0xf2); 846 else 847#endif 848 outb(xdev->id_iobase + com_mcr, 0); 849 already_init = TRUE; 850 } 851 852#ifdef PC98 853 /* 854 * If the port is i8251 UART (internal, B98_01) 855 */ 856 if(pc98_check_if_type(dev->id_iobase, &iod) == -1) 857 return 0; 858 if(IS_8251(iod.if_type)){ 859 if ( iod.irq > 0 ) 860 dev->id_irq = (1 << iod.irq); 861 outb(iod.cmd, 0); 862 DELAY(10); 863 outb(iod.cmd, 0); 864 DELAY(10); 865 outb(iod.cmd, 0); 866 DELAY(10); 867 outb(iod.cmd, CMD8251_RESET); 868 DELAY(1000); /* for a while...*/ 869 outb(iod.cmd, 0xf2); /* MODE (dummy) */ 870 DELAY(10); 871 outb(iod.cmd, 0x01); /* CMD (dummy) */ 872 DELAY(1000); /* for a while...*/ 873 if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) { 874 ret = 0; 875 } 876 switch (iod.if_type) { 877 case COM_IF_INTERNAL: 878 COM_INT_DISABLE 879 tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx)); 880 outb( iod.ctrl, tmp|IEN_TxEMP ); 881 ret = isa_irq_pending(dev) ? 4 : 0; 882 outb( iod.ctrl, tmp ); 883 COM_INT_ENABLE 884 break; 885#ifdef COM_IF_B98_01 886 case COM_IF_B98_01: 887 /* B98_01 doesn't activate TxEMP interrupt line 888 when being reset, so we can't check irq pending.*/ 889 ret = 4; 890 break; 891#endif 892 } 893 if (epson_machine_id==0x20) { /* XXX */ 894 ret = 4; 895 } 896 return ret; 897 } 898#endif /* PC98 */ 899 /* 900 * If the device is on a multiport card and has an AST/4 901 * compatible interrupt control register, initialize this 902 * register and prepare to leave MCR_IENABLE clear in the mcr. 903 * Otherwise, prepare to set MCR_IENABLE in the mcr. 904 * Point idev to the device struct giving the correct id_irq. 905 * This is the struct for the master device if there is one. 906 */ 907 idev = dev; 908 mcr_image = MCR_IENABLE; 909#ifdef COM_MULTIPORT 910 if (COM_ISMULTIPORT(dev)) { 911 idev = find_isadev(isa_devtab_tty, &siodriver, 912 COM_MPMASTER(dev)); 913 if (idev == NULL) { 914 printf("sio%d: master device %d not configured\n", 915 dev->id_unit, COM_MPMASTER(dev)); 916 return (0); 917 } 918#ifndef PC98 919 if (!COM_NOTAST4(dev)) { 920 outb(idev->id_iobase + com_scr, 921 idev->id_irq ? 0x80 : 0); 922 mcr_image = 0; 923 } 924#endif /* !PC98 */ 925 } 926#endif /* COM_MULTIPORT */ 927 if (idev->id_irq == 0) 928 mcr_image = 0; 929 930#ifdef PC98 931 switch(idev->id_irq){ 932 case IRQ3: irqout = 4; break; 933 case IRQ5: irqout = 5; break; 934 case IRQ6: irqout = 6; break; 935 case IRQ12: irqout = 7; break; 936 default: 937 printf("sio%d: irq configuration error\n",dev->id_unit); 938 return (0); 939 } 940 outb(dev->id_iobase+0x1000, irqout); 941#endif 942 bzero(failures, sizeof failures); 943 iobase = dev->id_iobase; 944 945 if (COM_LLCONSOLE(dev)) { 946 printf("sio%d: reserved for low-level i/o\n", dev->id_unit); 947 return (0); 948 } 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 2031 ++com->bytes_in; 2032 if (com->hotchar != 0 && recv_data == com->hotchar) 2033 setsofttty(); 2034 ioptr = com->iptr; 2035 if (ioptr >= com->ibufend) 2036 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2037 else { 2038 if (com->do_timestamp) 2039 microtime(&com->timestamp); 2040 ++com_events; 2041 schedsofttty(); 2042#if 0 /* for testing input latency vs efficiency */ 2043if (com->iptr - com->ibuf == 8) 2044 setsofttty(); 2045#endif 2046 ioptr[0] = recv_data; 2047 ioptr[CE_INPUT_OFFSET] = line_status; 2048 com->iptr = ++ioptr; 2049 if (ioptr == com->ihighwater 2050 && com->state & CS_RTS_IFLOW) 2051#ifdef PC98 2052 if(IS_8251(com->pc98_if_type)) 2053 com_tiocm_bic(com, TIOCM_RTS); 2054 else 2055#endif 2056 outb(com->modem_ctl_port, 2057 com->mcr_image &= ~MCR_RTS); 2058 if (line_status & LSR_OE) 2059 CE_RECORD(com, CE_OVERRUN); 2060 } 2061cont: 2062 /* 2063 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2064 * jump from the top of the loop to here 2065 */ 2066#ifdef PC98 2067 if(IS_8251(com->pc98_if_type)) 2068 goto status_read; 2069 else 2070#endif 2071 line_status = inb(com->line_status_port) & 0x7F; 2072 } 2073 2074 /* modem status change? (always check before doing output) */ 2075#ifdef PC98 2076 if(!IS_8251(com->pc98_if_type)){ 2077#endif 2078 modem_status = inb(com->modem_status_port); 2079 if (modem_status != com->last_modem_status) { 2080 if (com->do_dcd_timestamp 2081 && !(com->last_modem_status & MSR_DCD) 2082 && modem_status & MSR_DCD) 2083 microtime(&com->dcd_timestamp); 2084 2085 /* 2086 * Schedule high level to handle DCD changes. Note 2087 * that we don't use the delta bits anywhere. Some 2088 * UARTs mess them up, and it's easy to remember the 2089 * previous bits and calculate the delta. 2090 */ 2091 com->last_modem_status = modem_status; 2092 if (!(com->state & CS_CHECKMSR)) { 2093 com_events += LOTS_OF_EVENTS; 2094 com->state |= CS_CHECKMSR; 2095 setsofttty(); 2096 } 2097 2098 /* handle CTS change immediately for crisp flow ctl */ 2099 if (com->state & CS_CTS_OFLOW) { 2100 if (modem_status & MSR_CTS) 2101 com->state |= CS_ODEVREADY; 2102 else 2103 com->state &= ~CS_ODEVREADY; 2104 } 2105 } 2106#ifdef PC98 2107 } 2108#endif 2109 2110 /* output queued and everything ready? */ 2111 if (line_status & LSR_TXRDY 2112 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2113 ioptr = com->obufq.l_head; 2114 if (com->tx_fifo_size > 1) { 2115 u_int ocount; 2116 2117 ocount = com->obufq.l_tail - ioptr; 2118 if (ocount > com->tx_fifo_size) 2119 ocount = com->tx_fifo_size; 2120 com->bytes_out += ocount; 2121 do 2122 outb(com->data_port, *ioptr++); 2123 while (--ocount != 0); 2124 } else { 2125 outb(com->data_port, *ioptr++); 2126 ++com->bytes_out; 2127 } 2128#ifdef PC98 2129 if(IS_8251(com->pc98_if_type)) 2130 if ( !(pc98_check_i8251_interrupt(com) & IEN_TxFLAG) ) 2131 com_int_Tx_enable(com); 2132#endif 2133 com->obufq.l_head = ioptr; 2134 if (COM_IIR_TXRDYBUG(com)) { 2135 int_ctl_new = int_ctl | IER_ETXRDY; 2136 } 2137 if (ioptr >= com->obufq.l_tail) { 2138 struct lbq *qp; 2139 2140 qp = com->obufq.l_next; 2141 qp->l_queued = FALSE; 2142 qp = qp->l_next; 2143 if (qp != NULL) { 2144 com->obufq.l_head = qp->l_head; 2145 com->obufq.l_tail = qp->l_tail; 2146 com->obufq.l_next = qp; 2147 } else { 2148 /* output just completed */ 2149 if ( COM_IIR_TXRDYBUG(com) ) { 2150 int_ctl_new = int_ctl & ~IER_ETXRDY; 2151 } 2152 com->state &= ~CS_BUSY; 2153#if defined(PC98) 2154 if(IS_8251(com->pc98_if_type)) 2155 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2156 com_int_Tx_disable(com); 2157#endif 2158 } 2159 if (!(com->state & CS_ODONE)) { 2160 com_events += LOTS_OF_EVENTS; 2161 com->state |= CS_ODONE; 2162 setsofttty(); /* handle at high level ASAP */ 2163 } 2164 } 2165 if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { 2166 outb(com->intr_ctl_port, int_ctl_new); 2167 } 2168 } 2169#ifdef PC98 2170 else if (line_status & LSR_TXRDY) { 2171 if(IS_8251(com->pc98_if_type)) 2172 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2173 com_int_Tx_disable(com); 2174 } 2175 if(IS_8251(com->pc98_if_type)) 2176 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2177 goto more_intr; 2178#endif 2179 2180 /* finished? */ 2181#ifndef COM_MULTIPORT 2182#ifdef PC98 2183 if(IS_8251(com->pc98_if_type)) 2184 return; 2185#endif 2186 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2187#endif /* COM_MULTIPORT */ 2188 return; 2189 } 2190} 2191 2192static int 2193sioioctl(dev, cmd, data, flag, p) 2194 dev_t dev; 2195 int cmd; 2196 caddr_t data; 2197 int flag; 2198 struct proc *p; 2199{ 2200 struct com_s *com; 2201 int error; 2202 Port_t iobase; 2203 int mynor; 2204 int s; 2205 struct tty *tp; 2206#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2207 int oldcmd; 2208 struct termios term; 2209#endif 2210 2211 mynor = minor(dev); 2212 com = com_addr(MINOR_TO_UNIT(mynor)); 2213 if (com->gone) 2214 return (ENODEV); 2215 iobase = com->iobase; 2216 if (mynor & CONTROL_MASK) { 2217 struct termios *ct; 2218 2219 switch (mynor & CONTROL_MASK) { 2220 case CONTROL_INIT_STATE: 2221 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2222 break; 2223 case CONTROL_LOCK_STATE: 2224 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2225 break; 2226 default: 2227 return (ENODEV); /* /dev/nodev */ 2228 } 2229 switch (cmd) { 2230 case TIOCSETA: 2231 error = suser(p->p_ucred, &p->p_acflag); 2232 if (error != 0) 2233 return (error); 2234 *ct = *(struct termios *)data; 2235 return (0); 2236 case TIOCGETA: 2237 *(struct termios *)data = *ct; 2238 return (0); 2239 case TIOCGETD: 2240 *(int *)data = TTYDISC; 2241 return (0); 2242 case TIOCGWINSZ: 2243 bzero(data, sizeof(struct winsize)); 2244 return (0); 2245#ifdef DSI_SOFT_MODEM 2246 /* 2247 * Download micro-code to Digicom modem. 2248 */ 2249 case TIOCDSIMICROCODE: 2250 { 2251 u_long l; 2252 u_char *p,*pi; 2253 2254 pi = (u_char*)(*(caddr_t*)data); 2255 error = copyin(pi,&l,sizeof l); 2256 if(error) 2257 {return error;}; 2258 pi += sizeof l; 2259 2260 p = malloc(l,M_TEMP,M_NOWAIT); 2261 if(!p) 2262 {return ENOBUFS;} 2263 error = copyin(pi,p,l); 2264 if(error) 2265 {free(p,M_TEMP); return error;}; 2266 if(error = LoadSoftModem( 2267 MINOR_TO_UNIT(mynor),iobase,l,p)) 2268 {free(p,M_TEMP); return error;} 2269 free(p,M_TEMP); 2270 return(0); 2271 } 2272#endif /* DSI_SOFT_MODEM */ 2273 default: 2274 return (ENOTTY); 2275 } 2276 } 2277 tp = com->tp; 2278#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2279 term = tp->t_termios; 2280 oldcmd = cmd; 2281 error = ttsetcompat(tp, &cmd, data, &term); 2282 if (error != 0) 2283 return (error); 2284 if (cmd != oldcmd) 2285 data = (caddr_t)&term; 2286#endif 2287 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2288 int cc; 2289 struct termios *dt = (struct termios *)data; 2290 struct termios *lt = mynor & CALLOUT_MASK 2291 ? &com->lt_out : &com->lt_in; 2292 2293 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2294 | (dt->c_iflag & ~lt->c_iflag); 2295 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2296 | (dt->c_oflag & ~lt->c_oflag); 2297 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2298 | (dt->c_cflag & ~lt->c_cflag); 2299 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2300 | (dt->c_lflag & ~lt->c_lflag); 2301 for (cc = 0; cc < NCCS; ++cc) 2302 if (lt->c_cc[cc] != 0) 2303 dt->c_cc[cc] = tp->t_cc[cc]; 2304 if (lt->c_ispeed != 0) 2305 dt->c_ispeed = tp->t_ispeed; 2306 if (lt->c_ospeed != 0) 2307 dt->c_ospeed = tp->t_ospeed; 2308 } 2309 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2310 if (error != ENOIOCTL) 2311 return (error); 2312 s = spltty(); 2313 error = ttioctl(tp, cmd, data, flag); 2314 disc_optim(tp, &tp->t_termios, com); 2315 if (error != ENOIOCTL) { 2316 splx(s); 2317 return (error); 2318 } 2319#ifdef PC98 2320 if(IS_8251(com->pc98_if_type)){ 2321 switch (cmd) { 2322 case TIOCSBRK: 2323 com_send_break_on( com ); 2324 break; 2325 case TIOCCBRK: 2326 com_send_break_off( com ); 2327 break; 2328 case TIOCSDTR: 2329 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2330 break; 2331 case TIOCCDTR: 2332 com_tiocm_bic(com, TIOCM_DTR); 2333 break; 2334 /* 2335 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2336 * changes get undone on the next call to comparam(). 2337 */ 2338 case TIOCMSET: 2339 com_tiocm_set( com, *(int *)data ); 2340 break; 2341 case TIOCMBIS: 2342 com_tiocm_bis( com, *(int *)data ); 2343 break; 2344 case TIOCMBIC: 2345 com_tiocm_bic( com, *(int *)data ); 2346 break; 2347 case TIOCMGET: 2348 *(int *)data = com_tiocm_get(com); 2349 break; 2350 case TIOCMSDTRWAIT: 2351 /* must be root since the wait applies to following logins */ 2352 error = suser(p->p_ucred, &p->p_acflag); 2353 if (error != 0) { 2354 splx(s); 2355 return (error); 2356 } 2357 com->dtr_wait = *(int *)data * hz / 100; 2358 break; 2359 case TIOCMGDTRWAIT: 2360 *(int *)data = com->dtr_wait * 100 / hz; 2361 break; 2362 case TIOCTIMESTAMP: 2363 com->do_timestamp = TRUE; 2364 *(struct timeval *)data = com->timestamp; 2365 break; 2366 case TIOCDCDTIMESTAMP: 2367 com->do_dcd_timestamp = TRUE; 2368 *(struct timeval *)data = com->dcd_timestamp; 2369 break; 2370 default: 2371 splx(s); 2372 return (ENOTTY); 2373 } 2374 } else { 2375#endif 2376 switch (cmd) { 2377 case TIOCSBRK: 2378 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2379 break; 2380 case TIOCCBRK: 2381 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2382 break; 2383 case TIOCSDTR: 2384 (void)commctl(com, TIOCM_DTR, DMBIS); 2385 break; 2386 case TIOCCDTR: 2387 (void)commctl(com, TIOCM_DTR, DMBIC); 2388 break; 2389 case TIOCMSET: 2390 (void)commctl(com, *(int *)data, DMSET); 2391 break; 2392 case TIOCMBIS: 2393 (void)commctl(com, *(int *)data, DMBIS); 2394 break; 2395 case TIOCMBIC: 2396 (void)commctl(com, *(int *)data, DMBIC); 2397 break; 2398 case TIOCMGET: 2399 *(int *)data = commctl(com, 0, DMGET); 2400 break; 2401 case TIOCMSDTRWAIT: 2402 /* must be root since the wait applies to following logins */ 2403 error = suser(p->p_ucred, &p->p_acflag); 2404 if (error != 0) { 2405 splx(s); 2406 return (error); 2407 } 2408 com->dtr_wait = *(int *)data * hz / 100; 2409 break; 2410 case TIOCMGDTRWAIT: 2411 *(int *)data = com->dtr_wait * 100 / hz; 2412 break; 2413 case TIOCTIMESTAMP: 2414 com->do_timestamp = TRUE; 2415 *(struct timeval *)data = com->timestamp; 2416 break; 2417 default: 2418 splx(s); 2419 return (ENOTTY); 2420 } 2421#ifdef PC98 2422 } 2423#endif 2424 splx(s); 2425 return (0); 2426} 2427 2428void 2429siopoll() 2430{ 2431 int unit; 2432 2433 if (com_events == 0) 2434 return; 2435repeat: 2436 for (unit = 0; unit < NSIOTOT; ++unit) { 2437 u_char *buf; 2438 struct com_s *com; 2439 u_char *ibuf; 2440 int incc; 2441 struct tty *tp; 2442#ifdef PC98 2443 int tmp; 2444#endif 2445 2446 com = com_addr(unit); 2447 if (com == NULL) 2448 continue; 2449 if (com->gone) 2450 continue; 2451 tp = com->tp; 2452 if (tp == NULL) { 2453 /* 2454 * XXX forget any events related to closed devices 2455 * (actually never opened devices) so that we don't 2456 * loop. 2457 */ 2458 disable_intr(); 2459 incc = com->iptr - com->ibuf; 2460 com->iptr = com->ibuf; 2461 if (com->state & CS_CHECKMSR) { 2462 incc += LOTS_OF_EVENTS; 2463 com->state &= ~CS_CHECKMSR; 2464 } 2465 com_events -= incc; 2466 enable_intr(); 2467 if (incc != 0) 2468 log(LOG_DEBUG, 2469 "sio%d: %d events for device with no tp\n", 2470 unit, incc); 2471 continue; 2472 } 2473 2474 /* switch the role of the low-level input buffers */ 2475 if (com->iptr == (ibuf = com->ibuf)) { 2476 buf = NULL; /* not used, but compiler can't tell */ 2477 incc = 0; 2478 } else { 2479 buf = ibuf; 2480 disable_intr(); 2481 incc = com->iptr - buf; 2482 com_events -= incc; 2483 if (ibuf == com->ibuf1) 2484 ibuf = com->ibuf2; 2485 else 2486 ibuf = com->ibuf1; 2487 com->ibufend = ibuf + RS_IBUFSIZE; 2488 com->ihighwater = ibuf + RS_IHIGHWATER; 2489 com->iptr = ibuf; 2490 2491 /* 2492 * There is now room for another low-level buffer full 2493 * of input, so enable RTS if it is now disabled and 2494 * there is room in the high-level buffer. 2495 */ 2496#ifdef PC98 2497 if(IS_8251(com->pc98_if_type)) 2498 tmp = com_tiocm_get(com) & TIOCM_RTS; 2499 else 2500 tmp = com->mcr_image & MCR_RTS; 2501#endif 2502 if ((com->state & CS_RTS_IFLOW) 2503#ifdef PC98 2504 && !(tmp) 2505#else 2506 && !(com->mcr_image & MCR_RTS) 2507#endif 2508 && !(tp->t_state & TS_TBLOCK)) 2509#ifdef PC98 2510 if(IS_8251(com->pc98_if_type)) 2511 com_tiocm_bis(com, TIOCM_RTS); 2512 else 2513#endif 2514 outb(com->modem_ctl_port, 2515 com->mcr_image |= MCR_RTS); 2516 enable_intr(); 2517 com->ibuf = ibuf; 2518 } 2519 2520 if (com->state & CS_CHECKMSR) { 2521 u_char delta_modem_status; 2522 2523#ifdef PC98 2524 if(!IS_8251(com->pc98_if_type)){ 2525#endif 2526 disable_intr(); 2527 delta_modem_status = com->last_modem_status 2528 ^ com->prev_modem_status; 2529 com->prev_modem_status = com->last_modem_status; 2530 com_events -= LOTS_OF_EVENTS; 2531 com->state &= ~CS_CHECKMSR; 2532 enable_intr(); 2533 if (delta_modem_status & MSR_DCD) 2534 (*linesw[tp->t_line].l_modem) 2535 (tp, com->prev_modem_status & MSR_DCD); 2536#ifdef PC98 2537 } 2538#endif 2539 } 2540 if (com->state & CS_ODONE) { 2541 disable_intr(); 2542 com_events -= LOTS_OF_EVENTS; 2543 com->state &= ~CS_ODONE; 2544 enable_intr(); 2545 if (!(com->state & CS_BUSY) 2546 && !(com->extra_state & CSE_BUSYCHECK)) { 2547 timeout(siobusycheck, com, hz / 100); 2548 com->extra_state |= CSE_BUSYCHECK; 2549 } 2550 (*linesw[tp->t_line].l_start)(tp); 2551 } 2552 if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || 2553 !(tp->t_cflag & CREAD)) 2554 continue; 2555 /* 2556 * Avoid the grotesquely inefficient lineswitch routine 2557 * (ttyinput) in "raw" mode. It usually takes about 450 2558 * instructions (that's without canonical processing or echo!). 2559 * slinput is reasonably fast (usually 40 instructions plus 2560 * call overhead). 2561 */ 2562 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 2563 if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER 2564 && (com->state & CS_RTS_IFLOW 2565 || tp->t_iflag & IXOFF) 2566 && !(tp->t_state & TS_TBLOCK)) 2567 ttyblock(tp); 2568 tk_nin += incc; 2569 tk_rawcc += incc; 2570 tp->t_rawcc += incc; 2571 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 2572 += b_to_q((char *)buf, incc, &tp->t_rawq); 2573 ttwakeup(tp); 2574 if (tp->t_state & TS_TTSTOP 2575 && (tp->t_iflag & IXANY 2576 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 2577 tp->t_state &= ~TS_TTSTOP; 2578 tp->t_lflag &= ~FLUSHO; 2579 comstart(tp); 2580 } 2581 } else { 2582 do { 2583 u_char line_status; 2584 int recv_data; 2585 2586 line_status = (u_char) buf[CE_INPUT_OFFSET]; 2587 recv_data = (u_char) *buf++; 2588 if (line_status 2589 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 2590 if (line_status & LSR_BI) 2591 recv_data |= TTY_BI; 2592 if (line_status & LSR_FE) 2593 recv_data |= TTY_FE; 2594 if (line_status & LSR_OE) 2595 recv_data |= TTY_OE; 2596 if (line_status & LSR_PE) 2597 recv_data |= TTY_PE; 2598 } 2599 (*linesw[tp->t_line].l_rint)(recv_data, tp); 2600 } while (--incc > 0); 2601 } 2602 if (com_events == 0) 2603 break; 2604 } 2605 if (com_events >= LOTS_OF_EVENTS) 2606 goto repeat; 2607} 2608 2609static int 2610comparam(tp, t) 2611 struct tty *tp; 2612 struct termios *t; 2613{ 2614 u_int cfcr; 2615 int cflag; 2616 struct com_s *com; 2617 int divisor; 2618 u_char dlbh; 2619 u_char dlbl; 2620 int error; 2621 Port_t iobase; 2622 int s; 2623 int unit; 2624 int txtimeout; 2625#ifdef PC98 2626 Port_t tmp_port; 2627 int tmp_flg; 2628#endif 2629 2630#ifdef PC98 2631 cfcr = 0; 2632 unit = DEV_TO_UNIT(tp->t_dev); 2633 com = com_addr(unit); 2634 iobase = com->iobase; 2635 if(IS_8251(com->pc98_if_type)) { 2636 divisor = pc98_ttspeedtab(com, t->c_ospeed); 2637 } else 2638#endif 2639 /* do historical conversions */ 2640 if (t->c_ispeed == 0) 2641 t->c_ispeed = t->c_ospeed; 2642 2643 /* check requested parameters */ 2644 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 2645 if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed) 2646 return (EINVAL); 2647 2648 /* parameters are OK, convert them to the com struct and the device */ 2649#ifndef PC98 2650 unit = DEV_TO_UNIT(tp->t_dev); 2651 com = com_addr(unit); 2652 iobase = com->iobase; 2653#endif 2654 s = spltty(); 2655#ifdef PC98 2656 if(IS_8251(com->pc98_if_type)){ 2657 if(divisor == 0) 2658 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2659 else 2660 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 2661 } else { 2662#endif 2663 if (divisor == 0) 2664 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 2665 else 2666 (void)commctl(com, TIOCM_DTR, DMBIS); 2667#ifdef PC98 2668 } 2669#endif 2670 cflag = t->c_cflag; 2671#ifdef PC98 2672 if(!IS_8251(com->pc98_if_type)){ 2673#endif 2674 switch (cflag & CSIZE) { 2675 case CS5: 2676 cfcr = CFCR_5BITS; 2677 break; 2678 case CS6: 2679 cfcr = CFCR_6BITS; 2680 break; 2681 case CS7: 2682 cfcr = CFCR_7BITS; 2683 break; 2684 default: 2685 cfcr = CFCR_8BITS; 2686 break; 2687 } 2688 if (cflag & PARENB) { 2689 cfcr |= CFCR_PENAB; 2690 if (!(cflag & PARODD)) 2691 cfcr |= CFCR_PEVEN; 2692 } 2693 if (cflag & CSTOPB) 2694 cfcr |= CFCR_STOPB; 2695 2696 if (com->hasfifo && divisor != 0) { 2697 /* 2698 * Use a fifo trigger level low enough so that the input 2699 * latency from the fifo is less than about 16 msec and 2700 * the total latency is less than about 30 msec. These 2701 * latencies are reasonable for humans. Serial comms 2702 * protocols shouldn't expect anything better since modem 2703 * latencies are larger. 2704 */ 2705 com->fifo_image = t->c_ospeed <= 4800 2706 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 2707#ifdef COM_ESP 2708 /* 2709 * The Hayes ESP card needs the fifo DMA mode bit set 2710 * in compatibility mode. If not, it will interrupt 2711 * for each character received. 2712 */ 2713 if (com->esp) 2714 com->fifo_image |= FIFO_DMA_MODE; 2715#endif 2716 outb(iobase + com_fifo, com->fifo_image); 2717 } 2718 2719 /* 2720 * Some UARTs lock up if the divisor latch registers are selected 2721 * while the UART is doing output (they refuse to transmit anything 2722 * more until given a hard reset). Fix this by stopping filling 2723 * the device buffers and waiting for them to drain. Reading the 2724 * line status port outside of siointr1() might lose some receiver 2725 * error bits, but that is acceptable here. 2726 */ 2727#ifdef PC98 2728 } 2729#endif 2730 disable_intr(); 2731retry: 2732 com->state &= ~CS_TTGO; 2733 txtimeout = tp->t_timeout; 2734 enable_intr(); 2735#ifdef PC98 2736 if(IS_8251(com->pc98_if_type)){ 2737 tmp_port = com->sts_port; 2738 tmp_flg = (STS8251_TxRDY|STS8251_TxEMP); 2739 } else { 2740 tmp_port = com->line_status_port; 2741 tmp_flg = (LSR_TSRE|LSR_TXRDY); 2742 } 2743 while ((inb(tmp_port) & tmp_flg) != tmp_flg) { 2744#else 2745 while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2746 != (LSR_TSRE | LSR_TXRDY)) { 2747#endif 2748 tp->t_state |= TS_SO_OCOMPLETE; 2749 error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH, 2750 "siotx", hz / 100); 2751 if ( txtimeout != 0 2752 && (!error || error == EAGAIN) 2753 && (txtimeout -= hz / 100) <= 0 2754 ) 2755 error = EIO; 2756 if (com->gone) 2757 error = ENODEV; 2758 if (error != 0 && error != EAGAIN) { 2759 if (!(tp->t_state & TS_TTSTOP)) { 2760 disable_intr(); 2761 com->state |= CS_TTGO; 2762 enable_intr(); 2763 } 2764 splx(s); 2765 return (error); 2766 } 2767 } 2768 2769 disable_intr(); /* very important while com_data is hidden */ 2770 2771 /* 2772 * XXX - clearing CS_TTGO is not sufficient to stop further output, 2773 * because siopoll() calls comstart() which usually sets it again 2774 * because TS_TTSTOP is clear. Setting TS_TTSTOP would not be 2775 * sufficient, for similar reasons. 2776 */ 2777#ifdef PC98 2778 if ((inb(tmp_port) & tmp_flg) != tmp_flg) 2779#else 2780 if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2781 != (LSR_TSRE | LSR_TXRDY)) 2782#endif 2783 goto retry; 2784 2785#ifdef PC98 2786 if(!IS_8251(com->pc98_if_type)){ 2787#endif 2788 if (divisor != 0) { 2789 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 2790 /* 2791 * Only set the divisor registers if they would change, 2792 * since on some 16550 incompatibles (UMC8669F), setting 2793 * them while input is arriving them loses sync until 2794 * data stops arriving. 2795 */ 2796 dlbl = divisor & 0xFF; 2797 if (inb(iobase + com_dlbl) != dlbl) 2798 outb(iobase + com_dlbl, dlbl); 2799 dlbh = (u_int) divisor >> 8; 2800 if (inb(iobase + com_dlbh) != dlbh) 2801 outb(iobase + com_dlbh, dlbh); 2802 } 2803 2804 2805 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 2806 2807#ifdef PC98 2808 } else 2809 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 2810#endif 2811 if (!(tp->t_state & TS_TTSTOP)) 2812 if (com->st16650a) { 2813 outb(iobase + com_cfcr, 0xbf); 2814 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 2815 } 2816 com->state |= CS_TTGO; 2817 2818 if (cflag & CRTS_IFLOW) { 2819 com->state |= CS_RTS_IFLOW; 2820 /* 2821 * If CS_RTS_IFLOW just changed from off to on, the change 2822 * needs to be propagated to MCR_RTS. This isn't urgent, 2823 * so do it later by calling comstart() instead of repeating 2824 * a lot of code from comstart() here. 2825 */ 2826 } else if (com->state & CS_RTS_IFLOW) { 2827 com->state &= ~CS_RTS_IFLOW; 2828 /* 2829 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2830 * on here, since comstart() won't do it later. 2831 */ 2832#ifdef PC98 2833 if(IS_8251(com->pc98_if_type)) 2834 com_tiocm_bis(com, TIOCM_RTS); 2835 else 2836#endif 2837 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2838 if (com->st16650a) { 2839 outb(iobase + com_cfcr, 0xbf); 2840 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 2841 } 2842 } 2843 2844 2845 /* 2846 * Set up state to handle output flow control. 2847 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2848 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2849 */ 2850 com->state |= CS_ODEVREADY; 2851 com->state &= ~CS_CTS_OFLOW; 2852 if (cflag & CCTS_OFLOW) { 2853 com->state |= CS_CTS_OFLOW; 2854#ifdef PC98 2855 if(IS_8251(com->pc98_if_type)){ 2856 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 2857 com->state &= ~CS_ODEVREADY; 2858 } else { 2859#endif 2860 if (!(com->last_modem_status & MSR_CTS)) 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 com->state &= ~CS_ODEVREADY; 2874 } 2875 2876 2877 outb(iobase + com_cfcr, com->cfcr_image); 2878 2879 2880 /* XXX shouldn't call functions while intrs are disabled. */ 2881 disc_optim(tp, t, com); 2882 /* 2883 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2884 * unconditionally, but that defeated the careful discarding of 2885 * stale input in sioopen(). 2886 */ 2887 if (com->state >= (CS_BUSY | CS_TTGO)) 2888 siointr1(com); 2889 2890 enable_intr(); 2891 splx(s); 2892 comstart(tp); 2893 return (0); 2894} 2895 2896static void 2897comstart(tp) 2898 struct tty *tp; 2899{ 2900 struct com_s *com; 2901 int s; 2902 int unit; 2903#ifdef PC98 2904 int tmp; 2905#endif 2906 2907 unit = DEV_TO_UNIT(tp->t_dev); 2908 com = com_addr(unit); 2909 s = spltty(); 2910 disable_intr(); 2911 if (tp->t_state & TS_TTSTOP) 2912 com->state &= ~CS_TTGO; 2913 else 2914 com->state |= CS_TTGO; 2915 if (tp->t_state & TS_TBLOCK) { 2916#ifdef PC98 2917 if(IS_8251(com->pc98_if_type)) 2918 tmp = com_tiocm_get(com) & TIOCM_RTS; 2919 else 2920 tmp = com->mcr_image & MCR_RTS; 2921 if (tmp && (com->state & CS_RTS_IFLOW)) 2922#else 2923 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 2924#endif 2925#ifdef PC98 2926 if(IS_8251(com->pc98_if_type)) 2927 com_tiocm_bic(com, TIOCM_RTS); 2928 else 2929#endif 2930 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2931 } else { 2932#ifdef PC98 2933 if(IS_8251(com->pc98_if_type)) 2934 tmp = com_tiocm_get(com) & TIOCM_RTS; 2935 else 2936 tmp = com->mcr_image & MCR_RTS; 2937 if (!(tmp) && com->iptr < com->ihighwater 2938 && com->state & CS_RTS_IFLOW) 2939#else 2940 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 2941 && com->state & CS_RTS_IFLOW) 2942#endif 2943#ifdef PC98 2944 if(IS_8251(com->pc98_if_type)) 2945 com_tiocm_bis(com, TIOCM_RTS); 2946 else 2947#endif 2948 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2949 } 2950 enable_intr(); 2951 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2952 ttwwakeup(tp); 2953#ifdef PC98 2954/* if(IS_8251(com->pc98_if_type)) 2955 com_int_Tx_enable(com); */ 2956#endif 2957 splx(s); 2958 return; 2959 } 2960 if (tp->t_outq.c_cc != 0) { 2961 struct lbq *qp; 2962 struct lbq *next; 2963 2964 if (!com->obufs[0].l_queued) { 2965 com->obufs[0].l_tail 2966 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2967 sizeof com->obuf1); 2968 com->obufs[0].l_next = NULL; 2969 com->obufs[0].l_queued = TRUE; 2970 disable_intr(); 2971 if (com->state & CS_BUSY) { 2972 qp = com->obufq.l_next; 2973 while ((next = qp->l_next) != NULL) 2974 qp = next; 2975 qp->l_next = &com->obufs[0]; 2976 } else { 2977 com->obufq.l_head = com->obufs[0].l_head; 2978 com->obufq.l_tail = com->obufs[0].l_tail; 2979 com->obufq.l_next = &com->obufs[0]; 2980 com->state |= CS_BUSY; 2981 } 2982 enable_intr(); 2983 } 2984 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2985 com->obufs[1].l_tail 2986 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2987 sizeof com->obuf2); 2988 com->obufs[1].l_next = NULL; 2989 com->obufs[1].l_queued = TRUE; 2990 disable_intr(); 2991 if (com->state & CS_BUSY) { 2992 qp = com->obufq.l_next; 2993 while ((next = qp->l_next) != NULL) 2994 qp = next; 2995 qp->l_next = &com->obufs[1]; 2996 } else { 2997 com->obufq.l_head = com->obufs[1].l_head; 2998 com->obufq.l_tail = com->obufs[1].l_tail; 2999 com->obufq.l_next = &com->obufs[1]; 3000 com->state |= CS_BUSY; 3001 } 3002 enable_intr(); 3003 } 3004 tp->t_state |= TS_BUSY; 3005 } 3006 disable_intr(); 3007 if (com->state >= (CS_BUSY | CS_TTGO)) 3008 siointr1(com); /* fake interrupt to start output */ 3009 enable_intr(); 3010#ifdef PC98 3011/* if(IS_8251(com->pc98_if_type)) 3012 com_int_Tx_enable(com); */ 3013#endif 3014 ttwwakeup(tp); 3015 splx(s); 3016} 3017 3018static void 3019siostop(tp, rw) 3020 struct tty *tp; 3021 int rw; 3022{ 3023 struct com_s *com; 3024 3025 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 3026 if (com->gone) 3027 return; 3028 disable_intr(); 3029 if (rw & FWRITE) { 3030 if (com->hasfifo) 3031#ifdef COM_ESP 3032 /* XXX avoid h/w bug. */ 3033 if (!com->esp) 3034#endif 3035 /* XXX does this flush everything? */ 3036 outb(com->iobase + com_fifo, 3037 FIFO_XMT_RST | com->fifo_image); 3038 com->obufs[0].l_queued = FALSE; 3039 com->obufs[1].l_queued = FALSE; 3040 if (com->state & CS_ODONE) 3041 com_events -= LOTS_OF_EVENTS; 3042 com->state &= ~(CS_ODONE | CS_BUSY); 3043 com->tp->t_state &= ~TS_BUSY; 3044 } 3045 if (rw & FREAD) { 3046 if (com->hasfifo) 3047#ifdef COM_ESP 3048 /* XXX avoid h/w bug. */ 3049 if (!com->esp) 3050#endif 3051 /* XXX does this flush everything? */ 3052 outb(com->iobase + com_fifo, 3053 FIFO_RCV_RST | com->fifo_image); 3054 com_events -= (com->iptr - com->ibuf); 3055 com->iptr = com->ibuf; 3056 } 3057 enable_intr(); 3058 comstart(tp); 3059} 3060 3061static struct tty * 3062siodevtotty(dev) 3063 dev_t dev; 3064{ 3065 int mynor; 3066 int unit; 3067 3068 mynor = minor(dev); 3069 if (mynor & CONTROL_MASK) 3070 return (NULL); 3071 unit = MINOR_TO_UNIT(mynor); 3072 if ((u_int) unit >= NSIOTOT) 3073 return (NULL); 3074 return (&sio_tty[unit]); 3075} 3076 3077static int 3078commctl(com, bits, how) 3079 struct com_s *com; 3080 int bits; 3081 int how; 3082{ 3083 int mcr; 3084 int msr; 3085 3086 if (how == DMGET) { 3087 bits = TIOCM_LE; /* XXX - always enabled while open */ 3088 mcr = com->mcr_image; 3089 if (mcr & MCR_DTR) 3090 bits |= TIOCM_DTR; 3091 if (mcr & MCR_RTS) 3092 bits |= TIOCM_RTS; 3093 msr = com->prev_modem_status; 3094 if (msr & MSR_CTS) 3095 bits |= TIOCM_CTS; 3096 if (msr & MSR_DCD) 3097 bits |= TIOCM_CD; 3098 if (msr & MSR_DSR) 3099 bits |= TIOCM_DSR; 3100 /* 3101 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3102 * more volatile by reading the modem status a lot. Perhaps 3103 * we should latch both bits until the status is read here. 3104 */ 3105 if (msr & (MSR_RI | MSR_TERI)) 3106 bits |= TIOCM_RI; 3107 return (bits); 3108 } 3109 mcr = 0; 3110 if (bits & TIOCM_DTR) 3111 mcr |= MCR_DTR; 3112 if (bits & TIOCM_RTS) 3113 mcr |= MCR_RTS; 3114 if (com->gone) 3115 return(0); 3116 disable_intr(); 3117 switch (how) { 3118 case DMSET: 3119 outb(com->modem_ctl_port, 3120 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3121 break; 3122 case DMBIS: 3123 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3124 break; 3125 case DMBIC: 3126 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3127 break; 3128 } 3129 enable_intr(); 3130 return (0); 3131} 3132 3133static void 3134siosettimeout() 3135{ 3136 struct com_s *com; 3137 bool_t someopen; 3138 int unit; 3139 3140 /* 3141 * Set our timeout period to 1 second if no polled devices are open. 3142 * Otherwise set it to max(1/200, 1/hz). 3143 * Enable timeouts iff some device is open. 3144 */ 3145 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3146 sio_timeout = hz; 3147 someopen = FALSE; 3148 for (unit = 0; unit < NSIOTOT; ++unit) { 3149 com = com_addr(unit); 3150 if (com != NULL && com->tp != NULL 3151 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3152 someopen = TRUE; 3153 if (com->poll || com->poll_output) { 3154 sio_timeout = hz > 200 ? hz / 200 : 1; 3155 break; 3156 } 3157 } 3158 } 3159 if (someopen) { 3160 sio_timeouts_until_log = hz / sio_timeout; 3161 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3162 sio_timeout); 3163 } else { 3164 /* Flush error messages, if any. */ 3165 sio_timeouts_until_log = 1; 3166 comwakeup((void *)NULL); 3167 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3168 } 3169} 3170 3171static void 3172comwakeup(chan) 3173 void *chan; 3174{ 3175 struct com_s *com; 3176 int unit; 3177 3178 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3179 3180 /* 3181 * Recover from lost output interrupts. 3182 * Poll any lines that don't use interrupts. 3183 */ 3184 for (unit = 0; unit < NSIOTOT; ++unit) { 3185 com = com_addr(unit); 3186 if (com != NULL && !com->gone 3187 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3188 disable_intr(); 3189 siointr1(com); 3190 enable_intr(); 3191 } 3192 } 3193 3194 /* 3195 * Check for and log errors, but not too often. 3196 */ 3197 if (--sio_timeouts_until_log > 0) 3198 return; 3199 sio_timeouts_until_log = hz / sio_timeout; 3200 for (unit = 0; unit < NSIOTOT; ++unit) { 3201 int errnum; 3202 3203 com = com_addr(unit); 3204 if (com == NULL) 3205 continue; 3206 if (com->gone) 3207 continue; 3208 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3209 u_int delta; 3210 u_long total; 3211 3212 disable_intr(); 3213 delta = com->delta_error_counts[errnum]; 3214 com->delta_error_counts[errnum] = 0; 3215 enable_intr(); 3216 if (delta == 0) 3217 continue; 3218 total = com->error_counts[errnum] += delta; 3219 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3220 unit, delta, error_desc[errnum], 3221 delta == 1 ? "" : "s", total); 3222 } 3223 } 3224} 3225 3226#ifdef PC98 3227/* commint is called when modem control line changes */ 3228static void 3229commint(dev_t dev) 3230{ 3231 register struct tty *tp; 3232 int stat,delta; 3233 struct com_s *com; 3234 int mynor,unit; 3235 3236 mynor = minor(dev); 3237 unit = MINOR_TO_UNIT(mynor); 3238 com = com_addr(unit); 3239 tp = com->tp; 3240 3241 stat = com_tiocm_get(com); 3242 delta = com_tiocm_get_delta(com); 3243 3244 if (com->state & CS_CTS_OFLOW) { 3245 if (stat & TIOCM_CTS) 3246 com->state |= CS_ODEVREADY; 3247 else 3248 com->state &= ~CS_ODEVREADY; 3249 } 3250 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3251 if (stat & TIOCM_CAR ) 3252 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3253 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3254 /* negate DTR, RTS */ 3255 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3256 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3257 /* disable IENABLE */ 3258 com_int_TxRx_disable( com ); 3259 } 3260 } 3261} 3262#endif 3263 3264static void 3265disc_optim(tp, t, com) 3266 struct tty *tp; 3267 struct termios *t; 3268 struct com_s *com; 3269{ 3270 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3271 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3272 && (!(t->c_iflag & PARMRK) 3273 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3274 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3275 && linesw[tp->t_line].l_rint == ttyinput) 3276 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3277 else 3278 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3279 /* 3280 * Prepare to reduce input latency for packet 3281 * discplines with a end of packet character. 3282 */ 3283 if (tp->t_line == SLIPDISC) 3284 com->hotchar = 0xc0; 3285 else if (tp->t_line == PPPDISC) 3286 com->hotchar = 0x7e; 3287 else 3288 com->hotchar = 0; 3289} 3290 3291/* 3292 * Following are all routines needed for SIO to act as console 3293 */ 3294#include <machine/cons.h> 3295 3296struct siocnstate { 3297 u_char dlbl; 3298 u_char dlbh; 3299 u_char ier; 3300 u_char cfcr; 3301 u_char mcr; 3302}; 3303 3304static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3305static void siocnclose __P((struct siocnstate *sp)); 3306static void siocnopen __P((struct siocnstate *sp)); 3307static void siocntxwait __P((void)); 3308 3309static void 3310siocntxwait() 3311{ 3312 int timo; 3313 3314 /* 3315 * Wait for any pending transmission to finish. Required to avoid 3316 * the UART lockup bug when the speed is changed, and for normal 3317 * transmits. 3318 */ 3319 timo = 100000; 3320 while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3321 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3322 ; 3323} 3324 3325/* 3326 * Read the serial port specified and try to figure out what speed 3327 * it's currently running at. We're assuming the serial port has 3328 * been initialized and is basicly idle. This routine is only intended 3329 * to be run at system startup. 3330 * 3331 * If the value read from the serial port doesn't make sense, return 0. 3332 */ 3333 3334static speed_t 3335siocngetspeed(iobase, table) 3336 Port_t iobase; 3337 struct speedtab *table; 3338{ 3339 int code; 3340 u_char dlbh; 3341 u_char dlbl; 3342 u_char cfcr; 3343 3344 cfcr = inb(iobase + com_cfcr); 3345 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3346 3347 dlbl = inb(iobase + com_dlbl); 3348 dlbh = inb(iobase + com_dlbh); 3349 3350 outb(iobase + com_cfcr, cfcr); 3351 3352 code = dlbh << 8 | dlbl; 3353 3354 for ( ; table->sp_speed != -1; table++) 3355 if (table->sp_code == code) 3356 return (table->sp_speed); 3357 3358 return 0; /* didn't match anything sane */ 3359} 3360 3361static void 3362siocnopen(sp) 3363 struct siocnstate *sp; 3364{ 3365 int divisor; 3366 u_char dlbh; 3367 u_char dlbl; 3368 Port_t iobase; 3369 3370 /* 3371 * Save all the device control registers except the fifo register 3372 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3373 * We can't save the fifo register since it is read-only. 3374 */ 3375 iobase = siocniobase; 3376 sp->ier = inb(iobase + com_ier); 3377 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3378 siocntxwait(); 3379 sp->cfcr = inb(iobase + com_cfcr); 3380 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3381 sp->dlbl = inb(iobase + com_dlbl); 3382 sp->dlbh = inb(iobase + com_dlbh); 3383 /* 3384 * Only set the divisor registers if they would change, since on 3385 * some 16550 incompatibles (Startech), setting them clears the 3386 * data input register. This also reduces the effects of the 3387 * UMC8669F bug. 3388 */ 3389 divisor = ttspeedtab(comdefaultrate, comspeedtab); 3390 dlbl = divisor & 0xFF; 3391 if (sp->dlbl != dlbl) 3392 outb(iobase + com_dlbl, dlbl); 3393 dlbh = (u_int) divisor >> 8; 3394 if (sp->dlbh != dlbh) 3395 outb(iobase + com_dlbh, dlbh); 3396 outb(iobase + com_cfcr, CFCR_8BITS); 3397 sp->mcr = inb(iobase + com_mcr); 3398 /* 3399 * We don't want interrupts, but must be careful not to "disable" 3400 * them by clearing the MCR_IENABLE bit, since that might cause 3401 * an interrupt by floating the IRQ line. 3402 */ 3403 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 3404} 3405 3406static void 3407siocnclose(sp) 3408 struct siocnstate *sp; 3409{ 3410 Port_t iobase; 3411 3412 /* 3413 * Restore the device control registers. 3414 */ 3415 siocntxwait(); 3416 iobase = siocniobase; 3417 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3418 if (sp->dlbl != inb(iobase + com_dlbl)) 3419 outb(iobase + com_dlbl, sp->dlbl); 3420 if (sp->dlbh != inb(iobase + com_dlbh)) 3421 outb(iobase + com_dlbh, sp->dlbh); 3422 outb(iobase + com_cfcr, sp->cfcr); 3423 /* 3424 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 3425 */ 3426 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 3427 outb(iobase + com_ier, sp->ier); 3428} 3429 3430void 3431siocnprobe(cp) 3432 struct consdev *cp; 3433{ 3434 speed_t boot_speed; 3435 u_char cfcr; 3436 struct isa_device *dvp; 3437 int s; 3438 struct siocnstate sp; 3439 3440 /* 3441 * Find our first enabled console, if any. If it is a high-level 3442 * console device, then initialize it and return successfully. 3443 * If it is a low-level console device, then initialize it and 3444 * return unsuccessfully. It must be initialized in both cases 3445 * for early use by console drivers and debuggers. Initializing 3446 * the hardware is not necessary in all cases, since the i/o 3447 * routines initialize it on the fly, but it is necessary if 3448 * input might arrive while the hardware is switched back to an 3449 * uninitialized state. We can't handle multiple console devices 3450 * yet because our low-level routines don't take a device arg. 3451 * We trust the user to set the console flags properly so that we 3452 * don't need to probe. 3453 */ 3454 cp->cn_pri = CN_DEAD; 3455 for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) 3456 if (dvp->id_driver == &siodriver && dvp->id_enabled 3457 && COM_CONSOLE(dvp)) { 3458 siocniobase = dvp->id_iobase; 3459 s = spltty(); 3460 if (boothowto & RB_SERIAL) { 3461 boot_speed = siocngetspeed(siocniobase, 3462 comspeedtab); 3463 if (boot_speed) 3464 comdefaultrate = boot_speed; 3465 } 3466 3467 /* 3468 * Initialize the divisor latch. We can't rely on 3469 * siocnopen() to do this the first time, since it 3470 * avoids writing to the latch if the latch appears 3471 * to have the correct value. Also, if we didn't 3472 * just read the speed from the hardware, then we 3473 * need to set the speed in hardware so that 3474 * switching it later is null. 3475 */ 3476 cfcr = inb(siocniobase + com_cfcr); 3477 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 3478 outb(siocniobase + com_dlbl, 3479 COMBRD(comdefaultrate) & 0xff); 3480 outb(siocniobase + com_dlbh, 3481 (u_int) COMBRD(comdefaultrate) >> 8); 3482 outb(siocniobase + com_cfcr, cfcr); 3483 3484 siocnopen(&sp); 3485 splx(s); 3486 if (!COM_LLCONSOLE(dvp)) { 3487 cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); 3488 cp->cn_pri = COM_FORCECONSOLE(dvp) 3489 || boothowto & RB_SERIAL 3490 ? CN_REMOTE : CN_NORMAL; 3491 } 3492 break; 3493 } 3494} 3495 3496void 3497siocninit(cp) 3498 struct consdev *cp; 3499{ 3500 comconsole = DEV_TO_UNIT(cp->cn_dev); 3501} 3502 3503int 3504siocncheckc(dev) 3505 dev_t dev; 3506{ 3507 int c; 3508 Port_t iobase; 3509 int s; 3510 struct siocnstate sp; 3511 3512 iobase = siocniobase; 3513 s = spltty(); 3514 siocnopen(&sp); 3515 if (inb(iobase + com_lsr) & LSR_RXRDY) 3516 c = inb(iobase + com_data); 3517 else 3518 c = -1; 3519 siocnclose(&sp); 3520 splx(s); 3521 return (c); 3522} 3523 3524 3525int 3526siocngetc(dev) 3527 dev_t dev; 3528{ 3529 int c; 3530 Port_t iobase; 3531 int s; 3532 struct siocnstate sp; 3533 3534 iobase = siocniobase; 3535 s = spltty(); 3536 siocnopen(&sp); 3537 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 3538 ; 3539 c = inb(iobase + com_data); 3540 siocnclose(&sp); 3541 splx(s); 3542 return (c); 3543} 3544 3545void 3546siocnputc(dev, c) 3547 dev_t dev; 3548 int c; 3549{ 3550 int s; 3551 struct siocnstate sp; 3552 3553 s = spltty(); 3554 siocnopen(&sp); 3555 siocntxwait(); 3556 outb(siocniobase + com_data, c); 3557 siocnclose(&sp); 3558 splx(s); 3559} 3560 3561#ifdef DSI_SOFT_MODEM 3562/* 3563 * The magic code to download microcode to a "Connection 14.4+Fax" 3564 * modem from Digicom Systems Inc. Very magic. 3565 */ 3566 3567#define DSI_ERROR(str) { ptr = str; goto error; } 3568static int 3569LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr) 3570{ 3571 int int_c,int_k; 3572 int data_0188, data_0187; 3573 3574 /* 3575 * First see if it is a DSI SoftModem 3576 */ 3577 if(!((inb(base_io+7) ^ inb(base_io+7) & 0x80))) 3578 return ENODEV; 3579 3580 data_0188 = inb(base_io+4); 3581 data_0187 = inb(base_io+3); 3582 outb(base_io+3,0x80); 3583 outb(base_io+4,0x0C); 3584 outb(base_io+0,0x31); 3585 outb(base_io+1,0x8C); 3586 outb(base_io+7,0x10); 3587 outb(base_io+7,0x19); 3588 3589 if(0x18 != (inb(base_io+7) & 0x1A)) 3590 DSI_ERROR("dsp bus not granted"); 3591 3592 if(0x01 != (inb(base_io+7) & 0x01)) { 3593 outb(base_io+7,0x18); 3594 outb(base_io+7,0x19); 3595 if(0x01 != (inb(base_io+7) & 0x01)) 3596 DSI_ERROR("program mem not granted"); 3597 } 3598 3599 int_c = 0; 3600 3601 while(1) { 3602 if(int_c >= 7 || size <= 0x1800) 3603 break; 3604 3605 for(int_k = 0 ; int_k < 0x800; int_k++) { 3606 outb(base_io+0,*ptr++); 3607 outb(base_io+1,*ptr++); 3608 outb(base_io+2,*ptr++); 3609 } 3610 3611 size -= 0x1800; 3612 int_c++; 3613 } 3614 3615 if(size > 0x1800) { 3616 outb(base_io+7,0x18); 3617 outb(base_io+7,0x19); 3618 if(0x00 != (inb(base_io+7) & 0x01)) 3619 DSI_ERROR("program data not granted"); 3620 3621 for(int_k = 0 ; int_k < 0x800; int_k++) { 3622 outb(base_io+1,*ptr++); 3623 outb(base_io+2,0); 3624 outb(base_io+1,*ptr++); 3625 outb(base_io+2,*ptr++); 3626 } 3627 3628 size -= 0x1800; 3629 3630 while(size > 0x1800) { 3631 for(int_k = 0 ; int_k < 0xC00; int_k++) { 3632 outb(base_io+1,*ptr++); 3633 outb(base_io+2,*ptr++); 3634 } 3635 size -= 0x1800; 3636 } 3637 3638 if(size < 0x1800) { 3639 for(int_k=0;int_k<size/2;int_k++) { 3640 outb(base_io+1,*ptr++); 3641 outb(base_io+2,*ptr++); 3642 } 3643 } 3644 3645 } else if (size > 0) { 3646 if(int_c == 7) { 3647 outb(base_io+7,0x18); 3648 outb(base_io+7,0x19); 3649 if(0x00 != (inb(base_io+7) & 0x01)) 3650 DSI_ERROR("program data not granted"); 3651 for(int_k = 0 ; int_k < size/3; int_k++) { 3652 outb(base_io+1,*ptr++); 3653 outb(base_io+2,0); 3654 outb(base_io+1,*ptr++); 3655 outb(base_io+2,*ptr++); 3656 } 3657 } else { 3658 for(int_k = 0 ; int_k < size/3; int_k++) { 3659 outb(base_io+0,*ptr++); 3660 outb(base_io+1,*ptr++); 3661 outb(base_io+2,*ptr++); 3662 } 3663 } 3664 } 3665 outb(base_io+7,0x11); 3666 outb(base_io+7,3); 3667 3668 outb(base_io+4,data_0188 & 0xfb); 3669 3670 outb(base_io+3,data_0187); 3671 3672 return 0; 3673error: 3674 printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr); 3675 outb(base_io+7,0x00); \ 3676 outb(base_io+3,data_0187); \ 3677 outb(base_io+4,data_0188); \ 3678 return EIO; 3679} 3680#endif /* DSI_SOFT_MODEM */ 3681 3682/* 3683 * support PnP cards if we are using 'em 3684 */ 3685 3686#if NPNP > 0 3687 3688static struct siopnp_ids { 3689 u_long vend_id; 3690 char *id_str; 3691} siopnp_ids[] = { 3692 { 0x8113b04e, "Supra1381"}, 3693 { 0x9012b04e, "Supra1290"}, 3694 { 0x11007256, "USR0011"}, 3695 { 0 } 3696}; 3697 3698static char *siopnp_probe(u_long csn, u_long vend_id); 3699static void siopnp_attach(u_long csn, u_long vend_id, char *name, 3700 struct isa_device *dev); 3701static u_long nsiopnp = NSIO; 3702 3703static struct pnp_device siopnp = { 3704 "siopnp", 3705 siopnp_probe, 3706 siopnp_attach, 3707 &nsiopnp, 3708 &tty_imask 3709}; 3710DATA_SET (pnpdevice_set, siopnp); 3711 3712static char * 3713siopnp_probe(u_long csn, u_long vend_id) 3714{ 3715 struct siopnp_ids *ids; 3716 char *s = NULL; 3717 3718 for(ids = siopnp_ids; ids->vend_id != 0; ids++) { 3719 if (vend_id == ids->vend_id) { 3720 s = ids->id_str; 3721 break; 3722 } 3723 } 3724 3725 if (s) { 3726 struct pnp_cinfo d; 3727 read_pnp_parms(&d, 0); 3728 if (d.enable == 0 || d.flags & 1) { 3729 printf("CSN %d is disabled.\n", csn); 3730 return (NULL); 3731 } 3732 3733 } 3734 3735 return (s); 3736} 3737 3738static void 3739siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) 3740{ 3741 struct pnp_cinfo d; 3742 struct isa_device *dvp; 3743 3744 if (dev->id_unit >= NSIOTOT) 3745 return; 3746 3747 if (read_pnp_parms(&d, 0) == 0) { 3748 printf("failed to read pnp parms\n"); 3749 return; 3750 } 3751 3752 write_pnp_parms(&d, 0); 3753 3754 enable_pnp_card(); 3755 3756 dev->id_iobase = d.port[0]; 3757 dev->id_irq = (1 << d.irq[0]); 3758 dev->id_intr = siointr; 3759 dev->id_ri_flags = RI_FAST; 3760 dev->id_drq = -1; 3761 3762 if (dev->id_driver == NULL) { 3763 dev->id_driver = &siodriver; 3764 dvp = find_isadev(isa_devtab_tty, &siodriver, 0); 3765 if (dvp != NULL) 3766 dev->id_id = dvp->id_id; 3767 } 3768 3769 if ((dev->id_alive = sioprobe(dev)) != 0) 3770 sioattach(dev); 3771 else 3772 printf("sio%d: probe failed\n", dev->id_unit); 3773} 3774#endif 3775#ifdef PC98 3776/* 3777 * pc98 local function 3778 */ 3779 3780static void 3781com_tiocm_set(struct com_s *com, int msr) 3782{ 3783 int s; 3784 int tmp = 0; 3785 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 3786 3787 s=spltty(); 3788 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 3789 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3790 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 3791 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3792 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3793 pc98_i8251_clear_or_cmd( com, mask, tmp ); 3794 splx(s); 3795} 3796 3797static void 3798com_tiocm_bis(struct com_s *com, int msr) 3799{ 3800 int s; 3801 int tmp = 0; 3802 3803 s=spltty(); 3804 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3805 tmp |= CMD8251_TxEN|CMD8251_RxEN; 3806 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3807 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3808 3809 pc98_i8251_or_cmd( com, tmp ); 3810 splx(s); 3811} 3812 3813static void 3814com_tiocm_bic(struct com_s *com, int msr) 3815{ 3816 int s; 3817 int tmp = msr; 3818 3819 s=spltty(); 3820 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 3821 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 3822 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 3823 3824 pc98_i8251_clear_cmd( com, tmp ); 3825 splx(s); 3826} 3827 3828static int 3829com_tiocm_get(struct com_s *com) 3830{ 3831 return( com->pc98_prev_modem_status ); 3832} 3833 3834static int 3835com_tiocm_get_delta(struct com_s *com) 3836{ 3837 int tmp; 3838 3839 tmp = com->pc98_modem_delta; 3840 com->pc98_modem_delta = 0; 3841 return( tmp ); 3842} 3843 3844/* convert to TIOCM_?? ( ioctl.h ) */ 3845static int 3846pc98_get_modem_status(struct com_s *com) 3847{ 3848 int stat, stat2; 3849 register int msr; 3850 3851 stat = inb(com->sts_port); 3852 stat2 = inb(com->in_modem_port); 3853 msr = com->pc98_prev_modem_status 3854 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3855 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 3856 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 3857 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 3858 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 3859#if COM_CARRIER_DETECT_EMULATE 3860 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 3861 msr |= TIOCM_CAR; 3862 } 3863#endif 3864 return(msr); 3865} 3866 3867static void 3868pc98_check_msr(void* chan) 3869{ 3870 int msr, delta; 3871 int s; 3872 register struct tty *tp; 3873 struct com_s *com; 3874 int mynor; 3875 int unit; 3876 dev_t dev; 3877 3878 dev=(dev_t)chan; 3879 mynor = minor(dev); 3880 unit = MINOR_TO_UNIT(mynor); 3881 com = com_addr(unit); 3882 tp = com->tp; 3883 3884 s = spltty(); 3885 msr = pc98_get_modem_status(com); 3886 /* make change flag */ 3887 delta = msr ^ com->pc98_prev_modem_status; 3888 if ( delta & TIOCM_CAR ) { 3889 if ( com->modem_car_chg_timer ) { 3890 if ( -- com->modem_car_chg_timer ) 3891 msr ^= TIOCM_CAR; 3892 } else { 3893 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ? 3894 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE ) 3895 msr ^= TIOCM_CAR; 3896 } 3897 } else 3898 com->modem_car_chg_timer = 0; 3899 delta = ( msr ^ com->pc98_prev_modem_status ) & 3900 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 3901 com->pc98_prev_modem_status = msr; 3902 delta = ( com->pc98_modem_delta |= delta ); 3903 splx(s); 3904 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 3905 if ( delta ) { 3906 commint(dev); 3907 } 3908 timeout(pc98_check_msr, (caddr_t)dev, 3909 PC98_CHECK_MODEM_INTERVAL); 3910 } else { 3911 com->modem_checking = 0; 3912 } 3913} 3914 3915static void 3916pc98_msrint_start(dev_t dev) 3917{ 3918 struct com_s *com; 3919 int mynor; 3920 int unit; 3921 int s = spltty(); 3922 3923 mynor = minor(dev); 3924 unit = MINOR_TO_UNIT(mynor); 3925 com = com_addr(unit); 3926 /* modem control line check routine envoke interval is 1/10 sec */ 3927 if ( com->modem_checking == 0 ) { 3928 com->pc98_prev_modem_status = pc98_get_modem_status(com); 3929 com->pc98_modem_delta = 0; 3930 timeout(pc98_check_msr, (caddr_t)dev, 3931 PC98_CHECK_MODEM_INTERVAL); 3932 com->modem_checking = 1; 3933 } 3934 splx(s); 3935} 3936 3937static void 3938pc98_disable_i8251_interrupt(struct com_s *com, int mod) 3939{ 3940 /* disable interrupt */ 3941 register int tmp; 3942 3943 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3944 COM_INT_DISABLE 3945 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3946 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 3947 COM_INT_ENABLE 3948} 3949 3950static void 3951pc98_enable_i8251_interrupt(struct com_s *com, int mod) 3952{ 3953 register int tmp; 3954 3955 COM_INT_DISABLE 3956 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 3957 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 3958 COM_INT_ENABLE 3959} 3960 3961static int 3962pc98_check_i8251_interrupt(struct com_s *com) 3963{ 3964 return ( com->intr_enable & 0x07 ); 3965} 3966 3967static void 3968pc98_i8251_clear_cmd(struct com_s *com, int x) 3969{ 3970 int tmp; 3971 3972 COM_INT_DISABLE 3973 tmp = com->pc98_prev_siocmd & ~(x); 3974 outb(com->cmd_port, tmp); 3975 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3976 COM_INT_ENABLE 3977} 3978 3979static void 3980pc98_i8251_or_cmd(struct com_s *com, int x) 3981{ 3982 int tmp; 3983 3984 COM_INT_DISABLE 3985 tmp = com->pc98_prev_siocmd | (x); 3986 outb(com->cmd_port, tmp); 3987 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 3988 COM_INT_ENABLE 3989} 3990 3991static void 3992pc98_i8251_set_cmd(struct com_s *com, int x) 3993{ 3994 int tmp; 3995 3996 COM_INT_DISABLE 3997 tmp = (x); 3998 outb(com->cmd_port, tmp); 3999 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4000 COM_INT_ENABLE 4001} 4002 4003static void 4004pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4005{ 4006 int tmp; 4007 COM_INT_DISABLE 4008 tmp = com->pc98_prev_siocmd & ~(clr); 4009 tmp |= (x); 4010 outb(com->cmd_port, tmp); 4011 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4012 COM_INT_ENABLE 4013} 4014 4015static int 4016pc98_i8251_get_cmd(struct com_s *com) 4017{ 4018 return com->pc98_prev_siocmd; 4019} 4020 4021static int 4022pc98_i8251_get_mod(struct com_s *com) 4023{ 4024 return com->pc98_prev_siomod; 4025} 4026 4027static void 4028pc98_i8251_reset(struct com_s *com, int mode, int command) 4029{ 4030 outb(com->cmd_port, 0); /* dummy */ 4031 DELAY(2); 4032 outb(com->cmd_port, 0); /* dummy */ 4033 DELAY(2); 4034 outb(com->cmd_port, 0); /* dummy */ 4035 DELAY(2); 4036 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4037 DELAY(2); 4038 outb(com->cmd_port, mode ); /* mode register */ 4039 com->pc98_prev_siomod = mode; 4040 DELAY(2); 4041 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4042} 4043 4044static void 4045pc98_check_sysclock(void) 4046{ 4047 /* get system clock from port */ 4048 if ( pc98_machine_type & M_8M ) { 4049 /* 8 MHz system & H98 */ 4050 sysclock = 8; 4051 } else { 4052 /* 5 MHz system */ 4053 sysclock = 5; 4054 } 4055} 4056 4057static void 4058com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4059{ 4060 int cfcr=0, count; 4061 int previnterrupt; 4062 4063 count = pc98_ttspeedtab( com, speed ); 4064 if ( count < 0 ) return; 4065 4066 previnterrupt = pc98_check_i8251_interrupt(com); 4067 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4068 4069 switch ( cflag&CSIZE ) { 4070 case CS5: 4071 cfcr = MOD8251_5BITS; break; 4072 case CS6: 4073 cfcr = MOD8251_6BITS; break; 4074 case CS7: 4075 cfcr = MOD8251_7BITS; break; 4076 case CS8: 4077 cfcr = MOD8251_8BITS; break; 4078 } 4079 if ( cflag&PARENB ) { 4080 if ( cflag&PARODD ) 4081 cfcr |= MOD8251_PODD; 4082 else 4083 cfcr |= MOD8251_PEVEN; 4084 } else 4085 cfcr |= MOD8251_PDISAB; 4086 4087 if ( cflag&CSTOPB ) 4088 cfcr |= MOD8251_STOP2; 4089 else 4090 cfcr |= MOD8251_STOP1; 4091 4092 if ( count & 0x10000 ) 4093 cfcr |= MOD8251_CLKX1; 4094 else 4095 cfcr |= MOD8251_CLKX16; 4096 4097 if (epson_machine_id != 0x20) { /* XXX */ 4098 { 4099 int tmp; 4100 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4101 ; 4102 } 4103 } 4104 /* set baud rate from ospeed */ 4105 pc98_set_baud_rate( com, count ); 4106 4107 if ( cfcr != pc98_i8251_get_mod(com) ) 4108 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4109 4110 pc98_enable_i8251_interrupt( com, previnterrupt ); 4111} 4112 4113static int 4114pc98_ttspeedtab(struct com_s *com, int speed) 4115{ 4116 int effect_sp, count=-1, mod; 4117 4118 switch ( com->pc98_if_type ) { 4119 case COM_IF_INTERNAL: 4120 /* for *1CLK asynchronous! mode , TEFUTEFU */ 4121 effect_sp = ttspeedtab( speed, pc98speedtab ); 4122 if ( effect_sp < 0 ) 4123 effect_sp = ttspeedtab( (speed-1), pc98speedtab ); 4124 if ( effect_sp <= 0 ) 4125 return effect_sp; 4126 mod = (sysclock == 5 ? 2457600 : 1996800); 4127 if ( effect_sp == speed ) 4128 mod /= 16; 4129 count = mod / effect_sp; 4130 if ( count > 65535 ) 4131 return(-1); 4132 if ( effect_sp >= 2400 ) 4133 if ( !(sysclock != 5 && 4134 (effect_sp == 19200 || effect_sp == 38400)) ) 4135 if ( ( mod % effect_sp ) != 0 ) 4136 return(-1); 4137 if ( effect_sp != speed ) 4138 count |= 0x10000; 4139 break; 4140#ifdef COM_IF_PC9861K 4141 case COM_IF_PC9861K: 4142 effect_sp = speed; 4143 count = 1; 4144 break; 4145#endif 4146#ifdef COM_IF_PIO9032B 4147 case COM_IF_PIO9032B: 4148 if ( speed == 0 ) return 0; 4149 count = ttspeedtab( speed, comspeedtab_pio9032b ); 4150 if ( count < 0 ) return count; 4151 effect_sp = speed; 4152 break; 4153#endif 4154#ifdef COM_IF_B98_01 4155 case COM_IF_B98_01: 4156 effect_sp=speed; 4157 count = ttspeedtab( speed, comspeedtab_b98_01 ); 4158 if ( count <= 3 ) 4159 return -1; /* invalid speed/count */ 4160 if ( count <= 5 ) 4161 count |= 0x10000; /* x1 mode for 76800 and 153600 */ 4162 else 4163 count -= 4; /* x16 mode for slower */ 4164 break; 4165#endif 4166 } 4167 return count; 4168} 4169 4170static void 4171pc98_set_baud_rate( struct com_s *com, int count) 4172{ 4173 int s; 4174 4175 switch ( com->pc98_if_type ) { 4176 case COM_IF_INTERNAL: 4177 if ( count < 0 ) { 4178 printf( "[ Illegal count : %d ]", count ); 4179 return; 4180 } else if ( count == 0) 4181 return; 4182 /* set i8253 */ 4183 s = splclock(); 4184 outb( 0x77, 0xb6 ); 4185 outb( 0x5f, 0); 4186 outb( 0x75, count & 0xff ); 4187 outb( 0x5f, 0); 4188 outb( 0x75, (count >> 8) & 0xff ); 4189 splx(s); 4190 break; 4191#if 0 4192#ifdef COM_IF_PC9861K 4193 case COM_IF_PC9861K: 4194 break; 4195 /* ext. RS232C board: speed is determined by DIP switch */ 4196#endif 4197#endif /* 0 */ 4198#ifdef COM_IF_PIO9032B 4199 case COM_IF_PIO9032B: 4200 outb( com_addr[unit], count & 0x07 ); 4201 break; 4202#endif 4203#ifdef COM_IF_B98_01 4204 case COM_IF_B98_01: 4205 outb( com->iobase, count & 0x0f ); 4206#ifdef B98_01_OLD 4207 /* some old board should be controlled in different way, 4208 but this hasn't been tested yet.*/ 4209 outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 ); 4210#endif 4211 break; 4212#endif 4213 } 4214} 4215static int 4216pc98_check_if_type( int iobase, struct siodev *iod) 4217{ 4218 int irr = 0, tmp = 0; 4219 int ret = 0; 4220 static short irq_tab[2][8] = { 4221 { 3, 5, 6, 9, 10, 12, 13, -1}, 4222 { 3, 10, 12, 13, 5, 6, 9, -1} 4223 }; 4224 iod->irq = 0; 4225 switch ( iobase & 0xff ) { 4226 case IO_COM1: 4227 iod->if_type = COM_IF_INTERNAL; 4228 ret = 0; iod->irq = 4; break; 4229#ifdef COM_IF_PC9861K 4230 case IO_COM2: 4231 iod->if_type = COM_IF_PC9861K; 4232 ret = 1; irr = 0; tmp = 3; break; 4233 case IO_COM3: 4234 iod->if_type = COM_IF_PC9861K; 4235 ret = 2; irr = 1; tmp = 3; break; 4236#endif 4237#ifdef COM_IF_PIO9032B 4238 case IO_COM_PIO9032B_2: 4239 iod->if_type = COM_IF_PIO9032B; 4240 ret = 1; irr = 0; tmp = 7; break; 4241 case IO_COM_PIO9032B_3: 4242 iod->if_type = COM_IF_PIO9032B; 4243 ret = 2; irr = 1; tmp = 7; break; 4244#endif 4245#ifdef COM_IF_B98_01 4246 case IO_COM_B98_01_2: 4247 iod->if_type = COM_IF_B98_01; 4248 ret = 1; irr = 0; tmp = 7; 4249 outb(iobase + 2, 0xf2); 4250 outb(iobase, 4); 4251 break; 4252 case IO_COM_B98_01_3: 4253 iod->if_type = COM_IF_B98_01; 4254 ret = 2; irr = 1; tmp = 7; 4255 outb(iobase + 2, 0xf2); 4256 outb(iobase , 4); 4257 break; 4258#endif 4259 default: 4260 if((iobase & 0x0f0) == 0xd0){ 4261 iod->if_type = MC16550; 4262 return 0; 4263 } 4264 return -1; 4265 } 4266 4267 iod->cmd = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret); 4268 iod->sts = ( iobase & 0xff00 )|PC98SIO_sts_port(ret); 4269 iod->mod = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret); 4270 iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret); 4271 4272 if ( iod->irq == 0 ) { 4273 tmp &= inb( iod->mod ); 4274 iod->irq = irq_tab[irr][tmp]; 4275 if ( iod->irq == -1 ) return -1; 4276 } 4277 return 0; 4278} 4279static int 4280pc98_set_ioport( struct com_s *com, int io_base ) 4281{ 4282 int a, io, type; 4283 4284 switch ( io_base & 0xff ) { 4285 case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL; 4286 pc98_check_sysclock(); break; 4287#ifdef COM_IF_PC9861K 4288 case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break; 4289 case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break; 4290#endif /* COM_IF_PC9861K */ 4291#ifdef COM_IF_PIO9032B 4292 /* PIO9032B : I/O address is changeable */ 4293 case IO_COM_PIO9032B_2: 4294 a = 1; io = io_base & 0xff00; 4295 type = COM_IF_PIO9032B; break; 4296 case IO_COM_PIO9032B_3: 4297 a = 2; io = io_base & 0xff00; 4298 type = COM_IF_PIO9032B; break; 4299#endif /* COM_IF_PIO9032B */ 4300#ifdef COM_IF_B98_01 4301 case IO_COM_B98_01_2: 4302 a = 1; io = 0; type = COM_IF_B98_01; break; 4303 case IO_COM_B98_01_3: 4304 a = 2; io = 0; type = COM_IF_B98_01; break; 4305#endif /* COM_IF_B98_01*/ 4306 default: /* i/o address not match */ 4307 return -1; 4308 } 4309 4310 com->pc98_if_type = type; 4311 com->data_port = io | PC98SIO_data_port(a); 4312 com->cmd_port = io | PC98SIO_cmd_port(a); 4313 com->sts_port = io | PC98SIO_sts_port(a); 4314 com->in_modem_port = io | PC98SIO_in_modem_port(a); 4315 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(a); 4316 return 0; 4317} 4318#endif /* PC98 defined */ 4319