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