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