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