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