sio.c revision 43425
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.78 1999/01/28 11:24:36 kato Exp $
35 */
36
37#include "opt_comconsole.h"
38#include "opt_compat.h"
39#include "opt_ddb.h"
40#include "opt_devfs.h"
41#include "opt_sio.h"
42#include "sio.h"
43#include "pnp.h"
44
45/*
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);
1784determined_type: ;
1785#endif
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 &&
1916		    suser(p->p_ucred, &p->p_acflag)) {
1917			error = EBUSY;
1918			goto out;
1919		}
1920	} else {
1921		/*
1922		 * The device isn't open, so there are no conflicts.
1923		 * Initialize it.  Initialization is done twice in many
1924		 * cases: to preempt sleeping callin opens if we are
1925		 * callout, and to complete a callin open after DCD rises.
1926		 */
1927		tp->t_oproc = comstart;
1928		tp->t_param = comparam;
1929		tp->t_dev = dev;
1930		tp->t_termios = mynor & CALLOUT_MASK
1931				? com->it_out : com->it_in;
1932#ifndef PC98
1933		tp->t_ififosize = 2 * RS_IBUFSIZE;
1934#else
1935		tp->t_ififosize = 2 * com->CE_INPUT_OFFSET;
1936#endif
1937		tp->t_ispeedwat = (speed_t)-1;
1938		tp->t_ospeedwat = (speed_t)-1;
1939#ifdef PC98
1940		if (!IS_8251(com->pc98_if_type))
1941#endif
1942		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
1943		com->poll = com->no_irq;
1944		com->poll_output = com->loses_outints;
1945		++com->wopeners;
1946		error = comparam(tp, &tp->t_termios);
1947		--com->wopeners;
1948		if (error != 0)
1949			goto out;
1950#ifdef PC98
1951		if (IS_8251(com->pc98_if_type)) {
1952			com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS);
1953			pc98_msrint_start(dev);
1954		}
1955#endif
1956		/*
1957		 * XXX we should goto open_top if comparam() slept.
1958		 */
1959		iobase = com->iobase;
1960		if (com->hasfifo) {
1961			/*
1962			 * (Re)enable and drain fifos.
1963			 *
1964			 * Certain SMC chips cause problems if the fifos
1965			 * are enabled while input is ready.  Turn off the
1966			 * fifo if necessary to clear the input.  We test
1967			 * the input ready bit after enabling the fifos
1968			 * since we've already enabled them in comparam()
1969			 * and to handle races between enabling and fresh
1970			 * input.
1971			 */
1972			while (TRUE) {
1973#ifdef PC98
1974 				outb(iobase + (com_fifo << port_shift),
1975 				     FIFO_RCV_RST | FIFO_XMT_RST
1976 				     | com->fifo_image);
1977				if (com->pc98_if_type == COM_IF_RSA98III)
1978				  outb(com->rsabase + rsa_frr , 0x00);
1979#else
1980				outb(iobase + com_fifo,
1981				     FIFO_RCV_RST | FIFO_XMT_RST
1982				     | com->fifo_image);
1983#endif
1984				/*
1985				 * XXX the delays are for superstitious
1986				 * historical reasons.  It must be less than
1987				 * the character time at the maximum
1988				 * supported speed (87 usec at 115200 bps
1989				 * 8N1).  Otherwise we might loop endlessly
1990				 * if data is streaming in.  We used to use
1991				 * delays of 100.  That usually worked
1992				 * because DELAY(100) used to usually delay
1993				 * for about 85 usec instead of 100.
1994				 */
1995				DELAY(50);
1996#ifndef PC98
1997				if (!(inb(com->line_status_port) & LSR_RXRDY))
1998#else
1999				if (com->pc98_if_type == COM_IF_RSA98III
2000				    ? !(inb(com->rsabase + rsa_srr) & 0x08)
2001				    : !(inb(com->line_status_port) & LSR_RXRDY))
2002#endif
2003					break;
2004#ifdef PC98
2005 				outb(iobase + (com_fifo << port_shift), 0);
2006#else
2007				outb(iobase + com_fifo, 0);
2008#endif
2009				DELAY(50);
2010				(void) inb(com->data_port);
2011			}
2012		}
2013
2014		disable_intr();
2015#ifdef PC98
2016		if (IS_8251(com->pc98_if_type)) {
2017		    com_tiocm_bis(com, TIOCM_LE);
2018		    com->pc98_prev_modem_status = pc98_get_modem_status(com);
2019		    com_int_Rx_enable(com);
2020		} else {
2021#endif
2022		(void) inb(com->line_status_port);
2023		(void) inb(com->data_port);
2024		com->prev_modem_status = com->last_modem_status
2025		    = inb(com->modem_status_port);
2026		if (COM_IIR_TXRDYBUG(com)) {
2027			outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
2028						| IER_EMSC);
2029		} else {
2030			outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
2031						| IER_ERLS | IER_EMSC);
2032		}
2033#ifdef PC98
2034		if (com->pc98_if_type == COM_IF_RSA98III) {
2035			outb(com->rsabase + rsa_ier, 0x1d);
2036			outb(com->intr_ctl_port, IER_ERLS | IER_EMSC);
2037		}
2038#endif
2039#ifdef PC98
2040		}
2041#endif
2042		enable_intr();
2043		/*
2044		 * Handle initial DCD.  Callout devices get a fake initial
2045		 * DCD (trapdoor DCD).  If we are callout, then any sleeping
2046		 * callin opens get woken up and resume sleeping on "siobi"
2047		 * instead of "siodcd".
2048		 */
2049		/*
2050		 * XXX `mynor & CALLOUT_MASK' should be
2051		 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
2052		 * TRAPDOOR_CARRIER is the default initial state for callout
2053		 * devices and SOFT_CARRIER is like CLOCAL except it hides
2054		 * the true carrier.
2055		 */
2056#ifdef PC98
2057		if ((IS_8251(com->pc98_if_type) &&
2058			(pc98_get_modem_status(com) & TIOCM_CAR)) ||
2059		    (!IS_8251(com->pc98_if_type) &&
2060			(com->prev_modem_status & MSR_DCD)) ||
2061		    mynor & CALLOUT_MASK)
2062#else
2063		if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
2064#endif
2065			(*linesw[tp->t_line].l_modem)(tp, 1);
2066	}
2067	/*
2068	 * Wait for DCD if necessary.
2069	 */
2070	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
2071	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
2072		++com->wopeners;
2073		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
2074		if (com_addr(unit) == NULL)
2075			return (ENXIO);
2076		--com->wopeners;
2077		if (error != 0 || com->gone)
2078			goto out;
2079		goto open_top;
2080	}
2081	error =	(*linesw[tp->t_line].l_open)(dev, tp);
2082	disc_optim(tp, &tp->t_termios, com);
2083	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
2084		com->active_out = TRUE;
2085	siosettimeout();
2086out:
2087	splx(s);
2088	if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
2089		comhardclose(com);
2090	return (error);
2091}
2092
2093static int
2094sioclose(dev, flag, mode, p)
2095	dev_t		dev;
2096	int		flag;
2097	int		mode;
2098	struct proc	*p;
2099{
2100	struct com_s	*com;
2101	int		mynor;
2102	int		s;
2103	struct tty	*tp;
2104
2105	mynor = minor(dev);
2106	if (mynor & CONTROL_MASK)
2107		return (0);
2108	com = com_addr(MINOR_TO_UNIT(mynor));
2109	tp = com->tp;
2110	s = spltty();
2111	(*linesw[tp->t_line].l_close)(tp, flag);
2112#ifdef PC98
2113	com->modem_checking = 0;
2114#endif
2115	disc_optim(tp, &tp->t_termios, com);
2116	siostop(tp, FREAD | FWRITE);
2117	comhardclose(com);
2118	ttyclose(tp);
2119	siosettimeout();
2120	splx(s);
2121	if (com->gone) {
2122		printf("sio%d: gone\n", com->unit);
2123		s = spltty();
2124		com_addr(com->unit) = 0;
2125		bzero(tp,sizeof *tp);
2126		bzero(com,sizeof *com);
2127		free(com,M_TTYS);
2128		splx(s);
2129	}
2130	return (0);
2131}
2132
2133static void
2134comhardclose(com)
2135	struct com_s	*com;
2136{
2137	Port_t		iobase;
2138	int		s;
2139	struct tty	*tp;
2140	int		unit;
2141#ifdef PC98
2142	int		port_shift = 0;
2143#endif
2144
2145	unit = com->unit;
2146	iobase = com->iobase;
2147	s = spltty();
2148	com->poll = FALSE;
2149	com->poll_output = FALSE;
2150	com->do_timestamp = FALSE;
2151	com->do_dcd_timestamp = FALSE;
2152#ifdef PC98
2153	if (IS_8251(com->pc98_if_type))
2154	    com_send_break_off(com);
2155	else {
2156	    port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
2157	    outb(iobase + (com_cfcr << port_shift),
2158		 com->cfcr_image &= ~CFCR_SBREAK);
2159	}
2160#else
2161	outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2162#endif
2163	{
2164#ifdef PC98
2165		int tmp;
2166		if (IS_8251(com->pc98_if_type))
2167			com_int_TxRx_disable(com);
2168		else
2169			outb(iobase + (com_ier << port_shift), 0);
2170		if (com->pc98_if_type == COM_IF_RSA98III) {
2171			outb(com->rsabase + rsa_ier, 0x00);
2172		}
2173#else
2174		outb(iobase + com_ier, 0);
2175#endif
2176		tp = com->tp;
2177#ifdef PC98
2178		if (IS_8251(com->pc98_if_type))
2179			tmp = pc98_get_modem_status(com) & TIOCM_CAR;
2180		else
2181			tmp = com->prev_modem_status & MSR_DCD;
2182#endif
2183		if (tp->t_cflag & HUPCL
2184		    /*
2185		     * XXX we will miss any carrier drop between here and the
2186		     * next open.  Perhaps we should watch DCD even when the
2187		     * port is closed; it is not sufficient to check it at
2188		     * the next open because it might go up and down while
2189		     * we're not watching.
2190		     */
2191		    || !com->active_out
2192#ifdef PC98
2193		       && !(tmp)
2194#else
2195		       && !(com->prev_modem_status & MSR_DCD)
2196#endif
2197		       && !(com->it_in.c_cflag & CLOCAL)
2198		    || !(tp->t_state & TS_ISOPEN)) {
2199#ifdef PC98
2200			if (IS_8251(com->pc98_if_type))
2201			    com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
2202			else
2203#endif
2204			(void)commctl(com, TIOCM_DTR, DMBIC);
2205			if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
2206				timeout(siodtrwakeup, com, com->dtr_wait);
2207				com->state |= CS_DTR_OFF;
2208			}
2209		}
2210#ifdef PC98
2211		else {
2212			if (IS_8251(com->pc98_if_type))
2213				com_tiocm_bic(com, TIOCM_LE );
2214		}
2215#endif
2216	}
2217	if (com->hasfifo) {
2218		/*
2219		 * Disable fifos so that they are off after controlled
2220		 * reboots.  Some BIOSes fail to detect 16550s when the
2221		 * fifos are enabled.
2222		 */
2223#ifdef PC98
2224		outb(iobase + (com_fifo << port_shift), 0);
2225#else
2226		outb(iobase + com_fifo, 0);
2227#endif
2228	}
2229	com->active_out = FALSE;
2230	wakeup(&com->active_out);
2231	wakeup(TSA_CARR_ON(tp));	/* restart any wopeners */
2232	splx(s);
2233}
2234
2235static int
2236sioread(dev, uio, flag)
2237	dev_t		dev;
2238	struct uio	*uio;
2239	int		flag;
2240{
2241	int		mynor;
2242	int		unit;
2243	struct tty	*tp;
2244
2245	mynor = minor(dev);
2246	if (mynor & CONTROL_MASK)
2247		return (ENODEV);
2248	unit = MINOR_TO_UNIT(mynor);
2249	if (com_addr(unit)->gone)
2250		return (ENODEV);
2251	tp = com_addr(unit)->tp;
2252	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
2253}
2254
2255static int
2256siowrite(dev, uio, flag)
2257	dev_t		dev;
2258	struct uio	*uio;
2259	int		flag;
2260{
2261	int		mynor;
2262	struct tty	*tp;
2263	int		unit;
2264
2265	mynor = minor(dev);
2266	if (mynor & CONTROL_MASK)
2267		return (ENODEV);
2268
2269	unit = MINOR_TO_UNIT(mynor);
2270	if (com_addr(unit)->gone)
2271		return (ENODEV);
2272	tp = com_addr(unit)->tp;
2273	/*
2274	 * (XXX) We disallow virtual consoles if the physical console is
2275	 * a serial port.  This is in case there is a display attached that
2276	 * is not the console.  In that situation we don't need/want the X
2277	 * server taking over the console.
2278	 */
2279	if (constty != NULL && unit == comconsole)
2280		constty = NULL;
2281	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
2282}
2283
2284static void
2285siobusycheck(chan)
2286	void	*chan;
2287{
2288	struct com_s	*com;
2289	int		s;
2290
2291	com = (struct com_s *)chan;
2292
2293	/*
2294	 * Clear TS_BUSY if low-level output is complete.
2295	 * spl locking is sufficient because siointr1() does not set CS_BUSY.
2296	 * If siointr1() clears CS_BUSY after we look at it, then we'll get
2297	 * called again.  Reading the line status port outside of siointr1()
2298	 * is safe because CS_BUSY is clear so there are no output interrupts
2299	 * to lose.
2300	 */
2301	s = spltty();
2302	if (com->state & CS_BUSY)
2303		com->extra_state &= ~CSE_BUSYCHECK;	/* False alarm. */
2304#ifdef	PC98
2305	else if (IS_8251(com->pc98_if_type) &&
2306		 (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP))
2307		 == (STS8251_TxRDY | STS8251_TxEMP) ||
2308		 (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2309		 == (LSR_TSRE | LSR_TXRDY)) {
2310#else
2311	else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2312	    == (LSR_TSRE | LSR_TXRDY)) {
2313#endif
2314		com->tp->t_state &= ~TS_BUSY;
2315		ttwwakeup(com->tp);
2316		com->extra_state &= ~CSE_BUSYCHECK;
2317	} else
2318		timeout(siobusycheck, com, hz / 100);
2319	splx(s);
2320}
2321
2322static void
2323siodtrwakeup(chan)
2324	void	*chan;
2325{
2326	struct com_s	*com;
2327
2328	com = (struct com_s *)chan;
2329	com->state &= ~CS_DTR_OFF;
2330	wakeup(&com->dtr_wait);
2331}
2332
2333static void
2334siointr(unit)
2335	int	unit;
2336{
2337#ifndef COM_MULTIPORT
2338	COM_LOCK();
2339	siointr1(com_addr(unit));
2340	COM_UNLOCK();
2341#else /* COM_MULTIPORT */
2342	struct com_s    *com;
2343	bool_t		possibly_more_intrs;
2344#ifdef PC98
2345	u_char		rsa_buf_status;
2346#endif
2347
2348	/*
2349	 * Loop until there is no activity on any port.  This is necessary
2350	 * to get an interrupt edge more than to avoid another interrupt.
2351	 * If the IRQ signal is just an OR of the IRQ signals from several
2352	 * devices, then the edge from one may be lost because another is
2353	 * on.
2354	 */
2355	COM_LOCK();
2356	do {
2357		possibly_more_intrs = FALSE;
2358		for (unit = 0; unit < NSIOTOT; ++unit) {
2359			com = com_addr(unit);
2360			/*
2361			 * XXX COM_LOCK();
2362			 * would it work here, or be counter-productive?
2363			 */
2364#ifdef PC98
2365			if (com != NULL
2366			    && !com->gone
2367			    && IS_8251(com->pc98_if_type)){
2368				siointr1(com);
2369			} else
2370#endif /* PC98 */
2371#ifdef PC98
2372			if (com != NULL
2373			    && !com->gone
2374			    && com->pc98_if_type == COM_IF_RSA98III) {
2375			  rsa_buf_status = inb(com->rsabase + rsa_srr) & 0xc9;
2376			  if ((rsa_buf_status & 0xc8)
2377			      || !(rsa_buf_status & 0x01)) {
2378			    siointr1(com);
2379			    if(rsa_buf_status
2380			       != (inb(com->rsabase + rsa_srr) & 0xc9))
2381			      possibly_more_intrs = TRUE;
2382			  }
2383			} else
2384#endif
2385			if (com != NULL
2386			    && !com->gone
2387			    && (inb(com->int_id_port) & IIR_IMASK)
2388			       != IIR_NOPEND) {
2389				siointr1(com);
2390				possibly_more_intrs = TRUE;
2391			}
2392			/* XXX COM_UNLOCK(); */
2393		}
2394	} while (possibly_more_intrs);
2395	COM_UNLOCK();
2396#endif /* COM_MULTIPORT */
2397}
2398
2399static void
2400siointr1(com)
2401	struct com_s	*com;
2402{
2403	u_char	line_status;
2404	u_char	modem_status;
2405	u_char	*ioptr;
2406	u_char	recv_data;
2407	u_char	int_ctl;
2408	u_char	int_ctl_new;
2409
2410#ifdef PC98
2411	u_char	tmp=0;
2412	u_char	rsa_buf_status = 0;
2413	int	rsa_tx_fifo_size=0;
2414	recv_data=0;
2415#endif /* PC98 */
2416
2417	int_ctl = inb(com->intr_ctl_port);
2418	int_ctl_new = int_ctl;
2419
2420	while (!com->gone) {
2421#ifdef PC98
2422status_read:;
2423		if (IS_8251(com->pc98_if_type)) {
2424			tmp = inb(com->sts_port);
2425more_intr:
2426			line_status = 0;
2427			if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY;
2428			if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY;
2429			if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE;
2430			if (tmp & STS8251_PE)    line_status |= LSR_PE;
2431			if (tmp & STS8251_OE)    line_status |= LSR_OE;
2432			if (tmp & STS8251_FE)    line_status |= LSR_FE;
2433			if (tmp & STS8251_BD_SD) line_status |= LSR_BI;
2434		} else
2435#endif /* PC98 */
2436		line_status = inb(com->line_status_port);
2437#ifdef PC98
2438		if (com->pc98_if_type == COM_IF_RSA98III)
2439			rsa_buf_status = inb(com->rsabase + rsa_srr);
2440#endif /* PC98 */
2441
2442		/* input event? (check first to help avoid overruns) */
2443#ifndef PC98
2444		while (line_status & LSR_RCV_MASK) {
2445#else
2446		while ((line_status & LSR_RCV_MASK)
2447		       || (com->pc98_if_type == COM_IF_RSA98III
2448			   && (rsa_buf_status & 0x08))) {
2449#endif /* PC98 */
2450			/* break/unnattached error bits or real input? */
2451#ifdef PC98
2452			if (IS_8251(com->pc98_if_type)) {
2453				recv_data = inb(com->data_port);
2454				if (tmp & 0x78) {
2455					pc98_i8251_or_cmd(com,CMD8251_ER);
2456					recv_data = 0;
2457				}
2458			} else {
2459#endif /* PC98 */
2460#ifdef PC98
2461			if (com->pc98_if_type == COM_IF_RSA98III) {
2462			  if (!(rsa_buf_status & 0x08))
2463			    recv_data = 0;
2464			  else {
2465			    recv_data = inb(com->data_port);
2466			  }
2467			} else
2468#endif
2469			if (!(line_status & LSR_RXRDY))
2470				recv_data = 0;
2471			else
2472				recv_data = inb(com->data_port);
2473#ifdef PC98
2474			}
2475#endif
2476			if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
2477				/*
2478				 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
2479				 * Otherwise, push the work to a higher level
2480				 * (to handle PARMRK) if we're bypassing.
2481				 * Otherwise, convert BI/FE and PE+INPCK to 0.
2482				 *
2483				 * This makes bypassing work right in the
2484				 * usual "raw" case (IGNBRK set, and IGNPAR
2485				 * and INPCK clear).
2486				 *
2487				 * Note: BI together with FE/PE means just BI.
2488				 */
2489				if (line_status & LSR_BI) {
2490#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
2491					if (com->unit == comconsole) {
2492						breakpoint();
2493						goto cont;
2494					}
2495#endif
2496					if (com->tp == NULL
2497					    || com->tp->t_iflag & IGNBRK)
2498						goto cont;
2499				} else {
2500					if (com->tp == NULL
2501					    || com->tp->t_iflag & IGNPAR)
2502						goto cont;
2503				}
2504				if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
2505				    && (line_status & (LSR_BI | LSR_FE)
2506					|| com->tp->t_iflag & INPCK))
2507					recv_data = 0;
2508			}
2509			++com->bytes_in;
2510			if (com->hotchar != 0 && recv_data == com->hotchar)
2511				setsofttty();
2512			ioptr = com->iptr;
2513			if (ioptr >= com->ibufend)
2514				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
2515			else {
2516				if (com->do_timestamp)
2517					microtime(&com->timestamp);
2518				++com_events;
2519				schedsofttty();
2520#if 0 /* for testing input latency vs efficiency */
2521if (com->iptr - com->ibuf == 8)
2522	setsofttty();
2523#endif
2524				ioptr[0] = recv_data;
2525#ifdef PC98
2526				ioptr[com->CE_INPUT_OFFSET] = line_status;
2527#else
2528				ioptr[CE_INPUT_OFFSET] = line_status;
2529#endif
2530				com->iptr = ++ioptr;
2531				if (ioptr == com->ihighwater
2532				    && com->state & CS_RTS_IFLOW)
2533#ifdef PC98
2534					if (IS_8251(com->pc98_if_type))
2535						com_tiocm_bic(com, TIOCM_RTS);
2536					else
2537#endif
2538					outb(com->modem_ctl_port,
2539					     com->mcr_image &= ~MCR_RTS);
2540				if (line_status & LSR_OE)
2541					CE_RECORD(com, CE_OVERRUN);
2542			}
2543cont:
2544			/*
2545			 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
2546			 * jump from the top of the loop to here
2547			 */
2548#ifdef PC98
2549			if (IS_8251(com->pc98_if_type))
2550				goto status_read;
2551			else
2552#endif
2553			line_status = inb(com->line_status_port) & 0x7F;
2554#ifdef PC98
2555			if (com->pc98_if_type == COM_IF_RSA98III)
2556				rsa_buf_status = inb(com->rsabase + rsa_srr);
2557#endif /* PC98 */
2558		}
2559
2560		/* modem status change? (always check before doing output) */
2561#ifdef PC98
2562		if (!IS_8251(com->pc98_if_type)) {
2563#endif
2564		modem_status = inb(com->modem_status_port);
2565		if (modem_status != com->last_modem_status) {
2566			if (com->do_dcd_timestamp
2567			    && !(com->last_modem_status & MSR_DCD)
2568			    && modem_status & MSR_DCD)
2569				microtime(&com->dcd_timestamp);
2570
2571			/*
2572			 * Schedule high level to handle DCD changes.  Note
2573			 * that we don't use the delta bits anywhere.  Some
2574			 * UARTs mess them up, and it's easy to remember the
2575			 * previous bits and calculate the delta.
2576			 */
2577			com->last_modem_status = modem_status;
2578			if (!(com->state & CS_CHECKMSR)) {
2579				com_events += LOTS_OF_EVENTS;
2580				com->state |= CS_CHECKMSR;
2581				setsofttty();
2582			}
2583
2584			/* handle CTS change immediately for crisp flow ctl */
2585			if (com->state & CS_CTS_OFLOW) {
2586				if (modem_status & MSR_CTS)
2587					com->state |= CS_ODEVREADY;
2588				else
2589					com->state &= ~CS_ODEVREADY;
2590			}
2591		}
2592#ifdef PC98
2593		}
2594#endif
2595
2596		/* output queued and everything ready? */
2597#ifndef PC98
2598		if (line_status & LSR_TXRDY
2599		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2600#else
2601		if (((com->pc98_if_type == COM_IF_RSA98III)
2602		     ? (rsa_buf_status & 0x02)
2603		     : (line_status & LSR_TXRDY))
2604		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2605#endif
2606			ioptr = com->obufq.l_head;
2607			if (com->tx_fifo_size > 1) {
2608				u_int	ocount;
2609
2610				ocount = com->obufq.l_tail - ioptr;
2611#ifdef PC98
2612				if (com->pc98_if_type == COM_IF_RSA98III) {
2613				  rsa_buf_status = inb(com->rsabase + rsa_srr);
2614				  rsa_tx_fifo_size = 1024;
2615				  if (!(rsa_buf_status & 0x01))
2616				    rsa_tx_fifo_size = 2048;
2617				  if (ocount > rsa_tx_fifo_size)
2618				    ocount = rsa_tx_fifo_size;
2619				} else
2620#endif
2621				if (ocount > com->tx_fifo_size)
2622					ocount = com->tx_fifo_size;
2623				com->bytes_out += ocount;
2624				do
2625					outb(com->data_port, *ioptr++);
2626				while (--ocount != 0);
2627			} else {
2628				outb(com->data_port, *ioptr++);
2629				++com->bytes_out;
2630			}
2631#ifdef PC98
2632			if (IS_8251(com->pc98_if_type))
2633			    if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG))
2634					com_int_Tx_enable(com);
2635#endif
2636			com->obufq.l_head = ioptr;
2637			if (COM_IIR_TXRDYBUG(com)) {
2638				int_ctl_new = int_ctl | IER_ETXRDY;
2639			}
2640			if (ioptr >= com->obufq.l_tail) {
2641				struct lbq	*qp;
2642
2643				qp = com->obufq.l_next;
2644				qp->l_queued = FALSE;
2645				qp = qp->l_next;
2646				if (qp != NULL) {
2647					com->obufq.l_head = qp->l_head;
2648					com->obufq.l_tail = qp->l_tail;
2649					com->obufq.l_next = qp;
2650				} else {
2651					/* output just completed */
2652					if ( COM_IIR_TXRDYBUG(com) ) {
2653						int_ctl_new = int_ctl & ~IER_ETXRDY;
2654					}
2655					com->state &= ~CS_BUSY;
2656#if defined(PC98)
2657					if (IS_8251(com->pc98_if_type))
2658					    if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
2659						com_int_Tx_disable(com);
2660#endif
2661				}
2662				if (!(com->state & CS_ODONE)) {
2663					com_events += LOTS_OF_EVENTS;
2664					com->state |= CS_ODONE;
2665					setsofttty();	/* handle at high level ASAP */
2666				}
2667			}
2668			if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) {
2669				if (com->pc98_if_type == COM_IF_RSA98III) {
2670				  int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY);
2671				  outb(com->intr_ctl_port, int_ctl_new);
2672				  outb(com->rsabase + rsa_ier, 0x1d);
2673				} else
2674				outb(com->intr_ctl_port, int_ctl_new);
2675			}
2676		}
2677#ifdef PC98
2678		else if (line_status & LSR_TXRDY) {
2679		    if (IS_8251(com->pc98_if_type))
2680			if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
2681			    com_int_Tx_disable(com);
2682		}
2683		if (IS_8251(com->pc98_if_type))
2684		    if ((tmp = inb(com->sts_port)) & STS8251_RxRDY)
2685			goto more_intr;
2686#endif
2687
2688		/* finished? */
2689#ifndef COM_MULTIPORT
2690#ifdef PC98
2691		if (IS_8251(com->pc98_if_type))
2692			return;
2693#endif
2694		if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
2695#endif /* COM_MULTIPORT */
2696			return;
2697	}
2698}
2699
2700static int
2701sioioctl(dev, cmd, data, flag, p)
2702	dev_t		dev;
2703	u_long		cmd;
2704	caddr_t		data;
2705	int		flag;
2706	struct proc	*p;
2707{
2708	struct com_s	*com;
2709	int		error;
2710	Port_t		iobase;
2711	int		mynor;
2712	int		s;
2713	struct tty	*tp;
2714#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2715	int		oldcmd;
2716	struct termios	term;
2717#endif
2718
2719	mynor = minor(dev);
2720	com = com_addr(MINOR_TO_UNIT(mynor));
2721	if (com->gone)
2722		return (ENODEV);
2723	iobase = com->iobase;
2724	if (mynor & CONTROL_MASK) {
2725		struct termios	*ct;
2726
2727		switch (mynor & CONTROL_MASK) {
2728		case CONTROL_INIT_STATE:
2729			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
2730			break;
2731		case CONTROL_LOCK_STATE:
2732			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
2733			break;
2734		default:
2735			return (ENODEV);	/* /dev/nodev */
2736		}
2737		switch (cmd) {
2738		case TIOCSETA:
2739			error = suser(p->p_ucred, &p->p_acflag);
2740			if (error != 0)
2741				return (error);
2742			*ct = *(struct termios *)data;
2743			return (0);
2744		case TIOCGETA:
2745			*(struct termios *)data = *ct;
2746			return (0);
2747		case TIOCGETD:
2748			*(int *)data = TTYDISC;
2749			return (0);
2750		case TIOCGWINSZ:
2751			bzero(data, sizeof(struct winsize));
2752			return (0);
2753		default:
2754			return (ENOTTY);
2755		}
2756	}
2757	tp = com->tp;
2758#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2759	term = tp->t_termios;
2760	oldcmd = cmd;
2761	error = ttsetcompat(tp, &cmd, data, &term);
2762	if (error != 0)
2763		return (error);
2764	if (cmd != oldcmd)
2765		data = (caddr_t)&term;
2766#endif
2767	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
2768		int	cc;
2769		struct termios *dt = (struct termios *)data;
2770		struct termios *lt = mynor & CALLOUT_MASK
2771				     ? &com->lt_out : &com->lt_in;
2772
2773		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
2774			      | (dt->c_iflag & ~lt->c_iflag);
2775		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
2776			      | (dt->c_oflag & ~lt->c_oflag);
2777		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
2778			      | (dt->c_cflag & ~lt->c_cflag);
2779		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
2780			      | (dt->c_lflag & ~lt->c_lflag);
2781		for (cc = 0; cc < NCCS; ++cc)
2782			if (lt->c_cc[cc] != 0)
2783				dt->c_cc[cc] = tp->t_cc[cc];
2784		if (lt->c_ispeed != 0)
2785			dt->c_ispeed = tp->t_ispeed;
2786		if (lt->c_ospeed != 0)
2787			dt->c_ospeed = tp->t_ospeed;
2788	}
2789	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
2790	if (error != ENOIOCTL)
2791		return (error);
2792	s = spltty();
2793	error = ttioctl(tp, cmd, data, flag);
2794	disc_optim(tp, &tp->t_termios, com);
2795	if (error != ENOIOCTL) {
2796		splx(s);
2797		return (error);
2798	}
2799#ifdef PC98
2800	if (IS_8251(com->pc98_if_type)) {
2801	    switch (cmd) {
2802	    case TIOCSBRK:
2803		com_send_break_on( com );
2804		break;
2805	    case TIOCCBRK:
2806		com_send_break_off( com );
2807		break;
2808	    case TIOCSDTR:
2809		com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS );
2810		break;
2811	    case TIOCCDTR:
2812		com_tiocm_bic(com, TIOCM_DTR);
2813		break;
2814	/*
2815	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
2816	 * changes get undone on the next call to comparam().
2817	 */
2818	    case TIOCMSET:
2819		com_tiocm_set( com, *(int *)data );
2820		break;
2821	    case TIOCMBIS:
2822		com_tiocm_bis( com, *(int *)data );
2823		break;
2824	    case TIOCMBIC:
2825		com_tiocm_bic( com, *(int *)data );
2826		break;
2827	    case TIOCMGET:
2828		*(int *)data = com_tiocm_get(com);
2829		break;
2830	    case TIOCMSDTRWAIT:
2831		/* must be root since the wait applies to following logins */
2832		error = suser(p->p_ucred, &p->p_acflag);
2833		if (error != 0) {
2834			splx(s);
2835			return (error);
2836		}
2837		com->dtr_wait = *(int *)data * hz / 100;
2838		break;
2839	    case TIOCMGDTRWAIT:
2840		*(int *)data = com->dtr_wait * 100 / hz;
2841		break;
2842	    case TIOCTIMESTAMP:
2843		com->do_timestamp = TRUE;
2844		*(struct timeval *)data = com->timestamp;
2845		break;
2846	    case TIOCDCDTIMESTAMP:
2847		com->do_dcd_timestamp = TRUE;
2848		*(struct timeval *)data = com->dcd_timestamp;
2849		break;
2850	    default:
2851		splx(s);
2852		return (ENOTTY);
2853	    }
2854	} else {
2855	    int port_shift;
2856	    port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
2857#endif
2858	switch (cmd) {
2859	case TIOCSBRK:
2860#ifdef PC98
2861		outb(iobase + (com_cfcr << port_shift),
2862		     com->cfcr_image |= CFCR_SBREAK);
2863#else
2864		outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2865#endif
2866		break;
2867	case TIOCCBRK:
2868#ifdef PC98
2869		outb(iobase + (com_cfcr << port_shift),
2870		     com->cfcr_image &= ~CFCR_SBREAK);
2871#else
2872		outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2873#endif
2874		break;
2875	case TIOCSDTR:
2876		(void)commctl(com, TIOCM_DTR, DMBIS);
2877		break;
2878	case TIOCCDTR:
2879		(void)commctl(com, TIOCM_DTR, DMBIC);
2880		break;
2881	/*
2882	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
2883	 * changes get undone on the next call to comparam().
2884	 */
2885	case TIOCMSET:
2886		(void)commctl(com, *(int *)data, DMSET);
2887		break;
2888	case TIOCMBIS:
2889		(void)commctl(com, *(int *)data, DMBIS);
2890		break;
2891	case TIOCMBIC:
2892		(void)commctl(com, *(int *)data, DMBIC);
2893		break;
2894	case TIOCMGET:
2895		*(int *)data = commctl(com, 0, DMGET);
2896		break;
2897	case TIOCMSDTRWAIT:
2898		/* must be root since the wait applies to following logins */
2899		error = suser(p->p_ucred, &p->p_acflag);
2900		if (error != 0) {
2901			splx(s);
2902			return (error);
2903		}
2904		com->dtr_wait = *(int *)data * hz / 100;
2905		break;
2906	case TIOCMGDTRWAIT:
2907		*(int *)data = com->dtr_wait * 100 / hz;
2908		break;
2909	case TIOCTIMESTAMP:
2910		com->do_timestamp = TRUE;
2911		*(struct timeval *)data = com->timestamp;
2912		break;
2913	case TIOCDCDTIMESTAMP:
2914		com->do_dcd_timestamp = TRUE;
2915		*(struct timeval *)data = com->dcd_timestamp;
2916		break;
2917	default:
2918		splx(s);
2919		return (ENOTTY);
2920	}
2921#ifdef PC98
2922	}
2923#endif
2924	splx(s);
2925	return (0);
2926}
2927
2928static void
2929siopoll()
2930{
2931	int		unit;
2932
2933	if (com_events == 0)
2934		return;
2935repeat:
2936	for (unit = 0; unit < NSIOTOT; ++unit) {
2937		u_char		*buf;
2938		struct com_s	*com;
2939		u_char		*ibuf;
2940		int		incc;
2941		struct tty	*tp;
2942#ifdef PC98
2943		int		tmp;
2944#endif
2945
2946		com = com_addr(unit);
2947		if (com == NULL)
2948			continue;
2949		tp = com->tp;
2950		if (tp == NULL || com->gone) {
2951			/*
2952			 * Discard any events related to never-opened or
2953			 * going-away devices.
2954			 */
2955			disable_intr();
2956			incc = com->iptr - com->ibuf;
2957			com->iptr = com->ibuf;
2958			if (com->state & CS_CHECKMSR) {
2959				incc += LOTS_OF_EVENTS;
2960				com->state &= ~CS_CHECKMSR;
2961			}
2962			com_events -= incc;
2963			enable_intr();
2964			continue;
2965		}
2966
2967		/* switch the role of the low-level input buffers */
2968		if (com->iptr == (ibuf = com->ibuf)) {
2969			buf = NULL;     /* not used, but compiler can't tell */
2970			incc = 0;
2971		} else {
2972			buf = ibuf;
2973			disable_intr();
2974			incc = com->iptr - buf;
2975			com_events -= incc;
2976			if (ibuf == com->ibuf1)
2977				ibuf = com->ibuf2;
2978			else
2979				ibuf = com->ibuf1;
2980#ifndef PC98
2981			com->ibufend = ibuf + RS_IBUFSIZE;
2982			com->ihighwater = ibuf + RS_IHIGHWATER;
2983#else
2984			com->ibufend = ibuf + com->CE_INPUT_OFFSET;
2985			com->ihighwater = ibuf + (3 * com->CE_INPUT_OFFSET / 4);
2986#endif
2987			com->iptr = ibuf;
2988
2989			/*
2990			 * There is now room for another low-level buffer full
2991			 * of input, so enable RTS if it is now disabled and
2992			 * there is room in the high-level buffer.
2993			 */
2994#ifdef PC98
2995			if (IS_8251(com->pc98_if_type))
2996				tmp = com_tiocm_get(com) & TIOCM_RTS;
2997			else
2998				tmp = com->mcr_image & MCR_RTS;
2999#endif
3000			if ((com->state & CS_RTS_IFLOW)
3001#ifdef PC98
3002			    && !(tmp)
3003#else
3004			    && !(com->mcr_image & MCR_RTS)
3005#endif
3006			    && !(tp->t_state & TS_TBLOCK))
3007#ifdef PC98
3008				if (IS_8251(com->pc98_if_type))
3009					com_tiocm_bis(com, TIOCM_RTS);
3010				else
3011#endif
3012				outb(com->modem_ctl_port,
3013				     com->mcr_image |= MCR_RTS);
3014			enable_intr();
3015			com->ibuf = ibuf;
3016		}
3017
3018		if (com->state & CS_CHECKMSR) {
3019			u_char	delta_modem_status;
3020
3021#ifdef PC98
3022			if (!IS_8251(com->pc98_if_type)) {
3023#endif
3024			disable_intr();
3025			delta_modem_status = com->last_modem_status
3026					     ^ com->prev_modem_status;
3027			com->prev_modem_status = com->last_modem_status;
3028			com_events -= LOTS_OF_EVENTS;
3029			com->state &= ~CS_CHECKMSR;
3030			enable_intr();
3031			if (delta_modem_status & MSR_DCD)
3032				(*linesw[tp->t_line].l_modem)
3033					(tp, com->prev_modem_status & MSR_DCD);
3034#ifdef PC98
3035			}
3036#endif
3037		}
3038		if (com->state & CS_ODONE) {
3039			disable_intr();
3040			com_events -= LOTS_OF_EVENTS;
3041			com->state &= ~CS_ODONE;
3042			enable_intr();
3043			if (!(com->state & CS_BUSY)
3044			    && !(com->extra_state & CSE_BUSYCHECK)) {
3045				timeout(siobusycheck, com, hz / 100);
3046				com->extra_state |= CSE_BUSYCHECK;
3047			}
3048			(*linesw[tp->t_line].l_start)(tp);
3049		}
3050		if (incc <= 0 || !(tp->t_state & TS_ISOPEN) ||
3051		    !(tp->t_cflag & CREAD))
3052			continue;
3053		/*
3054		 * Avoid the grotesquely inefficient lineswitch routine
3055		 * (ttyinput) in "raw" mode.  It usually takes about 450
3056		 * instructions (that's without canonical processing or echo!).
3057		 * slinput is reasonably fast (usually 40 instructions plus
3058		 * call overhead).
3059		 */
3060		if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
3061			if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
3062			    && (com->state & CS_RTS_IFLOW
3063				|| tp->t_iflag & IXOFF)
3064			    && !(tp->t_state & TS_TBLOCK))
3065				ttyblock(tp);
3066			tk_nin += incc;
3067			tk_rawcc += incc;
3068			tp->t_rawcc += incc;
3069			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
3070				+= b_to_q((char *)buf, incc, &tp->t_rawq);
3071			ttwakeup(tp);
3072			if (tp->t_state & TS_TTSTOP
3073			    && (tp->t_iflag & IXANY
3074				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
3075				tp->t_state &= ~TS_TTSTOP;
3076				tp->t_lflag &= ~FLUSHO;
3077				comstart(tp);
3078			}
3079		} else {
3080			do {
3081				u_char	line_status;
3082				int	recv_data;
3083
3084#ifndef PC98
3085				line_status = (u_char) buf[CE_INPUT_OFFSET];
3086#else
3087				line_status = (u_char) buf[com->CE_INPUT_OFFSET];
3088#endif
3089				recv_data = (u_char) *buf++;
3090				if (line_status
3091				    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
3092					if (line_status & LSR_BI)
3093						recv_data |= TTY_BI;
3094					if (line_status & LSR_FE)
3095						recv_data |= TTY_FE;
3096					if (line_status & LSR_OE)
3097						recv_data |= TTY_OE;
3098					if (line_status & LSR_PE)
3099						recv_data |= TTY_PE;
3100				}
3101				(*linesw[tp->t_line].l_rint)(recv_data, tp);
3102			} while (--incc > 0);
3103		}
3104		if (com_events == 0)
3105			break;
3106	}
3107	if (com_events >= LOTS_OF_EVENTS)
3108		goto repeat;
3109}
3110
3111static int
3112comparam(tp, t)
3113	struct tty	*tp;
3114	struct termios	*t;
3115{
3116	u_int		cfcr;
3117	int		cflag;
3118	struct com_s	*com;
3119	int		divisor;
3120	u_char		dlbh;
3121	u_char		dlbl;
3122	Port_t		iobase;
3123	int		s;
3124	int		unit;
3125#ifdef PC98
3126	int		port_shift = 0;
3127	u_char		param = 0;
3128#endif
3129
3130#ifdef PC98
3131	cfcr = 0;
3132	unit = DEV_TO_UNIT(tp->t_dev);
3133	com = com_addr(unit);
3134	iobase = com->iobase;
3135	if (IS_8251(com->pc98_if_type)) {
3136	    divisor = pc98_ttspeedtab(com, t->c_ospeed);
3137	} else {
3138	    port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
3139
3140	    /* do historical conversions */
3141	    if (t->c_ispeed == 0)
3142		t->c_ispeed = t->c_ospeed;
3143
3144	    /* check requested parameters */
3145	    divisor = ttspeedtab(t->c_ospeed,
3146			if_16550a_type[com->pc98_if_type & 0x0f].speedtab);
3147	}
3148#else
3149	/* do historical conversions */
3150	if (t->c_ispeed == 0)
3151		t->c_ispeed = t->c_ospeed;
3152
3153	/* check requested parameters */
3154	divisor = ttspeedtab(t->c_ospeed, comspeedtab);
3155#endif
3156	if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed)
3157		return (EINVAL);
3158
3159	/* parameters are OK, convert them to the com struct and the device */
3160#ifndef PC98
3161	unit = DEV_TO_UNIT(tp->t_dev);
3162	com = com_addr(unit);
3163	iobase = com->iobase;
3164#endif
3165	s = spltty();
3166#ifdef PC98
3167	if (IS_8251(com->pc98_if_type)) {
3168		if (divisor == 0)
3169			com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
3170		else
3171			com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
3172	} else {
3173#endif
3174	if (divisor == 0)
3175		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
3176	else
3177		(void)commctl(com, TIOCM_DTR, DMBIS);
3178#ifdef PC98
3179	}
3180#endif
3181	cflag = t->c_cflag;
3182#ifdef PC98
3183	if (!IS_8251(com->pc98_if_type)) {
3184#endif
3185	switch (cflag & CSIZE) {
3186	case CS5:
3187		cfcr = CFCR_5BITS;
3188		break;
3189	case CS6:
3190		cfcr = CFCR_6BITS;
3191		break;
3192	case CS7:
3193		cfcr = CFCR_7BITS;
3194		break;
3195	default:
3196		cfcr = CFCR_8BITS;
3197		break;
3198	}
3199	if (cflag & PARENB) {
3200		cfcr |= CFCR_PENAB;
3201		if (!(cflag & PARODD))
3202			cfcr |= CFCR_PEVEN;
3203	}
3204	if (cflag & CSTOPB)
3205		cfcr |= CFCR_STOPB;
3206
3207	if (com->hasfifo && divisor != 0) {
3208		/*
3209		 * Use a fifo trigger level low enough so that the input
3210		 * latency from the fifo is less than about 16 msec and
3211		 * the total latency is less than about 30 msec.  These
3212		 * latencies are reasonable for humans.  Serial comms
3213		 * protocols shouldn't expect anything better since modem
3214		 * latencies are larger.
3215		 */
3216		com->fifo_image = t->c_ospeed <= 4800
3217				  ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH;
3218#ifdef COM_ESP
3219		/*
3220		 * The Hayes ESP card needs the fifo DMA mode bit set
3221		 * in compatibility mode.  If not, it will interrupt
3222		 * for each character received.
3223		 */
3224		if (com->esp)
3225			com->fifo_image |= FIFO_DMA_MODE;
3226#endif
3227#ifdef PC98
3228		outb(iobase + (com_fifo << port_shift), com->fifo_image);
3229#else
3230		outb(iobase + com_fifo, com->fifo_image);
3231#endif
3232	}
3233#ifdef PC98
3234	}
3235#endif
3236
3237  	disable_intr();		/* very important while com_data is hidden */
3238
3239#ifdef PC98
3240	if (IS_8251(com->pc98_if_type))
3241	    com_cflag_and_speed_set(com, cflag, t->c_ospeed);
3242	else {
3243#endif
3244	if (divisor != 0) {
3245#ifdef PC98
3246		outb(iobase + (com_cfcr << port_shift), cfcr | CFCR_DLAB);
3247#else
3248		outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
3249#endif
3250		/*
3251		 * Only set the divisor registers if they would change,
3252		 * since on some 16550 incompatibles (UMC8669F), setting
3253		 * them while input is arriving them loses sync until
3254		 * data stops arriving.
3255		 */
3256		dlbl = divisor & 0xFF;
3257#ifdef PC98
3258		if (inb(iobase + (com_dlbl << port_shift)) != dlbl)
3259			outb(iobase + (com_dlbl << port_shift), dlbl);
3260		dlbh = (u_int) divisor >> 8;
3261		if (inb(iobase + (com_dlbh << port_shift)) != dlbh)
3262			outb(iobase + (com_dlbh << port_shift), dlbh);
3263#else
3264		if (inb(iobase + com_dlbl) != dlbl)
3265			outb(iobase + com_dlbl, dlbl);
3266		dlbh = (u_int) divisor >> 8;
3267		if (inb(iobase + com_dlbh) != dlbh)
3268			outb(iobase + com_dlbh, dlbh);
3269#endif
3270	}
3271
3272
3273#ifdef PC98
3274	}
3275	outb(iobase + (com_cfcr << port_shift), com->cfcr_image = cfcr);
3276#else
3277	outb(iobase + com_cfcr, com->cfcr_image = cfcr);
3278#endif
3279
3280	if (!(tp->t_state & TS_TTSTOP))
3281		com->state |= CS_TTGO;
3282
3283	if (cflag & CRTS_IFLOW) {
3284		if (com->st16650a) {
3285			outb(iobase + com_cfcr, 0xbf);
3286			outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40);
3287		}
3288		com->state |= CS_RTS_IFLOW;
3289		/*
3290		 * If CS_RTS_IFLOW just changed from off to on, the change
3291		 * needs to be propagated to MCR_RTS.  This isn't urgent,
3292		 * so do it later by calling comstart() instead of repeating
3293		 * a lot of code from comstart() here.
3294		 */
3295	} else if (com->state & CS_RTS_IFLOW) {
3296		com->state &= ~CS_RTS_IFLOW;
3297		/*
3298		 * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
3299		 * on here, since comstart() won't do it later.
3300		 */
3301#ifdef PC98
3302		if (IS_8251(com->pc98_if_type))
3303			com_tiocm_bis(com, TIOCM_RTS);
3304		else
3305#endif
3306		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3307		if (com->st16650a) {
3308			outb(iobase + com_cfcr, 0xbf);
3309			outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40);
3310		}
3311	}
3312
3313
3314	/*
3315	 * Set up state to handle output flow control.
3316	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
3317	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
3318	 */
3319	com->state |= CS_ODEVREADY;
3320	com->state &= ~CS_CTS_OFLOW;
3321#ifdef PC98
3322	if (com->pc98_if_type == COM_IF_RSA98III) {
3323		param = inb(com->rsabase + rsa_msr);
3324		outb(com->rsabase + rsa_msr, param & 0x14);
3325	}
3326#endif
3327	if (cflag & CCTS_OFLOW) {
3328		com->state |= CS_CTS_OFLOW;
3329#ifdef PC98
3330		if (IS_8251(com->pc98_if_type)) {
3331			if (!(pc98_get_modem_status(com) & TIOCM_CTS))
3332				com->state &= ~CS_ODEVREADY;
3333		} else {
3334#endif
3335#ifdef PC98
3336		if (com->pc98_if_type == COM_IF_RSA98III) {
3337			/* Set automatic flow control mode */
3338			outb(com->rsabase + rsa_msr, param | 0x08);
3339		} else
3340#endif
3341		if (!(com->last_modem_status & MSR_CTS))
3342			com->state &= ~CS_ODEVREADY;
3343		if (com->st16650a) {
3344			outb(iobase + com_cfcr, 0xbf);
3345			outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80);
3346		}
3347#ifdef PC98
3348		}
3349#endif
3350	} else {
3351		if (com->st16650a) {
3352			outb(iobase + com_cfcr, 0xbf);
3353			outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80);
3354		}
3355	}
3356
3357
3358#ifdef PC98
3359	outb(iobase + (com_cfcr << port_shift), com->cfcr_image);
3360#else
3361	outb(iobase + com_cfcr, com->cfcr_image);
3362#endif
3363
3364
3365	/* XXX shouldn't call functions while intrs are disabled. */
3366	disc_optim(tp, t, com);
3367	/*
3368	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
3369	 * unconditionally, but that defeated the careful discarding of
3370	 * stale input in sioopen().
3371	 */
3372	if (com->state >= (CS_BUSY | CS_TTGO))
3373		siointr1(com);
3374
3375	enable_intr();
3376	splx(s);
3377	comstart(tp);
3378	return (0);
3379}
3380
3381static void
3382comstart(tp)
3383	struct tty	*tp;
3384{
3385	struct com_s	*com;
3386	int		s;
3387	int		unit;
3388#ifdef PC98
3389	int		tmp;
3390#endif
3391
3392	unit = DEV_TO_UNIT(tp->t_dev);
3393	com = com_addr(unit);
3394	s = spltty();
3395	disable_intr();
3396	if (tp->t_state & TS_TTSTOP)
3397		com->state &= ~CS_TTGO;
3398	else
3399		com->state |= CS_TTGO;
3400	if (tp->t_state & TS_TBLOCK) {
3401#ifdef PC98
3402		if (IS_8251(com->pc98_if_type))
3403			tmp = com_tiocm_get(com) & TIOCM_RTS;
3404		else
3405			tmp = com->mcr_image & MCR_RTS;
3406		if (tmp && (com->state & CS_RTS_IFLOW))
3407#else
3408		if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
3409#endif
3410#ifdef PC98
3411			if (IS_8251(com->pc98_if_type))
3412				com_tiocm_bic(com, TIOCM_RTS);
3413			else
3414#endif
3415			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
3416	} else {
3417#ifdef PC98
3418		if (IS_8251(com->pc98_if_type))
3419			tmp = com_tiocm_get(com) & TIOCM_RTS;
3420		else
3421			tmp = com->mcr_image & MCR_RTS;
3422		if (!(tmp) && com->iptr < com->ihighwater
3423			&& com->state & CS_RTS_IFLOW)
3424#else
3425		if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
3426		    && com->state & CS_RTS_IFLOW)
3427#endif
3428#ifdef PC98
3429			if (IS_8251(com->pc98_if_type))
3430				com_tiocm_bis(com, TIOCM_RTS);
3431			else
3432#endif
3433			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3434	}
3435	enable_intr();
3436	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
3437		ttwwakeup(tp);
3438#ifdef PC98
3439/*		if(IS_8251(com->pc98_if_type))
3440			com_int_Tx_enable(com); */
3441#endif
3442		splx(s);
3443		return;
3444	}
3445	if (tp->t_outq.c_cc != 0) {
3446		struct lbq	*qp;
3447		struct lbq	*next;
3448
3449		if (!com->obufs[0].l_queued) {
3450			com->obufs[0].l_tail
3451			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
3452#ifndef PC98
3453						  sizeof com->obuf1);
3454#else
3455						  com->CE_INPUT_OFFSET);
3456#endif
3457			com->obufs[0].l_next = NULL;
3458			com->obufs[0].l_queued = TRUE;
3459			disable_intr();
3460			if (com->state & CS_BUSY) {
3461				qp = com->obufq.l_next;
3462				while ((next = qp->l_next) != NULL)
3463					qp = next;
3464				qp->l_next = &com->obufs[0];
3465			} else {
3466				com->obufq.l_head = com->obufs[0].l_head;
3467				com->obufq.l_tail = com->obufs[0].l_tail;
3468				com->obufq.l_next = &com->obufs[0];
3469				com->state |= CS_BUSY;
3470			}
3471			enable_intr();
3472		}
3473		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
3474			com->obufs[1].l_tail
3475			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
3476#ifndef PC98
3477						  sizeof com->obuf2);
3478#else
3479						  com->CE_INPUT_OFFSET);
3480#endif
3481			com->obufs[1].l_next = NULL;
3482			com->obufs[1].l_queued = TRUE;
3483			disable_intr();
3484			if (com->state & CS_BUSY) {
3485				qp = com->obufq.l_next;
3486				while ((next = qp->l_next) != NULL)
3487					qp = next;
3488				qp->l_next = &com->obufs[1];
3489			} else {
3490				com->obufq.l_head = com->obufs[1].l_head;
3491				com->obufq.l_tail = com->obufs[1].l_tail;
3492				com->obufq.l_next = &com->obufs[1];
3493				com->state |= CS_BUSY;
3494			}
3495			enable_intr();
3496		}
3497		tp->t_state |= TS_BUSY;
3498	}
3499	disable_intr();
3500	if (com->state >= (CS_BUSY | CS_TTGO))
3501		siointr1(com);	/* fake interrupt to start output */
3502	enable_intr();
3503#ifdef PC98
3504/*		if(IS_8251(com->pc98_if_type))
3505			com_int_Tx_enable(com); */
3506#endif
3507	ttwwakeup(tp);
3508	splx(s);
3509}
3510
3511static void
3512siostop(tp, rw)
3513	struct tty	*tp;
3514	int		rw;
3515{
3516	struct com_s	*com;
3517#ifdef PC98
3518	int		port_shift = 0;
3519	int		rsa98_tmp  = 0;
3520#endif
3521
3522	com = com_addr(DEV_TO_UNIT(tp->t_dev));
3523	if (com->gone)
3524		return;
3525#ifdef PC98
3526	if (IS_8251(com->pc98_if_type))
3527	    port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
3528#endif
3529	disable_intr();
3530	if (rw & FWRITE) {
3531		if (com->hasfifo)
3532#ifdef COM_ESP
3533		    /* XXX avoid h/w bug. */
3534		    if (!com->esp)
3535#endif
3536#ifdef PC98
3537			outb(com->iobase + (com_fifo << port_shift),
3538			     FIFO_XMT_RST | com->fifo_image);
3539			if (com->pc98_if_type == COM_IF_RSA98III)
3540			    for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3541				outb(com->iobase + (com_fifo << port_shift),
3542				     FIFO_XMT_RST | com->fifo_image);
3543#else
3544			outb(com->iobase + com_fifo,
3545			     FIFO_XMT_RST | com->fifo_image);
3546#endif
3547		com->obufs[0].l_queued = FALSE;
3548		com->obufs[1].l_queued = FALSE;
3549		if (com->state & CS_ODONE)
3550			com_events -= LOTS_OF_EVENTS;
3551		com->state &= ~(CS_ODONE | CS_BUSY);
3552		com->tp->t_state &= ~TS_BUSY;
3553	}
3554	if (rw & FREAD) {
3555		if (com->hasfifo)
3556#ifdef COM_ESP
3557		    /* XXX avoid h/w bug. */
3558		    if (!com->esp)
3559#endif
3560#ifdef PC98
3561			if (com->pc98_if_type == COM_IF_RSA98III) {
3562			    for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3563				inb(com->data_port);
3564			}
3565			outb(com->iobase + (com_fifo << port_shift),
3566			     FIFO_RCV_RST | com->fifo_image);
3567#else
3568			outb(com->iobase + com_fifo,
3569			     FIFO_RCV_RST | com->fifo_image);
3570#endif
3571		com_events -= (com->iptr - com->ibuf);
3572		com->iptr = com->ibuf;
3573	}
3574	enable_intr();
3575	comstart(tp);
3576}
3577
3578static struct tty *
3579siodevtotty(dev)
3580	dev_t	dev;
3581{
3582	int	mynor;
3583	int	unit;
3584
3585	mynor = minor(dev);
3586	if (mynor & CONTROL_MASK)
3587		return (NULL);
3588	unit = MINOR_TO_UNIT(mynor);
3589	if ((u_int) unit >= NSIOTOT)
3590		return (NULL);
3591	return (&sio_tty[unit]);
3592}
3593
3594static int
3595commctl(com, bits, how)
3596	struct com_s	*com;
3597	int		bits;
3598	int		how;
3599{
3600	int	mcr;
3601	int	msr;
3602
3603	if (how == DMGET) {
3604		bits = TIOCM_LE;	/* XXX - always enabled while open */
3605		mcr = com->mcr_image;
3606		if (mcr & MCR_DTR)
3607			bits |= TIOCM_DTR;
3608		if (mcr & MCR_RTS)
3609			bits |= TIOCM_RTS;
3610		msr = com->prev_modem_status;
3611		if (msr & MSR_CTS)
3612			bits |= TIOCM_CTS;
3613		if (msr & MSR_DCD)
3614			bits |= TIOCM_CD;
3615		if (msr & MSR_DSR)
3616			bits |= TIOCM_DSR;
3617		/*
3618		 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
3619		 * more volatile by reading the modem status a lot.  Perhaps
3620		 * we should latch both bits until the status is read here.
3621		 */
3622		if (msr & (MSR_RI | MSR_TERI))
3623			bits |= TIOCM_RI;
3624		return (bits);
3625	}
3626	mcr = 0;
3627	if (bits & TIOCM_DTR)
3628		mcr |= MCR_DTR;
3629	if (bits & TIOCM_RTS)
3630		mcr |= MCR_RTS;
3631	if (com->gone)
3632		return(0);
3633	disable_intr();
3634	switch (how) {
3635	case DMSET:
3636		outb(com->modem_ctl_port,
3637		     com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
3638		break;
3639	case DMBIS:
3640		outb(com->modem_ctl_port, com->mcr_image |= mcr);
3641		break;
3642	case DMBIC:
3643		outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
3644		break;
3645	}
3646	enable_intr();
3647	return (0);
3648}
3649
3650static void
3651siosettimeout()
3652{
3653	struct com_s	*com;
3654	bool_t		someopen;
3655	int		unit;
3656
3657	/*
3658	 * Set our timeout period to 1 second if no polled devices are open.
3659	 * Otherwise set it to max(1/200, 1/hz).
3660	 * Enable timeouts iff some device is open.
3661	 */
3662	untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3663	sio_timeout = hz;
3664	someopen = FALSE;
3665	for (unit = 0; unit < NSIOTOT; ++unit) {
3666		com = com_addr(unit);
3667		if (com != NULL && com->tp != NULL
3668		    && com->tp->t_state & TS_ISOPEN && !com->gone) {
3669			someopen = TRUE;
3670			if (com->poll || com->poll_output) {
3671				sio_timeout = hz > 200 ? hz / 200 : 1;
3672				break;
3673			}
3674		}
3675	}
3676	if (someopen) {
3677		sio_timeouts_until_log = hz / sio_timeout;
3678		sio_timeout_handle = timeout(comwakeup, (void *)NULL,
3679					     sio_timeout);
3680	} else {
3681		/* Flush error messages, if any. */
3682		sio_timeouts_until_log = 1;
3683		comwakeup((void *)NULL);
3684		untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3685	}
3686}
3687
3688static void
3689comwakeup(chan)
3690	void	*chan;
3691{
3692	struct com_s	*com;
3693	int		unit;
3694
3695	sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
3696
3697	/*
3698	 * Recover from lost output interrupts.
3699	 * Poll any lines that don't use interrupts.
3700	 */
3701	for (unit = 0; unit < NSIOTOT; ++unit) {
3702		com = com_addr(unit);
3703		if (com != NULL && !com->gone
3704		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
3705			disable_intr();
3706			siointr1(com);
3707			enable_intr();
3708		}
3709	}
3710
3711	/*
3712	 * Check for and log errors, but not too often.
3713	 */
3714	if (--sio_timeouts_until_log > 0)
3715		return;
3716	sio_timeouts_until_log = hz / sio_timeout;
3717	for (unit = 0; unit < NSIOTOT; ++unit) {
3718		int	errnum;
3719
3720		com = com_addr(unit);
3721		if (com == NULL)
3722			continue;
3723		if (com->gone)
3724			continue;
3725		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
3726			u_int	delta;
3727			u_long	total;
3728
3729			disable_intr();
3730			delta = com->delta_error_counts[errnum];
3731			com->delta_error_counts[errnum] = 0;
3732			enable_intr();
3733			if (delta == 0)
3734				continue;
3735			total = com->error_counts[errnum] += delta;
3736			log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
3737			    unit, delta, error_desc[errnum],
3738			    delta == 1 ? "" : "s", total);
3739		}
3740	}
3741}
3742
3743#ifdef PC98
3744/* commint is called when modem control line changes */
3745static void
3746commint(dev_t dev)
3747{
3748	register struct tty *tp;
3749	int	stat,delta;
3750	struct com_s *com;
3751	int	mynor,unit;
3752
3753	mynor = minor(dev);
3754	unit = MINOR_TO_UNIT(mynor);
3755	com = com_addr(unit);
3756	tp = com->tp;
3757
3758	stat = com_tiocm_get(com);
3759	delta = com_tiocm_get_delta(com);
3760
3761	if (com->state & CS_CTS_OFLOW) {
3762		if (stat & TIOCM_CTS)
3763			com->state |= CS_ODEVREADY;
3764		else
3765			com->state &= ~CS_ODEVREADY;
3766	}
3767	if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) {
3768	    if (stat & TIOCM_CAR )
3769		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
3770	    else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
3771		/* negate DTR, RTS */
3772		com_tiocm_bic(com, (tp->t_cflag & HUPCL) ?
3773				TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE );
3774		/* disable IENABLE */
3775		com_int_TxRx_disable( com );
3776	    }
3777	}
3778}
3779#endif
3780
3781static void
3782disc_optim(tp, t, com)
3783	struct tty	*tp;
3784	struct termios	*t;
3785	struct com_s	*com;
3786{
3787	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
3788	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
3789	    && (!(t->c_iflag & PARMRK)
3790		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
3791	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
3792	    && linesw[tp->t_line].l_rint == ttyinput)
3793		tp->t_state |= TS_CAN_BYPASS_L_RINT;
3794	else
3795		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
3796	com->hotchar = linesw[tp->t_line].l_hotchar;
3797}
3798
3799/*
3800 * Following are all routines needed for SIO to act as console
3801 */
3802#include <machine/cons.h>
3803
3804struct siocnstate {
3805	u_char	dlbl;
3806	u_char	dlbh;
3807	u_char	ier;
3808	u_char	cfcr;
3809	u_char	mcr;
3810};
3811
3812static speed_t siocngetspeed __P((Port_t, struct speedtab *));
3813static void siocnclose	__P((struct siocnstate *sp));
3814static void siocnopen	__P((struct siocnstate *sp));
3815static void siocntxwait	__P((void));
3816
3817/*
3818 * XXX: sciocnget() and sciocnputc() are not declared static, as they are
3819 * referred to from i386/i386/i386-gdbstub.c.
3820 */
3821static cn_probe_t siocnprobe;
3822static cn_init_t siocninit;
3823static cn_checkc_t siocncheckc;
3824       cn_getc_t siocngetc;
3825       cn_putc_t siocnputc;
3826
3827CONS_DRIVER(sio, siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc);
3828
3829static void
3830siocntxwait()
3831{
3832	int	timo;
3833
3834	/*
3835	 * Wait for any pending transmission to finish.  Required to avoid
3836	 * the UART lockup bug when the speed is changed, and for normal
3837	 * transmits.
3838	 */
3839	timo = 100000;
3840	while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
3841	       != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
3842		;
3843}
3844
3845/*
3846 * Read the serial port specified and try to figure out what speed
3847 * it's currently running at.  We're assuming the serial port has
3848 * been initialized and is basicly idle.  This routine is only intended
3849 * to be run at system startup.
3850 *
3851 * If the value read from the serial port doesn't make sense, return 0.
3852 */
3853
3854static speed_t
3855siocngetspeed(iobase, table)
3856	Port_t iobase;
3857	struct speedtab *table;
3858{
3859	int	code;
3860	u_char	dlbh;
3861	u_char	dlbl;
3862	u_char  cfcr;
3863
3864	cfcr = inb(iobase + com_cfcr);
3865	outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3866
3867	dlbl = inb(iobase + com_dlbl);
3868	dlbh = inb(iobase + com_dlbh);
3869
3870	outb(iobase + com_cfcr, cfcr);
3871
3872	code = dlbh << 8 | dlbl;
3873
3874	for ( ; table->sp_speed != -1; table++)
3875		if (table->sp_code == code)
3876			return (table->sp_speed);
3877
3878	return 0;	/* didn't match anything sane */
3879}
3880
3881static void
3882siocnopen(sp)
3883	struct siocnstate	*sp;
3884{
3885	int	divisor;
3886	u_char	dlbh;
3887	u_char	dlbl;
3888	Port_t	iobase;
3889
3890	/*
3891	 * Save all the device control registers except the fifo register
3892	 * and set our default ones (cs8 -parenb speed=comdefaultrate).
3893	 * We can't save the fifo register since it is read-only.
3894	 */
3895	iobase = siocniobase;
3896	sp->ier = inb(iobase + com_ier);
3897	outb(iobase + com_ier, 0);	/* spltty() doesn't stop siointr() */
3898	siocntxwait();
3899	sp->cfcr = inb(iobase + com_cfcr);
3900	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3901	sp->dlbl = inb(iobase + com_dlbl);
3902	sp->dlbh = inb(iobase + com_dlbh);
3903	/*
3904	 * Only set the divisor registers if they would change, since on
3905	 * some 16550 incompatibles (Startech), setting them clears the
3906	 * data input register.  This also reduces the effects of the
3907	 * UMC8669F bug.
3908	 */
3909	divisor = ttspeedtab(comdefaultrate, comspeedtab);
3910	dlbl = divisor & 0xFF;
3911	if (sp->dlbl != dlbl)
3912		outb(iobase + com_dlbl, dlbl);
3913	dlbh = (u_int) divisor >> 8;
3914	if (sp->dlbh != dlbh)
3915		outb(iobase + com_dlbh, dlbh);
3916	outb(iobase + com_cfcr, CFCR_8BITS);
3917	sp->mcr = inb(iobase + com_mcr);
3918	/*
3919	 * We don't want interrupts, but must be careful not to "disable"
3920	 * them by clearing the MCR_IENABLE bit, since that might cause
3921	 * an interrupt by floating the IRQ line.
3922	 */
3923	outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
3924}
3925
3926static void
3927siocnclose(sp)
3928	struct siocnstate	*sp;
3929{
3930	Port_t	iobase;
3931
3932	/*
3933	 * Restore the device control registers.
3934	 */
3935	siocntxwait();
3936	iobase = siocniobase;
3937	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3938	if (sp->dlbl != inb(iobase + com_dlbl))
3939		outb(iobase + com_dlbl, sp->dlbl);
3940	if (sp->dlbh != inb(iobase + com_dlbh))
3941		outb(iobase + com_dlbh, sp->dlbh);
3942	outb(iobase + com_cfcr, sp->cfcr);
3943	/*
3944	 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
3945	 */
3946	outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
3947	outb(iobase + com_ier, sp->ier);
3948}
3949
3950static void
3951siocnprobe(cp)
3952	struct consdev	*cp;
3953{
3954	speed_t			boot_speed;
3955	u_char			cfcr;
3956	struct isa_device	*dvp;
3957	int			s;
3958	struct siocnstate	sp;
3959
3960	/*
3961	 * Find our first enabled console, if any.  If it is a high-level
3962	 * console device, then initialize it and return successfully.
3963	 * If it is a low-level console device, then initialize it and
3964	 * return unsuccessfully.  It must be initialized in both cases
3965	 * for early use by console drivers and debuggers.  Initializing
3966	 * the hardware is not necessary in all cases, since the i/o
3967	 * routines initialize it on the fly, but it is necessary if
3968	 * input might arrive while the hardware is switched back to an
3969	 * uninitialized state.  We can't handle multiple console devices
3970	 * yet because our low-level routines don't take a device arg.
3971	 * We trust the user to set the console flags properly so that we
3972	 * don't need to probe.
3973	 */
3974	cp->cn_pri = CN_DEAD;
3975	for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++)
3976		if (dvp->id_driver == &siodriver && dvp->id_enabled
3977		    && COM_CONSOLE(dvp)) {
3978			siocniobase = dvp->id_iobase;
3979			s = spltty();
3980			if (boothowto & RB_SERIAL) {
3981				boot_speed = siocngetspeed(siocniobase,
3982							   comspeedtab);
3983				if (boot_speed)
3984					comdefaultrate = boot_speed;
3985			}
3986
3987			/*
3988			 * Initialize the divisor latch.  We can't rely on
3989			 * siocnopen() to do this the first time, since it
3990			 * avoids writing to the latch if the latch appears
3991			 * to have the correct value.  Also, if we didn't
3992			 * just read the speed from the hardware, then we
3993			 * need to set the speed in hardware so that
3994			 * switching it later is null.
3995			 */
3996			cfcr = inb(siocniobase + com_cfcr);
3997			outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr);
3998			outb(siocniobase + com_dlbl,
3999			     COMBRD(comdefaultrate) & 0xff);
4000			outb(siocniobase + com_dlbh,
4001			     (u_int) COMBRD(comdefaultrate) >> 8);
4002			outb(siocniobase + com_cfcr, cfcr);
4003
4004			siocnopen(&sp);
4005			splx(s);
4006			if (!COM_LLCONSOLE(dvp)) {
4007				cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit);
4008				cp->cn_pri = COM_FORCECONSOLE(dvp)
4009					     || boothowto & RB_SERIAL
4010					     ? CN_REMOTE : CN_NORMAL;
4011			}
4012			break;
4013		}
4014}
4015
4016static void
4017siocninit(cp)
4018	struct consdev	*cp;
4019{
4020	comconsole = DEV_TO_UNIT(cp->cn_dev);
4021}
4022
4023static int
4024siocncheckc(dev)
4025	dev_t	dev;
4026{
4027	int	c;
4028	Port_t	iobase;
4029	int	s;
4030	struct siocnstate	sp;
4031
4032	iobase = siocniobase;
4033	s = spltty();
4034	siocnopen(&sp);
4035	if (inb(iobase + com_lsr) & LSR_RXRDY)
4036		c = inb(iobase + com_data);
4037	else
4038		c = -1;
4039	siocnclose(&sp);
4040	splx(s);
4041	return (c);
4042}
4043
4044
4045int
4046siocngetc(dev)
4047	dev_t	dev;
4048{
4049	int	c;
4050	Port_t	iobase;
4051	int	s;
4052	struct siocnstate	sp;
4053
4054	iobase = siocniobase;
4055	s = spltty();
4056	siocnopen(&sp);
4057	while (!(inb(iobase + com_lsr) & LSR_RXRDY))
4058		;
4059	c = inb(iobase + com_data);
4060	siocnclose(&sp);
4061	splx(s);
4062	return (c);
4063}
4064
4065void
4066siocnputc(dev, c)
4067	dev_t	dev;
4068	int	c;
4069{
4070	int	s;
4071	struct siocnstate	sp;
4072
4073	s = spltty();
4074	siocnopen(&sp);
4075	siocntxwait();
4076	outb(siocniobase + com_data, c);
4077	siocnclose(&sp);
4078	splx(s);
4079}
4080
4081
4082/*
4083 * support PnP cards if we are using 'em
4084 */
4085
4086#if NPNP > 0
4087
4088static pnpid_t siopnp_ids[] = {
4089	{ 0x5015f435, "MOT1550"},
4090	{ 0x8113b04e, "Supra1381"},
4091	{ 0x9012b04e, "Supra1290"},
4092	{ 0x7121b04e, "SupraExpress 56i Sp"},
4093	{ 0x11007256, "USR0011"},
4094	{ 0x30207256, "USR2030"},
4095	{ 0x31307256, "USR3031"},
4096	{ 0 }
4097};
4098
4099static char *siopnp_probe(u_long csn, u_long vend_id);
4100static void siopnp_attach(u_long csn, u_long vend_id, char *name,
4101	struct isa_device *dev);
4102static u_long nsiopnp = NSIO;
4103
4104static struct pnp_device siopnp = {
4105	"siopnp",
4106	siopnp_probe,
4107	siopnp_attach,
4108	&nsiopnp,
4109	&tty_imask
4110};
4111DATA_SET (pnpdevice_set, siopnp);
4112
4113static char *
4114siopnp_probe(u_long csn, u_long vend_id)
4115{
4116	pnpid_t *id;
4117	char *s = NULL;
4118
4119	for(id = siopnp_ids; id->vend_id != 0; id++) {
4120		if (vend_id == id->vend_id) {
4121			s = id->id_str;
4122			break;
4123		}
4124	}
4125
4126	if (s) {
4127		struct pnp_cinfo d;
4128		read_pnp_parms(&d, 0);
4129		if (d.enable == 0 || d.flags & 1) {
4130			printf("CSN %lu is disabled.\n", csn);
4131			return (NULL);
4132		}
4133
4134	}
4135
4136	return (s);
4137}
4138
4139static void
4140siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
4141{
4142	struct pnp_cinfo d;
4143	struct isa_device *dvp;
4144
4145	if (dev->id_unit >= NSIOTOT)
4146		return;
4147
4148	if (read_pnp_parms(&d, 0) == 0) {
4149		printf("failed to read pnp parms\n");
4150		return;
4151	}
4152
4153	write_pnp_parms(&d, 0);
4154
4155	enable_pnp_card();
4156
4157	dev->id_iobase = d.port[0];
4158	dev->id_irq = (1 << d.irq[0]);
4159	dev->id_ointr = siointr;
4160	dev->id_ri_flags = RI_FAST;
4161	dev->id_drq = -1;
4162
4163	if (dev->id_driver == NULL) {
4164		dev->id_driver = &siodriver;
4165		dvp = find_isadev(isa_devtab_tty, &siodriver, 0);
4166		if (dvp != NULL)
4167			dev->id_id = dvp->id_id;
4168	}
4169
4170	if ((dev->id_alive = sioprobe(dev)) != 0)
4171		sioattach(dev);
4172	else
4173		printf("sio%d: probe failed\n", dev->id_unit);
4174}
4175#endif
4176
4177#ifdef PC98
4178/*
4179 *  pc98 local function
4180 */
4181
4182static void
4183com_tiocm_set(struct com_s *com, int msr)
4184{
4185	int	s;
4186	int	tmp = 0;
4187	int	mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS;
4188
4189	s=spltty();
4190	com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) )
4191	   | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4192	tmp |= (CMD8251_TxEN|CMD8251_RxEN);
4193	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4194	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4195	pc98_i8251_clear_or_cmd( com, mask, tmp );
4196	splx(s);
4197}
4198
4199static void
4200com_tiocm_bis(struct com_s *com, int msr)
4201{
4202	int	s;
4203	int	tmp = 0;
4204
4205	s=spltty();
4206	com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4207	tmp |= CMD8251_TxEN|CMD8251_RxEN;
4208	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4209	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4210
4211	pc98_i8251_or_cmd( com, tmp );
4212	splx(s);
4213}
4214
4215static void
4216com_tiocm_bic(struct com_s *com, int msr)
4217{
4218	int	s;
4219	int	tmp = msr;
4220
4221	s=spltty();
4222	com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4223	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4224	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4225
4226	pc98_i8251_clear_cmd( com, tmp );
4227	splx(s);
4228}
4229
4230static int
4231com_tiocm_get(struct com_s *com)
4232{
4233	return( com->pc98_prev_modem_status );
4234}
4235
4236static int
4237com_tiocm_get_delta(struct com_s *com)
4238{
4239	int	tmp;
4240
4241	tmp = com->pc98_modem_delta;
4242	com->pc98_modem_delta = 0;
4243	return( tmp );
4244}
4245
4246/* convert to TIOCM_?? ( ioctl.h ) */
4247static int
4248pc98_get_modem_status(struct com_s *com)
4249{
4250	int	stat, stat2;
4251	register int	msr;
4252
4253	stat  = inb(com->sts_port);
4254	stat2 = inb(com->in_modem_port);
4255	msr = com->pc98_prev_modem_status
4256			& ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4257	if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR;
4258	if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI;
4259	if (   stat & STS8251_DSR ) msr |= TIOCM_DSR;
4260	if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS;
4261#if COM_CARRIER_DETECT_EMULATE
4262	if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
4263		msr |= TIOCM_CAR;
4264	}
4265#endif
4266	return(msr);
4267}
4268
4269static void
4270pc98_check_msr(void* chan)
4271{
4272	int	msr, delta;
4273	int	s;
4274	register struct tty *tp;
4275	struct	com_s *com;
4276	int	mynor;
4277	int	unit;
4278	dev_t	dev;
4279
4280	dev=(dev_t)chan;
4281	mynor = minor(dev);
4282	unit = MINOR_TO_UNIT(mynor);
4283	com = com_addr(unit);
4284	tp = com->tp;
4285
4286	s = spltty();
4287	msr = pc98_get_modem_status(com);
4288	/* make change flag */
4289	delta = msr ^ com->pc98_prev_modem_status;
4290	if ( delta & TIOCM_CAR ) {
4291	    if ( com->modem_car_chg_timer ) {
4292		if ( -- com->modem_car_chg_timer )
4293		    msr ^= TIOCM_CAR;
4294	    } else {
4295		if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ?
4296			     DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE )
4297		    msr ^= TIOCM_CAR;
4298	    }
4299	} else
4300	    com->modem_car_chg_timer = 0;
4301	delta = ( msr ^ com->pc98_prev_modem_status ) &
4302			(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4303	com->pc98_prev_modem_status = msr;
4304	delta = ( com->pc98_modem_delta |= delta );
4305	splx(s);
4306	if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) {
4307		if ( delta ) {
4308			commint(dev);
4309		}
4310		timeout(pc98_check_msr, (caddr_t)dev,
4311					PC98_CHECK_MODEM_INTERVAL);
4312	} else {
4313		com->modem_checking = 0;
4314	}
4315}
4316
4317static void
4318pc98_msrint_start(dev_t dev)
4319{
4320	struct	com_s *com;
4321	int	mynor;
4322	int	unit;
4323	int	s = spltty();
4324
4325	mynor = minor(dev);
4326	unit = MINOR_TO_UNIT(mynor);
4327	com = com_addr(unit);
4328	/* modem control line check routine envoke interval is 1/10 sec */
4329	if ( com->modem_checking == 0 ) {
4330		com->pc98_prev_modem_status = pc98_get_modem_status(com);
4331		com->pc98_modem_delta = 0;
4332		timeout(pc98_check_msr, (caddr_t)dev,
4333					PC98_CHECK_MODEM_INTERVAL);
4334		com->modem_checking = 1;
4335	}
4336	splx(s);
4337}
4338
4339static void
4340pc98_disable_i8251_interrupt(struct com_s *com, int mod)
4341{
4342	/* disable interrupt */
4343	register int	tmp;
4344
4345	mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4346	COM_INT_DISABLE
4347	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4348	outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp );
4349	COM_INT_ENABLE
4350}
4351
4352static void
4353pc98_enable_i8251_interrupt(struct com_s *com, int mod)
4354{
4355	register int	tmp;
4356
4357	COM_INT_DISABLE
4358	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4359	outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp );
4360	COM_INT_ENABLE
4361}
4362
4363static int
4364pc98_check_i8251_interrupt(struct com_s *com)
4365{
4366	return ( com->intr_enable & 0x07 );
4367}
4368
4369static void
4370pc98_i8251_clear_cmd(struct com_s *com, int x)
4371{
4372	int	tmp;
4373
4374	COM_INT_DISABLE
4375	tmp = com->pc98_prev_siocmd & ~(x);
4376	outb(com->cmd_port, tmp);
4377	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4378	COM_INT_ENABLE
4379}
4380
4381static void
4382pc98_i8251_or_cmd(struct com_s *com, int x)
4383{
4384	int	tmp;
4385
4386	COM_INT_DISABLE
4387	tmp = com->pc98_prev_siocmd | (x);
4388	outb(com->cmd_port, tmp);
4389	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4390	COM_INT_ENABLE
4391}
4392
4393static void
4394pc98_i8251_set_cmd(struct com_s *com, int x)
4395{
4396	int	tmp;
4397
4398	COM_INT_DISABLE
4399	tmp = (x);
4400	outb(com->cmd_port, tmp);
4401	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4402	COM_INT_ENABLE
4403}
4404
4405static void
4406pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x)
4407{
4408	int	tmp;
4409	COM_INT_DISABLE
4410	tmp = com->pc98_prev_siocmd & ~(clr);
4411	tmp |= (x);
4412	outb(com->cmd_port, tmp);
4413	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4414	COM_INT_ENABLE
4415}
4416
4417static int
4418pc98_i8251_get_cmd(struct com_s *com)
4419{
4420	return com->pc98_prev_siocmd;
4421}
4422
4423static int
4424pc98_i8251_get_mod(struct com_s *com)
4425{
4426	return com->pc98_prev_siomod;
4427}
4428
4429static void
4430pc98_i8251_reset(struct com_s *com, int mode, int command)
4431{
4432	outb(com->cmd_port, 0);	/* dummy */
4433	DELAY(2);
4434	outb(com->cmd_port, 0);	/* dummy */
4435	DELAY(2);
4436	outb(com->cmd_port, 0);	/* dummy */
4437	DELAY(2);
4438	outb(com->cmd_port, CMD8251_RESET);	/* internal reset */
4439	DELAY(2);
4440	outb(com->cmd_port, mode );	/* mode register */
4441	com->pc98_prev_siomod = mode;
4442	DELAY(2);
4443	pc98_i8251_set_cmd( com, (command|CMD8251_ER) );
4444}
4445
4446static void
4447pc98_check_sysclock(void)
4448{
4449	/* get system clock from port */
4450	if ( pc98_machine_type & M_8M ) {
4451	/* 8 MHz system & H98 */
4452		sysclock = 8;
4453	} else {
4454	/* 5 MHz system */
4455		sysclock = 5;
4456	}
4457}
4458
4459static void
4460com_cflag_and_speed_set( struct com_s *com, int cflag, int speed)
4461{
4462	int	cfcr=0, count;
4463	int	previnterrupt;
4464
4465	count = pc98_ttspeedtab( com, speed );
4466	if ( count < 0 ) return;
4467
4468	previnterrupt = pc98_check_i8251_interrupt(com);
4469	pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx );
4470
4471	switch ( cflag&CSIZE ) {
4472	  case CS5:
4473		cfcr = MOD8251_5BITS; break;
4474	  case CS6:
4475		cfcr = MOD8251_6BITS; break;
4476	  case CS7:
4477		cfcr = MOD8251_7BITS; break;
4478	  case CS8:
4479		cfcr = MOD8251_8BITS; break;
4480	}
4481	if ( cflag&PARENB ) {
4482	    if ( cflag&PARODD )
4483		cfcr |= MOD8251_PODD;
4484	    else
4485		cfcr |= MOD8251_PEVEN;
4486	} else
4487		cfcr |= MOD8251_PDISAB;
4488
4489	if ( cflag&CSTOPB )
4490		cfcr |= MOD8251_STOP2;
4491	else
4492		cfcr |= MOD8251_STOP1;
4493
4494	if ( count & 0x10000 )
4495		cfcr |= MOD8251_CLKX1;
4496	else
4497		cfcr |= MOD8251_CLKX16;
4498
4499	if (epson_machine_id != 0x20) {	/* XXX */
4500		int	tmp;
4501		while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP))
4502			;
4503	}
4504	/* set baud rate from ospeed */
4505	pc98_set_baud_rate( com, count );
4506
4507	if ( cfcr != pc98_i8251_get_mod(com) )
4508		pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) );
4509
4510	pc98_enable_i8251_interrupt( com, previnterrupt );
4511}
4512
4513static int
4514pc98_ttspeedtab(struct com_s *com, int speed)
4515{
4516	int	if_type, effect_sp, count = -1, mod;
4517
4518	if_type = com->pc98_if_type & 0x0f;
4519
4520	switch (com->pc98_if_type) {
4521	case COM_IF_INTERNAL:
4522	    if (PC98SIO_baud_rate_port(if_type) != -1) {
4523		count = ttspeedtab(speed, if_8251_type[if_type].speedtab);
4524		if (count > 0) {
4525		    count |= COM1_EXT_CLOCK;
4526		    break;
4527		}
4528	    }
4529
4530	    /* for *1CLK asynchronous! mode, TEFUTEFU */
4531	    mod = (sysclock == 5) ? 2457600 : 1996800;
4532	    effect_sp = ttspeedtab( speed, pc98speedtab );
4533	    if ( effect_sp < 0 )	/* XXX */
4534		effect_sp = ttspeedtab( (speed - 1), pc98speedtab );
4535	    if ( effect_sp <= 0 )
4536		return effect_sp;
4537	    if ( effect_sp == speed )
4538		mod /= 16;
4539	    if ( mod % effect_sp )
4540		return(-1);
4541	    count = mod / effect_sp;
4542	    if ( count > 65535 )
4543		return(-1);
4544	    if ( effect_sp != speed )
4545		count |= 0x10000;
4546	    break;
4547	case COM_IF_PC9861K_1:
4548	case COM_IF_PC9861K_2:
4549	    count = 1;
4550	    break;
4551	case COM_IF_IND_SS_1:
4552	case COM_IF_IND_SS_2:
4553	case COM_IF_PIO9032B_1:
4554	case COM_IF_PIO9032B_2:
4555	    if ( speed == 0 ) return 0;
4556	    count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4557	    break;
4558	case COM_IF_B98_01_1:
4559	case COM_IF_B98_01_2:
4560	    if ( speed == 0 ) return 0;
4561	    count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4562#ifdef B98_01_OLD
4563	    if (count == 0 || count == 1) {
4564		count += 4;
4565		count |= 0x20000;  /* x1 mode for 76800 and 153600 */
4566	    }
4567#endif
4568	    break;
4569	}
4570
4571	return count;
4572}
4573
4574static void
4575pc98_set_baud_rate( struct com_s *com, int count )
4576{
4577	int	if_type, io, s;
4578
4579	if_type = com->pc98_if_type & 0x0f;
4580	io = com->iobase & 0xff00;
4581
4582	switch (com->pc98_if_type) {
4583	case COM_IF_INTERNAL:
4584	    if (PC98SIO_baud_rate_port(if_type) != -1) {
4585		if (count & COM1_EXT_CLOCK) {
4586		    outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff);
4587		    break;
4588		} else {
4589		    outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09);
4590		}
4591	    }
4592
4593	    if ( count < 0 ) {
4594		printf( "[ Illegal count : %d ]", count );
4595		return;
4596	    } else if ( count == 0 )
4597		return;
4598	    /* set i8253 */
4599	    s = splclock();
4600	    if (count != 3)
4601		outb( 0x77, 0xb6 );
4602	    else
4603		outb( 0x77, 0xb4 );
4604	    outb( 0x5f, 0);
4605	    outb( 0x75, count & 0xff );
4606	    outb( 0x5f, 0);
4607	    outb( 0x75, (count >> 8) & 0xff );
4608	    splx(s);
4609	    break;
4610	case COM_IF_IND_SS_1:
4611	case COM_IF_IND_SS_2:
4612	    outb(io | PC98SIO_intr_ctrl_port(if_type), 0);
4613	    outb(io | PC98SIO_baud_rate_port(if_type), 0);
4614	    outb(io | PC98SIO_baud_rate_port(if_type), 0xc0);
4615	    outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80);
4616	    outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff);
4617	    break;
4618	case COM_IF_PIO9032B_1:
4619	case COM_IF_PIO9032B_2:
4620	    outb(io | PC98SIO_baud_rate_port(if_type), count);
4621	    break;
4622	case COM_IF_B98_01_1:
4623	case COM_IF_B98_01_2:
4624	    outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f);
4625#ifdef B98_01_OLD
4626	    /*
4627	     * Some old B98_01 board should be controlled
4628	     * in different way, but this hasn't been tested yet.
4629	     */
4630	    outb(io | PC98SIO_func_port(if_type),
4631		 (count & 0x20000) ? 0xf0 : 0xf2);
4632#endif
4633	    break;
4634	}
4635}
4636static int
4637pc98_check_if_type(struct isa_device *dev, struct siodev *iod)
4638{
4639	int	irr, io, if_type, tmp;
4640	static  short	irq_tab[2][8] = {
4641		{  3,  5,  6,  9, 10, 12, 13, -1},
4642		{  3, 10, 12, 13,  5,  6,  9, -1}
4643	};
4644
4645	iod->if_type = if_type = (dev->id_flags >> 24) & 0xff;
4646	if ((if_type < 0 || if_type > COM_IF_END1) &&
4647	    (if_type < 0x10 || if_type > COM_IF_END2))
4648	    return(-1);
4649	if_type &= 0x0f;
4650	iod->irq = 0;
4651	io = dev->id_iobase & 0xff00;
4652
4653	if (IS_8251(iod->if_type)) {
4654	    if (PC98SIO_func_port(if_type) != -1) {
4655		outb(io | PC98SIO_func_port(if_type), 0xf2);
4656		tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab);
4657		if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1)
4658		    outb(io | PC98SIO_baud_rate_port(if_type), tmp);
4659	    }
4660
4661	    iod->cmd  = io | PC98SIO_cmd_port(if_type);
4662	    iod->sts  = io | PC98SIO_sts_port(if_type);
4663	    iod->mod  = io | PC98SIO_in_modem_port(if_type);
4664	    iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type);
4665
4666	    if (iod->if_type == COM_IF_INTERNAL) {
4667		iod->irq = 4;
4668
4669		/* XXX check new internal port. */
4670		outb(0x138, 0);
4671		DELAY(10);
4672		for (tmp = 0; tmp < 100; tmp++) {
4673		    if ((inb(0x138) & 1) == 0) {
4674			PC98SIO_baud_rate_port(if_type) = 0x13a;
4675			if_8251_type[if_type].name = " (internal fast)";
4676			if_8251_type[if_type].speedtab = pc98fast_speedtab;
4677			break;
4678		    }
4679		    DELAY(1);
4680		}
4681	    } else {
4682		tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask;
4683		if ((dev->id_iobase & 0xff) == IO_COM2)
4684		    iod->irq = irq_tab[0][tmp];
4685		else
4686		    iod->irq = irq_tab[1][tmp];
4687	    }
4688	} else {
4689	    irr = if_16550a_type[if_type].irr_read;
4690#ifdef COM_MULTIPORT
4691	    if (!COM_ISMULTIPORT(dev) || dev->id_unit == COM_MPMASTER(dev))
4692#endif
4693	    if (irr != -1) {
4694		tmp = inb(io | irr);
4695		if (dev->id_iobase & 0x01)	/* XXX depend on RSB-384 */
4696		    iod->irq = irq_tab[1][tmp >> 3];
4697		else
4698		    iod->irq = irq_tab[0][tmp & 0x07];
4699	    }
4700	}
4701	if ( iod->irq == -1 ) return -1;
4702
4703	return 0;
4704}
4705static int
4706pc98_set_ioport( struct com_s *com, int id_flags )
4707{
4708	int	io, if_type;
4709
4710	if_type = (id_flags >> 24) & 0xff;
4711	if (IS_8251(if_type)) {
4712	    pc98_check_sysclock();
4713	    io = com->iobase & 0xff00;
4714	    com->pc98_if_type	= if_type;
4715	    if_type &= 0x0f;
4716	    com->data_port	= io | PC98SIO_data_port(if_type);
4717	    com->cmd_port	= io | PC98SIO_cmd_port(if_type);
4718	    com->sts_port	= io | PC98SIO_sts_port(if_type);
4719	    com->in_modem_port	= io | PC98SIO_in_modem_port(if_type);
4720	    com->intr_ctrl_port	= io | PC98SIO_intr_ctrl_port(if_type);
4721	    return 0;
4722	}
4723
4724	return -1;
4725}
4726#endif /* PC98 defined */
4727