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