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