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