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