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