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