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