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