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