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