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