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