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