sio.c revision 22200
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 *	$FreeBSD: head/sys/pc98/cbus/sio.c 22200 1997-02-02 08:09:41Z kato $
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/file.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 <i386/isa/icu.h>
142#include <i386/isa/isa_device.h>
143#include <pc98/pc98/sioreg.h>
144#include <i386/isa/ic/i8251.h>
145#else
146#include <i386/isa/isa.h>
147#include <i386/isa/isa_device.h>
148#include <i386/isa/sioreg.h>
149#endif
150
151#ifdef COM_ESP
152#include <i386/isa/ic/esp.h>
153#endif
154#include <i386/isa/ic/ns16550.h>
155
156#include "crd.h"
157#if NCRD > 0
158#include <pccard/card.h>
159#include <pccard/driver.h>
160#include <pccard/slot.h>
161#endif
162
163#define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
164#define	RB_I_HIGH_WATER	(TTYHOG - 2 * RS_IBUFSIZE)
165#define	RS_IBUFSIZE	256
166
167#define	CALLOUT_MASK		0x80
168#define	CONTROL_MASK		0x60
169#define	CONTROL_INIT_STATE	0x20
170#define	CONTROL_LOCK_STATE	0x40
171#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
172#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
173#define	MINOR_TO_UNIT(mynor)	((mynor) & ~MINOR_MAGIC_MASK)
174
175#ifdef COM_MULTIPORT
176/* checks in flags for multiport and which is multiport "master chip"
177 * for a given card
178 */
179#define	COM_ISMULTIPORT(dev)	((dev)->id_flags & 0x01)
180#define	COM_MPMASTER(dev)	(((dev)->id_flags >> 8) & 0x0ff)
181#define	COM_NOTAST4(dev)	((dev)->id_flags & 0x04)
182#endif /* COM_MULTIPORT */
183
184#define	COM_LOSESOUTINTS(dev)	((dev)->id_flags & 0x08)
185#define	COM_NOFIFO(dev)		((dev)->id_flags & 0x02)
186#define	COM_VERBOSE(dev)	((dev)->id_flags & 0x80)
187
188#ifndef PC98
189#define	com_scr		7	/* scratch register for 16450-16550 (R/W) */
190#endif /* !PC98 */
191
192/*
193 * Input buffer watermarks.
194 * The external device is asked to stop sending when the buffer exactly reaches
195 * high water, or when the high level requests it.
196 * The high level is notified immediately (rather than at a later clock tick)
197 * when this watermark is reached.
198 * The buffer size is chosen so the watermark should almost never be reached.
199 * The low watermark is invisibly 0 since the buffer is always emptied all at
200 * once.
201 */
202#define	RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
203
204/*
205 * com state bits.
206 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
207 * than the other bits so that they can be tested as a group without masking
208 * off the low bits.
209 *
210 * The following com and tty flags correspond closely:
211 *	CS_BUSY		= TS_BUSY (maintained by comstart(), siopoll() and
212 *				   siostop())
213 *	CS_TTGO		= ~TS_TTSTOP (maintained by comparam() and comstart())
214 *	CS_CTS_OFLOW	= CCTS_OFLOW (maintained by comparam())
215 *	CS_RTS_IFLOW	= CRTS_IFLOW (maintained by comparam())
216 * TS_FLUSH is not used.
217 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
218 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
219 */
220#define	CS_BUSY		0x80	/* output in progress */
221#define	CS_TTGO		0x40	/* output not stopped by XOFF */
222#define	CS_ODEVREADY	0x20	/* external device h/w ready (CTS) */
223#define	CS_CHECKMSR	1	/* check of MSR scheduled */
224#define	CS_CTS_OFLOW	2	/* use CTS output flow control */
225#define	CS_DTR_OFF	0x10	/* DTR held off */
226#define	CS_ODONE	4	/* output completed */
227#define	CS_RTS_IFLOW	8	/* use RTS input flow control */
228
229static	char const * const	error_desc[] = {
230#define	CE_OVERRUN			0
231	"silo overflow",
232#define	CE_INTERRUPT_BUF_OVERFLOW	1
233	"interrupt-level buffer overflow",
234#define	CE_TTY_BUF_OVERFLOW		2
235	"tty-level buffer overflow",
236};
237
238#define	CE_NTYPES			3
239#define	CE_RECORD(com, errnum)		(++(com)->delta_error_counts[errnum])
240
241/* types.  XXX - should be elsewhere */
242typedef u_int	Port_t;		/* hardware port */
243typedef u_char	bool_t;		/* boolean */
244
245/* queue of linear buffers */
246struct lbq {
247	u_char	*l_head;	/* next char to process */
248	u_char	*l_tail;	/* one past the last char to process */
249	struct lbq *l_next;	/* next in queue */
250	bool_t	l_queued;	/* nonzero if queued */
251};
252
253/* com device structure */
254struct com_s {
255	u_char	state;		/* miscellaneous flag bits */
256	bool_t  active_out;	/* nonzero if the callout device is open */
257	u_char	cfcr_image;	/* copy of value written to CFCR */
258#ifdef COM_ESP
259	bool_t	esp;		/* is this unit a hayes esp board? */
260#endif
261	u_char	fifo_image;	/* copy of value written to FIFO */
262	bool_t	hasfifo;	/* nonzero for 16550 UARTs */
263	bool_t	loses_outints;	/* nonzero if device loses output interrupts */
264	u_char	mcr_image;	/* copy of value written to MCR */
265#ifdef COM_MULTIPORT
266	bool_t	multiport;	/* is this unit part of a multiport device? */
267#endif /* COM_MULTIPORT */
268	bool_t	no_irq;		/* nonzero if irq is not attached */
269	bool_t  gone;		/* hardware disappeared */
270	bool_t	poll;		/* nonzero if polling is required */
271	bool_t	poll_output;	/* nonzero if polling for output is required */
272	int	unit;		/* unit	number */
273	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
274	u_int	tx_fifo_size;
275	u_int	wopeners;	/* # processes waiting for DCD in open() */
276
277	/*
278	 * The high level of the driver never reads status registers directly
279	 * because there would be too many side effects to handle conveniently.
280	 * Instead, it reads copies of the registers stored here by the
281	 * interrupt handler.
282	 */
283	u_char	last_modem_status;	/* last MSR read by intr handler */
284	u_char	prev_modem_status;	/* last MSR handled by high level */
285
286	u_char	hotchar;	/* ldisc-specific char to be handled ASAP */
287	u_char	*ibuf;		/* start of input buffer */
288	u_char	*ibufend;	/* end of input buffer */
289	u_char	*ihighwater;	/* threshold in input buffer */
290	u_char	*iptr;		/* next free spot in input buffer */
291
292	struct lbq	obufq;	/* head of queue of output buffers */
293	struct lbq	obufs[2];	/* output buffers */
294
295#ifdef PC98
296	Port_t	cmd_port;
297	Port_t	sts_port;
298	Port_t	in_modem_port;
299	Port_t	intr_ctrl_port;
300	int	intr_enable;
301	int	pc98_prev_modem_status;
302	int	pc98_modem_delta;
303	int	modem_car_chg_timer;
304	int	pc98_prev_siocmd;
305	int	pc98_prev_siomod;
306	int	modem_checking;
307	int	pc98_if_type;
308#endif /* PC98 */
309	Port_t	data_port;	/* i/o ports */
310#ifdef COM_ESP
311	Port_t	esp_port;
312#endif
313	Port_t	int_id_port;
314	Port_t	iobase;
315	Port_t	modem_ctl_port;
316	Port_t	line_status_port;
317	Port_t	modem_status_port;
318
319	struct tty	*tp;	/* cross reference */
320
321	/* Initial state. */
322	struct termios	it_in;	/* should be in struct tty */
323	struct termios	it_out;
324
325	/* Lock state. */
326	struct termios	lt_in;	/* should be in struct tty */
327	struct termios	lt_out;
328
329	bool_t	do_timestamp;
330	bool_t	do_dcd_timestamp;
331	struct timeval	timestamp;
332	struct timeval	dcd_timestamp;
333
334	u_long	bytes_in;	/* statistics */
335	u_long	bytes_out;
336	u_int	delta_error_counts[CE_NTYPES];
337	u_long	error_counts[CE_NTYPES];
338
339	/*
340	 * Ping-pong input buffers.  The extra factor of 2 in the sizes is
341	 * to allow for an error byte for each input byte.
342	 */
343#define	CE_INPUT_OFFSET		RS_IBUFSIZE
344	u_char	ibuf1[2 * RS_IBUFSIZE];
345	u_char	ibuf2[2 * RS_IBUFSIZE];
346
347	/*
348	 * Data area for output buffers.  Someday we should build the output
349	 * buffer queue without copying data.
350	 */
351	u_char	obuf1[256];
352	u_char	obuf2[256];
353#ifdef DEVFS
354	void	*devfs_token_ttyd;
355	void	*devfs_token_ttyl;
356	void	*devfs_token_ttyi;
357	void	*devfs_token_cuaa;
358	void	*devfs_token_cual;
359	void	*devfs_token_cuai;
360#endif
361};
362
363/*
364 * XXX public functions in drivers should be declared in headers produced
365 * by `config', not here.
366 */
367
368/* Interrupt handling entry point. */
369void	siopoll		__P((void));
370
371/* Device switch entry points. */
372#define	sioreset	noreset
373#define	siommap		nommap
374#define	siostrategy	nostrategy
375
376#ifdef COM_ESP
377static	int	espattach	__P((struct isa_device *isdp, struct com_s *com,
378				     Port_t esp_port));
379#endif
380static	int	sioattach	__P((struct isa_device *dev));
381static	timeout_t siobusycheck;
382static	timeout_t siodtrwakeup;
383static	void	comhardclose	__P((struct com_s *com));
384static	void	siointr1	__P((struct com_s *com));
385static	int	commctl		__P((struct com_s *com, int bits, int how));
386static	int	comparam	__P((struct tty *tp, struct termios *t));
387static	int	sioprobe	__P((struct isa_device *dev));
388static	void	siosettimeout	__P((void));
389static	void	comstart	__P((struct tty *tp));
390static	timeout_t comwakeup;
391static	int	tiocm_xxx2mcr	__P((int tiocm_xxx));
392static	void	disc_optim	__P((struct tty	*tp, struct termios *t,
393				     struct com_s *com));
394
395#ifdef DSI_SOFT_MODEM
396static  int 	LoadSoftModem   __P((int unit,int base_io, u_long size, u_char *ptr));
397#endif /* DSI_SOFT_MODEM */
398
399static char driver_name[] = "sio";
400
401/* table and macro for fast conversion from a unit number to its com struct */
402static	struct com_s	*p_com_addr[NSIO];
403#define	com_addr(unit)	(p_com_addr[unit])
404
405struct isa_driver	siodriver = {
406	sioprobe, sioattach, driver_name
407};
408
409static	d_open_t	sioopen;
410static	d_close_t	sioclose;
411static	d_read_t	sioread;
412static	d_write_t	siowrite;
413static	d_ioctl_t	sioioctl;
414static	d_stop_t	siostop;
415static	d_devtotty_t	siodevtotty;
416
417#define CDEV_MAJOR 28
418static struct cdevsw sio_cdevsw = {
419	sioopen,	sioclose,	sioread,	siowrite,
420	sioioctl,	siostop,	noreset,	siodevtotty,
421	ttselect,	nommap,		NULL,		driver_name,
422	NULL,		-1,
423};
424
425static	int	comconsole = -1;
426static	speed_t	comdefaultrate = CONSPEED;
427static	u_int	com_events;	/* input chars + weighted output completions */
428static	int	sio_timeout;
429static	int	sio_timeouts_until_log;
430#if 0 /* XXX */
431static struct tty	*sio_tty[NSIO];
432#else
433static struct tty	sio_tty[NSIO];
434#endif
435static	const int	nsio_tty = NSIO;
436
437#ifdef PC98
438struct	siodev	{
439	short	if_type;
440	short	irq;
441	Port_t	cmd, sts, ctrl, mod;
442	};
443static	int	sysclock;
444static	short	port_table[5][3] = {
445			{0x30, 0xb1, 0xb9},
446			{0x32, 0xb3, 0xbb},
447			{0x32, 0xb3, 0xbb},
448			{0x33, 0xb0, 0xb2},
449			{0x35, 0xb0, 0xb2}
450		};
451#define	PC98SIO_data_port(ch)		port_table[0][ch]
452#define	PC98SIO_cmd_port(ch)		port_table[1][ch]
453#define	PC98SIO_sts_port(ch)		port_table[2][ch]
454#define	PC98SIO_in_modem_port(ch)	port_table[3][ch]
455#define	PC98SIO_intr_ctrl_port(ch)	port_table[4][ch]
456#ifdef COM_IF_PIO9032B
457#define   IO_COM_PIO9032B_2	0x0b8
458#define   IO_COM_PIO9032B_3	0x0ba
459#endif /* COM_IF_PIO9032B */
460#ifdef COM_IF_B98_01
461#define	  IO_COM_B98_01_2	0x0d1
462#define	  IO_COM_B98_01_3	0x0d5
463#endif /* COM_IF_B98_01 */
464#define	COM_INT_DISABLE		{int previpri; previpri=spltty();
465#define	COM_INT_ENABLE		splx(previpri);}
466#define IEN_TxFLAG		IEN_Tx
467
468#define COM_CARRIER_DETECT_EMULATE	0
469#define	PC98_CHECK_MODEM_INTERVAL	(hz/10)
470#define DCD_OFF_TOLERANCE		2
471#define DCD_ON_RECOGNITION		2
472#define	IS_8251(type)		(type != MC16550)
473#define	IS_PC98IN(adr)		(adr == 0x30)
474
475static	void	commint		__P((dev_t dev));
476static	void	com_tiocm_set	__P((struct com_s *com, int msr));
477static	void	com_tiocm_bis	__P((struct com_s *com, int msr));
478static	void	com_tiocm_bic	__P((struct com_s *com, int msr));
479static	int	com_tiocm_get	__P((struct com_s *com));
480static	int	com_tiocm_get_delta	__P((struct com_s *com));
481static	void	pc98_msrint_start	__P((dev_t dev));
482static	void	com_cflag_and_speed_set	__P((struct com_s *com, int cflag, int speed));
483static	int	pc98_ttspeedtab		__P((struct com_s *com, int speed));
484static	int	pc98_get_modem_status	__P((struct com_s *com));
485static	timeout_t	pc98_check_msr;
486static	void	pc98_set_baud_rate	__P((struct com_s *com, int count));
487static	void	pc98_i8251_reset	__P((struct com_s *com, int mode, int command));
488static	void	pc98_disable_i8251_interrupt	__P((struct com_s *com, int mod));
489static	void	pc98_enable_i8251_interrupt	__P((struct com_s *com, int mod));
490static	int	pc98_check_i8251_interrupt	__P((struct com_s *com));
491static	int	pc98_i8251_get_cmd	__P((struct com_s *com));
492static	int	pc98_i8251_get_mod	__P((struct com_s *com));
493static	void	pc98_i8251_set_cmd	__P((struct com_s *com, int x));
494static	void	pc98_i8251_or_cmd	__P((struct com_s *com, int x));
495static	void	pc98_i8251_clear_cmd	__P((struct com_s *com, int x));
496static	void	pc98_i8251_clear_or_cmd	__P((struct com_s *com, int clr, int x));
497static	int	pc98_check_if_type	__P((int iobase, struct siodev *iod));
498static	void	pc98_check_sysclock	__P((void));
499static	int	pc98_set_ioport		__P((struct com_s *com, int io_base));
500
501#define com_int_Tx_disable(com) \
502		pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP)
503#define com_int_Tx_enable(com) \
504		pc98_enable_i8251_interrupt(com,IEN_TxFLAG)
505#define com_int_Rx_disable(com) \
506		pc98_disable_i8251_interrupt(com,IEN_Rx)
507#define com_int_Rx_enable(com) \
508		pc98_enable_i8251_interrupt(com,IEN_Rx)
509#define com_int_TxRx_disable(com) \
510		pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx)
511#define com_int_TxRx_enable(com) \
512		pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx)
513#define com_send_break_on(com) \
514		pc98_i8251_or_cmd(com,CMD8251_SBRK)
515#define com_send_break_off(com) \
516		pc98_i8251_clear_cmd(com,CMD8251_SBRK)
517
518struct speedtab pc98speedtab[] = {	/* internal RS232C interface */
519	0,	0,
520	50,	50,
521	75,	75,
522	150,	150,
523	200,	200,
524	300,	300,
525	600,	600,
526	1200,	1200,
527	2400,	2400,
528	4800,	4800,
529	9600,	9600,
530	19200,	19200,
531	38400,	38400,
532	76800,	76800,
533	20800,	20800,
534	41600,	41600,
535	15600,	15600,
536	31200,	31200,
537	62400,	62400,
538	-1,	-1
539};
540#ifdef COM_IF_PIO9032B
541struct speedtab comspeedtab_pio9032b[] = {
542	300,	6,
543	600,	5,
544	1200,	4,
545	2400,	3,
546	4800,	2,
547	9600,	1,
548	19200,	0,
549	38400,	7,
550	-1,	-1
551};
552#endif
553
554#ifdef COM_IF_B98_01
555struct speedtab comspeedtab_b98_01[] = {
556	0,	0,
557	75,	15,
558	150,	14,
559	300,	13,
560	600,	12,
561	1200,	11,
562	2400,	10,
563	4800,	9,
564	9600,	8,
565	19200,	7,
566	38400,	6,
567	76800,	5,
568	153600,	4,
569	-1,	-1
570};
571#endif
572#endif /* PC98 */
573
574static	struct speedtab comspeedtab[] = {
575	{ 0,		0 },
576	{ 50,		COMBRD(50) },
577	{ 75,		COMBRD(75) },
578	{ 110,		COMBRD(110) },
579	{ 134,		COMBRD(134) },
580	{ 150,		COMBRD(150) },
581	{ 200,		COMBRD(200) },
582	{ 300,		COMBRD(300) },
583	{ 600,		COMBRD(600) },
584	{ 1200,		COMBRD(1200) },
585	{ 1800,		COMBRD(1800) },
586	{ 2400,		COMBRD(2400) },
587	{ 4800,		COMBRD(4800) },
588	{ 9600,		COMBRD(9600) },
589	{ 19200,	COMBRD(19200) },
590	{ 38400,	COMBRD(38400) },
591	{ 57600,	COMBRD(57600) },
592	{ 115200,	COMBRD(115200) },
593	{ -1,		-1 }
594};
595
596#ifdef COM_ESP
597/* XXX configure this properly. */
598static	Port_t	likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
599static	Port_t	likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
600#endif
601
602#if NCRD > 0
603/*
604 *	PC-Card (PCMCIA) specific code.
605 */
606static int card_intr(struct pccard_dev *);	/* Interrupt handler */
607static void siounload(struct pccard_dev *);	/* Disable driver */
608static void siosuspend(struct pccard_dev *);	/* Suspend driver */
609static int sioinit(struct pccard_dev *, int);	/* init device */
610
611static struct pccard_drv sio_info = {
612	driver_name,
613	card_intr,
614	siounload,
615	siosuspend,
616	sioinit,
617	0,			/* Attributes - presently unused */
618	&tty_imask		/* Interrupt mask for device */
619				/* XXX - Should this also include net_imask? */
620};
621
622/*
623 *	Called when a power down is requested. Shuts down the
624 *	device and configures the device as unavailable (but
625 *	still loaded...). A resume is done by calling
626 *	sioinit with first=0. This is called when the user suspends
627 *	the system, or the APM code suspends the system.
628 */
629static void
630siosuspend(struct pccard_dev *dp)
631{
632	printf("sio%d: suspending\n", dp->isahd.id_unit);
633}
634
635/*
636 *	Initialize the device - called from Slot manager.
637 *	If first is set, then check for the device's existence
638 *	before initializing it.  Once initialized, the device table may
639 *	be set up.
640 */
641int
642sioinit(struct pccard_dev *dp, int first)
643{
644
645	/* validate unit number. */
646	if (first) {
647		if (dp->isahd.id_unit >= NSIO)
648			return(ENODEV);
649		/* Make sure it isn't already probed. */
650		if (com_addr(dp->isahd.id_unit))
651			return(EBUSY);
652		/*
653		 * Probe the device. If a value is returned, the
654		 * device was found at the location.
655		 */
656		if (sioprobe(&dp->isahd)==0)
657			return(ENXIO);
658		if (sioattach(&dp->isahd)==0)
659			return(ENXIO);
660	}
661	/*
662	 * XXX TODO:
663	 * If it was initialized before, the device structure
664	 * should also be initialized.  We should
665	 * reset (and possibly restart) the hardware, but
666	 * I am not sure of the best way to do this...
667	 */
668	return(0);
669}
670
671/*
672 *	siounload - unload the driver and clear the table.
673 *	XXX TODO:
674 *	This is usually called when the card is ejected, but
675 *	can be caused by a modunload of a controller driver.
676 *	The idea is to reset the driver's view of the device
677 *	and ensure that any driver entry points such as
678 *	read and write do not hang.
679 */
680static void
681siounload(struct pccard_dev *dp)
682{
683	struct com_s	*com;
684
685	com = com_addr(dp->isahd.id_unit);
686	if (!com->iobase) {
687		printf("sio%d already unloaded!\n",dp->isahd.id_unit);
688		return;
689	}
690	if (com->tp && (com->tp->t_state & TS_ISOPEN)) {
691		com->gone = 1;
692		printf("sio%d: unload\n", dp->isahd.id_unit);
693		com->tp->t_gen++;
694		ttyclose(com->tp);
695		ttwakeup(com->tp);
696		ttwwakeup(com->tp);
697	} else {
698		com_addr(com->unit) = NULL;
699		bzero(com, sizeof *com);
700		free(com,M_TTYS);
701		printf("sio%d: unload,gone\n", dp->isahd.id_unit);
702	}
703}
704
705/*
706 *	card_intr - Shared interrupt called from
707 *	front end of PC-Card handler.
708 */
709static int
710card_intr(struct pccard_dev *dp)
711{
712	struct com_s	*com;
713	com = com_addr(dp->isahd.id_unit);
714	if (com && !com_addr(dp->isahd.id_unit)->gone)
715		siointr1(com_addr(dp->isahd.id_unit));
716	return(1);
717}
718#endif /* NCRD > 0 */
719
720static int
721sioprobe(dev)
722	struct isa_device	*dev;
723{
724	static bool_t	already_init;
725	bool_t		failures[10];
726	int		fn;
727	struct isa_device	*idev;
728	Port_t		iobase;
729	u_char		mcr_image;
730	int		result;
731#ifdef PC98
732	struct isa_device	*xdev;
733	int		irqout=0;
734	int		ret = 0;
735	int		tmp;
736	struct		siodev	iod;
737#else
738	struct isa_device	*xdev;
739#endif
740
741	if (!already_init) {
742		/*
743		 * Turn off MCR_IENABLE for all likely serial ports.  An unused
744		 * port with its MCR_IENABLE gate open will inhibit interrupts
745		 * from any used port that shares the interrupt vector.
746		 * XXX the gate enable is elsewhere for some multiports.
747		 */
748		for (xdev = isa_devtab_tty; xdev->id_driver != NULL; xdev++)
749			if (xdev->id_driver == &siodriver && xdev->id_enabled)
750#ifdef PC98
751				if (IS_PC98IN(xdev->id_iobase))
752					outb(xdev->id_iobase + 2, 0xf2);
753				else
754#else
755				outb(xdev->id_iobase + com_mcr, 0);
756#endif
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	else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
1731	    == (LSR_TSRE | LSR_TXRDY)) {
1732		com->tp->t_state &= ~TS_BUSY;
1733		ttwwakeup(com->tp);
1734	} else
1735		timeout(siobusycheck, com, hz / 100);
1736	splx(s);
1737}
1738
1739static void
1740siodtrwakeup(chan)
1741	void	*chan;
1742{
1743	struct com_s	*com;
1744
1745	com = (struct com_s *)chan;
1746	com->state &= ~CS_DTR_OFF;
1747	wakeup(&com->dtr_wait);
1748}
1749
1750void
1751siointr(unit)
1752	int	unit;
1753{
1754#ifndef COM_MULTIPORT
1755	siointr1(com_addr(unit));
1756#else /* COM_MULTIPORT */
1757	struct com_s    *com;
1758	bool_t		possibly_more_intrs;
1759
1760	/*
1761	 * Loop until there is no activity on any port.  This is necessary
1762	 * to get an interrupt edge more than to avoid another interrupt.
1763	 * If the IRQ signal is just an OR of the IRQ signals from several
1764	 * devices, then the edge from one may be lost because another is
1765	 * on.
1766	 */
1767	do {
1768		possibly_more_intrs = FALSE;
1769		for (unit = 0; unit < NSIO; ++unit) {
1770			com = com_addr(unit);
1771#ifdef PC98
1772			if (com != NULL
1773			    && !com->gone
1774			    && IS_8251(com->pc98_if_type)){
1775				siointr1(com);
1776			} else
1777#endif /* PC98 */
1778			if (com != NULL
1779			    && !com->gone
1780			    && (inb(com->int_id_port) & IIR_IMASK)
1781			       != IIR_NOPEND) {
1782				siointr1(com);
1783				possibly_more_intrs = TRUE;
1784			}
1785		}
1786	} while (possibly_more_intrs);
1787#endif /* COM_MULTIPORT */
1788}
1789
1790static void
1791siointr1(com)
1792	struct com_s	*com;
1793{
1794	u_char	line_status;
1795	u_char	modem_status;
1796	u_char	*ioptr;
1797	u_char	recv_data;
1798#ifdef PC98
1799	u_char	tmp=0;
1800recv_data=0;
1801#endif /* PC98 */
1802
1803	while (TRUE) {
1804#ifdef PC98
1805status_read:;
1806		if (IS_8251(com->pc98_if_type)) {
1807			tmp = inb(com->sts_port);
1808more_intr:
1809			line_status = 0;
1810			if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY;
1811			if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY;
1812			if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE;
1813			if (tmp & STS8251_PE)    line_status |= LSR_PE;
1814			if (tmp & STS8251_OE)    line_status |= LSR_OE;
1815			if (tmp & STS8251_FE)    line_status |= LSR_FE;
1816			if (tmp & STS8251_BD_SD) line_status |= LSR_BI;
1817		} else
1818#endif /* PC98 */
1819		line_status = inb(com->line_status_port);
1820
1821		/* input event? (check first to help avoid overruns) */
1822		while (line_status & LSR_RCV_MASK) {
1823			/* break/unnattached error bits or real input? */
1824#ifdef PC98
1825			if(IS_8251(com->pc98_if_type)){
1826				recv_data = inb(com->data_port);
1827				if(tmp & 0x78){
1828					pc98_i8251_or_cmd(com,CMD8251_ER);
1829					recv_data = 0;
1830				}
1831			} else {
1832#endif /* PC98 */
1833			if (!(line_status & LSR_RXRDY))
1834				recv_data = 0;
1835			else
1836				recv_data = inb(com->data_port);
1837#ifdef PC98
1838			}
1839#endif
1840			if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
1841				/*
1842				 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
1843				 * Otherwise, push the work to a higher level
1844				 * (to handle PARMRK) if we're bypassing.
1845				 * Otherwise, convert BI/FE and PE+INPCK to 0.
1846				 *
1847				 * This makes bypassing work right in the
1848				 * usual "raw" case (IGNBRK set, and IGNPAR
1849				 * and INPCK clear).
1850				 *
1851				 * Note: BI together with FE/PE means just BI.
1852				 */
1853				if (line_status & LSR_BI) {
1854#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
1855					if (com->unit == comconsole) {
1856						breakpoint();
1857						goto cont;
1858					}
1859#endif
1860					if (com->tp == NULL
1861					    || com->tp->t_iflag & IGNBRK)
1862						goto cont;
1863				} else {
1864					if (com->tp == NULL
1865					    || com->tp->t_iflag & IGNPAR)
1866						goto cont;
1867				}
1868				if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
1869				    && (line_status & (LSR_BI | LSR_FE)
1870					|| com->tp->t_iflag & INPCK))
1871					recv_data = 0;
1872			}
1873
1874			++com->bytes_in;
1875			if (com->hotchar != 0 && recv_data == com->hotchar)
1876				setsofttty();
1877			ioptr = com->iptr;
1878			if (ioptr >= com->ibufend)
1879				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1880			else {
1881				if (com->do_timestamp)
1882					microtime(&com->timestamp);
1883				++com_events;
1884				schedsofttty();
1885#if 0 /* for testing input latency vs efficiency */
1886if (com->iptr - com->ibuf == 8)
1887	setsofttty();
1888#endif
1889				ioptr[0] = recv_data;
1890				ioptr[CE_INPUT_OFFSET] = line_status;
1891				com->iptr = ++ioptr;
1892				if (ioptr == com->ihighwater
1893				    && com->state & CS_RTS_IFLOW)
1894#ifdef PC98
1895					if(IS_8251(com->pc98_if_type))
1896						com_tiocm_bic(com, TIOCM_RTS);
1897					else
1898#endif
1899					outb(com->modem_ctl_port,
1900					     com->mcr_image &= ~MCR_RTS);
1901				if (line_status & LSR_OE)
1902					CE_RECORD(com, CE_OVERRUN);
1903			}
1904cont:
1905			/*
1906			 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
1907			 * jump from the top of the loop to here
1908			 */
1909#ifdef PC98
1910			if(IS_8251(com->pc98_if_type))
1911				goto status_read;
1912			else
1913#endif
1914			line_status = inb(com->line_status_port) & 0x7F;
1915		}
1916
1917		/* modem status change? (always check before doing output) */
1918#ifdef PC98
1919		if(!IS_8251(com->pc98_if_type)){
1920#endif
1921		modem_status = inb(com->modem_status_port);
1922		if (modem_status != com->last_modem_status) {
1923			if (com->do_dcd_timestamp
1924			    && !(com->last_modem_status & MSR_DCD)
1925			    && modem_status & MSR_DCD)
1926				microtime(&com->dcd_timestamp);
1927
1928			/*
1929			 * Schedule high level to handle DCD changes.  Note
1930			 * that we don't use the delta bits anywhere.  Some
1931			 * UARTs mess them up, and it's easy to remember the
1932			 * previous bits and calculate the delta.
1933			 */
1934			com->last_modem_status = modem_status;
1935			if (!(com->state & CS_CHECKMSR)) {
1936				com_events += LOTS_OF_EVENTS;
1937				com->state |= CS_CHECKMSR;
1938				setsofttty();
1939			}
1940
1941			/* handle CTS change immediately for crisp flow ctl */
1942			if (com->state & CS_CTS_OFLOW) {
1943				if (modem_status & MSR_CTS)
1944					com->state |= CS_ODEVREADY;
1945				else
1946					com->state &= ~CS_ODEVREADY;
1947			}
1948		}
1949#ifdef PC98
1950		}
1951#endif
1952
1953		/* output queued and everything ready? */
1954		if (line_status & LSR_TXRDY
1955		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1956			ioptr = com->obufq.l_head;
1957			if (com->tx_fifo_size > 1) {
1958				u_int	ocount;
1959
1960				ocount = com->obufq.l_tail - ioptr;
1961				if (ocount > com->tx_fifo_size)
1962					ocount = com->tx_fifo_size;
1963				com->bytes_out += ocount;
1964				do
1965					outb(com->data_port, *ioptr++);
1966				while (--ocount != 0);
1967			} else {
1968				outb(com->data_port, *ioptr++);
1969				++com->bytes_out;
1970			}
1971#ifdef PC98
1972			if(IS_8251(com->pc98_if_type))
1973				if ( !(pc98_check_i8251_interrupt(com) & IEN_TxFLAG) )
1974					com_int_Tx_enable(com);
1975#endif
1976			com->obufq.l_head = ioptr;
1977			if (ioptr >= com->obufq.l_tail) {
1978				struct lbq	*qp;
1979
1980				qp = com->obufq.l_next;
1981				qp->l_queued = FALSE;
1982				qp = qp->l_next;
1983				if (qp != NULL) {
1984					com->obufq.l_head = qp->l_head;
1985					com->obufq.l_tail = qp->l_tail;
1986					com->obufq.l_next = qp;
1987				} else {
1988					/* output just completed */
1989					com->state &= ~CS_BUSY;
1990#if defined(PC98)
1991					if(IS_8251(com->pc98_if_type))
1992						if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
1993							com_int_Tx_disable(com);
1994#endif
1995				}
1996				if (!(com->state & CS_ODONE)) {
1997					com_events += LOTS_OF_EVENTS;
1998					com->state |= CS_ODONE;
1999					setsofttty();	/* handle at high level ASAP */
2000				}
2001			}
2002		}
2003#ifdef PC98
2004		else if (line_status & LSR_TXRDY) {
2005			if(IS_8251(com->pc98_if_type))
2006				if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
2007					com_int_Tx_disable(com);
2008		}
2009		if(IS_8251(com->pc98_if_type))
2010			if ((tmp = inb(com->sts_port)) & STS8251_RxRDY)
2011				goto more_intr;
2012#endif
2013
2014		/* finished? */
2015#ifndef COM_MULTIPORT
2016#ifdef PC98
2017		if(IS_8251(com->pc98_if_type))
2018			return;
2019#endif
2020		if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
2021#endif /* COM_MULTIPORT */
2022			return;
2023	}
2024}
2025
2026static int
2027sioioctl(dev, cmd, data, flag, p)
2028	dev_t		dev;
2029	int		cmd;
2030	caddr_t		data;
2031	int		flag;
2032	struct proc	*p;
2033{
2034	struct com_s	*com;
2035	int		error;
2036	Port_t		iobase;
2037	int		mynor;
2038	int		s;
2039	struct tty	*tp;
2040#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2041	int		oldcmd;
2042	struct termios	term;
2043#endif
2044
2045	mynor = minor(dev);
2046	com = com_addr(MINOR_TO_UNIT(mynor));
2047	if (com->gone)
2048		return (ENODEV);
2049	iobase = com->iobase;
2050	if (mynor & CONTROL_MASK) {
2051		struct termios	*ct;
2052
2053		switch (mynor & CONTROL_MASK) {
2054		case CONTROL_INIT_STATE:
2055			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
2056			break;
2057		case CONTROL_LOCK_STATE:
2058			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
2059			break;
2060		default:
2061			return (ENODEV);	/* /dev/nodev */
2062		}
2063		switch (cmd) {
2064		case TIOCSETA:
2065			error = suser(p->p_ucred, &p->p_acflag);
2066			if (error != 0)
2067				return (error);
2068			*ct = *(struct termios *)data;
2069			return (0);
2070		case TIOCGETA:
2071			*(struct termios *)data = *ct;
2072			return (0);
2073		case TIOCGETD:
2074			*(int *)data = TTYDISC;
2075			return (0);
2076		case TIOCGWINSZ:
2077			bzero(data, sizeof(struct winsize));
2078			return (0);
2079#ifdef DSI_SOFT_MODEM
2080		/*
2081		 * Download micro-code to Digicom modem.
2082		 */
2083		case TIOCDSIMICROCODE:
2084			{
2085			u_long l;
2086			u_char *p,*pi;
2087
2088			pi = (u_char*)(*(caddr_t*)data);
2089			error = copyin(pi,&l,sizeof l);
2090			if(error)
2091				{return error;};
2092			pi += sizeof l;
2093
2094			p = malloc(l,M_TEMP,M_NOWAIT);
2095			if(!p)
2096				{return ENOBUFS;}
2097			error = copyin(pi,p,l);
2098			if(error)
2099				{free(p,M_TEMP); return error;};
2100			if(error = LoadSoftModem(
2101			    MINOR_TO_UNIT(mynor),iobase,l,p))
2102				{free(p,M_TEMP); return error;}
2103			free(p,M_TEMP);
2104			return(0);
2105			}
2106#endif /* DSI_SOFT_MODEM */
2107		default:
2108			return (ENOTTY);
2109		}
2110	}
2111	tp = com->tp;
2112#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2113	term = tp->t_termios;
2114	oldcmd = cmd;
2115	error = ttsetcompat(tp, &cmd, data, &term);
2116	if (error != 0)
2117		return (error);
2118	if (cmd != oldcmd)
2119		data = (caddr_t)&term;
2120#endif
2121	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
2122		int	cc;
2123		struct termios *dt = (struct termios *)data;
2124		struct termios *lt = mynor & CALLOUT_MASK
2125				     ? &com->lt_out : &com->lt_in;
2126
2127		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
2128			      | (dt->c_iflag & ~lt->c_iflag);
2129		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
2130			      | (dt->c_oflag & ~lt->c_oflag);
2131		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
2132			      | (dt->c_cflag & ~lt->c_cflag);
2133		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
2134			      | (dt->c_lflag & ~lt->c_lflag);
2135		for (cc = 0; cc < NCCS; ++cc)
2136			if (lt->c_cc[cc] != 0)
2137				dt->c_cc[cc] = tp->t_cc[cc];
2138		if (lt->c_ispeed != 0)
2139			dt->c_ispeed = tp->t_ispeed;
2140		if (lt->c_ospeed != 0)
2141			dt->c_ospeed = tp->t_ospeed;
2142	}
2143	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
2144	if (error >= 0)
2145		return (error);
2146	s = spltty();
2147	error = ttioctl(tp, cmd, data, flag);
2148	disc_optim(tp, &tp->t_termios, com);
2149	if (error >= 0) {
2150		splx(s);
2151		return (error);
2152	}
2153#ifdef PC98
2154	if(IS_8251(com->pc98_if_type)){
2155	switch (cmd) {
2156	case TIOCSBRK:
2157		com_send_break_on( com );
2158		break;
2159	case TIOCCBRK:
2160		com_send_break_off( com );
2161		break;
2162	case TIOCSDTR:
2163		(void)commctl(com, TIOCM_DTR, DMBIS);
2164		break;
2165	case TIOCCDTR:
2166		(void)commctl(com, TIOCM_DTR, DMBIC);
2167		break;
2168	/*
2169	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
2170	 * changes get undone on the next call to comparam().
2171	 */
2172	case TIOCMSET:
2173		(void)commctl(com, *(int *)data, DMSET);
2174		break;
2175	case TIOCMBIS:
2176		(void)commctl(com, *(int *)data, DMBIS);
2177		break;
2178	case TIOCMBIC:
2179		(void)commctl(com, *(int *)data, DMBIC);
2180		break;
2181	case TIOCMGET:
2182		*(int *)data = commctl(com, 0, DMGET);
2183		break;
2184	case TIOCMSDTRWAIT:
2185		/* must be root since the wait applies to following logins */
2186		error = suser(p->p_ucred, &p->p_acflag);
2187		if (error != 0) {
2188			splx(s);
2189			return (error);
2190		}
2191		com->dtr_wait = *(int *)data * hz / 100;
2192		break;
2193	case TIOCMGDTRWAIT:
2194		*(int *)data = com->dtr_wait * 100 / hz;
2195		break;
2196	case TIOCTIMESTAMP:
2197		com->do_timestamp = TRUE;
2198		*(struct timeval *)data = com->timestamp;
2199		break;
2200	case TIOCDCDTIMESTAMP:
2201		com->do_dcd_timestamp = TRUE;
2202		*(struct timeval *)data = com->dcd_timestamp;
2203		break;
2204	default:
2205		splx(s);
2206		return (ENOTTY);
2207	}
2208	} else {
2209#endif
2210	switch (cmd) {
2211	case TIOCSBRK:
2212		outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2213		break;
2214	case TIOCCBRK:
2215		outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2216		break;
2217	case TIOCSDTR:
2218		(void)commctl(com, TIOCM_DTR, DMBIS);
2219		break;
2220	case TIOCCDTR:
2221		(void)commctl(com, TIOCM_DTR, DMBIC);
2222		break;
2223	case TIOCMSET:
2224		(void)commctl(com, *(int *)data, DMSET);
2225		break;
2226	case TIOCMBIS:
2227		(void)commctl(com, *(int *)data, DMBIS);
2228		break;
2229	case TIOCMBIC:
2230		(void)commctl(com, *(int *)data, DMBIC);
2231		break;
2232	case TIOCMGET:
2233		*(int *)data = commctl(com, 0, DMGET);
2234		break;
2235	case TIOCMSDTRWAIT:
2236		/* must be root since the wait applies to following logins */
2237		error = suser(p->p_ucred, &p->p_acflag);
2238		if (error != 0) {
2239			splx(s);
2240			return (error);
2241		}
2242		com->dtr_wait = *(int *)data * hz / 100;
2243		break;
2244	case TIOCMGDTRWAIT:
2245		*(int *)data = com->dtr_wait * 100 / hz;
2246		break;
2247	case TIOCTIMESTAMP:
2248		com->do_timestamp = TRUE;
2249		*(struct timeval *)data = com->timestamp;
2250		break;
2251	default:
2252		splx(s);
2253		return (ENOTTY);
2254	}
2255#ifdef PC98
2256	}
2257#endif
2258	splx(s);
2259	return (0);
2260}
2261
2262void
2263siopoll()
2264{
2265	int		unit;
2266
2267	if (com_events == 0)
2268		return;
2269repeat:
2270	for (unit = 0; unit < NSIO; ++unit) {
2271		u_char		*buf;
2272		struct com_s	*com;
2273		u_char		*ibuf;
2274		int		incc;
2275		struct tty	*tp;
2276#ifdef PC98
2277		int		tmp;
2278#endif
2279
2280		com = com_addr(unit);
2281		if (com == NULL)
2282			continue;
2283		if (com->gone)
2284			continue;
2285		tp = com->tp;
2286		if (tp == NULL) {
2287			/*
2288			 * XXX forget any events related to closed devices
2289			 * (actually never opened devices) so that we don't
2290			 * loop.
2291			 */
2292			disable_intr();
2293			incc = com->iptr - com->ibuf;
2294			com->iptr = com->ibuf;
2295			if (com->state & CS_CHECKMSR) {
2296				incc += LOTS_OF_EVENTS;
2297				com->state &= ~CS_CHECKMSR;
2298			}
2299			com_events -= incc;
2300			enable_intr();
2301			if (incc != 0)
2302				log(LOG_DEBUG,
2303				    "sio%d: %d events for device with no tp\n",
2304				    unit, incc);
2305			continue;
2306		}
2307
2308		/* switch the role of the low-level input buffers */
2309		if (com->iptr == (ibuf = com->ibuf)) {
2310			buf = NULL;     /* not used, but compiler can't tell */
2311			incc = 0;
2312		} else {
2313			buf = ibuf;
2314			disable_intr();
2315			incc = com->iptr - buf;
2316			com_events -= incc;
2317			if (ibuf == com->ibuf1)
2318				ibuf = com->ibuf2;
2319			else
2320				ibuf = com->ibuf1;
2321			com->ibufend = ibuf + RS_IBUFSIZE;
2322			com->ihighwater = ibuf + RS_IHIGHWATER;
2323			com->iptr = ibuf;
2324
2325			/*
2326			 * There is now room for another low-level buffer full
2327			 * of input, so enable RTS if it is now disabled and
2328			 * there is room in the high-level buffer.
2329			 */
2330#ifdef PC98
2331			if(IS_8251(com->pc98_if_type))
2332				tmp = com_tiocm_get(com) & TIOCM_RTS;
2333			else
2334				tmp = com->mcr_image & MCR_RTS;
2335#endif
2336			if ((com->state & CS_RTS_IFLOW)
2337#ifdef PC98
2338			    && !(tmp)
2339#else
2340			    && !(com->mcr_image & MCR_RTS)
2341#endif
2342			    && !(tp->t_state & TS_TBLOCK))
2343#ifdef PC98
2344				if(IS_8251(com->pc98_if_type))
2345					com_tiocm_bis(com, TIOCM_RTS);
2346				else
2347#endif
2348				outb(com->modem_ctl_port,
2349				     com->mcr_image |= MCR_RTS);
2350			enable_intr();
2351			com->ibuf = ibuf;
2352		}
2353
2354		if (com->state & CS_CHECKMSR) {
2355			u_char	delta_modem_status;
2356
2357#ifdef PC98
2358			if(!IS_8251(com->pc98_if_type)){
2359#endif
2360			disable_intr();
2361			delta_modem_status = com->last_modem_status
2362					     ^ com->prev_modem_status;
2363			com->prev_modem_status = com->last_modem_status;
2364			com_events -= LOTS_OF_EVENTS;
2365			com->state &= ~CS_CHECKMSR;
2366			enable_intr();
2367			if (delta_modem_status & MSR_DCD)
2368				(*linesw[tp->t_line].l_modem)
2369					(tp, com->prev_modem_status & MSR_DCD);
2370#ifdef PC98
2371			}
2372#endif
2373		}
2374		if (com->state & CS_ODONE) {
2375			disable_intr();
2376			com_events -= LOTS_OF_EVENTS;
2377			com->state &= ~CS_ODONE;
2378			enable_intr();
2379			if (!(com->state & CS_BUSY))
2380				timeout(siobusycheck, com, hz / 100);
2381			(*linesw[tp->t_line].l_start)(tp);
2382		}
2383		if (incc <= 0 || !(tp->t_state & TS_ISOPEN) ||
2384		    !(tp->t_cflag & CREAD))
2385			continue;
2386		/*
2387		 * Avoid the grotesquely inefficient lineswitch routine
2388		 * (ttyinput) in "raw" mode.  It usually takes about 450
2389		 * instructions (that's without canonical processing or echo!).
2390		 * slinput is reasonably fast (usually 40 instructions plus
2391		 * call overhead).
2392		 */
2393		if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
2394			if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER
2395			    && (com->state & CS_RTS_IFLOW
2396				|| tp->t_iflag & IXOFF)
2397			    && !(tp->t_state & TS_TBLOCK))
2398				ttyblock(tp);
2399			tk_nin += incc;
2400			tk_rawcc += incc;
2401			tp->t_rawcc += incc;
2402			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
2403				+= b_to_q((char *)buf, incc, &tp->t_rawq);
2404			ttwakeup(tp);
2405			if (tp->t_state & TS_TTSTOP
2406			    && (tp->t_iflag & IXANY
2407				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
2408				tp->t_state &= ~TS_TTSTOP;
2409				tp->t_lflag &= ~FLUSHO;
2410				comstart(tp);
2411			}
2412		} else {
2413			do {
2414				u_char	line_status;
2415				int	recv_data;
2416
2417				line_status = (u_char) buf[CE_INPUT_OFFSET];
2418				recv_data = (u_char) *buf++;
2419				if (line_status
2420				    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
2421					if (line_status & LSR_BI)
2422						recv_data |= TTY_BI;
2423					if (line_status & LSR_FE)
2424						recv_data |= TTY_FE;
2425					if (line_status & LSR_OE)
2426						recv_data |= TTY_OE;
2427					if (line_status & LSR_PE)
2428						recv_data |= TTY_PE;
2429				}
2430				(*linesw[tp->t_line].l_rint)(recv_data, tp);
2431			} while (--incc > 0);
2432		}
2433		if (com_events == 0)
2434			break;
2435	}
2436	if (com_events >= LOTS_OF_EVENTS)
2437		goto repeat;
2438}
2439
2440static int
2441comparam(tp, t)
2442	struct tty	*tp;
2443	struct termios	*t;
2444{
2445	u_int		cfcr;
2446	int		cflag;
2447	struct com_s	*com;
2448	int		divisor;
2449	u_char		dlbh;
2450	u_char		dlbl;
2451	int		error;
2452	Port_t		iobase;
2453	int		s;
2454	int		unit;
2455	int		txtimeout;
2456#ifdef PC98
2457	Port_t		tmp_port;
2458	int		tmp_flg;
2459#endif
2460
2461#ifdef PC98
2462	cfcr = 0;
2463	unit = DEV_TO_UNIT(tp->t_dev);
2464	com = com_addr(unit);
2465	iobase = com->iobase;
2466	if(IS_8251(com->pc98_if_type)) {
2467		divisor = pc98_ttspeedtab(com, t->c_ospeed);
2468	} else
2469#endif
2470	/* do historical conversions */
2471	if (t->c_ispeed == 0)
2472		t->c_ispeed = t->c_ospeed;
2473
2474	/* check requested parameters */
2475	divisor = ttspeedtab(t->c_ospeed, comspeedtab);
2476	if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed)
2477		return (EINVAL);
2478
2479	/* parameters are OK, convert them to the com struct and the device */
2480#ifndef PC98
2481	unit = DEV_TO_UNIT(tp->t_dev);
2482	com = com_addr(unit);
2483	iobase = com->iobase;
2484#endif
2485	s = spltty();
2486#ifdef PC98
2487	if(IS_8251(com->pc98_if_type)){
2488		if(divisor == 0){
2489			com_int_TxRx_disable( com );
2490			com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
2491		}
2492	} else {
2493#endif
2494	if (divisor == 0)
2495		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
2496	else
2497		(void)commctl(com, TIOCM_DTR, DMBIS);
2498#ifdef PC98
2499	}
2500#endif
2501	cflag = t->c_cflag;
2502#ifdef PC98
2503	if(!IS_8251(com->pc98_if_type)){
2504#endif
2505	switch (cflag & CSIZE) {
2506	case CS5:
2507		cfcr = CFCR_5BITS;
2508		break;
2509	case CS6:
2510		cfcr = CFCR_6BITS;
2511		break;
2512	case CS7:
2513		cfcr = CFCR_7BITS;
2514		break;
2515	default:
2516		cfcr = CFCR_8BITS;
2517		break;
2518	}
2519	if (cflag & PARENB) {
2520		cfcr |= CFCR_PENAB;
2521		if (!(cflag & PARODD))
2522			cfcr |= CFCR_PEVEN;
2523	}
2524	if (cflag & CSTOPB)
2525		cfcr |= CFCR_STOPB;
2526
2527	if (com->hasfifo && divisor != 0) {
2528		/*
2529		 * Use a fifo trigger level low enough so that the input
2530		 * latency from the fifo is less than about 16 msec and
2531		 * the total latency is less than about 30 msec.  These
2532		 * latencies are reasonable for humans.  Serial comms
2533		 * protocols shouldn't expect anything better since modem
2534		 * latencies are larger.
2535		 */
2536		com->fifo_image = t->c_ospeed <= 4800
2537				  ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH;
2538#ifdef COM_ESP
2539		/*
2540		 * The Hayes ESP card needs the fifo DMA mode bit set
2541		 * in compatibility mode.  If not, it will interrupt
2542		 * for each character received.
2543		 */
2544		if (com->esp)
2545			com->fifo_image |= FIFO_DMA_MODE;
2546#endif
2547		outb(iobase + com_fifo, com->fifo_image);
2548	}
2549
2550	/*
2551	 * Some UARTs lock up if the divisor latch registers are selected
2552	 * while the UART is doing output (they refuse to transmit anything
2553	 * more until given a hard reset).  Fix this by stopping filling
2554	 * the device buffers and waiting for them to drain.  Reading the
2555	 * line status port outside of siointr1() might lose some receiver
2556	 * error bits, but that is acceptable here.
2557	 */
2558#ifdef PC98
2559	}
2560#endif
2561	disable_intr();
2562retry:
2563	com->state &= ~CS_TTGO;
2564	txtimeout = tp->t_timeout;
2565	enable_intr();
2566#ifdef PC98
2567	if(IS_8251(com->pc98_if_type)){
2568		tmp_port = com->sts_port;
2569		tmp_flg = (STS8251_TxRDY|STS8251_TxEMP);
2570	} else {
2571		tmp_port = com->line_status_port;
2572		tmp_flg = (LSR_TSRE|LSR_TXRDY);
2573	}
2574	while ((inb(tmp_port) & tmp_flg) != tmp_flg) {
2575#else
2576	while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2577	       != (LSR_TSRE | LSR_TXRDY)) {
2578#endif
2579		tp->t_state |= TS_SO_OCOMPLETE;
2580		error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH,
2581				 "siotx", hz / 100);
2582		if (   txtimeout != 0
2583		    && (!error || error	== EAGAIN)
2584		    && (txtimeout -= hz	/ 100) <= 0
2585		   )
2586			error = EIO;
2587		if (com->gone)
2588			error = ENODEV;
2589		if (error != 0 && error != EAGAIN) {
2590			if (!(tp->t_state & TS_TTSTOP)) {
2591				disable_intr();
2592				com->state |= CS_TTGO;
2593				enable_intr();
2594			}
2595			splx(s);
2596			return (error);
2597		}
2598	}
2599
2600	disable_intr();		/* very important while com_data is hidden */
2601
2602	/*
2603	 * XXX - clearing CS_TTGO is not sufficient to stop further output,
2604	 * because siopoll() calls comstart() which usually sets it again
2605	 * because TS_TTSTOP is clear.  Setting TS_TTSTOP would not be
2606	 * sufficient, for similar reasons.
2607	 */
2608#ifdef PC98
2609	if ((inb(tmp_port) & tmp_flg) != tmp_flg)
2610#else
2611	if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2612	    != (LSR_TSRE | LSR_TXRDY))
2613#endif
2614		goto retry;
2615
2616#ifdef PC98
2617	if(!IS_8251(com->pc98_if_type)){
2618#endif
2619	if (divisor != 0) {
2620		outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
2621		/*
2622		 * Only set the divisor registers if they would change,
2623		 * since on some 16550 incompatibles (UMC8669F), setting
2624		 * them while input is arriving them loses sync until
2625		 * data stops arriving.
2626		 */
2627		dlbl = divisor & 0xFF;
2628		if (inb(iobase + com_dlbl) != dlbl)
2629			outb(iobase + com_dlbl, dlbl);
2630		dlbh = (u_int) divisor >> 8;
2631		if (inb(iobase + com_dlbh) != dlbh)
2632			outb(iobase + com_dlbh, dlbh);
2633	}
2634	outb(iobase + com_cfcr, com->cfcr_image = cfcr);
2635#ifdef PC98
2636	} else
2637		com_cflag_and_speed_set(com, cflag, t->c_ospeed);
2638#endif
2639	if (!(tp->t_state & TS_TTSTOP))
2640		com->state |= CS_TTGO;
2641	if (cflag & CRTS_IFLOW) {
2642		com->state |= CS_RTS_IFLOW;
2643		/*
2644		 * If CS_RTS_IFLOW just changed from off to on, the change
2645		 * needs to be propagated to MCR_RTS.  This isn't urgent,
2646		 * so do it later by calling comstart() instead of repeating
2647		 * a lot of code from comstart() here.
2648		 */
2649	} else if (com->state & CS_RTS_IFLOW) {
2650		com->state &= ~CS_RTS_IFLOW;
2651		/*
2652		 * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
2653		 * on here, since comstart() won't do it later.
2654		 */
2655		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2656	}
2657
2658	/*
2659	 * Set up state to handle output flow control.
2660	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2661	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2662	 */
2663	com->state |= CS_ODEVREADY;
2664	com->state &= ~CS_CTS_OFLOW;
2665	if (cflag & CCTS_OFLOW) {
2666		com->state |= CS_CTS_OFLOW;
2667#ifdef PC98
2668		if(IS_8251(com->pc98_if_type)){
2669			if (!(pc98_get_modem_status(com) & TIOCM_CTS))
2670				com->state &= ~CS_ODEVREADY;
2671		} else {
2672#endif
2673		if (!(com->last_modem_status & MSR_CTS))
2674			com->state &= ~CS_ODEVREADY;
2675#ifdef PC98
2676		}
2677#endif
2678	}
2679	/* XXX shouldn't call functions while intrs are disabled. */
2680	disc_optim(tp, t, com);
2681	/*
2682	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
2683	 * unconditionally, but that defeated the careful discarding of
2684	 * stale input in sioopen().
2685	 */
2686	if (com->state >= (CS_BUSY | CS_TTGO))
2687		siointr1(com);
2688
2689	enable_intr();
2690	splx(s);
2691	comstart(tp);
2692	return (0);
2693}
2694
2695static void
2696comstart(tp)
2697	struct tty	*tp;
2698{
2699	struct com_s	*com;
2700	int		s;
2701	int		unit;
2702#ifdef PC98
2703	int		tmp;
2704#endif
2705
2706	unit = DEV_TO_UNIT(tp->t_dev);
2707	com = com_addr(unit);
2708	s = spltty();
2709	disable_intr();
2710	if (tp->t_state & TS_TTSTOP)
2711		com->state &= ~CS_TTGO;
2712	else
2713		com->state |= CS_TTGO;
2714	if (tp->t_state & TS_TBLOCK) {
2715#ifdef PC98
2716		if(IS_8251(com->pc98_if_type))
2717			tmp = com_tiocm_get(com) & TIOCM_RTS;
2718		else
2719			tmp = com->mcr_image & MCR_RTS;
2720		if (tmp && (com->state & CS_RTS_IFLOW))
2721#else
2722		if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2723#endif
2724#ifdef PC98
2725			if(IS_8251(com->pc98_if_type))
2726				com_tiocm_bic(com, TIOCM_RTS);
2727			else
2728#endif
2729			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2730	} else {
2731#ifdef PC98
2732		if(IS_8251(com->pc98_if_type))
2733			tmp = com_tiocm_get(com) & TIOCM_RTS;
2734		else
2735			tmp = com->mcr_image & MCR_RTS;
2736		if (!(tmp) && com->iptr < com->ihighwater
2737			&& com->state & CS_RTS_IFLOW)
2738#else
2739		if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2740		    && com->state & CS_RTS_IFLOW)
2741#endif
2742#ifdef PC98
2743			if(IS_8251(com->pc98_if_type))
2744				com_tiocm_bis(com, TIOCM_RTS);
2745			else
2746#endif
2747			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2748	}
2749	enable_intr();
2750	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2751#ifdef PC98
2752/*		if(IS_8251(com->pc98_if_type))
2753			com_int_Tx_enable(com); */
2754#endif
2755		splx(s);
2756		return;
2757	}
2758	if (tp->t_outq.c_cc != 0) {
2759		struct lbq	*qp;
2760		struct lbq	*next;
2761
2762		if (!com->obufs[0].l_queued) {
2763			com->obufs[0].l_tail
2764			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2765						  sizeof com->obuf1);
2766			com->obufs[0].l_next = NULL;
2767			com->obufs[0].l_queued = TRUE;
2768			disable_intr();
2769			if (com->state & CS_BUSY) {
2770				qp = com->obufq.l_next;
2771				while ((next = qp->l_next) != NULL)
2772					qp = next;
2773				qp->l_next = &com->obufs[0];
2774			} else {
2775				com->obufq.l_head = com->obufs[0].l_head;
2776				com->obufq.l_tail = com->obufs[0].l_tail;
2777				com->obufq.l_next = &com->obufs[0];
2778				com->state |= CS_BUSY;
2779			}
2780			enable_intr();
2781		}
2782		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2783			com->obufs[1].l_tail
2784			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2785						  sizeof com->obuf2);
2786			com->obufs[1].l_next = NULL;
2787			com->obufs[1].l_queued = TRUE;
2788			disable_intr();
2789			if (com->state & CS_BUSY) {
2790				qp = com->obufq.l_next;
2791				while ((next = qp->l_next) != NULL)
2792					qp = next;
2793				qp->l_next = &com->obufs[1];
2794			} else {
2795				com->obufq.l_head = com->obufs[1].l_head;
2796				com->obufq.l_tail = com->obufs[1].l_tail;
2797				com->obufq.l_next = &com->obufs[1];
2798				com->state |= CS_BUSY;
2799			}
2800			enable_intr();
2801		}
2802		tp->t_state |= TS_BUSY;
2803	}
2804	disable_intr();
2805	if (com->state >= (CS_BUSY | CS_TTGO))
2806		siointr1(com);	/* fake interrupt to start output */
2807	enable_intr();
2808#ifdef PC98
2809/*		if(IS_8251(com->pc98_if_type))
2810			com_int_Tx_enable(com); */
2811#endif
2812	ttwwakeup(tp);
2813	splx(s);
2814}
2815
2816static void
2817siostop(tp, rw)
2818	struct tty	*tp;
2819	int		rw;
2820{
2821	struct com_s	*com;
2822
2823	com = com_addr(DEV_TO_UNIT(tp->t_dev));
2824	if (com->gone)
2825		return;
2826	disable_intr();
2827	if (rw & FWRITE) {
2828		if (com->hasfifo)
2829#ifdef COM_ESP
2830		    /* XXX avoid h/w bug. */
2831		    if (!com->esp)
2832#endif
2833			/* XXX does this flush everything? */
2834			outb(com->iobase + com_fifo,
2835			     FIFO_XMT_RST | com->fifo_image);
2836		com->obufs[0].l_queued = FALSE;
2837		com->obufs[1].l_queued = FALSE;
2838		if (com->state & CS_ODONE)
2839			com_events -= LOTS_OF_EVENTS;
2840		com->state &= ~(CS_ODONE | CS_BUSY);
2841		com->tp->t_state &= ~TS_BUSY;
2842	}
2843	if (rw & FREAD) {
2844		if (com->hasfifo)
2845#ifdef COM_ESP
2846		    /* XXX avoid h/w bug. */
2847		    if (!com->esp)
2848#endif
2849			/* XXX does this flush everything? */
2850			outb(com->iobase + com_fifo,
2851			     FIFO_RCV_RST | com->fifo_image);
2852		com_events -= (com->iptr - com->ibuf);
2853		com->iptr = com->ibuf;
2854	}
2855	enable_intr();
2856	comstart(tp);
2857}
2858
2859static struct tty *
2860siodevtotty(dev)
2861	dev_t	dev;
2862{
2863	int	mynor;
2864	int	unit;
2865
2866	mynor = minor(dev);
2867	if (mynor & CONTROL_MASK)
2868		return (NULL);
2869	unit = MINOR_TO_UNIT(mynor);
2870	if ((u_int) unit >= NSIO)
2871		return (NULL);
2872	return (&sio_tty[unit]);
2873}
2874
2875static int
2876commctl(com, bits, how)
2877	struct com_s	*com;
2878	int		bits;
2879	int		how;
2880{
2881	int	mcr;
2882	int	msr;
2883
2884	if (how == DMGET) {
2885		bits = TIOCM_LE;	/* XXX - always enabled while open */
2886		mcr = com->mcr_image;
2887		if (mcr & MCR_DTR)
2888			bits |= TIOCM_DTR;
2889		if (mcr & MCR_RTS)
2890			bits |= TIOCM_RTS;
2891		msr = com->prev_modem_status;
2892		if (msr & MSR_CTS)
2893			bits |= TIOCM_CTS;
2894		if (msr & MSR_DCD)
2895			bits |= TIOCM_CD;
2896		if (msr & MSR_DSR)
2897			bits |= TIOCM_DSR;
2898		/*
2899		 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
2900		 * more volatile by reading the modem status a lot.  Perhaps
2901		 * we should latch both bits until the status is read here.
2902		 */
2903		if (msr & (MSR_RI | MSR_TERI))
2904			bits |= TIOCM_RI;
2905		return (bits);
2906	}
2907	mcr = 0;
2908	if (bits & TIOCM_DTR)
2909		mcr |= MCR_DTR;
2910	if (bits & TIOCM_RTS)
2911		mcr |= MCR_RTS;
2912	if (com->gone)
2913		return(0);
2914	disable_intr();
2915	switch (how) {
2916	case DMSET:
2917		outb(com->modem_ctl_port,
2918		     com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
2919		break;
2920	case DMBIS:
2921		outb(com->modem_ctl_port, com->mcr_image |= mcr);
2922		break;
2923	case DMBIC:
2924		outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
2925		break;
2926	}
2927	enable_intr();
2928	return (0);
2929}
2930
2931static void
2932siosettimeout()
2933{
2934	struct com_s	*com;
2935	bool_t		someopen;
2936	int		unit;
2937
2938	/*
2939	 * Set our timeout period to 1 second if no polled devices are open.
2940	 * Otherwise set it to max(1/200, 1/hz).
2941	 * Enable timeouts iff some device is open.
2942	 */
2943	untimeout(comwakeup, (void *)NULL);
2944	sio_timeout = hz;
2945	someopen = FALSE;
2946	for (unit = 0; unit < NSIO; ++unit) {
2947		com = com_addr(unit);
2948		if (com != NULL && com->tp != NULL
2949		    && com->tp->t_state & TS_ISOPEN && !com->gone) {
2950			someopen = TRUE;
2951			if (com->poll || com->poll_output) {
2952				sio_timeout = hz > 200 ? hz / 200 : 1;
2953				break;
2954			}
2955		}
2956	}
2957	if (someopen) {
2958		sio_timeouts_until_log = hz / sio_timeout;
2959		timeout(comwakeup, (void *)NULL, sio_timeout);
2960	} else {
2961		/* Flush error messages, if any. */
2962		sio_timeouts_until_log = 1;
2963		comwakeup((void *)NULL);
2964		untimeout(comwakeup, (void *)NULL);
2965	}
2966}
2967
2968static void
2969comwakeup(chan)
2970	void	*chan;
2971{
2972	struct com_s	*com;
2973	int		unit;
2974
2975	timeout(comwakeup, (void *)NULL, sio_timeout);
2976
2977	/*
2978	 * Recover from lost output interrupts.
2979	 * Poll any lines that don't use interrupts.
2980	 */
2981	for (unit = 0; unit < NSIO; ++unit) {
2982		com = com_addr(unit);
2983		if (com != NULL && !com->gone
2984		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2985			disable_intr();
2986			siointr1(com);
2987			enable_intr();
2988		}
2989	}
2990
2991	/*
2992	 * Check for and log errors, but not too often.
2993	 */
2994	if (--sio_timeouts_until_log > 0)
2995		return;
2996	sio_timeouts_until_log = hz / sio_timeout;
2997	for (unit = 0; unit < NSIO; ++unit) {
2998		int	errnum;
2999
3000		com = com_addr(unit);
3001		if (com == NULL)
3002			continue;
3003		if (com->gone)
3004			continue;
3005		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
3006			u_int	delta;
3007			u_long	total;
3008
3009			disable_intr();
3010			delta = com->delta_error_counts[errnum];
3011			com->delta_error_counts[errnum] = 0;
3012			enable_intr();
3013			if (delta == 0)
3014				continue;
3015			total = com->error_counts[errnum] += delta;
3016			log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
3017			    unit, delta, error_desc[errnum],
3018			    delta == 1 ? "" : "s", total);
3019		}
3020	}
3021}
3022
3023#ifdef PC98
3024/* commint is called when modem control line changes */
3025static void
3026commint(dev_t dev)
3027{
3028	register struct tty *tp;
3029	int	stat,delta;
3030	struct com_s *com;
3031	int	mynor,unit;
3032
3033	mynor = minor(dev);
3034	unit = MINOR_TO_UNIT(mynor);
3035	com = com_addr(unit);
3036	tp = com->tp;
3037
3038	stat = com_tiocm_get(com);
3039	delta = com_tiocm_get_delta(com);
3040
3041	if (com->state & CS_CTS_OFLOW) {
3042		if (stat & TIOCM_CTS)
3043			com->state |= CS_ODEVREADY;
3044		else
3045			com->state &= ~CS_ODEVREADY;
3046	}
3047	if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) {
3048	    if (stat & TIOCM_CAR )
3049		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
3050	    else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
3051		/* negate DTR, RTS */
3052		com_tiocm_bic(com, (tp->t_cflag & HUPCL) ?
3053				TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE );
3054		/* disable IENABLE */
3055		com_int_TxRx_disable( com );
3056	    }
3057	}
3058}
3059#endif
3060
3061static void
3062disc_optim(tp, t, com)
3063	struct tty	*tp;
3064	struct termios	*t;
3065	struct com_s	*com;
3066{
3067	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
3068	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
3069	    && (!(t->c_iflag & PARMRK)
3070		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
3071	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
3072	    && linesw[tp->t_line].l_rint == ttyinput)
3073		tp->t_state |= TS_CAN_BYPASS_L_RINT;
3074	else
3075		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
3076	/*
3077	 * Prepare to reduce input latency for packet
3078	 * discplines with a end of packet character.
3079	 */
3080	if (tp->t_line == SLIPDISC)
3081		com->hotchar = 0xc0;
3082	else if (tp->t_line == PPPDISC)
3083		com->hotchar = 0x7e;
3084	else
3085		com->hotchar = 0;
3086}
3087
3088/*
3089 * Following are all routines needed for SIO to act as console
3090 */
3091#include <machine/cons.h>
3092
3093struct siocnstate {
3094	u_char	dlbl;
3095	u_char	dlbh;
3096	u_char	ier;
3097	u_char	cfcr;
3098	u_char	mcr;
3099};
3100
3101static	Port_t	siocniobase;
3102
3103static void siocnclose	__P((struct siocnstate *sp));
3104static void siocnopen	__P((struct siocnstate *sp));
3105static void siocntxwait	__P((void));
3106
3107static void
3108siocntxwait()
3109{
3110	int	timo;
3111
3112	/*
3113	 * Wait for any pending transmission to finish.  Required to avoid
3114	 * the UART lockup bug when the speed is changed, and for normal
3115	 * transmits.
3116	 */
3117	timo = 100000;
3118	while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
3119	       != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
3120		;
3121}
3122
3123static void
3124siocnopen(sp)
3125	struct siocnstate	*sp;
3126{
3127	int	divisor;
3128	u_char	dlbh;
3129	u_char	dlbl;
3130	Port_t	iobase;
3131
3132	/*
3133	 * Save all the device control registers except the fifo register
3134	 * and set our default ones (cs8 -parenb speed=comdefaultrate).
3135	 * We can't save the fifo register since it is read-only.
3136	 */
3137	iobase = siocniobase;
3138	sp->ier = inb(iobase + com_ier);
3139	outb(iobase + com_ier, 0);	/* spltty() doesn't stop siointr() */
3140	siocntxwait();
3141	sp->cfcr = inb(iobase + com_cfcr);
3142	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3143	sp->dlbl = inb(iobase + com_dlbl);
3144	sp->dlbh = inb(iobase + com_dlbh);
3145	/*
3146	 * Only set the divisor registers if they would change, since on
3147	 * some 16550 incompatibles (Startech), setting them clears the
3148	 * data input register.  This also reduces the effects of the
3149	 * UMC8669F bug.
3150	 */
3151	divisor = ttspeedtab(comdefaultrate, comspeedtab);
3152	dlbl = divisor & 0xFF;
3153	if (sp->dlbl != dlbl)
3154		outb(iobase + com_dlbl, dlbl);
3155	dlbh = (u_int) divisor >> 8;
3156	if (sp->dlbh != dlbh)
3157		outb(iobase + com_dlbh, dlbh);
3158	outb(iobase + com_cfcr, CFCR_8BITS);
3159	sp->mcr = inb(iobase + com_mcr);
3160	/*
3161	 * We don't want interrupts, but must be careful not to "disable"
3162	 * them by clearing the MCR_IENABLE bit, since that might cause
3163	 * an interrupt by floating the IRQ line.
3164	 */
3165	outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
3166}
3167
3168static void
3169siocnclose(sp)
3170	struct siocnstate	*sp;
3171{
3172	Port_t	iobase;
3173
3174	/*
3175	 * Restore the device control registers.
3176	 */
3177	siocntxwait();
3178	iobase = siocniobase;
3179	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3180	if (sp->dlbl != inb(iobase + com_dlbl))
3181		outb(iobase + com_dlbl, sp->dlbl);
3182	if (sp->dlbh != inb(iobase + com_dlbh))
3183		outb(iobase + com_dlbh, sp->dlbh);
3184	outb(iobase + com_cfcr, sp->cfcr);
3185	/*
3186	 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
3187	 */
3188	outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
3189	outb(iobase + com_ier, sp->ier);
3190}
3191
3192void
3193siocnprobe(cp)
3194	struct consdev	*cp;
3195{
3196	int	unit;
3197
3198	/* XXX: ick */
3199	unit = DEV_TO_UNIT(CONUNIT);
3200	siocniobase = CONADDR;
3201
3202	/* make sure hardware exists?  XXX */
3203
3204	/* initialize required fields */
3205	cp->cn_dev = makedev(CDEV_MAJOR, unit);
3206#ifdef COMCONSOLE
3207	cp->cn_pri = CN_REMOTE;		/* Force a serial port console */
3208#else
3209	cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
3210#endif
3211}
3212
3213void
3214siocninit(cp)
3215	struct consdev	*cp;
3216{
3217	comconsole = DEV_TO_UNIT(cp->cn_dev);
3218}
3219
3220int
3221siocncheckc(dev)
3222	dev_t	dev;
3223{
3224	int	c;
3225	Port_t	iobase;
3226	int	s;
3227	struct siocnstate	sp;
3228
3229	iobase = siocniobase;
3230	s = spltty();
3231	siocnopen(&sp);
3232	if (inb(iobase + com_lsr) & LSR_RXRDY)
3233		c = inb(iobase + com_data);
3234	else
3235		c = -1;
3236	siocnclose(&sp);
3237	splx(s);
3238	return (c);
3239}
3240
3241
3242int
3243siocngetc(dev)
3244	dev_t	dev;
3245{
3246	int	c;
3247	Port_t	iobase;
3248	int	s;
3249	struct siocnstate	sp;
3250
3251	iobase = siocniobase;
3252	s = spltty();
3253	siocnopen(&sp);
3254	while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3255		;
3256	c = inb(iobase + com_data);
3257	siocnclose(&sp);
3258	splx(s);
3259	return (c);
3260}
3261
3262void
3263siocnputc(dev, c)
3264	dev_t	dev;
3265	int	c;
3266{
3267	int	s;
3268	struct siocnstate	sp;
3269
3270	s = spltty();
3271	siocnopen(&sp);
3272	siocntxwait();
3273	outb(siocniobase + com_data, c);
3274	siocnclose(&sp);
3275	splx(s);
3276}
3277
3278#ifdef DSI_SOFT_MODEM
3279/*
3280 * The magic code to download microcode to a "Connection 14.4+Fax"
3281 * modem from Digicom Systems Inc.  Very magic.
3282 */
3283
3284#define DSI_ERROR(str) { ptr = str; goto error; }
3285static int
3286LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
3287{
3288    int int_c,int_k;
3289    int data_0188, data_0187;
3290
3291    /*
3292     * First see if it is a DSI SoftModem
3293     */
3294    if(!((inb(base_io+7) ^ inb(base_io+7) & 0x80)))
3295	return ENODEV;
3296
3297    data_0188 = inb(base_io+4);
3298    data_0187 = inb(base_io+3);
3299    outb(base_io+3,0x80);
3300    outb(base_io+4,0x0C);
3301    outb(base_io+0,0x31);
3302    outb(base_io+1,0x8C);
3303    outb(base_io+7,0x10);
3304    outb(base_io+7,0x19);
3305
3306    if(0x18 != (inb(base_io+7) & 0x1A))
3307	DSI_ERROR("dsp bus not granted");
3308
3309    if(0x01 != (inb(base_io+7) & 0x01)) {
3310	outb(base_io+7,0x18);
3311	outb(base_io+7,0x19);
3312	if(0x01 != (inb(base_io+7) & 0x01))
3313	    DSI_ERROR("program mem not granted");
3314    }
3315
3316    int_c = 0;
3317
3318    while(1) {
3319	if(int_c >= 7 || size <= 0x1800)
3320	    break;
3321
3322	for(int_k = 0 ; int_k < 0x800; int_k++) {
3323	    outb(base_io+0,*ptr++);
3324	    outb(base_io+1,*ptr++);
3325	    outb(base_io+2,*ptr++);
3326	}
3327
3328	size -= 0x1800;
3329	int_c++;
3330    }
3331
3332    if(size > 0x1800) {
3333 	outb(base_io+7,0x18);
3334 	outb(base_io+7,0x19);
3335	if(0x00 != (inb(base_io+7) & 0x01))
3336	    DSI_ERROR("program data not granted");
3337
3338	for(int_k = 0 ; int_k < 0x800; int_k++) {
3339	    outb(base_io+1,*ptr++);
3340	    outb(base_io+2,0);
3341	    outb(base_io+1,*ptr++);
3342	    outb(base_io+2,*ptr++);
3343	}
3344
3345	size -= 0x1800;
3346
3347	while(size > 0x1800) {
3348	    for(int_k = 0 ; int_k < 0xC00; int_k++) {
3349		outb(base_io+1,*ptr++);
3350		outb(base_io+2,*ptr++);
3351	    }
3352	    size -= 0x1800;
3353	}
3354
3355	if(size < 0x1800) {
3356	    for(int_k=0;int_k<size/2;int_k++) {
3357		outb(base_io+1,*ptr++);
3358		outb(base_io+2,*ptr++);
3359	    }
3360	}
3361
3362    } else if (size > 0) {
3363	if(int_c == 7) {
3364	    outb(base_io+7,0x18);
3365	    outb(base_io+7,0x19);
3366	    if(0x00 != (inb(base_io+7) & 0x01))
3367		DSI_ERROR("program data not granted");
3368	    for(int_k = 0 ; int_k < size/3; int_k++) {
3369		outb(base_io+1,*ptr++);
3370		outb(base_io+2,0);
3371		outb(base_io+1,*ptr++);
3372		outb(base_io+2,*ptr++);
3373	    }
3374	} else {
3375	    for(int_k = 0 ; int_k < size/3; int_k++) {
3376		outb(base_io+0,*ptr++);
3377		outb(base_io+1,*ptr++);
3378		outb(base_io+2,*ptr++);
3379	    }
3380	}
3381    }
3382    outb(base_io+7,0x11);
3383    outb(base_io+7,3);
3384
3385    outb(base_io+4,data_0188 & 0xfb);
3386
3387    outb(base_io+3,data_0187);
3388
3389    return 0;
3390error:
3391    printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr);
3392    outb(base_io+7,0x00); \
3393    outb(base_io+3,data_0187); \
3394    outb(base_io+4,data_0188);  \
3395    return EIO;
3396}
3397#endif /* DSI_SOFT_MODEM */
3398#ifdef PC98
3399/*
3400 *  pc98 local function
3401 */
3402
3403static void
3404com_tiocm_set(struct com_s *com, int msr)
3405{
3406	int	s;
3407	int	tmp = 0;
3408	int	mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS;
3409
3410	s=spltty();
3411	com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) )
3412	   | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3413	tmp |= (CMD8251_TxEN|CMD8251_RxEN);
3414	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3415	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3416	pc98_i8251_clear_or_cmd( com, mask, tmp );
3417	splx(s);
3418}
3419
3420static void
3421com_tiocm_bis(struct com_s *com, int msr)
3422{
3423	int	s;
3424	int	tmp = 0;
3425
3426	s=spltty();
3427	com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3428	tmp |= CMD8251_TxEN|CMD8251_RxEN;
3429	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3430	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3431
3432	pc98_i8251_or_cmd( com, tmp );
3433	splx(s);
3434}
3435
3436static void
3437com_tiocm_bic(struct com_s *com, int msr)
3438{
3439	int	s;
3440	int	tmp = msr;
3441
3442	s=spltty();
3443	com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3444	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3445	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3446
3447	pc98_i8251_clear_cmd( com, tmp );
3448	splx(s);
3449}
3450
3451static int
3452com_tiocm_get(struct com_s *com)
3453{
3454	return( com->pc98_prev_modem_status );
3455}
3456
3457static int
3458com_tiocm_get_delta(struct com_s *com)
3459{
3460	int	tmp;
3461
3462	tmp = com->pc98_modem_delta;
3463	com->pc98_modem_delta = 0;
3464	return( tmp );
3465}
3466
3467/* convert to TIOCM_?? ( ioctl.h ) */
3468static int
3469pc98_get_modem_status(struct com_s *com)
3470{
3471	int	stat, stat2;
3472	register int	msr;
3473
3474	stat  = inb(com->sts_port);
3475	stat2 = inb(com->in_modem_port);
3476	msr = com->pc98_prev_modem_status
3477			& ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
3478	if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR;
3479	if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI;
3480	if (   stat & STS8251_DSR ) msr |= TIOCM_DSR;
3481	if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS;
3482#if COM_CARRIER_DETECT_EMULATE
3483	if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
3484		msr |= TIOCM_CAR;
3485	}
3486#endif
3487	return(msr);
3488}
3489
3490static void
3491pc98_check_msr(void* chan)
3492{
3493	int	msr, delta;
3494	int	s;
3495	register struct tty *tp;
3496	struct	com_s *com;
3497	int	mynor;
3498	int	unit;
3499	dev_t	dev;
3500
3501	dev=(dev_t)chan;
3502	mynor = minor(dev);
3503	unit = MINOR_TO_UNIT(mynor);
3504	com = com_addr(unit);
3505	tp = com->tp;
3506
3507	s = spltty();
3508	msr = pc98_get_modem_status(com);
3509	/* make change flag */
3510	delta = msr ^ com->pc98_prev_modem_status;
3511	if ( delta & TIOCM_CAR ) {
3512	    if ( com->modem_car_chg_timer ) {
3513		if ( -- com->modem_car_chg_timer )
3514		    msr ^= TIOCM_CAR;
3515	    } else {
3516		if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ?
3517			     DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE )
3518		    msr ^= TIOCM_CAR;
3519	    }
3520	} else
3521	    com->modem_car_chg_timer = 0;
3522	delta = ( msr ^ com->pc98_prev_modem_status ) &
3523			(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
3524	com->pc98_prev_modem_status = msr;
3525	delta = ( com->pc98_modem_delta |= delta );
3526	splx(s);
3527	if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) {
3528		if ( delta ) {
3529			commint(dev);
3530		}
3531		timeout(pc98_check_msr, (caddr_t)dev,
3532					PC98_CHECK_MODEM_INTERVAL);
3533	} else {
3534		com->modem_checking = 0;
3535	}
3536}
3537
3538static void
3539pc98_msrint_start(dev_t dev)
3540{
3541	struct	com_s *com;
3542	int	mynor;
3543	int	unit;
3544	int	s = spltty();
3545
3546	mynor = minor(dev);
3547	unit = MINOR_TO_UNIT(mynor);
3548	com = com_addr(unit);
3549	/* modem control line check routine envoke interval is 1/10 sec */
3550	if ( com->modem_checking == 0 ) {
3551		com->pc98_prev_modem_status = pc98_get_modem_status(com);
3552		com->pc98_modem_delta = 0;
3553		timeout(pc98_check_msr, (caddr_t)dev,
3554					PC98_CHECK_MODEM_INTERVAL);
3555		com->modem_checking = 1;
3556	}
3557	splx(s);
3558}
3559
3560static void
3561pc98_disable_i8251_interrupt(struct com_s *com, int mod)
3562{
3563	/* disable interrupt */
3564	register int	tmp;
3565
3566	mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3567	COM_INT_DISABLE
3568	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3569	outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp );
3570	COM_INT_ENABLE
3571}
3572
3573static void
3574pc98_enable_i8251_interrupt(struct com_s *com, int mod)
3575{
3576	register int	tmp;
3577
3578	COM_INT_DISABLE
3579	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3580	outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp );
3581	COM_INT_ENABLE
3582}
3583
3584static int
3585pc98_check_i8251_interrupt(struct com_s *com)
3586{
3587	return ( com->intr_enable & 0x07 );
3588}
3589
3590static void
3591pc98_i8251_clear_cmd(struct com_s *com, int x)
3592{
3593	int	tmp;
3594
3595	COM_INT_DISABLE
3596	tmp = com->pc98_prev_siocmd & ~(x);
3597	outb(com->cmd_port, tmp);
3598	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3599	COM_INT_ENABLE
3600}
3601
3602static void
3603pc98_i8251_or_cmd(struct com_s *com, int x)
3604{
3605	int	tmp;
3606
3607	COM_INT_DISABLE
3608	tmp = com->pc98_prev_siocmd | (x);
3609	outb(com->cmd_port, tmp);
3610	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3611	COM_INT_ENABLE
3612}
3613
3614static void
3615pc98_i8251_set_cmd(struct com_s *com, int x)
3616{
3617	int	tmp;
3618
3619	COM_INT_DISABLE
3620	tmp = (x);
3621	outb(com->cmd_port, tmp);
3622	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3623	COM_INT_ENABLE
3624}
3625
3626static void
3627pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x)
3628{
3629	int	tmp;
3630	COM_INT_DISABLE
3631	tmp = com->pc98_prev_siocmd & ~(clr);
3632	tmp |= (x);
3633	outb(com->cmd_port, tmp);
3634	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3635	COM_INT_ENABLE
3636}
3637
3638static int
3639pc98_i8251_get_cmd(struct com_s *com)
3640{
3641	return com->pc98_prev_siocmd;
3642}
3643
3644static int
3645pc98_i8251_get_mod(struct com_s *com)
3646{
3647	return com->pc98_prev_siomod;
3648}
3649
3650static void
3651pc98_i8251_reset(struct com_s *com, int mode, int command)
3652{
3653	outb(com->cmd_port, 0);	/* dummy */
3654	DELAY(2);
3655	outb(com->cmd_port, 0);	/* dummy */
3656	DELAY(2);
3657	outb(com->cmd_port, 0);	/* dummy */
3658	DELAY(2);
3659	outb(com->cmd_port, CMD8251_RESET);	/* internal reset */
3660	DELAY(2);
3661	outb(com->cmd_port, mode );	/* mode register */
3662	com->pc98_prev_siomod = mode;
3663	DELAY(2);
3664	pc98_i8251_set_cmd( com, (command|CMD8251_ER) );
3665}
3666
3667static void
3668pc98_check_sysclock(void)
3669{
3670	/* get system clock from port */
3671	if ( pc98_machine_type & M_8M ) {
3672	/* 8 MHz system & H98 */
3673		sysclock = 8;
3674	} else {
3675	/* 5 MHz system */
3676		sysclock = 5;
3677	}
3678}
3679
3680static void
3681com_cflag_and_speed_set( struct com_s *com, int cflag, int speed)
3682{
3683	int	cfcr=0, count;
3684	int	previnterrupt;
3685
3686	count = pc98_ttspeedtab( com, speed );
3687	if ( count < 0 ) return;
3688
3689	previnterrupt = pc98_check_i8251_interrupt(com);
3690	pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx );
3691
3692	switch ( cflag&CSIZE ) {
3693	  case CS5:
3694		cfcr = MOD8251_5BITS; break;
3695	  case CS6:
3696		cfcr = MOD8251_6BITS; break;
3697	  case CS7:
3698		cfcr = MOD8251_7BITS; break;
3699	  case CS8:
3700		cfcr = MOD8251_8BITS; break;
3701	}
3702	if ( cflag&PARENB ) {
3703	    if ( cflag&PARODD )
3704		cfcr |= MOD8251_PODD;
3705	    else
3706		cfcr |= MOD8251_PEVEN;
3707	} else
3708		cfcr |= MOD8251_PDISAB;
3709
3710	if ( cflag&CSTOPB )
3711		cfcr |= MOD8251_STOP2;
3712	else
3713		cfcr |= MOD8251_STOP1;
3714
3715	if ( count & 0x10000 )
3716		cfcr |= MOD8251_CLKX1;
3717	else
3718		cfcr |= MOD8251_CLKX16;
3719
3720	if (epson_machine_id != 0x20) {	/* XXX */
3721	{
3722		int	tmp;
3723		while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP))
3724			;
3725	}
3726	}
3727	/* set baud rate from ospeed */
3728	pc98_set_baud_rate( com, count );
3729
3730	if ( cfcr != pc98_i8251_get_mod(com) )
3731		pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) );
3732
3733	pc98_enable_i8251_interrupt( com, previnterrupt );
3734}
3735
3736static int
3737pc98_ttspeedtab(struct com_s *com, int speed)
3738{
3739	int	effect_sp, count=-1, mod;
3740
3741	switch ( com->pc98_if_type ) {
3742	    case COM_IF_INTERNAL:
3743		/* for *1CLK asynchronous! mode		, TEFUTEFU */
3744		effect_sp = ttspeedtab( speed, pc98speedtab );
3745		if ( effect_sp < 0 )
3746			effect_sp = ttspeedtab( (speed-1), pc98speedtab );
3747		if ( effect_sp <= 0 )
3748			return effect_sp;
3749		mod = (sysclock == 5 ? 2457600 : 1996800);
3750		if ( effect_sp == speed )
3751			mod /= 16;
3752		count = mod / effect_sp;
3753		if ( count > 65535 )
3754			return(-1);
3755		if ( effect_sp >= 2400 )
3756			if ( !(sysclock != 5 &&
3757				(effect_sp == 19200 || effect_sp == 38400)) )
3758				if ( ( mod % effect_sp ) != 0 )
3759					return(-1);
3760		if ( effect_sp != speed )
3761			count |= 0x10000;
3762		break;
3763#ifdef COM_IF_PC9861K
3764	    case COM_IF_PC9861K:
3765		effect_sp = speed;
3766		count = 1;
3767		break;
3768#endif
3769#ifdef COM_IF_PIO9032B
3770	    case COM_IF_PIO9032B:
3771		if ( speed == 0 ) return 0;
3772		count = ttspeedtab( speed, comspeedtab_pio9032b );
3773		if ( count < 0 ) return count;
3774		effect_sp = speed;
3775		break;
3776#endif
3777#ifdef COM_IF_B98_01
3778	    case COM_IF_B98_01:
3779		effect_sp=speed;
3780		count = ttspeedtab( speed, comspeedtab_b98_01 );
3781		if ( count <= 3 )
3782			return -1;         /* invalid speed/count */
3783		if ( count <= 5 )
3784			count |= 0x10000;  /* x1 mode for 76800 and 153600 */
3785		else
3786			count -= 4;        /* x16 mode for slower */
3787		break;
3788#endif
3789	}
3790	return count;
3791}
3792
3793static void
3794pc98_set_baud_rate( struct com_s *com, int count)
3795{
3796	int	s;
3797
3798	switch ( com->pc98_if_type ) {
3799	    case COM_IF_INTERNAL:
3800		if ( count < 0 ) {
3801			printf( "[ Illegal count : %d ]", count );
3802			return;
3803		} else if ( count == 0)
3804			return;
3805		/* set i8253 */
3806		s = splclock();
3807		outb( 0x77, 0xb6 );
3808		outb( 0x5f, 0);
3809		outb( 0x75, count & 0xff );
3810		outb( 0x5f, 0);
3811		outb( 0x75, (count >> 8) & 0xff );
3812		splx(s);
3813		break;
3814#if 0
3815#ifdef COM_IF_PC9861K
3816	    case COM_IF_PC9861K:
3817		break;
3818		/* ext. RS232C board: speed is determined by DIP switch */
3819#endif
3820#endif /* 0 */
3821#ifdef COM_IF_PIO9032B
3822	    case COM_IF_PIO9032B:
3823		outb( com_addr[unit], count & 0x07 );
3824		break;
3825#endif
3826#ifdef COM_IF_B98_01
3827	    case COM_IF_B98_01:
3828		outb( com->iobase,     count & 0x0f );
3829#ifdef B98_01_OLD
3830		/* some old board should be controlled in different way,
3831		   but this hasn't been tested yet.*/
3832		outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 );
3833#endif
3834		break;
3835#endif
3836	}
3837}
3838static int
3839pc98_check_if_type( int iobase, struct siodev *iod)
3840{
3841	int	irr = 0, tmp = 0;
3842	int	ret = 0;
3843	static  short	irq_tab[2][8] = {
3844		{  3,  5,  6,  9, 10, 12, 13, -1},
3845		{  3, 10, 12, 13,  5,  6,  9, -1}
3846	};
3847	iod->irq = 0;
3848	switch ( iobase & 0xff ) {
3849		case IO_COM1:
3850			iod->if_type = COM_IF_INTERNAL;
3851			ret = 0; iod->irq = 4; break;
3852#ifdef COM_IF_PC9861K
3853		case IO_COM2:
3854			iod->if_type = COM_IF_PC9861K;
3855			ret = 1; irr = 0; tmp = 3; break;
3856		case IO_COM3:
3857			iod->if_type = COM_IF_PC9861K;
3858			ret = 2; irr = 1; tmp = 3; break;
3859#endif
3860#ifdef COM_IF_PIO9032B
3861	    case IO_COM_PIO9032B_2:
3862			iod->if_type = COM_IF_PIO9032B;
3863			ret = 1; irr = 0; tmp = 7; break;
3864	    case IO_COM_PIO9032B_3:
3865			iod->if_type = COM_IF_PIO9032B;
3866			ret = 2; irr = 1; tmp = 7; break;
3867#endif
3868#ifdef COM_IF_B98_01
3869	    case IO_COM_B98_01_2:
3870			iod->if_type = COM_IF_B98_01;
3871			ret = 1; irr = 0; tmp = 7;
3872			outb(iobase + 2, 0xf2);
3873			outb(iobase,     4);
3874			break;
3875	    case IO_COM_B98_01_3:
3876			iod->if_type = COM_IF_B98_01;
3877			ret = 2; irr = 1; tmp = 7;
3878			outb(iobase + 2, 0xf2);
3879			outb(iobase    , 4);
3880			break;
3881#endif
3882	    default:
3883			if((iobase & 0x0f0) == 0xd0){
3884				iod->if_type = MC16550;
3885				return 0;
3886			}
3887			return -1;
3888	}
3889
3890	iod->cmd  = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret);
3891	iod->sts  = ( iobase & 0xff00 )|PC98SIO_sts_port(ret);
3892	iod->mod  = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret);
3893	iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret);
3894
3895	if ( iod->irq == 0 ) {
3896		tmp &= inb( iod->mod );
3897		iod->irq = irq_tab[irr][tmp];
3898		if ( iod->irq == -1 ) return -1;
3899	}
3900	return 0;
3901}
3902static int
3903pc98_set_ioport( struct com_s *com, int io_base )
3904{
3905	int	a, io, type;
3906
3907	switch ( io_base & 0xff ) {
3908	    case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL;
3909					 pc98_check_sysclock(); break;
3910#ifdef COM_IF_PC9861K
3911	    case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break;
3912	    case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break;
3913#endif /* COM_IF_PC9861K */
3914#ifdef COM_IF_PIO9032B
3915			/* PIO9032B : I/O address is changeable */
3916	    case IO_COM_PIO9032B_2:
3917			a = 1; io = io_base & 0xff00;
3918			type = COM_IF_PIO9032B; break;
3919	    case IO_COM_PIO9032B_3:
3920			a = 2; io = io_base & 0xff00;
3921			type = COM_IF_PIO9032B; break;
3922#endif /* COM_IF_PIO9032B */
3923#ifdef COM_IF_B98_01
3924	    case IO_COM_B98_01_2:
3925			a = 1; io = 0; type = COM_IF_B98_01; break;
3926	    case IO_COM_B98_01_3:
3927			a = 2; io = 0; type = COM_IF_B98_01; break;
3928#endif /* COM_IF_B98_01*/
3929	    default:	/* i/o address not match */
3930		return -1;
3931	}
3932
3933	com->pc98_if_type	= type;
3934	com->data_port		= io | PC98SIO_data_port(a);
3935	com->cmd_port		= io | PC98SIO_cmd_port(a);
3936	com->sts_port		= io | PC98SIO_sts_port(a);
3937	com->in_modem_port	= io | PC98SIO_in_modem_port(a);
3938	com->intr_ctrl_port	= io | PC98SIO_intr_ctrl_port(a);
3939	return 0;
3940}
3941#endif /* PC98 defined */
3942