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