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