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