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