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