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