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