sio.c revision 43275
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.76 1999/01/19 00:21:53 peter 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); 1784#endif 1785determined_type: ; 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 && p->p_ucred->cr_uid != 0) { 1916 error = EBUSY; 1917 goto out; 1918 } 1919 } else { 1920 /* 1921 * The device isn't open, so there are no conflicts. 1922 * Initialize it. Initialization is done twice in many 1923 * cases: to preempt sleeping callin opens if we are 1924 * callout, and to complete a callin open after DCD rises. 1925 */ 1926 tp->t_oproc = comstart; 1927 tp->t_param = comparam; 1928 tp->t_dev = dev; 1929 tp->t_termios = mynor & CALLOUT_MASK 1930 ? com->it_out : com->it_in; 1931#ifndef PC98 1932 tp->t_ififosize = 2 * RS_IBUFSIZE; 1933#else 1934 tp->t_ififosize = 2 * com->CE_INPUT_OFFSET; 1935#endif 1936 tp->t_ispeedwat = (speed_t)-1; 1937 tp->t_ospeedwat = (speed_t)-1; 1938#ifdef PC98 1939 if (!IS_8251(com->pc98_if_type)) 1940#endif 1941 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 1942 com->poll = com->no_irq; 1943 com->poll_output = com->loses_outints; 1944 ++com->wopeners; 1945 error = comparam(tp, &tp->t_termios); 1946 --com->wopeners; 1947 if (error != 0) 1948 goto out; 1949#ifdef PC98 1950 if (IS_8251(com->pc98_if_type)) { 1951 com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS); 1952 pc98_msrint_start(dev); 1953 } 1954#endif 1955 /* 1956 * XXX we should goto open_top if comparam() slept. 1957 */ 1958 iobase = com->iobase; 1959 if (com->hasfifo) { 1960 /* 1961 * (Re)enable and drain fifos. 1962 * 1963 * Certain SMC chips cause problems if the fifos 1964 * are enabled while input is ready. Turn off the 1965 * fifo if necessary to clear the input. We test 1966 * the input ready bit after enabling the fifos 1967 * since we've already enabled them in comparam() 1968 * and to handle races between enabling and fresh 1969 * input. 1970 */ 1971 while (TRUE) { 1972#ifdef PC98 1973 outb(iobase + (com_fifo << port_shift), 1974 FIFO_RCV_RST | FIFO_XMT_RST 1975 | com->fifo_image); 1976 if (com->pc98_if_type == COM_IF_RSA98III) 1977 outb(com->rsabase + rsa_frr , 0x00); 1978#else 1979 outb(iobase + com_fifo, 1980 FIFO_RCV_RST | FIFO_XMT_RST 1981 | com->fifo_image); 1982#endif 1983 /* 1984 * XXX the delays are for superstitious 1985 * historical reasons. It must be less than 1986 * the character time at the maximum 1987 * supported speed (87 usec at 115200 bps 1988 * 8N1). Otherwise we might loop endlessly 1989 * if data is streaming in. We used to use 1990 * delays of 100. That usually worked 1991 * because DELAY(100) used to usually delay 1992 * for about 85 usec instead of 100. 1993 */ 1994 DELAY(50); 1995#ifndef PC98 1996 if (!(inb(com->line_status_port) & LSR_RXRDY)) 1997#else 1998 if (com->pc98_if_type == COM_IF_RSA98III 1999 ? !(inb(com->rsabase + rsa_srr) & 0x08) 2000 : !(inb(com->line_status_port) & LSR_RXRDY)) 2001#endif 2002 break; 2003#ifdef PC98 2004 outb(iobase + (com_fifo << port_shift), 0); 2005#else 2006 outb(iobase + com_fifo, 0); 2007#endif 2008 DELAY(50); 2009 (void) inb(com->data_port); 2010 } 2011 } 2012 2013 disable_intr(); 2014#ifdef PC98 2015 if (IS_8251(com->pc98_if_type)) { 2016 com_tiocm_bis(com, TIOCM_LE); 2017 com->pc98_prev_modem_status = pc98_get_modem_status(com); 2018 com_int_Rx_enable(com); 2019 } else { 2020#endif 2021 (void) inb(com->line_status_port); 2022 (void) inb(com->data_port); 2023 com->prev_modem_status = com->last_modem_status 2024 = inb(com->modem_status_port); 2025 if (COM_IIR_TXRDYBUG(com)) { 2026 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS 2027 | IER_EMSC); 2028 } else { 2029 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY 2030 | IER_ERLS | IER_EMSC); 2031 } 2032#ifdef PC98 2033 if (com->pc98_if_type == COM_IF_RSA98III) { 2034 outb(com->rsabase + rsa_ier, 0x1d); 2035 outb(com->intr_ctl_port, IER_ERLS | IER_EMSC); 2036 } 2037#endif 2038#ifdef PC98 2039 } 2040#endif 2041 enable_intr(); 2042 /* 2043 * Handle initial DCD. Callout devices get a fake initial 2044 * DCD (trapdoor DCD). If we are callout, then any sleeping 2045 * callin opens get woken up and resume sleeping on "siobi" 2046 * instead of "siodcd". 2047 */ 2048 /* 2049 * XXX `mynor & CALLOUT_MASK' should be 2050 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 2051 * TRAPDOOR_CARRIER is the default initial state for callout 2052 * devices and SOFT_CARRIER is like CLOCAL except it hides 2053 * the true carrier. 2054 */ 2055#ifdef PC98 2056 if ((IS_8251(com->pc98_if_type) && 2057 (pc98_get_modem_status(com) & TIOCM_CAR)) || 2058 (!IS_8251(com->pc98_if_type) && 2059 (com->prev_modem_status & MSR_DCD)) || 2060 mynor & CALLOUT_MASK) 2061#else 2062 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 2063#endif 2064 (*linesw[tp->t_line].l_modem)(tp, 1); 2065 } 2066 /* 2067 * Wait for DCD if necessary. 2068 */ 2069 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 2070 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 2071 ++com->wopeners; 2072 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0); 2073 if (com_addr(unit) == NULL) 2074 return (ENXIO); 2075 --com->wopeners; 2076 if (error != 0 || com->gone) 2077 goto out; 2078 goto open_top; 2079 } 2080 error = (*linesw[tp->t_line].l_open)(dev, tp); 2081 disc_optim(tp, &tp->t_termios, com); 2082 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 2083 com->active_out = TRUE; 2084 siosettimeout(); 2085out: 2086 splx(s); 2087 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 2088 comhardclose(com); 2089 return (error); 2090} 2091 2092static int 2093sioclose(dev, flag, mode, p) 2094 dev_t dev; 2095 int flag; 2096 int mode; 2097 struct proc *p; 2098{ 2099 struct com_s *com; 2100 int mynor; 2101 int s; 2102 struct tty *tp; 2103 2104 mynor = minor(dev); 2105 if (mynor & CONTROL_MASK) 2106 return (0); 2107 com = com_addr(MINOR_TO_UNIT(mynor)); 2108 tp = com->tp; 2109 s = spltty(); 2110 (*linesw[tp->t_line].l_close)(tp, flag); 2111#ifdef PC98 2112 com->modem_checking = 0; 2113#endif 2114 disc_optim(tp, &tp->t_termios, com); 2115 siostop(tp, FREAD | FWRITE); 2116 comhardclose(com); 2117 ttyclose(tp); 2118 siosettimeout(); 2119 splx(s); 2120 if (com->gone) { 2121 printf("sio%d: gone\n", com->unit); 2122 s = spltty(); 2123 com_addr(com->unit) = 0; 2124 bzero(tp,sizeof *tp); 2125 bzero(com,sizeof *com); 2126 free(com,M_TTYS); 2127 splx(s); 2128 } 2129 return (0); 2130} 2131 2132static void 2133comhardclose(com) 2134 struct com_s *com; 2135{ 2136 Port_t iobase; 2137 int s; 2138 struct tty *tp; 2139 int unit; 2140#ifdef PC98 2141 int port_shift = 0; 2142#endif 2143 2144 unit = com->unit; 2145 iobase = com->iobase; 2146 s = spltty(); 2147 com->poll = FALSE; 2148 com->poll_output = FALSE; 2149 com->do_timestamp = FALSE; 2150 com->do_dcd_timestamp = FALSE; 2151#ifdef PC98 2152 if (IS_8251(com->pc98_if_type)) 2153 com_send_break_off(com); 2154 else { 2155 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 2156 outb(iobase + (com_cfcr << port_shift), 2157 com->cfcr_image &= ~CFCR_SBREAK); 2158 } 2159#else 2160 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2161#endif 2162 { 2163#ifdef PC98 2164 int tmp; 2165 if (IS_8251(com->pc98_if_type)) 2166 com_int_TxRx_disable(com); 2167 else 2168 outb(iobase + (com_ier << port_shift), 0); 2169 if (com->pc98_if_type == COM_IF_RSA98III) { 2170 outb(com->rsabase + rsa_ier, 0x00); 2171 } 2172#else 2173 outb(iobase + com_ier, 0); 2174#endif 2175 tp = com->tp; 2176#ifdef PC98 2177 if (IS_8251(com->pc98_if_type)) 2178 tmp = pc98_get_modem_status(com) & TIOCM_CAR; 2179 else 2180 tmp = com->prev_modem_status & MSR_DCD; 2181#endif 2182 if (tp->t_cflag & HUPCL 2183 /* 2184 * XXX we will miss any carrier drop between here and the 2185 * next open. Perhaps we should watch DCD even when the 2186 * port is closed; it is not sufficient to check it at 2187 * the next open because it might go up and down while 2188 * we're not watching. 2189 */ 2190 || !com->active_out 2191#ifdef PC98 2192 && !(tmp) 2193#else 2194 && !(com->prev_modem_status & MSR_DCD) 2195#endif 2196 && !(com->it_in.c_cflag & CLOCAL) 2197 || !(tp->t_state & TS_ISOPEN)) { 2198#ifdef PC98 2199 if (IS_8251(com->pc98_if_type)) 2200 com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE); 2201 else 2202#endif 2203 (void)commctl(com, TIOCM_DTR, DMBIC); 2204 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 2205 timeout(siodtrwakeup, com, com->dtr_wait); 2206 com->state |= CS_DTR_OFF; 2207 } 2208 } 2209#ifdef PC98 2210 else { 2211 if (IS_8251(com->pc98_if_type)) 2212 com_tiocm_bic(com, TIOCM_LE ); 2213 } 2214#endif 2215 } 2216 if (com->hasfifo) { 2217 /* 2218 * Disable fifos so that they are off after controlled 2219 * reboots. Some BIOSes fail to detect 16550s when the 2220 * fifos are enabled. 2221 */ 2222#ifdef PC98 2223 outb(iobase + (com_fifo << port_shift), 0); 2224#else 2225 outb(iobase + com_fifo, 0); 2226#endif 2227 } 2228 com->active_out = FALSE; 2229 wakeup(&com->active_out); 2230 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 2231 splx(s); 2232} 2233 2234static int 2235sioread(dev, uio, flag) 2236 dev_t dev; 2237 struct uio *uio; 2238 int flag; 2239{ 2240 int mynor; 2241 int unit; 2242 struct tty *tp; 2243 2244 mynor = minor(dev); 2245 if (mynor & CONTROL_MASK) 2246 return (ENODEV); 2247 unit = MINOR_TO_UNIT(mynor); 2248 if (com_addr(unit)->gone) 2249 return (ENODEV); 2250 tp = com_addr(unit)->tp; 2251 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 2252} 2253 2254static int 2255siowrite(dev, uio, flag) 2256 dev_t dev; 2257 struct uio *uio; 2258 int flag; 2259{ 2260 int mynor; 2261 struct tty *tp; 2262 int unit; 2263 2264 mynor = minor(dev); 2265 if (mynor & CONTROL_MASK) 2266 return (ENODEV); 2267 2268 unit = MINOR_TO_UNIT(mynor); 2269 if (com_addr(unit)->gone) 2270 return (ENODEV); 2271 tp = com_addr(unit)->tp; 2272 /* 2273 * (XXX) We disallow virtual consoles if the physical console is 2274 * a serial port. This is in case there is a display attached that 2275 * is not the console. In that situation we don't need/want the X 2276 * server taking over the console. 2277 */ 2278 if (constty != NULL && unit == comconsole) 2279 constty = NULL; 2280 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 2281} 2282 2283static void 2284siobusycheck(chan) 2285 void *chan; 2286{ 2287 struct com_s *com; 2288 int s; 2289 2290 com = (struct com_s *)chan; 2291 2292 /* 2293 * Clear TS_BUSY if low-level output is complete. 2294 * spl locking is sufficient because siointr1() does not set CS_BUSY. 2295 * If siointr1() clears CS_BUSY after we look at it, then we'll get 2296 * called again. Reading the line status port outside of siointr1() 2297 * is safe because CS_BUSY is clear so there are no output interrupts 2298 * to lose. 2299 */ 2300 s = spltty(); 2301 if (com->state & CS_BUSY) 2302 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ 2303#ifdef PC98 2304 else if (IS_8251(com->pc98_if_type) && 2305 (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP)) 2306 == (STS8251_TxRDY | STS8251_TxEMP) || 2307 (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2308 == (LSR_TSRE | LSR_TXRDY)) { 2309#else 2310 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) 2311 == (LSR_TSRE | LSR_TXRDY)) { 2312#endif 2313 com->tp->t_state &= ~TS_BUSY; 2314 ttwwakeup(com->tp); 2315 com->extra_state &= ~CSE_BUSYCHECK; 2316 } else 2317 timeout(siobusycheck, com, hz / 100); 2318 splx(s); 2319} 2320 2321static void 2322siodtrwakeup(chan) 2323 void *chan; 2324{ 2325 struct com_s *com; 2326 2327 com = (struct com_s *)chan; 2328 com->state &= ~CS_DTR_OFF; 2329 wakeup(&com->dtr_wait); 2330} 2331 2332static void 2333siointr(unit) 2334 int unit; 2335{ 2336#ifndef COM_MULTIPORT 2337 COM_LOCK(); 2338 siointr1(com_addr(unit)); 2339 COM_UNLOCK(); 2340#else /* COM_MULTIPORT */ 2341 struct com_s *com; 2342 bool_t possibly_more_intrs; 2343#ifdef PC98 2344 u_char rsa_buf_status; 2345#endif 2346 2347 /* 2348 * Loop until there is no activity on any port. This is necessary 2349 * to get an interrupt edge more than to avoid another interrupt. 2350 * If the IRQ signal is just an OR of the IRQ signals from several 2351 * devices, then the edge from one may be lost because another is 2352 * on. 2353 */ 2354 COM_LOCK(); 2355 do { 2356 possibly_more_intrs = FALSE; 2357 for (unit = 0; unit < NSIOTOT; ++unit) { 2358 com = com_addr(unit); 2359 /* 2360 * XXX COM_LOCK(); 2361 * would it work here, or be counter-productive? 2362 */ 2363#ifdef PC98 2364 if (com != NULL 2365 && !com->gone 2366 && IS_8251(com->pc98_if_type)){ 2367 siointr1(com); 2368 } else 2369#endif /* PC98 */ 2370#ifdef PC98 2371 if (com != NULL 2372 && !com->gone 2373 && com->pc98_if_type == COM_IF_RSA98III) { 2374 rsa_buf_status = inb(com->rsabase + rsa_srr) & 0xc9; 2375 if ((rsa_buf_status & 0xc8) 2376 || !(rsa_buf_status & 0x01)) { 2377 siointr1(com); 2378 if(rsa_buf_status 2379 != (inb(com->rsabase + rsa_srr) & 0xc9)) 2380 possibly_more_intrs = TRUE; 2381 } 2382 } else 2383#endif 2384 if (com != NULL 2385 && !com->gone 2386 && (inb(com->int_id_port) & IIR_IMASK) 2387 != IIR_NOPEND) { 2388 siointr1(com); 2389 possibly_more_intrs = TRUE; 2390 } 2391 /* XXX COM_UNLOCK(); */ 2392 } 2393 } while (possibly_more_intrs); 2394 COM_UNLOCK(); 2395#endif /* COM_MULTIPORT */ 2396} 2397 2398static void 2399siointr1(com) 2400 struct com_s *com; 2401{ 2402 u_char line_status; 2403 u_char modem_status; 2404 u_char *ioptr; 2405 u_char recv_data; 2406 u_char int_ctl; 2407 u_char int_ctl_new; 2408 2409#ifdef PC98 2410 u_char tmp=0; 2411 u_char rsa_buf_status = 0; 2412 int rsa_tx_fifo_size=0; 2413 recv_data=0; 2414#endif /* PC98 */ 2415 2416 int_ctl = inb(com->intr_ctl_port); 2417 int_ctl_new = int_ctl; 2418 2419 while (!com->gone) { 2420#ifdef PC98 2421status_read:; 2422 if (IS_8251(com->pc98_if_type)) { 2423 tmp = inb(com->sts_port); 2424more_intr: 2425 line_status = 0; 2426 if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY; 2427 if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY; 2428 if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE; 2429 if (tmp & STS8251_PE) line_status |= LSR_PE; 2430 if (tmp & STS8251_OE) line_status |= LSR_OE; 2431 if (tmp & STS8251_FE) line_status |= LSR_FE; 2432 if (tmp & STS8251_BD_SD) line_status |= LSR_BI; 2433 } else 2434#endif /* PC98 */ 2435 line_status = inb(com->line_status_port); 2436#ifdef PC98 2437 if (com->pc98_if_type == COM_IF_RSA98III) 2438 rsa_buf_status = inb(com->rsabase + rsa_srr); 2439#endif /* PC98 */ 2440 2441 /* input event? (check first to help avoid overruns) */ 2442#ifndef PC98 2443 while (line_status & LSR_RCV_MASK) { 2444#else 2445 while ((line_status & LSR_RCV_MASK) 2446 || (com->pc98_if_type == COM_IF_RSA98III 2447 && (rsa_buf_status & 0x08))) { 2448#endif /* PC98 */ 2449 /* break/unnattached error bits or real input? */ 2450#ifdef PC98 2451 if (IS_8251(com->pc98_if_type)) { 2452 recv_data = inb(com->data_port); 2453 if (tmp & 0x78) { 2454 pc98_i8251_or_cmd(com,CMD8251_ER); 2455 recv_data = 0; 2456 } 2457 } else { 2458#endif /* PC98 */ 2459#ifdef PC98 2460 if (com->pc98_if_type == COM_IF_RSA98III) { 2461 if (!(rsa_buf_status & 0x08)) 2462 recv_data = 0; 2463 else { 2464 recv_data = inb(com->data_port); 2465 } 2466 } else 2467#endif 2468 if (!(line_status & LSR_RXRDY)) 2469 recv_data = 0; 2470 else 2471 recv_data = inb(com->data_port); 2472#ifdef PC98 2473 } 2474#endif 2475 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) { 2476 /* 2477 * Don't store BI if IGNBRK or FE/PE if IGNPAR. 2478 * Otherwise, push the work to a higher level 2479 * (to handle PARMRK) if we're bypassing. 2480 * Otherwise, convert BI/FE and PE+INPCK to 0. 2481 * 2482 * This makes bypassing work right in the 2483 * usual "raw" case (IGNBRK set, and IGNPAR 2484 * and INPCK clear). 2485 * 2486 * Note: BI together with FE/PE means just BI. 2487 */ 2488 if (line_status & LSR_BI) { 2489#if defined(DDB) && defined(BREAK_TO_DEBUGGER) 2490 if (com->unit == comconsole) { 2491 breakpoint(); 2492 goto cont; 2493 } 2494#endif 2495 if (com->tp == NULL 2496 || com->tp->t_iflag & IGNBRK) 2497 goto cont; 2498 } else { 2499 if (com->tp == NULL 2500 || com->tp->t_iflag & IGNPAR) 2501 goto cont; 2502 } 2503 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT 2504 && (line_status & (LSR_BI | LSR_FE) 2505 || com->tp->t_iflag & INPCK)) 2506 recv_data = 0; 2507 } 2508 ++com->bytes_in; 2509 if (com->hotchar != 0 && recv_data == com->hotchar) 2510 setsofttty(); 2511 ioptr = com->iptr; 2512 if (ioptr >= com->ibufend) 2513 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 2514 else { 2515 if (com->do_timestamp) 2516 microtime(&com->timestamp); 2517 ++com_events; 2518 schedsofttty(); 2519#if 0 /* for testing input latency vs efficiency */ 2520if (com->iptr - com->ibuf == 8) 2521 setsofttty(); 2522#endif 2523 ioptr[0] = recv_data; 2524#ifdef PC98 2525 ioptr[com->CE_INPUT_OFFSET] = line_status; 2526#else 2527 ioptr[CE_INPUT_OFFSET] = line_status; 2528#endif 2529 com->iptr = ++ioptr; 2530 if (ioptr == com->ihighwater 2531 && com->state & CS_RTS_IFLOW) 2532#ifdef PC98 2533 if (IS_8251(com->pc98_if_type)) 2534 com_tiocm_bic(com, TIOCM_RTS); 2535 else 2536#endif 2537 outb(com->modem_ctl_port, 2538 com->mcr_image &= ~MCR_RTS); 2539 if (line_status & LSR_OE) 2540 CE_RECORD(com, CE_OVERRUN); 2541 } 2542cont: 2543 /* 2544 * "& 0x7F" is to avoid the gcc-1.40 generating a slow 2545 * jump from the top of the loop to here 2546 */ 2547#ifdef PC98 2548 if (IS_8251(com->pc98_if_type)) 2549 goto status_read; 2550 else 2551#endif 2552 line_status = inb(com->line_status_port) & 0x7F; 2553#ifdef PC98 2554 if (com->pc98_if_type == COM_IF_RSA98III) 2555 rsa_buf_status = inb(com->rsabase + rsa_srr); 2556#endif /* PC98 */ 2557 } 2558 2559 /* modem status change? (always check before doing output) */ 2560#ifdef PC98 2561 if (!IS_8251(com->pc98_if_type)) { 2562#endif 2563 modem_status = inb(com->modem_status_port); 2564 if (modem_status != com->last_modem_status) { 2565 if (com->do_dcd_timestamp 2566 && !(com->last_modem_status & MSR_DCD) 2567 && modem_status & MSR_DCD) 2568 microtime(&com->dcd_timestamp); 2569 2570 /* 2571 * Schedule high level to handle DCD changes. Note 2572 * that we don't use the delta bits anywhere. Some 2573 * UARTs mess them up, and it's easy to remember the 2574 * previous bits and calculate the delta. 2575 */ 2576 com->last_modem_status = modem_status; 2577 if (!(com->state & CS_CHECKMSR)) { 2578 com_events += LOTS_OF_EVENTS; 2579 com->state |= CS_CHECKMSR; 2580 setsofttty(); 2581 } 2582 2583 /* handle CTS change immediately for crisp flow ctl */ 2584 if (com->state & CS_CTS_OFLOW) { 2585 if (modem_status & MSR_CTS) 2586 com->state |= CS_ODEVREADY; 2587 else 2588 com->state &= ~CS_ODEVREADY; 2589 } 2590 } 2591#ifdef PC98 2592 } 2593#endif 2594 2595 /* output queued and everything ready? */ 2596#ifndef PC98 2597 if (line_status & LSR_TXRDY 2598 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2599#else 2600 if (((com->pc98_if_type == COM_IF_RSA98III) 2601 ? (rsa_buf_status & 0x02) 2602 : (line_status & LSR_TXRDY)) 2603 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2604#endif 2605 ioptr = com->obufq.l_head; 2606 if (com->tx_fifo_size > 1) { 2607 u_int ocount; 2608 2609 ocount = com->obufq.l_tail - ioptr; 2610#ifdef PC98 2611 if (com->pc98_if_type == COM_IF_RSA98III) { 2612 rsa_buf_status = inb(com->rsabase + rsa_srr); 2613 rsa_tx_fifo_size = 1024; 2614 if (!(rsa_buf_status & 0x01)) 2615 rsa_tx_fifo_size = 2048; 2616 if (ocount > rsa_tx_fifo_size) 2617 ocount = rsa_tx_fifo_size; 2618 } else 2619#endif 2620 if (ocount > com->tx_fifo_size) 2621 ocount = com->tx_fifo_size; 2622 com->bytes_out += ocount; 2623 do 2624 outb(com->data_port, *ioptr++); 2625 while (--ocount != 0); 2626 } else { 2627 outb(com->data_port, *ioptr++); 2628 ++com->bytes_out; 2629 } 2630#ifdef PC98 2631 if (IS_8251(com->pc98_if_type)) 2632 if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG)) 2633 com_int_Tx_enable(com); 2634#endif 2635 com->obufq.l_head = ioptr; 2636 if (COM_IIR_TXRDYBUG(com)) { 2637 int_ctl_new = int_ctl | IER_ETXRDY; 2638 } 2639 if (ioptr >= com->obufq.l_tail) { 2640 struct lbq *qp; 2641 2642 qp = com->obufq.l_next; 2643 qp->l_queued = FALSE; 2644 qp = qp->l_next; 2645 if (qp != NULL) { 2646 com->obufq.l_head = qp->l_head; 2647 com->obufq.l_tail = qp->l_tail; 2648 com->obufq.l_next = qp; 2649 } else { 2650 /* output just completed */ 2651 if ( COM_IIR_TXRDYBUG(com) ) { 2652 int_ctl_new = int_ctl & ~IER_ETXRDY; 2653 } 2654 com->state &= ~CS_BUSY; 2655#if defined(PC98) 2656 if (IS_8251(com->pc98_if_type)) 2657 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2658 com_int_Tx_disable(com); 2659#endif 2660 } 2661 if (!(com->state & CS_ODONE)) { 2662 com_events += LOTS_OF_EVENTS; 2663 com->state |= CS_ODONE; 2664 setsofttty(); /* handle at high level ASAP */ 2665 } 2666 } 2667 if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { 2668 if (com->pc98_if_type == COM_IF_RSA98III) { 2669 int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY); 2670 outb(com->intr_ctl_port, int_ctl_new); 2671 outb(com->rsabase + rsa_ier, 0x1d); 2672 } else 2673 outb(com->intr_ctl_port, int_ctl_new); 2674 } 2675 } 2676#ifdef PC98 2677 else if (line_status & LSR_TXRDY) { 2678 if (IS_8251(com->pc98_if_type)) 2679 if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG ) 2680 com_int_Tx_disable(com); 2681 } 2682 if (IS_8251(com->pc98_if_type)) 2683 if ((tmp = inb(com->sts_port)) & STS8251_RxRDY) 2684 goto more_intr; 2685#endif 2686 2687 /* finished? */ 2688#ifndef COM_MULTIPORT 2689#ifdef PC98 2690 if (IS_8251(com->pc98_if_type)) 2691 return; 2692#endif 2693 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) 2694#endif /* COM_MULTIPORT */ 2695 return; 2696 } 2697} 2698 2699static int 2700sioioctl(dev, cmd, data, flag, p) 2701 dev_t dev; 2702 u_long cmd; 2703 caddr_t data; 2704 int flag; 2705 struct proc *p; 2706{ 2707 struct com_s *com; 2708 int error; 2709 Port_t iobase; 2710 int mynor; 2711 int s; 2712 struct tty *tp; 2713#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2714 int oldcmd; 2715 struct termios term; 2716#endif 2717 2718 mynor = minor(dev); 2719 com = com_addr(MINOR_TO_UNIT(mynor)); 2720 if (com->gone) 2721 return (ENODEV); 2722 iobase = com->iobase; 2723 if (mynor & CONTROL_MASK) { 2724 struct termios *ct; 2725 2726 switch (mynor & CONTROL_MASK) { 2727 case CONTROL_INIT_STATE: 2728 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 2729 break; 2730 case CONTROL_LOCK_STATE: 2731 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 2732 break; 2733 default: 2734 return (ENODEV); /* /dev/nodev */ 2735 } 2736 switch (cmd) { 2737 case TIOCSETA: 2738 error = suser(p->p_ucred, &p->p_acflag); 2739 if (error != 0) 2740 return (error); 2741 *ct = *(struct termios *)data; 2742 return (0); 2743 case TIOCGETA: 2744 *(struct termios *)data = *ct; 2745 return (0); 2746 case TIOCGETD: 2747 *(int *)data = TTYDISC; 2748 return (0); 2749 case TIOCGWINSZ: 2750 bzero(data, sizeof(struct winsize)); 2751 return (0); 2752 default: 2753 return (ENOTTY); 2754 } 2755 } 2756 tp = com->tp; 2757#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2758 term = tp->t_termios; 2759 oldcmd = cmd; 2760 error = ttsetcompat(tp, &cmd, data, &term); 2761 if (error != 0) 2762 return (error); 2763 if (cmd != oldcmd) 2764 data = (caddr_t)&term; 2765#endif 2766 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 2767 int cc; 2768 struct termios *dt = (struct termios *)data; 2769 struct termios *lt = mynor & CALLOUT_MASK 2770 ? &com->lt_out : &com->lt_in; 2771 2772 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 2773 | (dt->c_iflag & ~lt->c_iflag); 2774 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 2775 | (dt->c_oflag & ~lt->c_oflag); 2776 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 2777 | (dt->c_cflag & ~lt->c_cflag); 2778 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 2779 | (dt->c_lflag & ~lt->c_lflag); 2780 for (cc = 0; cc < NCCS; ++cc) 2781 if (lt->c_cc[cc] != 0) 2782 dt->c_cc[cc] = tp->t_cc[cc]; 2783 if (lt->c_ispeed != 0) 2784 dt->c_ispeed = tp->t_ispeed; 2785 if (lt->c_ospeed != 0) 2786 dt->c_ospeed = tp->t_ospeed; 2787 } 2788 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 2789 if (error != ENOIOCTL) 2790 return (error); 2791 s = spltty(); 2792 error = ttioctl(tp, cmd, data, flag); 2793 disc_optim(tp, &tp->t_termios, com); 2794 if (error != ENOIOCTL) { 2795 splx(s); 2796 return (error); 2797 } 2798#ifdef PC98 2799 if (IS_8251(com->pc98_if_type)) { 2800 switch (cmd) { 2801 case TIOCSBRK: 2802 com_send_break_on( com ); 2803 break; 2804 case TIOCCBRK: 2805 com_send_break_off( com ); 2806 break; 2807 case TIOCSDTR: 2808 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS ); 2809 break; 2810 case TIOCCDTR: 2811 com_tiocm_bic(com, TIOCM_DTR); 2812 break; 2813 /* 2814 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2815 * changes get undone on the next call to comparam(). 2816 */ 2817 case TIOCMSET: 2818 com_tiocm_set( com, *(int *)data ); 2819 break; 2820 case TIOCMBIS: 2821 com_tiocm_bis( com, *(int *)data ); 2822 break; 2823 case TIOCMBIC: 2824 com_tiocm_bic( com, *(int *)data ); 2825 break; 2826 case TIOCMGET: 2827 *(int *)data = com_tiocm_get(com); 2828 break; 2829 case TIOCMSDTRWAIT: 2830 /* must be root since the wait applies to following logins */ 2831 error = suser(p->p_ucred, &p->p_acflag); 2832 if (error != 0) { 2833 splx(s); 2834 return (error); 2835 } 2836 com->dtr_wait = *(int *)data * hz / 100; 2837 break; 2838 case TIOCMGDTRWAIT: 2839 *(int *)data = com->dtr_wait * 100 / hz; 2840 break; 2841 case TIOCTIMESTAMP: 2842 com->do_timestamp = TRUE; 2843 *(struct timeval *)data = com->timestamp; 2844 break; 2845 case TIOCDCDTIMESTAMP: 2846 com->do_dcd_timestamp = TRUE; 2847 *(struct timeval *)data = com->dcd_timestamp; 2848 break; 2849 default: 2850 splx(s); 2851 return (ENOTTY); 2852 } 2853 } else { 2854 int port_shift; 2855 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 2856#endif 2857 switch (cmd) { 2858 case TIOCSBRK: 2859#ifdef PC98 2860 outb(iobase + (com_cfcr << port_shift), 2861 com->cfcr_image |= CFCR_SBREAK); 2862#else 2863 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 2864#endif 2865 break; 2866 case TIOCCBRK: 2867#ifdef PC98 2868 outb(iobase + (com_cfcr << port_shift), 2869 com->cfcr_image &= ~CFCR_SBREAK); 2870#else 2871 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 2872#endif 2873 break; 2874 case TIOCSDTR: 2875 (void)commctl(com, TIOCM_DTR, DMBIS); 2876 break; 2877 case TIOCCDTR: 2878 (void)commctl(com, TIOCM_DTR, DMBIC); 2879 break; 2880 /* 2881 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 2882 * changes get undone on the next call to comparam(). 2883 */ 2884 case TIOCMSET: 2885 (void)commctl(com, *(int *)data, DMSET); 2886 break; 2887 case TIOCMBIS: 2888 (void)commctl(com, *(int *)data, DMBIS); 2889 break; 2890 case TIOCMBIC: 2891 (void)commctl(com, *(int *)data, DMBIC); 2892 break; 2893 case TIOCMGET: 2894 *(int *)data = commctl(com, 0, DMGET); 2895 break; 2896 case TIOCMSDTRWAIT: 2897 /* must be root since the wait applies to following logins */ 2898 error = suser(p->p_ucred, &p->p_acflag); 2899 if (error != 0) { 2900 splx(s); 2901 return (error); 2902 } 2903 com->dtr_wait = *(int *)data * hz / 100; 2904 break; 2905 case TIOCMGDTRWAIT: 2906 *(int *)data = com->dtr_wait * 100 / hz; 2907 break; 2908 case TIOCTIMESTAMP: 2909 com->do_timestamp = TRUE; 2910 *(struct timeval *)data = com->timestamp; 2911 break; 2912 case TIOCDCDTIMESTAMP: 2913 com->do_dcd_timestamp = TRUE; 2914 *(struct timeval *)data = com->dcd_timestamp; 2915 break; 2916 default: 2917 splx(s); 2918 return (ENOTTY); 2919 } 2920#ifdef PC98 2921 } 2922#endif 2923 splx(s); 2924 return (0); 2925} 2926 2927static void 2928siopoll() 2929{ 2930 int unit; 2931 2932 if (com_events == 0) 2933 return; 2934repeat: 2935 for (unit = 0; unit < NSIOTOT; ++unit) { 2936 u_char *buf; 2937 struct com_s *com; 2938 u_char *ibuf; 2939 int incc; 2940 struct tty *tp; 2941#ifdef PC98 2942 int tmp; 2943#endif 2944 2945 com = com_addr(unit); 2946 if (com == NULL) 2947 continue; 2948 tp = com->tp; 2949 if (tp == NULL || com->gone) { 2950 /* 2951 * Discard any events related to never-opened or 2952 * going-away devices. 2953 */ 2954 disable_intr(); 2955 incc = com->iptr - com->ibuf; 2956 com->iptr = com->ibuf; 2957 if (com->state & CS_CHECKMSR) { 2958 incc += LOTS_OF_EVENTS; 2959 com->state &= ~CS_CHECKMSR; 2960 } 2961 com_events -= incc; 2962 enable_intr(); 2963 continue; 2964 } 2965 2966 /* switch the role of the low-level input buffers */ 2967 if (com->iptr == (ibuf = com->ibuf)) { 2968 buf = NULL; /* not used, but compiler can't tell */ 2969 incc = 0; 2970 } else { 2971 buf = ibuf; 2972 disable_intr(); 2973 incc = com->iptr - buf; 2974 com_events -= incc; 2975 if (ibuf == com->ibuf1) 2976 ibuf = com->ibuf2; 2977 else 2978 ibuf = com->ibuf1; 2979#ifndef PC98 2980 com->ibufend = ibuf + RS_IBUFSIZE; 2981 com->ihighwater = ibuf + RS_IHIGHWATER; 2982#else 2983 com->ibufend = ibuf + com->CE_INPUT_OFFSET; 2984 com->ihighwater = ibuf + (3 * com->CE_INPUT_OFFSET / 4); 2985#endif 2986 com->iptr = ibuf; 2987 2988 /* 2989 * There is now room for another low-level buffer full 2990 * of input, so enable RTS if it is now disabled and 2991 * there is room in the high-level buffer. 2992 */ 2993#ifdef PC98 2994 if (IS_8251(com->pc98_if_type)) 2995 tmp = com_tiocm_get(com) & TIOCM_RTS; 2996 else 2997 tmp = com->mcr_image & MCR_RTS; 2998#endif 2999 if ((com->state & CS_RTS_IFLOW) 3000#ifdef PC98 3001 && !(tmp) 3002#else 3003 && !(com->mcr_image & MCR_RTS) 3004#endif 3005 && !(tp->t_state & TS_TBLOCK)) 3006#ifdef PC98 3007 if (IS_8251(com->pc98_if_type)) 3008 com_tiocm_bis(com, TIOCM_RTS); 3009 else 3010#endif 3011 outb(com->modem_ctl_port, 3012 com->mcr_image |= MCR_RTS); 3013 enable_intr(); 3014 com->ibuf = ibuf; 3015 } 3016 3017 if (com->state & CS_CHECKMSR) { 3018 u_char delta_modem_status; 3019 3020#ifdef PC98 3021 if (!IS_8251(com->pc98_if_type)) { 3022#endif 3023 disable_intr(); 3024 delta_modem_status = com->last_modem_status 3025 ^ com->prev_modem_status; 3026 com->prev_modem_status = com->last_modem_status; 3027 com_events -= LOTS_OF_EVENTS; 3028 com->state &= ~CS_CHECKMSR; 3029 enable_intr(); 3030 if (delta_modem_status & MSR_DCD) 3031 (*linesw[tp->t_line].l_modem) 3032 (tp, com->prev_modem_status & MSR_DCD); 3033#ifdef PC98 3034 } 3035#endif 3036 } 3037 if (com->state & CS_ODONE) { 3038 disable_intr(); 3039 com_events -= LOTS_OF_EVENTS; 3040 com->state &= ~CS_ODONE; 3041 enable_intr(); 3042 if (!(com->state & CS_BUSY) 3043 && !(com->extra_state & CSE_BUSYCHECK)) { 3044 timeout(siobusycheck, com, hz / 100); 3045 com->extra_state |= CSE_BUSYCHECK; 3046 } 3047 (*linesw[tp->t_line].l_start)(tp); 3048 } 3049 if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || 3050 !(tp->t_cflag & CREAD)) 3051 continue; 3052 /* 3053 * Avoid the grotesquely inefficient lineswitch routine 3054 * (ttyinput) in "raw" mode. It usually takes about 450 3055 * instructions (that's without canonical processing or echo!). 3056 * slinput is reasonably fast (usually 40 instructions plus 3057 * call overhead). 3058 */ 3059 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 3060 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 3061 && (com->state & CS_RTS_IFLOW 3062 || tp->t_iflag & IXOFF) 3063 && !(tp->t_state & TS_TBLOCK)) 3064 ttyblock(tp); 3065 tk_nin += incc; 3066 tk_rawcc += incc; 3067 tp->t_rawcc += incc; 3068 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 3069 += b_to_q((char *)buf, incc, &tp->t_rawq); 3070 ttwakeup(tp); 3071 if (tp->t_state & TS_TTSTOP 3072 && (tp->t_iflag & IXANY 3073 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 3074 tp->t_state &= ~TS_TTSTOP; 3075 tp->t_lflag &= ~FLUSHO; 3076 comstart(tp); 3077 } 3078 } else { 3079 do { 3080 u_char line_status; 3081 int recv_data; 3082 3083#ifndef PC98 3084 line_status = (u_char) buf[CE_INPUT_OFFSET]; 3085#else 3086 line_status = (u_char) buf[com->CE_INPUT_OFFSET]; 3087#endif 3088 recv_data = (u_char) *buf++; 3089 if (line_status 3090 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 3091 if (line_status & LSR_BI) 3092 recv_data |= TTY_BI; 3093 if (line_status & LSR_FE) 3094 recv_data |= TTY_FE; 3095 if (line_status & LSR_OE) 3096 recv_data |= TTY_OE; 3097 if (line_status & LSR_PE) 3098 recv_data |= TTY_PE; 3099 } 3100 (*linesw[tp->t_line].l_rint)(recv_data, tp); 3101 } while (--incc > 0); 3102 } 3103 if (com_events == 0) 3104 break; 3105 } 3106 if (com_events >= LOTS_OF_EVENTS) 3107 goto repeat; 3108} 3109 3110static int 3111comparam(tp, t) 3112 struct tty *tp; 3113 struct termios *t; 3114{ 3115 u_int cfcr; 3116 int cflag; 3117 struct com_s *com; 3118 int divisor; 3119 u_char dlbh; 3120 u_char dlbl; 3121 Port_t iobase; 3122 int s; 3123 int unit; 3124#ifdef PC98 3125 Port_t tmp_port; 3126 int tmp_flg; 3127 int port_shift = 0; 3128 u_char param = 0; 3129#endif 3130 3131#ifdef PC98 3132 cfcr = 0; 3133 unit = DEV_TO_UNIT(tp->t_dev); 3134 com = com_addr(unit); 3135 iobase = com->iobase; 3136 if (IS_8251(com->pc98_if_type)) { 3137 divisor = pc98_ttspeedtab(com, t->c_ospeed); 3138 } else { 3139 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 3140 3141 /* do historical conversions */ 3142 if (t->c_ispeed == 0) 3143 t->c_ispeed = t->c_ospeed; 3144 3145 /* check requested parameters */ 3146 divisor = ttspeedtab(t->c_ospeed, 3147 if_16550a_type[com->pc98_if_type & 0x0f].speedtab); 3148 } 3149#else 3150 /* do historical conversions */ 3151 if (t->c_ispeed == 0) 3152 t->c_ispeed = t->c_ospeed; 3153 3154 /* check requested parameters */ 3155 divisor = ttspeedtab(t->c_ospeed, comspeedtab); 3156#endif 3157 if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed) 3158 return (EINVAL); 3159 3160 /* parameters are OK, convert them to the com struct and the device */ 3161#ifndef PC98 3162 unit = DEV_TO_UNIT(tp->t_dev); 3163 com = com_addr(unit); 3164 iobase = com->iobase; 3165#endif 3166 s = spltty(); 3167#ifdef PC98 3168 if (IS_8251(com->pc98_if_type)) { 3169 if (divisor == 0) 3170 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3171 else 3172 com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE ); 3173 } else { 3174#endif 3175 if (divisor == 0) 3176 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 3177 else 3178 (void)commctl(com, TIOCM_DTR, DMBIS); 3179#ifdef PC98 3180 } 3181#endif 3182 cflag = t->c_cflag; 3183#ifdef PC98 3184 if (!IS_8251(com->pc98_if_type)) { 3185#endif 3186 switch (cflag & CSIZE) { 3187 case CS5: 3188 cfcr = CFCR_5BITS; 3189 break; 3190 case CS6: 3191 cfcr = CFCR_6BITS; 3192 break; 3193 case CS7: 3194 cfcr = CFCR_7BITS; 3195 break; 3196 default: 3197 cfcr = CFCR_8BITS; 3198 break; 3199 } 3200 if (cflag & PARENB) { 3201 cfcr |= CFCR_PENAB; 3202 if (!(cflag & PARODD)) 3203 cfcr |= CFCR_PEVEN; 3204 } 3205 if (cflag & CSTOPB) 3206 cfcr |= CFCR_STOPB; 3207 3208 if (com->hasfifo && divisor != 0) { 3209 /* 3210 * Use a fifo trigger level low enough so that the input 3211 * latency from the fifo is less than about 16 msec and 3212 * the total latency is less than about 30 msec. These 3213 * latencies are reasonable for humans. Serial comms 3214 * protocols shouldn't expect anything better since modem 3215 * latencies are larger. 3216 */ 3217 com->fifo_image = t->c_ospeed <= 4800 3218 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; 3219#ifdef COM_ESP 3220 /* 3221 * The Hayes ESP card needs the fifo DMA mode bit set 3222 * in compatibility mode. If not, it will interrupt 3223 * for each character received. 3224 */ 3225 if (com->esp) 3226 com->fifo_image |= FIFO_DMA_MODE; 3227#endif 3228#ifdef PC98 3229 outb(iobase + (com_fifo << port_shift), com->fifo_image); 3230#else 3231 outb(iobase + com_fifo, com->fifo_image); 3232#endif 3233 } 3234#ifdef PC98 3235 } 3236#endif 3237 3238 disable_intr(); /* very important while com_data is hidden */ 3239 3240#ifdef PC98 3241 if (IS_8251(com->pc98_if_type)) 3242 com_cflag_and_speed_set(com, cflag, t->c_ospeed); 3243 else { 3244#endif 3245 if (divisor != 0) { 3246#ifdef PC98 3247 outb(iobase + (com_cfcr << port_shift), cfcr | CFCR_DLAB); 3248#else 3249 outb(iobase + com_cfcr, cfcr | CFCR_DLAB); 3250#endif 3251 /* 3252 * Only set the divisor registers if they would change, 3253 * since on some 16550 incompatibles (UMC8669F), setting 3254 * them while input is arriving them loses sync until 3255 * data stops arriving. 3256 */ 3257 dlbl = divisor & 0xFF; 3258#ifdef PC98 3259 if (inb(iobase + (com_dlbl << port_shift)) != dlbl) 3260 outb(iobase + (com_dlbl << port_shift), dlbl); 3261 dlbh = (u_int) divisor >> 8; 3262 if (inb(iobase + (com_dlbh << port_shift)) != dlbh) 3263 outb(iobase + (com_dlbh << port_shift), dlbh); 3264#else 3265 if (inb(iobase + com_dlbl) != dlbl) 3266 outb(iobase + com_dlbl, dlbl); 3267 dlbh = (u_int) divisor >> 8; 3268 if (inb(iobase + com_dlbh) != dlbh) 3269 outb(iobase + com_dlbh, dlbh); 3270#endif 3271 } 3272 3273 3274#ifdef PC98 3275 } 3276 outb(iobase + (com_cfcr << port_shift), com->cfcr_image = cfcr); 3277#else 3278 outb(iobase + com_cfcr, com->cfcr_image = cfcr); 3279#endif 3280 3281 if (!(tp->t_state & TS_TTSTOP)) 3282 com->state |= CS_TTGO; 3283 3284 if (cflag & CRTS_IFLOW) { 3285 if (com->st16650a) { 3286 outb(iobase + com_cfcr, 0xbf); 3287 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40); 3288 } 3289 com->state |= CS_RTS_IFLOW; 3290 /* 3291 * If CS_RTS_IFLOW just changed from off to on, the change 3292 * needs to be propagated to MCR_RTS. This isn't urgent, 3293 * so do it later by calling comstart() instead of repeating 3294 * a lot of code from comstart() here. 3295 */ 3296 } else if (com->state & CS_RTS_IFLOW) { 3297 com->state &= ~CS_RTS_IFLOW; 3298 /* 3299 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 3300 * on here, since comstart() won't do it later. 3301 */ 3302#ifdef PC98 3303 if (IS_8251(com->pc98_if_type)) 3304 com_tiocm_bis(com, TIOCM_RTS); 3305 else 3306#endif 3307 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3308 if (com->st16650a) { 3309 outb(iobase + com_cfcr, 0xbf); 3310 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40); 3311 } 3312 } 3313 3314 3315 /* 3316 * Set up state to handle output flow control. 3317 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 3318 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 3319 */ 3320 com->state |= CS_ODEVREADY; 3321 com->state &= ~CS_CTS_OFLOW; 3322#ifdef PC98 3323 if (com->pc98_if_type == COM_IF_RSA98III) { 3324 param = inb(com->rsabase + rsa_msr); 3325 outb(com->rsabase + rsa_msr, param & 0x14); 3326 } 3327#endif 3328 if (cflag & CCTS_OFLOW) { 3329 com->state |= CS_CTS_OFLOW; 3330#ifdef PC98 3331 if (IS_8251(com->pc98_if_type)) { 3332 if (!(pc98_get_modem_status(com) & TIOCM_CTS)) 3333 com->state &= ~CS_ODEVREADY; 3334 } else { 3335#endif 3336#ifdef PC98 3337 if (com->pc98_if_type == COM_IF_RSA98III) { 3338 /* Set automatic flow control mode */ 3339 outb(com->rsabase + rsa_msr, param | 0x08); 3340 } else 3341#endif 3342 if (!(com->last_modem_status & MSR_CTS)) 3343 com->state &= ~CS_ODEVREADY; 3344 if (com->st16650a) { 3345 outb(iobase + com_cfcr, 0xbf); 3346 outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80); 3347 } 3348#ifdef PC98 3349 } 3350#endif 3351 } else { 3352 if (com->st16650a) { 3353 outb(iobase + com_cfcr, 0xbf); 3354 outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80); 3355 } 3356 } 3357 3358 3359#ifdef PC98 3360 outb(iobase + (com_cfcr << port_shift), com->cfcr_image); 3361#else 3362 outb(iobase + com_cfcr, com->cfcr_image); 3363#endif 3364 3365 3366 /* XXX shouldn't call functions while intrs are disabled. */ 3367 disc_optim(tp, t, com); 3368 /* 3369 * Recover from fiddling with CS_TTGO. We used to call siointr1() 3370 * unconditionally, but that defeated the careful discarding of 3371 * stale input in sioopen(). 3372 */ 3373 if (com->state >= (CS_BUSY | CS_TTGO)) 3374 siointr1(com); 3375 3376 enable_intr(); 3377 splx(s); 3378 comstart(tp); 3379 return (0); 3380} 3381 3382static void 3383comstart(tp) 3384 struct tty *tp; 3385{ 3386 struct com_s *com; 3387 int s; 3388 int unit; 3389#ifdef PC98 3390 int tmp; 3391#endif 3392 3393 unit = DEV_TO_UNIT(tp->t_dev); 3394 com = com_addr(unit); 3395 s = spltty(); 3396 disable_intr(); 3397 if (tp->t_state & TS_TTSTOP) 3398 com->state &= ~CS_TTGO; 3399 else 3400 com->state |= CS_TTGO; 3401 if (tp->t_state & TS_TBLOCK) { 3402#ifdef PC98 3403 if (IS_8251(com->pc98_if_type)) 3404 tmp = com_tiocm_get(com) & TIOCM_RTS; 3405 else 3406 tmp = com->mcr_image & MCR_RTS; 3407 if (tmp && (com->state & CS_RTS_IFLOW)) 3408#else 3409 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) 3410#endif 3411#ifdef PC98 3412 if (IS_8251(com->pc98_if_type)) 3413 com_tiocm_bic(com, TIOCM_RTS); 3414 else 3415#endif 3416 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 3417 } else { 3418#ifdef PC98 3419 if (IS_8251(com->pc98_if_type)) 3420 tmp = com_tiocm_get(com) & TIOCM_RTS; 3421 else 3422 tmp = com->mcr_image & MCR_RTS; 3423 if (!(tmp) && com->iptr < com->ihighwater 3424 && com->state & CS_RTS_IFLOW) 3425#else 3426 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater 3427 && com->state & CS_RTS_IFLOW) 3428#endif 3429#ifdef PC98 3430 if (IS_8251(com->pc98_if_type)) 3431 com_tiocm_bis(com, TIOCM_RTS); 3432 else 3433#endif 3434 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 3435 } 3436 enable_intr(); 3437 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 3438 ttwwakeup(tp); 3439#ifdef PC98 3440/* if(IS_8251(com->pc98_if_type)) 3441 com_int_Tx_enable(com); */ 3442#endif 3443 splx(s); 3444 return; 3445 } 3446 if (tp->t_outq.c_cc != 0) { 3447 struct lbq *qp; 3448 struct lbq *next; 3449 3450 if (!com->obufs[0].l_queued) { 3451 com->obufs[0].l_tail 3452 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 3453#ifndef PC98 3454 sizeof com->obuf1); 3455#else 3456 com->CE_INPUT_OFFSET); 3457#endif 3458 com->obufs[0].l_next = NULL; 3459 com->obufs[0].l_queued = TRUE; 3460 disable_intr(); 3461 if (com->state & CS_BUSY) { 3462 qp = com->obufq.l_next; 3463 while ((next = qp->l_next) != NULL) 3464 qp = next; 3465 qp->l_next = &com->obufs[0]; 3466 } else { 3467 com->obufq.l_head = com->obufs[0].l_head; 3468 com->obufq.l_tail = com->obufs[0].l_tail; 3469 com->obufq.l_next = &com->obufs[0]; 3470 com->state |= CS_BUSY; 3471 } 3472 enable_intr(); 3473 } 3474 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 3475 com->obufs[1].l_tail 3476 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 3477#ifndef PC98 3478 sizeof com->obuf2); 3479#else 3480 com->CE_INPUT_OFFSET); 3481#endif 3482 com->obufs[1].l_next = NULL; 3483 com->obufs[1].l_queued = TRUE; 3484 disable_intr(); 3485 if (com->state & CS_BUSY) { 3486 qp = com->obufq.l_next; 3487 while ((next = qp->l_next) != NULL) 3488 qp = next; 3489 qp->l_next = &com->obufs[1]; 3490 } else { 3491 com->obufq.l_head = com->obufs[1].l_head; 3492 com->obufq.l_tail = com->obufs[1].l_tail; 3493 com->obufq.l_next = &com->obufs[1]; 3494 com->state |= CS_BUSY; 3495 } 3496 enable_intr(); 3497 } 3498 tp->t_state |= TS_BUSY; 3499 } 3500 disable_intr(); 3501 if (com->state >= (CS_BUSY | CS_TTGO)) 3502 siointr1(com); /* fake interrupt to start output */ 3503 enable_intr(); 3504#ifdef PC98 3505/* if(IS_8251(com->pc98_if_type)) 3506 com_int_Tx_enable(com); */ 3507#endif 3508 ttwwakeup(tp); 3509 splx(s); 3510} 3511 3512static void 3513siostop(tp, rw) 3514 struct tty *tp; 3515 int rw; 3516{ 3517 struct com_s *com; 3518#ifdef PC98 3519 int port_shift = 0; 3520 int rsa98_tmp = 0; 3521#endif 3522 3523 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 3524 if (com->gone) 3525 return; 3526#ifdef PC98 3527 if (IS_8251(com->pc98_if_type)) 3528 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift; 3529#endif 3530 disable_intr(); 3531 if (rw & FWRITE) { 3532 if (com->hasfifo) 3533#ifdef COM_ESP 3534 /* XXX avoid h/w bug. */ 3535 if (!com->esp) 3536#endif 3537#ifdef PC98 3538 outb(com->iobase + (com_fifo << port_shift), 3539 FIFO_XMT_RST | com->fifo_image); 3540 if (com->pc98_if_type == COM_IF_RSA98III) 3541 for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) 3542 outb(com->iobase + (com_fifo << port_shift), 3543 FIFO_XMT_RST | com->fifo_image); 3544#else 3545 outb(com->iobase + com_fifo, 3546 FIFO_XMT_RST | com->fifo_image); 3547#endif 3548 com->obufs[0].l_queued = FALSE; 3549 com->obufs[1].l_queued = FALSE; 3550 if (com->state & CS_ODONE) 3551 com_events -= LOTS_OF_EVENTS; 3552 com->state &= ~(CS_ODONE | CS_BUSY); 3553 com->tp->t_state &= ~TS_BUSY; 3554 } 3555 if (rw & FREAD) { 3556 if (com->hasfifo) 3557#ifdef COM_ESP 3558 /* XXX avoid h/w bug. */ 3559 if (!com->esp) 3560#endif 3561#ifdef PC98 3562 if (com->pc98_if_type == COM_IF_RSA98III) { 3563 for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++) 3564 inb(com->data_port); 3565 } 3566 outb(com->iobase + (com_fifo << port_shift), 3567 FIFO_RCV_RST | com->fifo_image); 3568#else 3569 outb(com->iobase + com_fifo, 3570 FIFO_RCV_RST | com->fifo_image); 3571#endif 3572 com_events -= (com->iptr - com->ibuf); 3573 com->iptr = com->ibuf; 3574 } 3575 enable_intr(); 3576 comstart(tp); 3577} 3578 3579static struct tty * 3580siodevtotty(dev) 3581 dev_t dev; 3582{ 3583 int mynor; 3584 int unit; 3585 3586 mynor = minor(dev); 3587 if (mynor & CONTROL_MASK) 3588 return (NULL); 3589 unit = MINOR_TO_UNIT(mynor); 3590 if ((u_int) unit >= NSIOTOT) 3591 return (NULL); 3592 return (&sio_tty[unit]); 3593} 3594 3595static int 3596commctl(com, bits, how) 3597 struct com_s *com; 3598 int bits; 3599 int how; 3600{ 3601 int mcr; 3602 int msr; 3603 3604 if (how == DMGET) { 3605 bits = TIOCM_LE; /* XXX - always enabled while open */ 3606 mcr = com->mcr_image; 3607 if (mcr & MCR_DTR) 3608 bits |= TIOCM_DTR; 3609 if (mcr & MCR_RTS) 3610 bits |= TIOCM_RTS; 3611 msr = com->prev_modem_status; 3612 if (msr & MSR_CTS) 3613 bits |= TIOCM_CTS; 3614 if (msr & MSR_DCD) 3615 bits |= TIOCM_CD; 3616 if (msr & MSR_DSR) 3617 bits |= TIOCM_DSR; 3618 /* 3619 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI 3620 * more volatile by reading the modem status a lot. Perhaps 3621 * we should latch both bits until the status is read here. 3622 */ 3623 if (msr & (MSR_RI | MSR_TERI)) 3624 bits |= TIOCM_RI; 3625 return (bits); 3626 } 3627 mcr = 0; 3628 if (bits & TIOCM_DTR) 3629 mcr |= MCR_DTR; 3630 if (bits & TIOCM_RTS) 3631 mcr |= MCR_RTS; 3632 if (com->gone) 3633 return(0); 3634 disable_intr(); 3635 switch (how) { 3636 case DMSET: 3637 outb(com->modem_ctl_port, 3638 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); 3639 break; 3640 case DMBIS: 3641 outb(com->modem_ctl_port, com->mcr_image |= mcr); 3642 break; 3643 case DMBIC: 3644 outb(com->modem_ctl_port, com->mcr_image &= ~mcr); 3645 break; 3646 } 3647 enable_intr(); 3648 return (0); 3649} 3650 3651static void 3652siosettimeout() 3653{ 3654 struct com_s *com; 3655 bool_t someopen; 3656 int unit; 3657 3658 /* 3659 * Set our timeout period to 1 second if no polled devices are open. 3660 * Otherwise set it to max(1/200, 1/hz). 3661 * Enable timeouts iff some device is open. 3662 */ 3663 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3664 sio_timeout = hz; 3665 someopen = FALSE; 3666 for (unit = 0; unit < NSIOTOT; ++unit) { 3667 com = com_addr(unit); 3668 if (com != NULL && com->tp != NULL 3669 && com->tp->t_state & TS_ISOPEN && !com->gone) { 3670 someopen = TRUE; 3671 if (com->poll || com->poll_output) { 3672 sio_timeout = hz > 200 ? hz / 200 : 1; 3673 break; 3674 } 3675 } 3676 } 3677 if (someopen) { 3678 sio_timeouts_until_log = hz / sio_timeout; 3679 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 3680 sio_timeout); 3681 } else { 3682 /* Flush error messages, if any. */ 3683 sio_timeouts_until_log = 1; 3684 comwakeup((void *)NULL); 3685 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 3686 } 3687} 3688 3689static void 3690comwakeup(chan) 3691 void *chan; 3692{ 3693 struct com_s *com; 3694 int unit; 3695 3696 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 3697 3698 /* 3699 * Recover from lost output interrupts. 3700 * Poll any lines that don't use interrupts. 3701 */ 3702 for (unit = 0; unit < NSIOTOT; ++unit) { 3703 com = com_addr(unit); 3704 if (com != NULL && !com->gone 3705 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 3706 disable_intr(); 3707 siointr1(com); 3708 enable_intr(); 3709 } 3710 } 3711 3712 /* 3713 * Check for and log errors, but not too often. 3714 */ 3715 if (--sio_timeouts_until_log > 0) 3716 return; 3717 sio_timeouts_until_log = hz / sio_timeout; 3718 for (unit = 0; unit < NSIOTOT; ++unit) { 3719 int errnum; 3720 3721 com = com_addr(unit); 3722 if (com == NULL) 3723 continue; 3724 if (com->gone) 3725 continue; 3726 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 3727 u_int delta; 3728 u_long total; 3729 3730 disable_intr(); 3731 delta = com->delta_error_counts[errnum]; 3732 com->delta_error_counts[errnum] = 0; 3733 enable_intr(); 3734 if (delta == 0) 3735 continue; 3736 total = com->error_counts[errnum] += delta; 3737 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n", 3738 unit, delta, error_desc[errnum], 3739 delta == 1 ? "" : "s", total); 3740 } 3741 } 3742} 3743 3744#ifdef PC98 3745/* commint is called when modem control line changes */ 3746static void 3747commint(dev_t dev) 3748{ 3749 register struct tty *tp; 3750 int stat,delta; 3751 struct com_s *com; 3752 int mynor,unit; 3753 3754 mynor = minor(dev); 3755 unit = MINOR_TO_UNIT(mynor); 3756 com = com_addr(unit); 3757 tp = com->tp; 3758 3759 stat = com_tiocm_get(com); 3760 delta = com_tiocm_get_delta(com); 3761 3762 if (com->state & CS_CTS_OFLOW) { 3763 if (stat & TIOCM_CTS) 3764 com->state |= CS_ODEVREADY; 3765 else 3766 com->state &= ~CS_ODEVREADY; 3767 } 3768 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) { 3769 if (stat & TIOCM_CAR ) 3770 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 3771 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 3772 /* negate DTR, RTS */ 3773 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ? 3774 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE ); 3775 /* disable IENABLE */ 3776 com_int_TxRx_disable( com ); 3777 } 3778 } 3779} 3780#endif 3781 3782static void 3783disc_optim(tp, t, com) 3784 struct tty *tp; 3785 struct termios *t; 3786 struct com_s *com; 3787{ 3788 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 3789 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 3790 && (!(t->c_iflag & PARMRK) 3791 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 3792 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 3793 && linesw[tp->t_line].l_rint == ttyinput) 3794 tp->t_state |= TS_CAN_BYPASS_L_RINT; 3795 else 3796 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 3797 com->hotchar = linesw[tp->t_line].l_hotchar; 3798} 3799 3800/* 3801 * Following are all routines needed for SIO to act as console 3802 */ 3803#include <machine/cons.h> 3804 3805struct siocnstate { 3806 u_char dlbl; 3807 u_char dlbh; 3808 u_char ier; 3809 u_char cfcr; 3810 u_char mcr; 3811}; 3812 3813static speed_t siocngetspeed __P((Port_t, struct speedtab *)); 3814static void siocnclose __P((struct siocnstate *sp)); 3815static void siocnopen __P((struct siocnstate *sp)); 3816static void siocntxwait __P((void)); 3817 3818/* 3819 * XXX: sciocnget() and sciocnputc() are not declared static, as they are 3820 * referred to from i386/i386/i386-gdbstub.c. 3821 */ 3822static cn_probe_t siocnprobe; 3823static cn_init_t siocninit; 3824static cn_checkc_t siocncheckc; 3825 cn_getc_t siocngetc; 3826 cn_putc_t siocnputc; 3827 3828CONS_DRIVER(sio, siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc); 3829 3830static void 3831siocntxwait() 3832{ 3833 int timo; 3834 3835 /* 3836 * Wait for any pending transmission to finish. Required to avoid 3837 * the UART lockup bug when the speed is changed, and for normal 3838 * transmits. 3839 */ 3840 timo = 100000; 3841 while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) 3842 != (LSR_TSRE | LSR_TXRDY) && --timo != 0) 3843 ; 3844} 3845 3846/* 3847 * Read the serial port specified and try to figure out what speed 3848 * it's currently running at. We're assuming the serial port has 3849 * been initialized and is basicly idle. This routine is only intended 3850 * to be run at system startup. 3851 * 3852 * If the value read from the serial port doesn't make sense, return 0. 3853 */ 3854 3855static speed_t 3856siocngetspeed(iobase, table) 3857 Port_t iobase; 3858 struct speedtab *table; 3859{ 3860 int code; 3861 u_char dlbh; 3862 u_char dlbl; 3863 u_char cfcr; 3864 3865 cfcr = inb(iobase + com_cfcr); 3866 outb(iobase + com_cfcr, CFCR_DLAB | cfcr); 3867 3868 dlbl = inb(iobase + com_dlbl); 3869 dlbh = inb(iobase + com_dlbh); 3870 3871 outb(iobase + com_cfcr, cfcr); 3872 3873 code = dlbh << 8 | dlbl; 3874 3875 for ( ; table->sp_speed != -1; table++) 3876 if (table->sp_code == code) 3877 return (table->sp_speed); 3878 3879 return 0; /* didn't match anything sane */ 3880} 3881 3882static void 3883siocnopen(sp) 3884 struct siocnstate *sp; 3885{ 3886 int divisor; 3887 u_char dlbh; 3888 u_char dlbl; 3889 Port_t iobase; 3890 3891 /* 3892 * Save all the device control registers except the fifo register 3893 * and set our default ones (cs8 -parenb speed=comdefaultrate). 3894 * We can't save the fifo register since it is read-only. 3895 */ 3896 iobase = siocniobase; 3897 sp->ier = inb(iobase + com_ier); 3898 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ 3899 siocntxwait(); 3900 sp->cfcr = inb(iobase + com_cfcr); 3901 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3902 sp->dlbl = inb(iobase + com_dlbl); 3903 sp->dlbh = inb(iobase + com_dlbh); 3904 /* 3905 * Only set the divisor registers if they would change, since on 3906 * some 16550 incompatibles (Startech), setting them clears the 3907 * data input register. This also reduces the effects of the 3908 * UMC8669F bug. 3909 */ 3910 divisor = ttspeedtab(comdefaultrate, comspeedtab); 3911 dlbl = divisor & 0xFF; 3912 if (sp->dlbl != dlbl) 3913 outb(iobase + com_dlbl, dlbl); 3914 dlbh = (u_int) divisor >> 8; 3915 if (sp->dlbh != dlbh) 3916 outb(iobase + com_dlbh, dlbh); 3917 outb(iobase + com_cfcr, CFCR_8BITS); 3918 sp->mcr = inb(iobase + com_mcr); 3919 /* 3920 * We don't want interrupts, but must be careful not to "disable" 3921 * them by clearing the MCR_IENABLE bit, since that might cause 3922 * an interrupt by floating the IRQ line. 3923 */ 3924 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); 3925} 3926 3927static void 3928siocnclose(sp) 3929 struct siocnstate *sp; 3930{ 3931 Port_t iobase; 3932 3933 /* 3934 * Restore the device control registers. 3935 */ 3936 siocntxwait(); 3937 iobase = siocniobase; 3938 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); 3939 if (sp->dlbl != inb(iobase + com_dlbl)) 3940 outb(iobase + com_dlbl, sp->dlbl); 3941 if (sp->dlbh != inb(iobase + com_dlbh)) 3942 outb(iobase + com_dlbh, sp->dlbh); 3943 outb(iobase + com_cfcr, sp->cfcr); 3944 /* 3945 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. 3946 */ 3947 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); 3948 outb(iobase + com_ier, sp->ier); 3949} 3950 3951static void 3952siocnprobe(cp) 3953 struct consdev *cp; 3954{ 3955 speed_t boot_speed; 3956 u_char cfcr; 3957 struct isa_device *dvp; 3958 int s; 3959 struct siocnstate sp; 3960 3961 /* 3962 * Find our first enabled console, if any. If it is a high-level 3963 * console device, then initialize it and return successfully. 3964 * If it is a low-level console device, then initialize it and 3965 * return unsuccessfully. It must be initialized in both cases 3966 * for early use by console drivers and debuggers. Initializing 3967 * the hardware is not necessary in all cases, since the i/o 3968 * routines initialize it on the fly, but it is necessary if 3969 * input might arrive while the hardware is switched back to an 3970 * uninitialized state. We can't handle multiple console devices 3971 * yet because our low-level routines don't take a device arg. 3972 * We trust the user to set the console flags properly so that we 3973 * don't need to probe. 3974 */ 3975 cp->cn_pri = CN_DEAD; 3976 for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) 3977 if (dvp->id_driver == &siodriver && dvp->id_enabled 3978 && COM_CONSOLE(dvp)) { 3979 siocniobase = dvp->id_iobase; 3980 s = spltty(); 3981 if (boothowto & RB_SERIAL) { 3982 boot_speed = siocngetspeed(siocniobase, 3983 comspeedtab); 3984 if (boot_speed) 3985 comdefaultrate = boot_speed; 3986 } 3987 3988 /* 3989 * Initialize the divisor latch. We can't rely on 3990 * siocnopen() to do this the first time, since it 3991 * avoids writing to the latch if the latch appears 3992 * to have the correct value. Also, if we didn't 3993 * just read the speed from the hardware, then we 3994 * need to set the speed in hardware so that 3995 * switching it later is null. 3996 */ 3997 cfcr = inb(siocniobase + com_cfcr); 3998 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); 3999 outb(siocniobase + com_dlbl, 4000 COMBRD(comdefaultrate) & 0xff); 4001 outb(siocniobase + com_dlbh, 4002 (u_int) COMBRD(comdefaultrate) >> 8); 4003 outb(siocniobase + com_cfcr, cfcr); 4004 4005 siocnopen(&sp); 4006 splx(s); 4007 if (!COM_LLCONSOLE(dvp)) { 4008 cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); 4009 cp->cn_pri = COM_FORCECONSOLE(dvp) 4010 || boothowto & RB_SERIAL 4011 ? CN_REMOTE : CN_NORMAL; 4012 } 4013 break; 4014 } 4015} 4016 4017static void 4018siocninit(cp) 4019 struct consdev *cp; 4020{ 4021 comconsole = DEV_TO_UNIT(cp->cn_dev); 4022} 4023 4024static int 4025siocncheckc(dev) 4026 dev_t dev; 4027{ 4028 int c; 4029 Port_t iobase; 4030 int s; 4031 struct siocnstate sp; 4032 4033 iobase = siocniobase; 4034 s = spltty(); 4035 siocnopen(&sp); 4036 if (inb(iobase + com_lsr) & LSR_RXRDY) 4037 c = inb(iobase + com_data); 4038 else 4039 c = -1; 4040 siocnclose(&sp); 4041 splx(s); 4042 return (c); 4043} 4044 4045 4046int 4047siocngetc(dev) 4048 dev_t dev; 4049{ 4050 int c; 4051 Port_t iobase; 4052 int s; 4053 struct siocnstate sp; 4054 4055 iobase = siocniobase; 4056 s = spltty(); 4057 siocnopen(&sp); 4058 while (!(inb(iobase + com_lsr) & LSR_RXRDY)) 4059 ; 4060 c = inb(iobase + com_data); 4061 siocnclose(&sp); 4062 splx(s); 4063 return (c); 4064} 4065 4066void 4067siocnputc(dev, c) 4068 dev_t dev; 4069 int c; 4070{ 4071 int s; 4072 struct siocnstate sp; 4073 4074 s = spltty(); 4075 siocnopen(&sp); 4076 siocntxwait(); 4077 outb(siocniobase + com_data, c); 4078 siocnclose(&sp); 4079 splx(s); 4080} 4081 4082 4083/* 4084 * support PnP cards if we are using 'em 4085 */ 4086 4087#if NPNP > 0 4088 4089static pnpid_t siopnp_ids[] = { 4090 { 0x5015f435, "MOT1550"}, 4091 { 0x8113b04e, "Supra1381"}, 4092 { 0x9012b04e, "Supra1290"}, 4093 { 0x7121b04e, "SupraExpress 56i Sp"}, 4094 { 0x11007256, "USR0011"}, 4095 { 0x30207256, "USR2030"}, 4096 { 0x31307256, "USR3031"}, 4097 { 0 } 4098}; 4099 4100static char *siopnp_probe(u_long csn, u_long vend_id); 4101static void siopnp_attach(u_long csn, u_long vend_id, char *name, 4102 struct isa_device *dev); 4103static u_long nsiopnp = NSIO; 4104 4105static struct pnp_device siopnp = { 4106 "siopnp", 4107 siopnp_probe, 4108 siopnp_attach, 4109 &nsiopnp, 4110 &tty_imask 4111}; 4112DATA_SET (pnpdevice_set, siopnp); 4113 4114static char * 4115siopnp_probe(u_long csn, u_long vend_id) 4116{ 4117 pnpid_t *id; 4118 char *s = NULL; 4119 4120 for(id = siopnp_ids; id->vend_id != 0; id++) { 4121 if (vend_id == id->vend_id) { 4122 s = id->id_str; 4123 break; 4124 } 4125 } 4126 4127 if (s) { 4128 struct pnp_cinfo d; 4129 read_pnp_parms(&d, 0); 4130 if (d.enable == 0 || d.flags & 1) { 4131 printf("CSN %lu is disabled.\n", csn); 4132 return (NULL); 4133 } 4134 4135 } 4136 4137 return (s); 4138} 4139 4140static void 4141siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) 4142{ 4143 struct pnp_cinfo d; 4144 struct isa_device *dvp; 4145 4146 if (dev->id_unit >= NSIOTOT) 4147 return; 4148 4149 if (read_pnp_parms(&d, 0) == 0) { 4150 printf("failed to read pnp parms\n"); 4151 return; 4152 } 4153 4154 write_pnp_parms(&d, 0); 4155 4156 enable_pnp_card(); 4157 4158 dev->id_iobase = d.port[0]; 4159 dev->id_irq = (1 << d.irq[0]); 4160 dev->id_ointr = siointr; 4161 dev->id_ri_flags = RI_FAST; 4162 dev->id_drq = -1; 4163 4164 if (dev->id_driver == NULL) { 4165 dev->id_driver = &siodriver; 4166 dvp = find_isadev(isa_devtab_tty, &siodriver, 0); 4167 if (dvp != NULL) 4168 dev->id_id = dvp->id_id; 4169 } 4170 4171 if ((dev->id_alive = sioprobe(dev)) != 0) 4172 sioattach(dev); 4173 else 4174 printf("sio%d: probe failed\n", dev->id_unit); 4175} 4176#endif 4177 4178#ifdef PC98 4179/* 4180 * pc98 local function 4181 */ 4182 4183static void 4184com_tiocm_set(struct com_s *com, int msr) 4185{ 4186 int s; 4187 int tmp = 0; 4188 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS; 4189 4190 s=spltty(); 4191 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ) 4192 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4193 tmp |= (CMD8251_TxEN|CMD8251_RxEN); 4194 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4195 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4196 pc98_i8251_clear_or_cmd( com, mask, tmp ); 4197 splx(s); 4198} 4199 4200static void 4201com_tiocm_bis(struct com_s *com, int msr) 4202{ 4203 int s; 4204 int tmp = 0; 4205 4206 s=spltty(); 4207 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4208 tmp |= CMD8251_TxEN|CMD8251_RxEN; 4209 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4210 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4211 4212 pc98_i8251_or_cmd( com, tmp ); 4213 splx(s); 4214} 4215 4216static void 4217com_tiocm_bic(struct com_s *com, int msr) 4218{ 4219 int s; 4220 int tmp = msr; 4221 4222 s=spltty(); 4223 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) ); 4224 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR; 4225 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS; 4226 4227 pc98_i8251_clear_cmd( com, tmp ); 4228 splx(s); 4229} 4230 4231static int 4232com_tiocm_get(struct com_s *com) 4233{ 4234 return( com->pc98_prev_modem_status ); 4235} 4236 4237static int 4238com_tiocm_get_delta(struct com_s *com) 4239{ 4240 int tmp; 4241 4242 tmp = com->pc98_modem_delta; 4243 com->pc98_modem_delta = 0; 4244 return( tmp ); 4245} 4246 4247/* convert to TIOCM_?? ( ioctl.h ) */ 4248static int 4249pc98_get_modem_status(struct com_s *com) 4250{ 4251 int stat, stat2; 4252 register int msr; 4253 4254 stat = inb(com->sts_port); 4255 stat2 = inb(com->in_modem_port); 4256 msr = com->pc98_prev_modem_status 4257 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4258 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR; 4259 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI; 4260 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR; 4261 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS; 4262#if COM_CARRIER_DETECT_EMULATE 4263 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) { 4264 msr |= TIOCM_CAR; 4265 } 4266#endif 4267 return(msr); 4268} 4269 4270static void 4271pc98_check_msr(void* chan) 4272{ 4273 int msr, delta; 4274 int s; 4275 register struct tty *tp; 4276 struct com_s *com; 4277 int mynor; 4278 int unit; 4279 dev_t dev; 4280 4281 dev=(dev_t)chan; 4282 mynor = minor(dev); 4283 unit = MINOR_TO_UNIT(mynor); 4284 com = com_addr(unit); 4285 tp = com->tp; 4286 4287 s = spltty(); 4288 msr = pc98_get_modem_status(com); 4289 /* make change flag */ 4290 delta = msr ^ com->pc98_prev_modem_status; 4291 if ( delta & TIOCM_CAR ) { 4292 if ( com->modem_car_chg_timer ) { 4293 if ( -- com->modem_car_chg_timer ) 4294 msr ^= TIOCM_CAR; 4295 } else { 4296 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ? 4297 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE ) 4298 msr ^= TIOCM_CAR; 4299 } 4300 } else 4301 com->modem_car_chg_timer = 0; 4302 delta = ( msr ^ com->pc98_prev_modem_status ) & 4303 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS); 4304 com->pc98_prev_modem_status = msr; 4305 delta = ( com->pc98_modem_delta |= delta ); 4306 splx(s); 4307 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) { 4308 if ( delta ) { 4309 commint(dev); 4310 } 4311 timeout(pc98_check_msr, (caddr_t)dev, 4312 PC98_CHECK_MODEM_INTERVAL); 4313 } else { 4314 com->modem_checking = 0; 4315 } 4316} 4317 4318static void 4319pc98_msrint_start(dev_t dev) 4320{ 4321 struct com_s *com; 4322 int mynor; 4323 int unit; 4324 int s = spltty(); 4325 4326 mynor = minor(dev); 4327 unit = MINOR_TO_UNIT(mynor); 4328 com = com_addr(unit); 4329 /* modem control line check routine envoke interval is 1/10 sec */ 4330 if ( com->modem_checking == 0 ) { 4331 com->pc98_prev_modem_status = pc98_get_modem_status(com); 4332 com->pc98_modem_delta = 0; 4333 timeout(pc98_check_msr, (caddr_t)dev, 4334 PC98_CHECK_MODEM_INTERVAL); 4335 com->modem_checking = 1; 4336 } 4337 splx(s); 4338} 4339 4340static void 4341pc98_disable_i8251_interrupt(struct com_s *com, int mod) 4342{ 4343 /* disable interrupt */ 4344 register int tmp; 4345 4346 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4347 COM_INT_DISABLE 4348 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4349 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp ); 4350 COM_INT_ENABLE 4351} 4352 4353static void 4354pc98_enable_i8251_interrupt(struct com_s *com, int mod) 4355{ 4356 register int tmp; 4357 4358 COM_INT_DISABLE 4359 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx); 4360 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp ); 4361 COM_INT_ENABLE 4362} 4363 4364static int 4365pc98_check_i8251_interrupt(struct com_s *com) 4366{ 4367 return ( com->intr_enable & 0x07 ); 4368} 4369 4370static void 4371pc98_i8251_clear_cmd(struct com_s *com, int x) 4372{ 4373 int tmp; 4374 4375 COM_INT_DISABLE 4376 tmp = com->pc98_prev_siocmd & ~(x); 4377 outb(com->cmd_port, tmp); 4378 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4379 COM_INT_ENABLE 4380} 4381 4382static void 4383pc98_i8251_or_cmd(struct com_s *com, int x) 4384{ 4385 int tmp; 4386 4387 COM_INT_DISABLE 4388 tmp = com->pc98_prev_siocmd | (x); 4389 outb(com->cmd_port, tmp); 4390 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4391 COM_INT_ENABLE 4392} 4393 4394static void 4395pc98_i8251_set_cmd(struct com_s *com, int x) 4396{ 4397 int tmp; 4398 4399 COM_INT_DISABLE 4400 tmp = (x); 4401 outb(com->cmd_port, tmp); 4402 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4403 COM_INT_ENABLE 4404} 4405 4406static void 4407pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x) 4408{ 4409 int tmp; 4410 COM_INT_DISABLE 4411 tmp = com->pc98_prev_siocmd & ~(clr); 4412 tmp |= (x); 4413 outb(com->cmd_port, tmp); 4414 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH); 4415 COM_INT_ENABLE 4416} 4417 4418static int 4419pc98_i8251_get_cmd(struct com_s *com) 4420{ 4421 return com->pc98_prev_siocmd; 4422} 4423 4424static int 4425pc98_i8251_get_mod(struct com_s *com) 4426{ 4427 return com->pc98_prev_siomod; 4428} 4429 4430static void 4431pc98_i8251_reset(struct com_s *com, int mode, int command) 4432{ 4433 outb(com->cmd_port, 0); /* dummy */ 4434 DELAY(2); 4435 outb(com->cmd_port, 0); /* dummy */ 4436 DELAY(2); 4437 outb(com->cmd_port, 0); /* dummy */ 4438 DELAY(2); 4439 outb(com->cmd_port, CMD8251_RESET); /* internal reset */ 4440 DELAY(2); 4441 outb(com->cmd_port, mode ); /* mode register */ 4442 com->pc98_prev_siomod = mode; 4443 DELAY(2); 4444 pc98_i8251_set_cmd( com, (command|CMD8251_ER) ); 4445} 4446 4447static void 4448pc98_check_sysclock(void) 4449{ 4450 /* get system clock from port */ 4451 if ( pc98_machine_type & M_8M ) { 4452 /* 8 MHz system & H98 */ 4453 sysclock = 8; 4454 } else { 4455 /* 5 MHz system */ 4456 sysclock = 5; 4457 } 4458} 4459 4460static void 4461com_cflag_and_speed_set( struct com_s *com, int cflag, int speed) 4462{ 4463 int cfcr=0, count; 4464 int previnterrupt; 4465 4466 count = pc98_ttspeedtab( com, speed ); 4467 if ( count < 0 ) return; 4468 4469 previnterrupt = pc98_check_i8251_interrupt(com); 4470 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx ); 4471 4472 switch ( cflag&CSIZE ) { 4473 case CS5: 4474 cfcr = MOD8251_5BITS; break; 4475 case CS6: 4476 cfcr = MOD8251_6BITS; break; 4477 case CS7: 4478 cfcr = MOD8251_7BITS; break; 4479 case CS8: 4480 cfcr = MOD8251_8BITS; break; 4481 } 4482 if ( cflag&PARENB ) { 4483 if ( cflag&PARODD ) 4484 cfcr |= MOD8251_PODD; 4485 else 4486 cfcr |= MOD8251_PEVEN; 4487 } else 4488 cfcr |= MOD8251_PDISAB; 4489 4490 if ( cflag&CSTOPB ) 4491 cfcr |= MOD8251_STOP2; 4492 else 4493 cfcr |= MOD8251_STOP1; 4494 4495 if ( count & 0x10000 ) 4496 cfcr |= MOD8251_CLKX1; 4497 else 4498 cfcr |= MOD8251_CLKX16; 4499 4500 if (epson_machine_id != 0x20) { /* XXX */ 4501 int tmp; 4502 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP)) 4503 ; 4504 } 4505 /* set baud rate from ospeed */ 4506 pc98_set_baud_rate( com, count ); 4507 4508 if ( cfcr != pc98_i8251_get_mod(com) ) 4509 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) ); 4510 4511 pc98_enable_i8251_interrupt( com, previnterrupt ); 4512} 4513 4514static int 4515pc98_ttspeedtab(struct com_s *com, int speed) 4516{ 4517 int if_type, effect_sp, count = -1, mod; 4518 4519 if_type = com->pc98_if_type & 0x0f; 4520 4521 switch (com->pc98_if_type) { 4522 case COM_IF_INTERNAL: 4523 if (PC98SIO_baud_rate_port(if_type) != -1) { 4524 count = ttspeedtab(speed, if_8251_type[if_type].speedtab); 4525 if (count > 0) { 4526 count |= COM1_EXT_CLOCK; 4527 break; 4528 } 4529 } 4530 4531 /* for *1CLK asynchronous! mode, TEFUTEFU */ 4532 mod = (sysclock == 5) ? 2457600 : 1996800; 4533 effect_sp = ttspeedtab( speed, pc98speedtab ); 4534 if ( effect_sp < 0 ) /* XXX */ 4535 effect_sp = ttspeedtab( (speed - 1), pc98speedtab ); 4536 if ( effect_sp <= 0 ) 4537 return effect_sp; 4538 if ( effect_sp == speed ) 4539 mod /= 16; 4540 if ( mod % effect_sp ) 4541 return(-1); 4542 count = mod / effect_sp; 4543 if ( count > 65535 ) 4544 return(-1); 4545 if ( effect_sp != speed ) 4546 count |= 0x10000; 4547 break; 4548 case COM_IF_PC9861K_1: 4549 case COM_IF_PC9861K_2: 4550 count = 1; 4551 break; 4552 case COM_IF_IND_SS_1: 4553 case COM_IF_IND_SS_2: 4554 case COM_IF_PIO9032B_1: 4555 case COM_IF_PIO9032B_2: 4556 if ( speed == 0 ) return 0; 4557 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4558 break; 4559 case COM_IF_B98_01_1: 4560 case COM_IF_B98_01_2: 4561 if ( speed == 0 ) return 0; 4562 count = ttspeedtab( speed, if_8251_type[if_type].speedtab ); 4563#ifdef B98_01_OLD 4564 if (count == 0 || count == 1) { 4565 count += 4; 4566 count |= 0x20000; /* x1 mode for 76800 and 153600 */ 4567 } 4568#endif 4569 break; 4570 } 4571 4572 return count; 4573} 4574 4575static void 4576pc98_set_baud_rate( struct com_s *com, int count ) 4577{ 4578 int if_type, io, s; 4579 4580 if_type = com->pc98_if_type & 0x0f; 4581 io = com->iobase & 0xff00; 4582 4583 switch (com->pc98_if_type) { 4584 case COM_IF_INTERNAL: 4585 if (PC98SIO_baud_rate_port(if_type) != -1) { 4586 if (count & COM1_EXT_CLOCK) { 4587 outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff); 4588 break; 4589 } else { 4590 outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09); 4591 } 4592 } 4593 4594 if ( count < 0 ) { 4595 printf( "[ Illegal count : %d ]", count ); 4596 return; 4597 } else if ( count == 0 ) 4598 return; 4599 /* set i8253 */ 4600 s = splclock(); 4601 if (count != 3) 4602 outb( 0x77, 0xb6 ); 4603 else 4604 outb( 0x77, 0xb4 ); 4605 outb( 0x5f, 0); 4606 outb( 0x75, count & 0xff ); 4607 outb( 0x5f, 0); 4608 outb( 0x75, (count >> 8) & 0xff ); 4609 splx(s); 4610 break; 4611 case COM_IF_IND_SS_1: 4612 case COM_IF_IND_SS_2: 4613 outb(io | PC98SIO_intr_ctrl_port(if_type), 0); 4614 outb(io | PC98SIO_baud_rate_port(if_type), 0); 4615 outb(io | PC98SIO_baud_rate_port(if_type), 0xc0); 4616 outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80); 4617 outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff); 4618 break; 4619 case COM_IF_PIO9032B_1: 4620 case COM_IF_PIO9032B_2: 4621 outb(io | PC98SIO_baud_rate_port(if_type), count); 4622 break; 4623 case COM_IF_B98_01_1: 4624 case COM_IF_B98_01_2: 4625 outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f); 4626#ifdef B98_01_OLD 4627 /* 4628 * Some old B98_01 board should be controlled 4629 * in different way, but this hasn't been tested yet. 4630 */ 4631 outb(io | PC98SIO_func_port(if_type), 4632 (count & 0x20000) ? 0xf0 : 0xf2); 4633#endif 4634 break; 4635 } 4636} 4637static int 4638pc98_check_if_type(struct isa_device *dev, struct siodev *iod) 4639{ 4640 int irr, io, if_type, tmp; 4641 static short irq_tab[2][8] = { 4642 { 3, 5, 6, 9, 10, 12, 13, -1}, 4643 { 3, 10, 12, 13, 5, 6, 9, -1} 4644 }; 4645 4646 iod->if_type = if_type = (dev->id_flags >> 24) & 0xff; 4647 if ((if_type < 0 || if_type > COM_IF_END1) && 4648 (if_type < 0x10 || if_type > COM_IF_END2)) 4649 return(-1); 4650 if_type &= 0x0f; 4651 iod->irq = 0; 4652 io = dev->id_iobase & 0xff00; 4653 4654 if (IS_8251(iod->if_type)) { 4655 if (PC98SIO_func_port(if_type) != -1) { 4656 outb(io | PC98SIO_func_port(if_type), 0xf2); 4657 tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab); 4658 if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1) 4659 outb(io | PC98SIO_baud_rate_port(if_type), tmp); 4660 } 4661 4662 iod->cmd = io | PC98SIO_cmd_port(if_type); 4663 iod->sts = io | PC98SIO_sts_port(if_type); 4664 iod->mod = io | PC98SIO_in_modem_port(if_type); 4665 iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type); 4666 4667 if (iod->if_type == COM_IF_INTERNAL) { 4668 iod->irq = 4; 4669 4670 /* XXX check new internal port. */ 4671 outb(0x138, 0); 4672 DELAY(10); 4673 for (tmp = 0; tmp < 100; tmp++) { 4674 if ((inb(0x138) & 1) == 0) { 4675 PC98SIO_baud_rate_port(if_type) = 0x13a; 4676 if_8251_type[if_type].name = " (internal fast)"; 4677 if_8251_type[if_type].speedtab = pc98fast_speedtab; 4678 break; 4679 } 4680 DELAY(1); 4681 } 4682 } else { 4683 tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask; 4684 if ((dev->id_iobase & 0xff) == IO_COM2) 4685 iod->irq = irq_tab[0][tmp]; 4686 else 4687 iod->irq = irq_tab[1][tmp]; 4688 } 4689 } else { 4690 irr = if_16550a_type[if_type].irr_read; 4691#ifdef COM_MULTIPORT 4692 if (!COM_ISMULTIPORT(dev) || dev->id_unit == COM_MPMASTER(dev)) 4693#endif 4694 if (irr != -1) { 4695 tmp = inb(io | irr); 4696 if (dev->id_iobase & 0x01) /* XXX depend on RSB-384 */ 4697 iod->irq = irq_tab[1][tmp >> 3]; 4698 else 4699 iod->irq = irq_tab[0][tmp & 0x07]; 4700 } 4701 } 4702 if ( iod->irq == -1 ) return -1; 4703 4704 return 0; 4705} 4706static int 4707pc98_set_ioport( struct com_s *com, int id_flags ) 4708{ 4709 int io, if_type; 4710 4711 if_type = (id_flags >> 24) & 0xff; 4712 if (IS_8251(if_type)) { 4713 pc98_check_sysclock(); 4714 io = com->iobase & 0xff00; 4715 com->pc98_if_type = if_type; 4716 if_type &= 0x0f; 4717 com->data_port = io | PC98SIO_data_port(if_type); 4718 com->cmd_port = io | PC98SIO_cmd_port(if_type); 4719 com->sts_port = io | PC98SIO_sts_port(if_type); 4720 com->in_modem_port = io | PC98SIO_in_modem_port(if_type); 4721 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(if_type); 4722 return 0; 4723 } 4724 4725 return -1; 4726} 4727#endif /* PC98 defined */ 4728