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