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