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