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