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