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