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