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