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