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