sio.c revision 30772
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 *	from: @(#)com.c	7.5 (Berkeley) 5/16/91
34 *	$Id: sio.c,v 1.40 1997/10/13 09:23:14 kato Exp $
35 */
36
37#include "opt_comconsole.h"
38#include "opt_ddb.h"
39#include "opt_sio.h"
40#include "sio.h"
41#include "pnp.h"
42
43#ifndef EXTRA_SIO
44#if NPNP > 0
45#define EXTRA_SIO 2
46#else
47#define EXTRA_SIO 0
48#endif
49#endif
50
51#define NSIOTOT (NSIO + EXTRA_SIO)
52
53/*
54 * Serial driver, based on 386BSD-0.1 com driver.
55 * Mostly rewritten to use pseudo-DMA.
56 * Works for National Semiconductor NS8250-NS16550AF UARTs.
57 * COM driver, based on HP dca driver.
58 *
59 * Changes for PC-Card integration:
60 *	- Added PC-Card driver table and handlers
61 */
62/*===============================================================
63 * 386BSD(98),FreeBSD-1.1x(98) com driver.
64 * -----
65 * modified for PC9801 by M.Ishii
66 *			Kyoto University Microcomputer Club (KMC)
67 * Chou "TEFUTEFU" Hirotomi
68 *			Kyoto Univ.  the faculty of medicine
69 *===============================================================
70 * FreeBSD-2.0.1(98) sio driver.
71 * -----
72 * modified for pc98 Internal i8251 and MICRO CORE MC16550II
73 *			T.Koike(hfc01340@niftyserve.or.jp)
74 * implement kernel device configuration
75 *			aizu@orient.center.nitech.ac.jp
76 *
77 * Notes.
78 * -----
79 *  PC98 localization based on 386BSD(98) com driver. Using its PC98 local
80 *  functions.
81 *  This driver is under debugging,has bugs.
82 *
83 * 1) config
84 *  options COM_MULTIPORT  #if using MC16550II
85 *  device sio0 at nec? port 0x30  tty irq 4 vector siointr #internal
86 *  device sio1 at nec? port 0xd2  tty irq 5 flags 0x101 vector siointr #mc1
87 *  device sio2 at nec? port 0x8d2 tty flags 0x101 vector siointr       #mc2
88 *                         # ~~~~~iobase        ~~multi port flag
89 *                         #                   ~  master device is sio1
90 * 2) device
91 *  cd /dev; MAKEDEV ttyd0 ttyd1 ..
92 * 3) /etc/rc.serial
93 *  57600bps is too fast for sio0(internal8251)
94 *  my ex.
95 *    #set default speed 9600
96 *    modem()
97 *       :
98 *      stty </dev/ttyid$i crtscts 9600
99 *       :                 #       ~~~~ default speed(can change after init.)
100 *    modem 0 1 2
101 * 4) COMCONSOLE
102 *  not changed.
103 * 5) PC9861K,PIO9032B,B98_01
104 *  not tested.
105 */
106/*
107 * modified for AIWA B98-01
108 * by T.Hatanou <hatanou@yasuda.comm.waseda.ac.jp>  last update: 15 Sep.1995
109 *
110 * How to configure...
111 *   # options COM_MULTIPORT         # support for MICROCORE MC16550II
112 *      ... comment-out this line, which will conflict with B98_01.
113 *   options "B98_01"                # support for AIWA B98-01
114 *   device  sio1 at nec? port 0x00d1 tty irq ? vector siointr
115 *   device  sio2 at nec? port 0x00d5 tty irq ? vector siointr
116 *      ... you can leave these lines `irq ?', irq will be autodetected.
117 */
118#ifdef PC98
119#define	MC16550		0
120#define COM_IF_INTERNAL	1
121#if 0
122#define COM_IF_PC9861K	2
123#define COM_IF_PIO9032B	3
124#endif
125#ifdef	B98_01
126#undef  COM_MULTIPORT	/* COM_MULTIPORT will conflict with B98_01 */
127#define COM_IF_B98_01	4
128#endif /* B98_01 */
129#endif /* PC98 */
130
131#include <sys/param.h>
132#include <sys/systm.h>
133#include <sys/reboot.h>
134#include <sys/malloc.h>
135#include <sys/tty.h>
136#include <sys/proc.h>
137#include <sys/conf.h>
138#include <sys/dkstat.h>
139#include <sys/fcntl.h>
140#include <sys/kernel.h>
141#include <sys/syslog.h>
142#include <sys/sysctl.h>
143#ifdef DEVFS
144#include <sys/devfsext.h>
145#endif
146
147#include <machine/clock.h>
148
149#ifdef PC98
150#include <pc98/pc98/pc98.h>
151#include <pc98/pc98/pc98_machdep.h>
152#include <i386/isa/icu.h>
153#include <i386/isa/isa_device.h>
154#include <pc98/pc98/sioreg.h>
155#include <i386/isa/ic/i8251.h>
156#else
157#include <i386/isa/isa.h>
158#include <i386/isa/isa_device.h>
159#include <i386/isa/sioreg.h>
160#endif
161#include <i386/isa/intr_machdep.h>
162
163#ifdef COM_ESP
164#include <i386/isa/ic/esp.h>
165#endif
166#include <i386/isa/ic/ns16550.h>
167
168#include "card.h"
169#if NCARD > 0
170#include <pccard/card.h>
171#include <pccard/driver.h>
172#include <pccard/slot.h>
173#endif
174
175#if NPNP > 0
176#include <i386/isa/pnp.h>
177#endif
178
179#ifdef SMP
180#define disable_intr()	COM_DISABLE_INTR()
181#define enable_intr()	COM_ENABLE_INTR()
182#endif /* SMP */
183
184#ifdef APIC_IO
185/*
186 * INTs are masked in the (global) IO APIC,
187 *  but the IRR register is in each LOCAL APIC,
188 *  so we would have to unmask the INT to be able to "see INT pending".
189 * So instead we just look in the 8259 ICU.
190 */
191#define isa_irq_pending		icu_irq_pending
192#endif /* APIC_IO */
193
194#define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
195#define	RB_I_HIGH_WATER	(TTYHOG - 2 * RS_IBUFSIZE)
196#define	RS_IBUFSIZE	256
197
198#define	CALLOUT_MASK		0x80
199#define	CONTROL_MASK		0x60
200#define	CONTROL_INIT_STATE	0x20
201#define	CONTROL_LOCK_STATE	0x40
202#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
203#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
204#define	MINOR_TO_UNIT(mynor)	((mynor) & ~MINOR_MAGIC_MASK)
205
206#ifdef COM_MULTIPORT
207/* checks in flags for multiport and which is multiport "master chip"
208 * for a given card
209 */
210#define	COM_ISMULTIPORT(dev)	((dev)->id_flags & 0x01)
211#define	COM_MPMASTER(dev)	(((dev)->id_flags >> 8) & 0x0ff)
212#define	COM_NOTAST4(dev)	((dev)->id_flags & 0x04)
213#endif /* COM_MULTIPORT */
214
215#define	COM_CONSOLE(dev)	((dev)->id_flags & 0x10)
216#define	COM_FORCECONSOLE(dev)	((dev)->id_flags & 0x20)
217#define	COM_LLCONSOLE(dev)	((dev)->id_flags & 0x40)
218#define	COM_LOSESOUTINTS(dev)	((dev)->id_flags & 0x08)
219#define	COM_NOFIFO(dev)		((dev)->id_flags & 0x02)
220#define	COM_VERBOSE(dev)	((dev)->id_flags & 0x80)
221#define	COM_NOTST3(dev)		((dev)->id_flags & 0x10000)
222#define COM_ST16650A(dev)	((dev)->id_flags & 0x20000)
223#define	COM_FIFOSIZE(dev)	(((dev)->id_flags & 0xff000000) >> 24)
224
225#ifndef PC98
226#define	com_scr		7	/* scratch register for 16450-16550 (R/W) */
227#endif /* !PC98 */
228
229/*
230 * Input buffer watermarks.
231 * The external device is asked to stop sending when the buffer exactly reaches
232 * high water, or when the high level requests it.
233 * The high level is notified immediately (rather than at a later clock tick)
234 * when this watermark is reached.
235 * The buffer size is chosen so the watermark should almost never be reached.
236 * The low watermark is invisibly 0 since the buffer is always emptied all at
237 * once.
238 */
239#define	RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
240
241/*
242 * com state bits.
243 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
244 * than the other bits so that they can be tested as a group without masking
245 * off the low bits.
246 *
247 * The following com and tty flags correspond closely:
248 *	CS_BUSY		= TS_BUSY (maintained by comstart(), siopoll() and
249 *				   siostop())
250 *	CS_TTGO		= ~TS_TTSTOP (maintained by comparam() and comstart())
251 *	CS_CTS_OFLOW	= CCTS_OFLOW (maintained by comparam())
252 *	CS_RTS_IFLOW	= CRTS_IFLOW (maintained by comparam())
253 * TS_FLUSH is not used.
254 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
255 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
256 */
257#define	CS_BUSY		0x80	/* output in progress */
258#define	CS_TTGO		0x40	/* output not stopped by XOFF */
259#define	CS_ODEVREADY	0x20	/* external device h/w ready (CTS) */
260#define	CS_CHECKMSR	1	/* check of MSR scheduled */
261#define	CS_CTS_OFLOW	2	/* use CTS output flow control */
262#define	CS_DTR_OFF	0x10	/* DTR held off */
263#define	CS_ODONE	4	/* output completed */
264#define	CS_RTS_IFLOW	8	/* use RTS input flow control */
265#define	CSE_BUSYCHECK	1	/* siobusycheck() scheduled */
266
267static	char const * const	error_desc[] = {
268#define	CE_OVERRUN			0
269	"silo overflow",
270#define	CE_INTERRUPT_BUF_OVERFLOW	1
271	"interrupt-level buffer overflow",
272#define	CE_TTY_BUF_OVERFLOW		2
273	"tty-level buffer overflow",
274};
275
276#define	CE_NTYPES			3
277#define	CE_RECORD(com, errnum)		(++(com)->delta_error_counts[errnum])
278
279/* types.  XXX - should be elsewhere */
280typedef u_int	Port_t;		/* hardware port */
281typedef u_char	bool_t;		/* boolean */
282
283/* queue of linear buffers */
284struct lbq {
285	u_char	*l_head;	/* next char to process */
286	u_char	*l_tail;	/* one past the last char to process */
287	struct lbq *l_next;	/* next in queue */
288	bool_t	l_queued;	/* nonzero if queued */
289};
290
291/* com device structure */
292struct com_s {
293	u_char	state;		/* miscellaneous flag bits */
294	bool_t  active_out;	/* nonzero if the callout device is open */
295	u_char	cfcr_image;	/* copy of value written to CFCR */
296#ifdef COM_ESP
297	bool_t	esp;		/* is this unit a hayes esp board? */
298#endif
299	u_char	extra_state;	/* more flag bits, separate for order trick */
300	u_char	fifo_image;	/* copy of value written to FIFO */
301	bool_t	hasfifo;	/* nonzero for 16550 UARTs */
302	bool_t	st16650a;	/* Is a Startech 16650A or RTS/CTS compat */
303	bool_t	loses_outints;	/* nonzero if device loses output interrupts */
304	u_char	mcr_image;	/* copy of value written to MCR */
305#ifdef COM_MULTIPORT
306	bool_t	multiport;	/* is this unit part of a multiport device? */
307#endif /* COM_MULTIPORT */
308	bool_t	no_irq;		/* nonzero if irq is not attached */
309	bool_t  gone;		/* hardware disappeared */
310	bool_t	poll;		/* nonzero if polling is required */
311	bool_t	poll_output;	/* nonzero if polling for output is required */
312	int	unit;		/* unit	number */
313	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
314	u_int	tx_fifo_size;
315	u_int	wopeners;	/* # processes waiting for DCD in open() */
316
317	/*
318	 * The high level of the driver never reads status registers directly
319	 * because there would be too many side effects to handle conveniently.
320	 * Instead, it reads copies of the registers stored here by the
321	 * interrupt handler.
322	 */
323	u_char	last_modem_status;	/* last MSR read by intr handler */
324	u_char	prev_modem_status;	/* last MSR handled by high level */
325
326	u_char	hotchar;	/* ldisc-specific char to be handled ASAP */
327	u_char	*ibuf;		/* start of input buffer */
328	u_char	*ibufend;	/* end of input buffer */
329	u_char	*ihighwater;	/* threshold in input buffer */
330	u_char	*iptr;		/* next free spot in input buffer */
331
332	struct lbq	obufq;	/* head of queue of output buffers */
333	struct lbq	obufs[2];	/* output buffers */
334
335#ifdef PC98
336	Port_t	cmd_port;
337	Port_t	sts_port;
338	Port_t	in_modem_port;
339	Port_t	intr_ctrl_port;
340	int	intr_enable;
341	int	pc98_prev_modem_status;
342	int	pc98_modem_delta;
343	int	modem_car_chg_timer;
344	int	pc98_prev_siocmd;
345	int	pc98_prev_siomod;
346	int	modem_checking;
347	int	pc98_if_type;
348#endif /* PC98 */
349	Port_t	data_port;	/* i/o ports */
350#ifdef COM_ESP
351	Port_t	esp_port;
352#endif
353	Port_t	int_id_port;
354	Port_t	iobase;
355	Port_t	modem_ctl_port;
356	Port_t	line_status_port;
357	Port_t	modem_status_port;
358
359	struct tty	*tp;	/* cross reference */
360
361	/* Initial state. */
362	struct termios	it_in;	/* should be in struct tty */
363	struct termios	it_out;
364
365	/* Lock state. */
366	struct termios	lt_in;	/* should be in struct tty */
367	struct termios	lt_out;
368
369	bool_t	do_timestamp;
370	bool_t	do_dcd_timestamp;
371	struct timeval	timestamp;
372	struct timeval	dcd_timestamp;
373
374	u_long	bytes_in;	/* statistics */
375	u_long	bytes_out;
376	u_int	delta_error_counts[CE_NTYPES];
377	u_long	error_counts[CE_NTYPES];
378
379	/*
380	 * Ping-pong input buffers.  The extra factor of 2 in the sizes is
381	 * to allow for an error byte for each input byte.
382	 */
383#define	CE_INPUT_OFFSET		RS_IBUFSIZE
384	u_char	ibuf1[2 * RS_IBUFSIZE];
385	u_char	ibuf2[2 * RS_IBUFSIZE];
386
387	/*
388	 * Data area for output buffers.  Someday we should build the output
389	 * buffer queue without copying data.
390	 */
391	u_char	obuf1[256];
392	u_char	obuf2[256];
393#ifdef DEVFS
394	void	*devfs_token_ttyd;
395	void	*devfs_token_ttyl;
396	void	*devfs_token_ttyi;
397	void	*devfs_token_cuaa;
398	void	*devfs_token_cual;
399	void	*devfs_token_cuai;
400#endif
401};
402
403/*
404 * XXX public functions in drivers should be declared in headers produced
405 * by `config', not here.
406 */
407
408/* Interrupt handling entry point. */
409void	siopoll		__P((void));
410
411/* Device switch entry points. */
412#define	sioreset	noreset
413#define	siommap		nommap
414#define	siostrategy	nostrategy
415
416#ifdef COM_ESP
417static	int	espattach	__P((struct isa_device *isdp, struct com_s *com,
418				     Port_t esp_port));
419#endif
420static	int	sioattach	__P((struct isa_device *dev));
421static	timeout_t siobusycheck;
422static	timeout_t siodtrwakeup;
423static	void	comhardclose	__P((struct com_s *com));
424static	void	siointr1	__P((struct com_s *com));
425static	int	commctl		__P((struct com_s *com, int bits, int how));
426static	int	comparam	__P((struct tty *tp, struct termios *t));
427static	int	sioprobe	__P((struct isa_device *dev));
428static	void	siosettimeout	__P((void));
429static	void	comstart	__P((struct tty *tp));
430static	timeout_t comwakeup;
431static	int	tiocm_xxx2mcr	__P((int tiocm_xxx));
432static	void	disc_optim	__P((struct tty	*tp, struct termios *t,
433				     struct com_s *com));
434
435#ifdef DSI_SOFT_MODEM
436static  int 	LoadSoftModem   __P((int unit,int base_io, u_long size, u_char *ptr));
437#endif /* DSI_SOFT_MODEM */
438
439static char driver_name[] = "sio";
440
441/* table and macro for fast conversion from a unit number to its com struct */
442static	struct com_s	*p_com_addr[NSIOTOT];
443#define	com_addr(unit)	(p_com_addr[unit])
444
445struct isa_driver	siodriver = {
446	sioprobe, sioattach, driver_name
447};
448
449static	d_open_t	sioopen;
450static	d_close_t	sioclose;
451static	d_read_t	sioread;
452static	d_write_t	siowrite;
453static	d_ioctl_t	sioioctl;
454static	d_stop_t	siostop;
455static	d_devtotty_t	siodevtotty;
456
457#define CDEV_MAJOR 28
458static struct cdevsw sio_cdevsw = {
459	sioopen,	sioclose,	sioread,	siowrite,
460	sioioctl,	siostop,	noreset,	siodevtotty,
461	ttpoll,		nommap,		NULL,		driver_name,
462	NULL,		-1,
463};
464
465static	int	comconsole = -1;
466static	volatile speed_t	comdefaultrate = CONSPEED;
467static	u_int	com_events;	/* input chars + weighted output completions */
468static	Port_t	siocniobase;
469static	int	sio_timeout;
470static	int	sio_timeouts_until_log;
471static	struct	callout_handle sio_timeout_handle
472    = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
473#if 0 /* XXX */
474static struct tty	*sio_tty[NSIOTOT];
475#else
476static struct tty	sio_tty[NSIOTOT];
477#endif
478static	const int	nsio_tty = NSIOTOT;
479
480#ifdef PC98
481struct	siodev	{
482	short	if_type;
483	short	irq;
484	Port_t	cmd, sts, ctrl, mod;
485	};
486static	int	sysclock;
487static	short	port_table[5][3] = {
488			{0x30, 0xb1, 0xb9},
489			{0x32, 0xb3, 0xbb},
490			{0x32, 0xb3, 0xbb},
491			{0x33, 0xb0, 0xb2},
492			{0x35, 0xb0, 0xb2}
493		};
494#define	PC98SIO_data_port(ch)		port_table[0][ch]
495#define	PC98SIO_cmd_port(ch)		port_table[1][ch]
496#define	PC98SIO_sts_port(ch)		port_table[2][ch]
497#define	PC98SIO_in_modem_port(ch)	port_table[3][ch]
498#define	PC98SIO_intr_ctrl_port(ch)	port_table[4][ch]
499#ifdef COM_IF_PIO9032B
500#define   IO_COM_PIO9032B_2	0x0b8
501#define   IO_COM_PIO9032B_3	0x0ba
502#endif /* COM_IF_PIO9032B */
503#ifdef COM_IF_B98_01
504#define	  IO_COM_B98_01_2	0x0d1
505#define	  IO_COM_B98_01_3	0x0d5
506#endif /* COM_IF_B98_01 */
507#define	COM_INT_DISABLE		{int previpri; previpri=spltty();
508#define	COM_INT_ENABLE		splx(previpri);}
509#define IEN_TxFLAG		IEN_Tx
510
511#define COM_CARRIER_DETECT_EMULATE	0
512#define	PC98_CHECK_MODEM_INTERVAL	(hz/10)
513#define DCD_OFF_TOLERANCE		2
514#define DCD_ON_RECOGNITION		2
515#define	IS_8251(type)		(type != MC16550)
516#define	IS_PC98IN(adr)		(adr == 0x30)
517
518static	void	commint		__P((dev_t dev));
519static	void	com_tiocm_set	__P((struct com_s *com, int msr));
520static	void	com_tiocm_bis	__P((struct com_s *com, int msr));
521static	void	com_tiocm_bic	__P((struct com_s *com, int msr));
522static	int	com_tiocm_get	__P((struct com_s *com));
523static	int	com_tiocm_get_delta	__P((struct com_s *com));
524static	void	pc98_msrint_start	__P((dev_t dev));
525static	void	com_cflag_and_speed_set	__P((struct com_s *com, int cflag, int speed));
526static	int	pc98_ttspeedtab		__P((struct com_s *com, int speed));
527static	int	pc98_get_modem_status	__P((struct com_s *com));
528static	timeout_t	pc98_check_msr;
529static	void	pc98_set_baud_rate	__P((struct com_s *com, int count));
530static	void	pc98_i8251_reset	__P((struct com_s *com, int mode, int command));
531static	void	pc98_disable_i8251_interrupt	__P((struct com_s *com, int mod));
532static	void	pc98_enable_i8251_interrupt	__P((struct com_s *com, int mod));
533static	int	pc98_check_i8251_interrupt	__P((struct com_s *com));
534static	int	pc98_i8251_get_cmd	__P((struct com_s *com));
535static	int	pc98_i8251_get_mod	__P((struct com_s *com));
536static	void	pc98_i8251_set_cmd	__P((struct com_s *com, int x));
537static	void	pc98_i8251_or_cmd	__P((struct com_s *com, int x));
538static	void	pc98_i8251_clear_cmd	__P((struct com_s *com, int x));
539static	void	pc98_i8251_clear_or_cmd	__P((struct com_s *com, int clr, int x));
540static	int	pc98_check_if_type	__P((int iobase, struct siodev *iod));
541static	void	pc98_check_sysclock	__P((void));
542static	int	pc98_set_ioport		__P((struct com_s *com, int io_base));
543
544#define com_int_Tx_disable(com) \
545		pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP)
546#define com_int_Tx_enable(com) \
547		pc98_enable_i8251_interrupt(com,IEN_TxFLAG)
548#define com_int_Rx_disable(com) \
549		pc98_disable_i8251_interrupt(com,IEN_Rx)
550#define com_int_Rx_enable(com) \
551		pc98_enable_i8251_interrupt(com,IEN_Rx)
552#define com_int_TxRx_disable(com) \
553		pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx)
554#define com_int_TxRx_enable(com) \
555		pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx)
556#define com_send_break_on(com) \
557		pc98_i8251_or_cmd(com,CMD8251_SBRK)
558#define com_send_break_off(com) \
559		pc98_i8251_clear_cmd(com,CMD8251_SBRK)
560
561struct speedtab pc98speedtab[] = {	/* internal RS232C interface */
562	0,	0,
563	50,	50,
564	75,	75,
565	150,	150,
566	200,	200,
567	300,	300,
568	600,	600,
569	1200,	1200,
570	2400,	2400,
571	4800,	4800,
572	9600,	9600,
573	19200,	19200,
574	38400,	38400,
575	76800,	76800,
576	20800,	20800,
577	41600,	41600,
578	15600,	15600,
579	31200,	31200,
580	62400,	62400,
581	-1,	-1
582};
583#ifdef COM_IF_PIO9032B
584struct speedtab comspeedtab_pio9032b[] = {
585	300,	6,
586	600,	5,
587	1200,	4,
588	2400,	3,
589	4800,	2,
590	9600,	1,
591	19200,	0,
592	38400,	7,
593	-1,	-1
594};
595#endif
596
597#ifdef COM_IF_B98_01
598struct speedtab comspeedtab_b98_01[] = {
599	0,	0,
600	75,	15,
601	150,	14,
602	300,	13,
603	600,	12,
604	1200,	11,
605	2400,	10,
606	4800,	9,
607	9600,	8,
608	19200,	7,
609	38400,	6,
610	76800,	5,
611	153600,	4,
612	-1,	-1
613};
614#endif
615#endif /* PC98 */
616
617static	struct speedtab comspeedtab[] = {
618	{ 0,		0 },
619	{ 50,		COMBRD(50) },
620	{ 75,		COMBRD(75) },
621	{ 110,		COMBRD(110) },
622	{ 134,		COMBRD(134) },
623	{ 150,		COMBRD(150) },
624	{ 200,		COMBRD(200) },
625	{ 300,		COMBRD(300) },
626	{ 600,		COMBRD(600) },
627	{ 1200,		COMBRD(1200) },
628	{ 1800,		COMBRD(1800) },
629	{ 2400,		COMBRD(2400) },
630	{ 4800,		COMBRD(4800) },
631	{ 9600,		COMBRD(9600) },
632	{ 19200,	COMBRD(19200) },
633	{ 38400,	COMBRD(38400) },
634	{ 57600,	COMBRD(57600) },
635	{ 115200,	COMBRD(115200) },
636	{ -1,		-1 }
637};
638
639#ifdef COM_ESP
640/* XXX configure this properly. */
641static	Port_t	likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
642static	Port_t	likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
643#endif
644
645/*
646 * handle sysctl read/write requests for console speed
647 *
648 * In addition to setting comdefaultrate for I/O through /dev/console,
649 * also set the initial and lock values for the /dev/ttyXX device
650 * if there is one associated with the console.  Finally, if the /dev/tty
651 * device has already been open, change the speed on the open running port
652 * itself.
653 */
654
655static int
656sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS
657{
658	int error, s;
659	speed_t newspeed;
660	struct com_s *com;
661	struct tty *tp;
662
663	newspeed = comdefaultrate;
664
665	error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
666	if (error || !req->newptr)
667		return (error);
668
669	comdefaultrate = newspeed;
670
671	if (comconsole < 0)		/* serial console not selected? */
672		return (0);
673
674	com = com_addr(comconsole);
675	if (!com)
676		return (ENXIO);
677
678	/*
679	 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
680	 * (note, the lock rates really are boolean -- if non-zero, disallow
681	 *  speed changes)
682	 */
683	com->it_in.c_ispeed  = com->it_in.c_ospeed =
684	com->lt_in.c_ispeed  = com->lt_in.c_ospeed =
685	com->it_out.c_ispeed = com->it_out.c_ospeed =
686	com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
687
688	/*
689	 * if we're open, change the running rate too
690	 */
691	tp = com->tp;
692	if (tp && (tp->t_state & TS_ISOPEN)) {
693		tp->t_termios.c_ispeed =
694		tp->t_termios.c_ospeed = comdefaultrate;
695		s = spltty();
696		error = comparam(tp, &tp->t_termios);
697		splx(s);
698	}
699	return error;
700}
701
702SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
703	    0, 0, sysctl_machdep_comdefaultrate, "I", "");
704
705#if NCARD > 0
706/*
707 *	PC-Card (PCMCIA) specific code.
708 */
709static int sioinit(struct pccard_devinfo *);		/* init device */
710static void siounload(struct pccard_devinfo *);		/* Disable driver */
711static int card_intr(struct pccard_devinfo *);		/* Interrupt handler */
712
713static struct pccard_device sio_info = {
714	driver_name,
715	sioinit,
716	siounload,
717	card_intr,
718	0,			/* Attributes - presently unused */
719	&tty_imask		/* Interrupt mask for device */
720				/* XXX - Should this also include net_imask? */
721};
722
723DATA_SET(pccarddrv_set, sio_info);
724
725/*
726 *	Initialize the device - called from Slot manager.
727 */
728int
729sioinit(struct pccard_devinfo *devi)
730{
731
732	/* validate unit number. */
733	if (devi->isahd.id_unit >= (NSIOTOT))
734		return(ENODEV);
735	/* Make sure it isn't already probed. */
736	if (com_addr(devi->isahd.id_unit))
737		return(EBUSY);
738	/*
739	 * Probe the device. If a value is returned, the
740	 * device was found at the location.
741	 */
742	if (sioprobe(&devi->isahd) == 0)
743		return(ENXIO);
744	if (sioattach(&devi->isahd) == 0)
745		return(ENXIO);
746
747	return(0);
748}
749
750/*
751 *	siounload - unload the driver and clear the table.
752 *	XXX TODO:
753 *	This is usually called when the card is ejected, but
754 *	can be caused by a modunload of a controller driver.
755 *	The idea is to reset the driver's view of the device
756 *	and ensure that any driver entry points such as
757 *	read and write do not hang.
758 */
759static void
760siounload(struct pccard_devinfo *devi)
761{
762	struct com_s	*com;
763
764	com = com_addr(devi->isahd.id_unit);
765	if (!com->iobase) {
766		printf("sio%d already unloaded!\n",devi->isahd.id_unit);
767		return;
768	}
769	if (com->tp && (com->tp->t_state & TS_ISOPEN)) {
770		com->gone = 1;
771		printf("sio%d: unload\n", devi->isahd.id_unit);
772		com->tp->t_gen++;
773		ttyclose(com->tp);
774		ttwakeup(com->tp);
775		ttwwakeup(com->tp);
776	} else {
777		com_addr(com->unit) = NULL;
778		bzero(com, sizeof *com);
779		free(com,M_TTYS);
780		printf("sio%d: unload,gone\n", devi->isahd.id_unit);
781	}
782}
783
784/*
785 *	card_intr - Shared interrupt called from
786 *	front end of PC-Card handler.
787 */
788static int
789card_intr(struct pccard_devinfo *devi)
790{
791	struct com_s	*com;
792	COM_LOCK();
793	com = com_addr(devi->isahd.id_unit);
794	if (com && !com_addr(devi->isahd.id_unit)->gone)
795		siointr1(com_addr(devi->isahd.id_unit));
796	COM_UNLOCK();
797	return(1);
798}
799#endif /* NCARD > 0 */
800
801static int
802sioprobe(dev)
803	struct isa_device	*dev;
804{
805	static bool_t	already_init;
806	bool_t		failures[10];
807	int		fn;
808	struct isa_device	*idev;
809	Port_t		iobase;
810	u_char		mcr_image;
811	int		result;
812#ifdef PC98
813	struct isa_device	*xdev;
814	int		irqout=0;
815	int		ret = 0;
816	int		tmp;
817	struct		siodev	iod;
818#else
819	struct isa_device	*xdev;
820#endif
821
822	if (!already_init) {
823		/*
824		 * Turn off MCR_IENABLE for all likely serial ports.  An unused
825		 * port with its MCR_IENABLE gate open will inhibit interrupts
826		 * from any used port that shares the interrupt vector.
827		 * XXX the gate enable is elsewhere for some multiports.
828		 */
829		for (xdev = isa_devtab_tty; xdev->id_driver != NULL; xdev++)
830			if (xdev->id_driver == &siodriver && xdev->id_enabled)
831#ifdef PC98
832				if (IS_PC98IN(xdev->id_iobase))
833					outb(xdev->id_iobase + 2, 0xf2);
834				else
835#endif
836				outb(xdev->id_iobase + com_mcr, 0);
837		already_init = TRUE;
838	}
839
840#ifdef PC98
841	/*
842	 * If the port is i8251 UART (internal, B98_01)
843	 */
844	if(pc98_check_if_type(dev->id_iobase, &iod) == -1)
845		return 0;
846	if(IS_8251(iod.if_type)){
847		if ( iod.irq > 0 )
848			dev->id_irq = (1 << iod.irq);
849		outb(iod.cmd, 0);
850		DELAY(10);
851		outb(iod.cmd, 0);
852		DELAY(10);
853		outb(iod.cmd, 0);
854		DELAY(10);
855		outb(iod.cmd, CMD8251_RESET);
856		DELAY(1000);		/* for a while...*/
857		outb(iod.cmd, 0xf2);	/* MODE (dummy) */
858		DELAY(10);
859		outb(iod.cmd, 0x01);	/* CMD (dummy) */
860		DELAY(1000);		/* for a while...*/
861		if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) {
862			ret = 0;
863		}
864		switch (iod.if_type) {
865		case COM_IF_INTERNAL:
866			COM_INT_DISABLE
867			tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx));
868			outb( iod.ctrl, tmp|IEN_TxEMP );
869			ret = isa_irq_pending(dev) ? 4 : 0;
870			outb( iod.ctrl, tmp );
871			COM_INT_ENABLE
872			break;
873#ifdef COM_IF_B98_01
874		case COM_IF_B98_01:
875			/* B98_01 doesn't activate TxEMP interrupt line
876			   when being reset, so we can't check irq pending.*/
877			ret = 4;
878			break;
879#endif
880		}
881		if (epson_machine_id==0x20) {	/* XXX */
882			ret = 4;
883		}
884		return ret;
885	}
886#endif /* PC98 */
887	/*
888	 * If the device is on a multiport card and has an AST/4
889	 * compatible interrupt control register, initialize this
890	 * register and prepare to leave MCR_IENABLE clear in the mcr.
891	 * Otherwise, prepare to set MCR_IENABLE in the mcr.
892	 * Point idev to the device struct giving the correct id_irq.
893	 * This is the struct for the master device if there is one.
894	 */
895	idev = dev;
896	mcr_image = MCR_IENABLE;
897#ifdef COM_MULTIPORT
898	if (COM_ISMULTIPORT(dev)) {
899		idev = find_isadev(isa_devtab_tty, &siodriver,
900				   COM_MPMASTER(dev));
901		if (idev == NULL) {
902			printf("sio%d: master device %d not configured\n",
903			       dev->id_unit, COM_MPMASTER(dev));
904			return (0);
905		}
906#ifndef PC98
907		if (!COM_NOTAST4(dev)) {
908			outb(idev->id_iobase + com_scr,
909			     idev->id_irq ? 0x80 : 0);
910			mcr_image = 0;
911		}
912#endif /* !PC98 */
913	}
914#endif /* COM_MULTIPORT */
915	if (idev->id_irq == 0)
916		mcr_image = 0;
917
918#ifdef PC98
919	switch(idev->id_irq){
920		case IRQ3: irqout = 4; break;
921		case IRQ5: irqout = 5; break;
922		case IRQ6: irqout = 6; break;
923		case IRQ12: irqout = 7; break;
924		default:
925			printf("sio%d: irq configuration error\n",dev->id_unit);
926			return (0);
927	}
928	outb(dev->id_iobase+0x1000, irqout);
929#endif
930	bzero(failures, sizeof failures);
931	iobase = dev->id_iobase;
932
933	if (COM_LLCONSOLE(dev)) {
934		printf("sio%d: reserved for low-level i/o\n", dev->id_unit);
935		return (0);
936	}
937
938	/*
939	 * We don't want to get actual interrupts, just masked ones.
940	 * Interrupts from this line should already be masked in the ICU,
941	 * but mask them in the processor as well in case there are some
942	 * (misconfigured) shared interrupts.
943	 */
944	disable_intr();
945/* EXTRA DELAY? */
946
947	/*
948	 * Initialize the speed and the word size and wait long enough to
949	 * drain the maximum of 16 bytes of junk in device output queues.
950	 * The speed is undefined after a master reset and must be set
951	 * before relying on anything related to output.  There may be
952	 * junk after a (very fast) soft reboot and (apparently) after
953	 * master reset.
954	 * XXX what about the UART bug avoided by waiting in comparam()?
955	 * We don't want to to wait long enough to drain at 2 bps.
956	 */
957	if (iobase == siocniobase)
958		DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
959	else {
960		outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
961		outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff);
962		outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8);
963		outb(iobase + com_cfcr, CFCR_8BITS);
964		DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
965	}
966
967	/*
968	 * Enable the interrupt gate and disable device interupts.  This
969	 * should leave the device driving the interrupt line low and
970	 * guarantee an edge trigger if an interrupt can be generated.
971	 */
972/* EXTRA DELAY? */
973	outb(iobase + com_mcr, mcr_image);
974	outb(iobase + com_ier, 0);
975
976	/*
977	 * Attempt to set loopback mode so that we can send a null byte
978	 * without annoying any external device.
979	 */
980/* EXTRA DELAY? */
981	outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK);
982
983	/*
984	 * Attempt to generate an output interrupt.  On 8250's, setting
985	 * IER_ETXRDY generates an interrupt independent of the current
986	 * setting and independent of whether the THR is empty.  On 16450's,
987	 * setting IER_ETXRDY generates an interrupt independent of the
988	 * current setting.  On 16550A's, setting IER_ETXRDY only
989	 * generates an interrupt when IER_ETXRDY is not already set.
990	 */
991	outb(iobase + com_ier, IER_ETXRDY);
992
993	/*
994	 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
995	 * an interrupt.  They'd better generate one for actually doing
996	 * output.  Loopback may be broken on the same incompatibles but
997	 * it's unlikely to do more than allow the null byte out.
998	 */
999	outb(iobase + com_data, 0);
1000	DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
1001
1002	/*
1003	 * Turn off loopback mode so that the interrupt gate works again
1004	 * (MCR_IENABLE was hidden).  This should leave the device driving
1005	 * an interrupt line high.  It doesn't matter if the interrupt
1006	 * line oscillates while we are not looking at it, since interrupts
1007	 * are disabled.
1008	 */
1009/* EXTRA DELAY? */
1010	outb(iobase + com_mcr, mcr_image);
1011
1012	/*
1013	 * Check that
1014	 *	o the CFCR, IER and MCR in UART hold the values written to them
1015	 *	  (the values happen to be all distinct - this is good for
1016	 *	  avoiding false positive tests from bus echoes).
1017	 *	o an output interrupt is generated and its vector is correct.
1018	 *	o the interrupt goes away when the IIR in the UART is read.
1019	 */
1020/* EXTRA DELAY? */
1021	failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS;
1022	failures[1] = inb(iobase + com_ier) - IER_ETXRDY;
1023	failures[2] = inb(iobase + com_mcr) - mcr_image;
1024	DELAY(10000);		/* Some internal modems need this time */
1025	if (idev->id_irq != 0 && !COM_NOTST3(idev))
1026		failures[3] = isa_irq_pending(idev) ? 0 : 1;
1027	failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY;
1028	DELAY(1000);		/* XXX */
1029	if (idev->id_irq != 0)
1030		failures[5] = isa_irq_pending(idev) ? 1	: 0;
1031	failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
1032
1033	/*
1034	 * Turn off all device interrupts and check that they go off properly.
1035	 * Leave MCR_IENABLE alone.  For ports without a master port, it gates
1036	 * the OUT2 output of the UART to
1037	 * the ICU input.  Closing the gate would give a floating ICU input
1038	 * (unless there is another device driving at) and spurious interrupts.
1039	 * (On the system that this was first tested on, the input floats high
1040	 * and gives a (masked) interrupt as soon as the gate is closed.)
1041	 */
1042	outb(iobase + com_ier, 0);
1043	outb(iobase + com_cfcr, CFCR_8BITS);	/* dummy to avoid bus echo */
1044	failures[7] = inb(iobase + com_ier);
1045	DELAY(1000);		/* XXX */
1046	if (idev->id_irq != 0)
1047		failures[8] = isa_irq_pending(idev) ? 1	: 0;
1048	failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
1049
1050	enable_intr();
1051
1052	result = IO_COMSIZE;
1053	for (fn = 0; fn < sizeof failures; ++fn)
1054		if (failures[fn]) {
1055			outb(iobase + com_mcr, 0);
1056			result = 0;
1057			if (COM_VERBOSE(dev))
1058				printf("sio%d: probe test %d failed\n",
1059				       dev->id_unit, fn);
1060		}
1061	return (result);
1062}
1063
1064#ifdef COM_ESP
1065static int
1066espattach(isdp, com, esp_port)
1067	struct isa_device	*isdp;
1068	struct com_s		*com;
1069	Port_t			esp_port;
1070{
1071	u_char	dips;
1072	u_char	val;
1073
1074	/*
1075	 * Check the ESP-specific I/O port to see if we're an ESP
1076	 * card.  If not, return failure immediately.
1077	 */
1078	if ((inb(esp_port) & 0xf3) == 0) {
1079		printf(" port 0x%x is not an ESP board?\n", esp_port);
1080		return (0);
1081	}
1082
1083	/*
1084	 * We've got something that claims to be a Hayes ESP card.
1085	 * Let's hope so.
1086	 */
1087
1088	/* Get the dip-switch configuration */
1089	outb(esp_port + ESP_CMD1, ESP_GETDIPS);
1090	dips = inb(esp_port + ESP_STATUS1);
1091
1092	/*
1093	 * Bits 0,1 of dips say which COM port we are.
1094	 */
1095	if (com->iobase == likely_com_ports[dips & 0x03])
1096		printf(" : ESP");
1097	else {
1098		printf(" esp_port has com %d\n", dips & 0x03);
1099		return (0);
1100	}
1101
1102	/*
1103	 * Check for ESP version 2.0 or later:  bits 4,5,6 = 010.
1104	 */
1105	outb(esp_port + ESP_CMD1, ESP_GETTEST);
1106	val = inb(esp_port + ESP_STATUS1);	/* clear reg 1 */
1107	val = inb(esp_port + ESP_STATUS2);
1108	if ((val & 0x70) < 0x20) {
1109		printf("-old (%o)", val & 0x70);
1110		return (0);
1111	}
1112
1113	/*
1114	 * Check for ability to emulate 16550:  bit 7 == 1
1115	 */
1116	if ((dips & 0x80) == 0) {
1117		printf(" slave");
1118		return (0);
1119	}
1120
1121	/*
1122	 * Okay, we seem to be a Hayes ESP card.  Whee.
1123	 */
1124	com->esp = TRUE;
1125	com->esp_port = esp_port;
1126	return (1);
1127}
1128#endif /* COM_ESP */
1129
1130static int
1131sioattach(isdp)
1132	struct isa_device	*isdp;
1133{
1134	struct com_s	*com;
1135	dev_t		dev;
1136#ifdef COM_ESP
1137	Port_t		*espp;
1138#endif
1139	Port_t		iobase;
1140	int		s;
1141	int		unit;
1142
1143	isdp->id_ri_flags |= RI_FAST;
1144	iobase = isdp->id_iobase;
1145	unit = isdp->id_unit;
1146	com = malloc(sizeof *com, M_TTYS, M_NOWAIT);
1147	if (com == NULL)
1148		return (0);
1149
1150	/*
1151	 * sioprobe() has initialized the device registers as follows:
1152	 *	o cfcr = CFCR_8BITS.
1153	 *	  It is most important that CFCR_DLAB is off, so that the
1154	 *	  data port is not hidden when we enable interrupts.
1155	 *	o ier = 0.
1156	 *	  Interrupts are only enabled when the line is open.
1157	 *	o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
1158	 *	  interrupt control register or the config specifies no irq.
1159	 *	  Keeping MCR_DTR and MCR_RTS off might stop the external
1160	 *	  device from sending before we are ready.
1161	 */
1162	bzero(com, sizeof *com);
1163	com->unit = unit;
1164	com->cfcr_image = CFCR_8BITS;
1165	com->dtr_wait = 3 * hz;
1166	com->loses_outints = COM_LOSESOUTINTS(isdp) != 0;
1167	com->no_irq = isdp->id_irq == 0;
1168	com->tx_fifo_size = 1;
1169	com->iptr = com->ibuf = com->ibuf1;
1170	com->ibufend = com->ibuf1 + RS_IBUFSIZE;
1171	com->ihighwater = com->ibuf1 + RS_IHIGHWATER;
1172	com->obufs[0].l_head = com->obuf1;
1173	com->obufs[1].l_head = com->obuf2;
1174
1175	com->iobase = iobase;
1176#ifdef PC98
1177	if(pc98_set_ioport(com, iobase) == -1)
1178		if((iobase & 0x0f0) == 0xd0) {
1179			com->pc98_if_type = MC16550;
1180			com->data_port = iobase + com_data;
1181			com->int_id_port = iobase + com_iir;
1182			com->modem_ctl_port = iobase + com_mcr;
1183			com->mcr_image = inb(com->modem_ctl_port);
1184			com->line_status_port = iobase + com_lsr;
1185			com->modem_status_port = iobase + com_msr;
1186		}
1187#else /* not PC98 */
1188	com->data_port = iobase + com_data;
1189	com->int_id_port = iobase + com_iir;
1190	com->modem_ctl_port = iobase + com_mcr;
1191	com->mcr_image = inb(com->modem_ctl_port);
1192	com->line_status_port = iobase + com_lsr;
1193	com->modem_status_port = iobase + com_msr;
1194#endif
1195
1196	/*
1197	 * We don't use all the flags from <sys/ttydefaults.h> since they
1198	 * are only relevant for logins.  It's important to have echo off
1199	 * initially so that the line doesn't start blathering before the
1200	 * echo flag can be turned off.
1201	 */
1202	com->it_in.c_iflag = 0;
1203	com->it_in.c_oflag = 0;
1204	com->it_in.c_cflag = TTYDEF_CFLAG;
1205	com->it_in.c_lflag = 0;
1206	if (unit == comconsole) {
1207#ifdef PC98
1208		if(IS_8251(com->pc98_if_type))
1209			DELAY(100000);
1210#endif
1211		com->it_in.c_iflag = TTYDEF_IFLAG;
1212		com->it_in.c_oflag = TTYDEF_OFLAG;
1213		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
1214		com->it_in.c_lflag = TTYDEF_LFLAG;
1215		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
1216		com->lt_out.c_ispeed = com->lt_out.c_ospeed =
1217		com->lt_in.c_ispeed = com->lt_in.c_ospeed =
1218		com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
1219	} else
1220		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1221	termioschars(&com->it_in);
1222	com->it_out = com->it_in;
1223
1224	/* attempt to determine UART type */
1225	printf("sio%d: type", unit);
1226
1227#ifdef DSI_SOFT_MODEM
1228	if((inb(iobase+7) ^ inb(iobase+7)) & 0x80) {
1229	    printf(" Digicom Systems, Inc. SoftModem");
1230	goto determined_type;
1231	}
1232#endif /* DSI_SOFT_MODEM */
1233
1234#ifndef PC98
1235#ifdef COM_MULTIPORT
1236	if (!COM_ISMULTIPORT(isdp))
1237#endif
1238	{
1239		u_char	scr;
1240		u_char	scr1;
1241		u_char	scr2;
1242
1243		scr = inb(iobase + com_scr);
1244		outb(iobase + com_scr, 0xa5);
1245		scr1 = inb(iobase + com_scr);
1246		outb(iobase + com_scr, 0x5a);
1247		scr2 = inb(iobase + com_scr);
1248		outb(iobase + com_scr, scr);
1249		if (scr1 != 0xa5 || scr2 != 0x5a) {
1250			printf(" 8250");
1251			goto determined_type;
1252		}
1253	}
1254#endif /* !PC98 */
1255#ifdef PC98
1256	if(IS_8251(com->pc98_if_type)){
1257		com_int_TxRx_disable( com );
1258		com_cflag_and_speed_set( com, com->it_in.c_cflag,
1259						comdefaultrate );
1260		com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
1261		com_send_break_off( com );
1262		switch(com->pc98_if_type){
1263		case COM_IF_INTERNAL:
1264			printf(" 8251 (internal)");
1265			break;
1266#ifdef COM_IF_PC9861K
1267		case COM_IF_PC9861K:
1268			printf(" 8251 (PC9861K)");
1269			break;
1270#endif
1271#ifdef COM_IF_PIO9032B
1272		case COM_IF_PIO9032B:
1273			printf(" 8251 (PIO9032B)");
1274			break;
1275#endif
1276#ifdef COM_IF_B98_01
1277		case COM_IF_B98_01:
1278			printf(" 8251 (B98_01)");
1279			break;
1280#endif
1281		}
1282	} else {
1283#endif /* PC98 */
1284	outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1285	DELAY(100);
1286	com->st16650a = 0;
1287	switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1288	case FIFO_RX_LOW:
1289		printf(" 16450");
1290		break;
1291	case FIFO_RX_MEDL:
1292		printf(" 16450?");
1293		break;
1294	case FIFO_RX_MEDH:
1295		printf(" 16550?");
1296		break;
1297	case FIFO_RX_HIGH:
1298		if (COM_NOFIFO(isdp)) {
1299			printf(" 16550A fifo disabled");
1300		} else {
1301			com->hasfifo = TRUE;
1302			if (COM_ST16650A(isdp)) {
1303				com->st16650a = 1;
1304				com->tx_fifo_size = 32;
1305				printf(" ST16650A");
1306			} else {
1307				com->tx_fifo_size = COM_FIFOSIZE(isdp);
1308				printf(" 16550A");
1309			}
1310		}
1311#ifdef COM_ESP
1312		for (espp = likely_esp_ports; *espp != 0; espp++)
1313			if (espattach(isdp, com, *espp)) {
1314				com->tx_fifo_size = 1024;
1315				break;
1316			}
1317#endif
1318		if (!com->st16650a) {
1319			if (!com->tx_fifo_size)
1320				com->tx_fifo_size = 16;
1321			else
1322				printf(" lookalike with %d bytes FIFO",
1323				    com->tx_fifo_size);
1324		}
1325
1326		break;
1327	}
1328
1329#ifdef COM_ESP
1330	if (com->esp) {
1331		/*
1332		 * Set 16550 compatibility mode.
1333		 * We don't use the ESP_MODE_SCALE bit to increase the
1334		 * fifo trigger levels because we can't handle large
1335		 * bursts of input.
1336		 * XXX flow control should be set in comparam(), not here.
1337		 */
1338		outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
1339		outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1340
1341		/* Set RTS/CTS flow control. */
1342		outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
1343		outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
1344		outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
1345
1346		/* Set flow-control levels. */
1347		outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
1348		outb(com->esp_port + ESP_CMD2, HIBYTE(768));
1349		outb(com->esp_port + ESP_CMD2, LOBYTE(768));
1350		outb(com->esp_port + ESP_CMD2, HIBYTE(512));
1351		outb(com->esp_port + ESP_CMD2, LOBYTE(512));
1352	}
1353#endif /* COM_ESP */
1354	outb(iobase + com_fifo, 0);
1355determined_type: ;
1356
1357#ifdef COM_MULTIPORT
1358	if (COM_ISMULTIPORT(isdp)) {
1359		com->multiport = TRUE;
1360		printf(" (multiport");
1361		if (unit == COM_MPMASTER(isdp))
1362			printf(" master");
1363		printf(")");
1364		com->no_irq = find_isadev(isa_devtab_tty, &siodriver,
1365					  COM_MPMASTER(isdp))->id_irq == 0;
1366	 }
1367#endif /* COM_MULTIPORT */
1368#ifdef PC98
1369	}
1370#endif
1371	if (unit == comconsole)
1372		printf(", console");
1373	printf("\n");
1374
1375	s = spltty();
1376	com_addr(unit) = com;
1377	splx(s);
1378
1379	dev = makedev(CDEV_MAJOR, 0);
1380	cdevsw_add(&dev, &sio_cdevsw, NULL);
1381#ifdef DEVFS
1382	com->devfs_token_ttyd = devfs_add_devswf(&sio_cdevsw,
1383		unit, DV_CHR,
1384		UID_ROOT, GID_WHEEL, 0600, "ttyd%n", unit);
1385	com->devfs_token_ttyi = devfs_add_devswf(&sio_cdevsw,
1386		unit | CONTROL_INIT_STATE, DV_CHR,
1387		UID_ROOT, GID_WHEEL, 0600, "ttyid%n", unit);
1388	com->devfs_token_ttyl = devfs_add_devswf(&sio_cdevsw,
1389		unit | CONTROL_LOCK_STATE, DV_CHR,
1390		UID_ROOT, GID_WHEEL, 0600, "ttyld%n", unit);
1391	com->devfs_token_cuaa = devfs_add_devswf(&sio_cdevsw,
1392		unit | CALLOUT_MASK, DV_CHR,
1393		UID_UUCP, GID_DIALER, 0660, "cuaa%n", unit);
1394	com->devfs_token_cuai = devfs_add_devswf(&sio_cdevsw,
1395		unit | CALLOUT_MASK | CONTROL_INIT_STATE, DV_CHR,
1396		UID_UUCP, GID_DIALER, 0660, "cuaia%n", unit);
1397	com->devfs_token_cual = devfs_add_devswf(&sio_cdevsw,
1398		unit | CALLOUT_MASK | CONTROL_LOCK_STATE, DV_CHR,
1399		UID_UUCP, GID_DIALER, 0660, "cuala%n", unit);
1400#endif
1401	return (1);
1402}
1403
1404static int
1405sioopen(dev, flag, mode, p)
1406	dev_t		dev;
1407	int		flag;
1408	int		mode;
1409	struct proc	*p;
1410{
1411	struct com_s	*com;
1412	int		error;
1413	Port_t		iobase;
1414	int		mynor;
1415	int		s;
1416	struct tty	*tp;
1417	int		unit;
1418
1419	mynor = minor(dev);
1420	unit = MINOR_TO_UNIT(mynor);
1421	if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL)
1422		return (ENXIO);
1423	if (com->gone)
1424		return (ENXIO);
1425	if (mynor & CONTROL_MASK)
1426		return (0);
1427#if 0 /* XXX */
1428	tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]);
1429#else
1430	tp = com->tp = &sio_tty[unit];
1431#endif
1432	s = spltty();
1433	/*
1434	 * We jump to this label after all non-interrupted sleeps to pick
1435	 * up any changes of the device state.
1436	 */
1437open_top:
1438	while (com->state & CS_DTR_OFF) {
1439		error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0);
1440		if (com_addr(unit) == NULL)
1441			return (ENXIO);
1442		if (error != 0 || com->gone)
1443			goto out;
1444	}
1445	if (tp->t_state & TS_ISOPEN) {
1446		/*
1447		 * The device is open, so everything has been initialized.
1448		 * Handle conflicts.
1449		 */
1450		if (mynor & CALLOUT_MASK) {
1451			if (!com->active_out) {
1452				error = EBUSY;
1453				goto out;
1454			}
1455		} else {
1456			if (com->active_out) {
1457				if (flag & O_NONBLOCK) {
1458					error = EBUSY;
1459					goto out;
1460				}
1461				error =	tsleep(&com->active_out,
1462					       TTIPRI | PCATCH, "siobi", 0);
1463				if (com_addr(unit) == NULL)
1464					return (ENXIO);
1465				if (error != 0 || com->gone)
1466					goto out;
1467				goto open_top;
1468			}
1469		}
1470		if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
1471			error = EBUSY;
1472			goto out;
1473		}
1474	} else {
1475		/*
1476		 * The device isn't open, so there are no conflicts.
1477		 * Initialize it.  Initialization is done twice in many
1478		 * cases: to preempt sleeping callin opens if we are
1479		 * callout, and to complete a callin open after DCD rises.
1480		 */
1481		tp->t_oproc = comstart;
1482		tp->t_param = comparam;
1483		tp->t_dev = dev;
1484		tp->t_termios = mynor & CALLOUT_MASK
1485				? com->it_out : com->it_in;
1486#ifdef PC98
1487		if(!IS_8251(com->pc98_if_type))
1488#endif
1489		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
1490		com->poll = com->no_irq;
1491		com->poll_output = com->loses_outints;
1492		++com->wopeners;
1493		error = comparam(tp, &tp->t_termios);
1494		--com->wopeners;
1495		if (error != 0)
1496			goto out;
1497#ifdef PC98
1498		if(IS_8251(com->pc98_if_type)){
1499			com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS);
1500			pc98_msrint_start(dev);
1501		}
1502#endif
1503		/*
1504		 * XXX we should goto open_top if comparam() slept.
1505		 */
1506		ttsetwater(tp);
1507		iobase = com->iobase;
1508		if (com->hasfifo) {
1509			/*
1510			 * (Re)enable and drain fifos.
1511			 *
1512			 * Certain SMC chips cause problems if the fifos
1513			 * are enabled while input is ready.  Turn off the
1514			 * fifo if necessary to clear the input.  We test
1515			 * the input ready bit after enabling the fifos
1516			 * since we've already enabled them in comparam()
1517			 * and to handle races between enabling and fresh
1518			 * input.
1519			 */
1520			while (TRUE) {
1521				outb(iobase + com_fifo,
1522				     FIFO_RCV_RST | FIFO_XMT_RST
1523				     | com->fifo_image);
1524				/*
1525				 * XXX the delays are for superstitious
1526				 * historical reasons.  It must be less than
1527				 * the character time at the maximum
1528				 * supported speed (87 usec at 115200 bps
1529				 * 8N1).  Otherwise we might loop endlessly
1530				 * if data is streaming in.  We used to use
1531				 * delays of 100.  That usually worked
1532				 * because DELAY(100) used to usually delay
1533				 * for about 85 usec instead of 100.
1534				 */
1535				DELAY(50);
1536				if (!(inb(com->line_status_port) & LSR_RXRDY))
1537					break;
1538				outb(iobase + com_fifo, 0);
1539				DELAY(50);
1540				(void) inb(com->data_port);
1541			}
1542		}
1543
1544		disable_intr();
1545#ifdef PC98
1546		if(IS_8251(com->pc98_if_type)){
1547			com_tiocm_bis(com, TIOCM_LE);
1548			com->pc98_prev_modem_status =
1549				pc98_get_modem_status(com);
1550			com_int_Rx_enable(com);
1551		} else {
1552#endif
1553		(void) inb(com->line_status_port);
1554		(void) inb(com->data_port);
1555		com->prev_modem_status = com->last_modem_status
1556		    = inb(com->modem_status_port);
1557		outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
1558				       | IER_EMSC);
1559#ifdef PC98
1560		}
1561#endif
1562		enable_intr();
1563		/*
1564		 * Handle initial DCD.  Callout devices get a fake initial
1565		 * DCD (trapdoor DCD).  If we are callout, then any sleeping
1566		 * callin opens get woken up and resume sleeping on "siobi"
1567		 * instead of "siodcd".
1568		 */
1569		/*
1570		 * XXX `mynor & CALLOUT_MASK' should be
1571		 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
1572		 * TRAPDOOR_CARRIER is the default initial state for callout
1573		 * devices and SOFT_CARRIER is like CLOCAL except it hides
1574		 * the true carrier.
1575		 */
1576#ifdef PC98
1577		if ((IS_8251(com->pc98_if_type) &&
1578			(pc98_get_modem_status(com) & TIOCM_CAR)) ||
1579		    (!IS_8251(com->pc98_if_type) &&
1580			(com->prev_modem_status & MSR_DCD)) ||
1581		    mynor & CALLOUT_MASK)
1582#else
1583		if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
1584#endif
1585			(*linesw[tp->t_line].l_modem)(tp, 1);
1586	}
1587	/*
1588	 * Wait for DCD if necessary.
1589	 */
1590	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
1591	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
1592		++com->wopeners;
1593		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
1594		if (com_addr(unit) == NULL)
1595			return (ENXIO);
1596		--com->wopeners;
1597		if (error != 0 || com->gone)
1598			goto out;
1599		goto open_top;
1600	}
1601	error =	(*linesw[tp->t_line].l_open)(dev, tp);
1602	disc_optim(tp, &tp->t_termios, com);
1603	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
1604		com->active_out = TRUE;
1605	siosettimeout();
1606out:
1607	splx(s);
1608	if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
1609		comhardclose(com);
1610	return (error);
1611}
1612
1613static int
1614sioclose(dev, flag, mode, p)
1615	dev_t		dev;
1616	int		flag;
1617	int		mode;
1618	struct proc	*p;
1619{
1620	struct com_s	*com;
1621	int		mynor;
1622	int		s;
1623	struct tty	*tp;
1624
1625	mynor = minor(dev);
1626	if (mynor & CONTROL_MASK)
1627		return (0);
1628	com = com_addr(MINOR_TO_UNIT(mynor));
1629	tp = com->tp;
1630	s = spltty();
1631	(*linesw[tp->t_line].l_close)(tp, flag);
1632#ifdef PC98
1633	com->modem_checking = 0;
1634#endif
1635	disc_optim(tp, &tp->t_termios, com);
1636	siostop(tp, FREAD | FWRITE);
1637	comhardclose(com);
1638	ttyclose(tp);
1639	siosettimeout();
1640	splx(s);
1641	if (com->gone) {
1642		printf("sio%d: gone\n", com->unit);
1643		s = spltty();
1644		com_addr(com->unit) = 0;
1645		bzero(tp,sizeof *tp);
1646		bzero(com,sizeof *com);
1647		free(com,M_TTYS);
1648		splx(s);
1649	}
1650	return (0);
1651}
1652
1653static void
1654comhardclose(com)
1655	struct com_s	*com;
1656{
1657	Port_t		iobase;
1658	int		s;
1659	struct tty	*tp;
1660	int		unit;
1661
1662	unit = com->unit;
1663	iobase = com->iobase;
1664	s = spltty();
1665	com->poll = FALSE;
1666	com->poll_output = FALSE;
1667	com->do_timestamp = FALSE;
1668	com->do_dcd_timestamp = FALSE;
1669#ifdef PC98
1670	if(IS_8251(com->pc98_if_type))
1671		com_send_break_off(com);
1672	else
1673#endif
1674	outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1675	{
1676#ifdef PC98
1677		int tmp;
1678		if(IS_8251(com->pc98_if_type))
1679			com_int_TxRx_disable(com);
1680		else
1681#endif
1682		outb(iobase + com_ier, 0);
1683		tp = com->tp;
1684#ifdef PC98
1685		if(IS_8251(com->pc98_if_type))
1686			tmp = pc98_get_modem_status(com) & TIOCM_CAR;
1687		else
1688			tmp = com->prev_modem_status & MSR_DCD;
1689#endif
1690		if (tp->t_cflag & HUPCL
1691		    /*
1692		     * XXX we will miss any carrier drop between here and the
1693		     * next open.  Perhaps we should watch DCD even when the
1694		     * port is closed; it is not sufficient to check it at
1695		     * the next open because it might go up and down while
1696		     * we're not watching.
1697		     */
1698		    || !com->active_out
1699#ifdef PC98
1700		       && !(tmp)
1701#else
1702		       && !(com->prev_modem_status & MSR_DCD)
1703#endif
1704		       && !(com->it_in.c_cflag & CLOCAL)
1705		    || !(tp->t_state & TS_ISOPEN)) {
1706#ifdef PC98
1707			if(IS_8251(com->pc98_if_type))
1708				com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
1709			else
1710#endif
1711			(void)commctl(com, TIOCM_DTR, DMBIC);
1712			if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
1713				timeout(siodtrwakeup, com, com->dtr_wait);
1714				com->state |= CS_DTR_OFF;
1715			}
1716		}
1717#ifdef PC98
1718		else {
1719			if(IS_8251(com->pc98_if_type))
1720				com_tiocm_bic(com, TIOCM_LE );
1721		}
1722#endif
1723	}
1724	if (com->hasfifo) {
1725		/*
1726		 * Disable fifos so that they are off after controlled
1727		 * reboots.  Some BIOSes fail to detect 16550s when the
1728		 * fifos are enabled.
1729		 */
1730		outb(iobase + com_fifo, 0);
1731	}
1732	com->active_out = FALSE;
1733	wakeup(&com->active_out);
1734	wakeup(TSA_CARR_ON(tp));	/* restart any wopeners */
1735	splx(s);
1736}
1737
1738static int
1739sioread(dev, uio, flag)
1740	dev_t		dev;
1741	struct uio	*uio;
1742	int		flag;
1743{
1744	int		mynor;
1745	int		unit;
1746	struct tty	*tp;
1747
1748	mynor = minor(dev);
1749	if (mynor & CONTROL_MASK)
1750		return (ENODEV);
1751	unit = MINOR_TO_UNIT(mynor);
1752	if (com_addr(unit)->gone)
1753		return (ENODEV);
1754	tp = com_addr(unit)->tp;
1755	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
1756}
1757
1758static int
1759siowrite(dev, uio, flag)
1760	dev_t		dev;
1761	struct uio	*uio;
1762	int		flag;
1763{
1764	int		mynor;
1765	struct tty	*tp;
1766	int		unit;
1767
1768	mynor = minor(dev);
1769	if (mynor & CONTROL_MASK)
1770		return (ENODEV);
1771
1772	unit = MINOR_TO_UNIT(mynor);
1773	if (com_addr(unit)->gone)
1774		return (ENODEV);
1775	tp = com_addr(unit)->tp;
1776	/*
1777	 * (XXX) We disallow virtual consoles if the physical console is
1778	 * a serial port.  This is in case there is a display attached that
1779	 * is not the console.  In that situation we don't need/want the X
1780	 * server taking over the console.
1781	 */
1782	if (constty != NULL && unit == comconsole)
1783		constty = NULL;
1784	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
1785}
1786
1787static void
1788siobusycheck(chan)
1789	void	*chan;
1790{
1791	struct com_s	*com;
1792	int		s;
1793
1794	com = (struct com_s *)chan;
1795
1796	/*
1797	 * Clear TS_BUSY if low-level output is complete.
1798	 * spl locking is sufficient because siointr1() does not set CS_BUSY.
1799	 * If siointr1() clears CS_BUSY after we look at it, then we'll get
1800	 * called again.  Reading the line status port outside of siointr1()
1801	 * is safe because CS_BUSY is clear so there are no output interrupts
1802	 * to lose.
1803	 */
1804	s = spltty();
1805	if (com->state & CS_BUSY)
1806		com->extra_state &= ~CSE_BUSYCHECK;	/* False alarm. */
1807#ifdef	PC98
1808	else if (IS_8251(com->pc98_if_type) &&
1809		 (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP))
1810		 == (STS8251_TxRDY | STS8251_TxEMP) ||
1811		 (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
1812		 == (LSR_TSRE | LSR_TXRDY)) {
1813#else
1814	else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
1815	    == (LSR_TSRE | LSR_TXRDY)) {
1816#endif
1817		com->tp->t_state &= ~TS_BUSY;
1818		ttwwakeup(com->tp);
1819		com->extra_state &= ~CSE_BUSYCHECK;
1820	} else
1821		timeout(siobusycheck, com, hz / 100);
1822	splx(s);
1823}
1824
1825static void
1826siodtrwakeup(chan)
1827	void	*chan;
1828{
1829	struct com_s	*com;
1830
1831	com = (struct com_s *)chan;
1832	com->state &= ~CS_DTR_OFF;
1833	wakeup(&com->dtr_wait);
1834}
1835
1836void
1837siointr(unit)
1838	int	unit;
1839{
1840#ifndef COM_MULTIPORT
1841	COM_LOCK();
1842	siointr1(com_addr(unit));
1843	COM_UNLOCK();
1844#else /* COM_MULTIPORT */
1845	struct com_s    *com;
1846	bool_t		possibly_more_intrs;
1847
1848	/*
1849	 * Loop until there is no activity on any port.  This is necessary
1850	 * to get an interrupt edge more than to avoid another interrupt.
1851	 * If the IRQ signal is just an OR of the IRQ signals from several
1852	 * devices, then the edge from one may be lost because another is
1853	 * on.
1854	 */
1855	COM_LOCK();
1856	do {
1857		possibly_more_intrs = FALSE;
1858		for (unit = 0; unit < NSIOTOT; ++unit) {
1859			com = com_addr(unit);
1860			/*
1861			 * XXX COM_LOCK();
1862			 * would it work here, or be counter-productive?
1863			 */
1864#ifdef PC98
1865			if (com != NULL
1866			    && !com->gone
1867			    && IS_8251(com->pc98_if_type)){
1868				siointr1(com);
1869			} else
1870#endif /* PC98 */
1871			if (com != NULL
1872			    && !com->gone
1873			    && (inb(com->int_id_port) & IIR_IMASK)
1874			       != IIR_NOPEND) {
1875				siointr1(com);
1876				possibly_more_intrs = TRUE;
1877			}
1878			/* XXX COM_UNLOCK(); */
1879		}
1880	} while (possibly_more_intrs);
1881	COM_UNLOCK();
1882#endif /* COM_MULTIPORT */
1883}
1884
1885static void
1886siointr1(com)
1887	struct com_s	*com;
1888{
1889	u_char	line_status;
1890	u_char	modem_status;
1891	u_char	*ioptr;
1892	u_char	recv_data;
1893#ifdef PC98
1894	u_char	tmp=0;
1895recv_data=0;
1896#endif /* PC98 */
1897
1898	while (TRUE) {
1899#ifdef PC98
1900status_read:;
1901		if (IS_8251(com->pc98_if_type)) {
1902			tmp = inb(com->sts_port);
1903more_intr:
1904			line_status = 0;
1905			if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY;
1906			if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY;
1907			if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE;
1908			if (tmp & STS8251_PE)    line_status |= LSR_PE;
1909			if (tmp & STS8251_OE)    line_status |= LSR_OE;
1910			if (tmp & STS8251_FE)    line_status |= LSR_FE;
1911			if (tmp & STS8251_BD_SD) line_status |= LSR_BI;
1912		} else
1913#endif /* PC98 */
1914		line_status = inb(com->line_status_port);
1915
1916		/* input event? (check first to help avoid overruns) */
1917		while (line_status & LSR_RCV_MASK) {
1918			/* break/unnattached error bits or real input? */
1919#ifdef PC98
1920			if(IS_8251(com->pc98_if_type)){
1921				recv_data = inb(com->data_port);
1922				if(tmp & 0x78){
1923					pc98_i8251_or_cmd(com,CMD8251_ER);
1924					recv_data = 0;
1925				}
1926			} else {
1927#endif /* PC98 */
1928			if (!(line_status & LSR_RXRDY))
1929				recv_data = 0;
1930			else
1931				recv_data = inb(com->data_port);
1932#ifdef PC98
1933			}
1934#endif
1935			if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
1936				/*
1937				 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
1938				 * Otherwise, push the work to a higher level
1939				 * (to handle PARMRK) if we're bypassing.
1940				 * Otherwise, convert BI/FE and PE+INPCK to 0.
1941				 *
1942				 * This makes bypassing work right in the
1943				 * usual "raw" case (IGNBRK set, and IGNPAR
1944				 * and INPCK clear).
1945				 *
1946				 * Note: BI together with FE/PE means just BI.
1947				 */
1948				if (line_status & LSR_BI) {
1949#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
1950					if (com->unit == comconsole) {
1951						breakpoint();
1952						goto cont;
1953					}
1954#endif
1955					if (com->tp == NULL
1956					    || com->tp->t_iflag & IGNBRK)
1957						goto cont;
1958				} else {
1959					if (com->tp == NULL
1960					    || com->tp->t_iflag & IGNPAR)
1961						goto cont;
1962				}
1963				if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
1964				    && (line_status & (LSR_BI | LSR_FE)
1965					|| com->tp->t_iflag & INPCK))
1966					recv_data = 0;
1967			}
1968
1969			++com->bytes_in;
1970			if (com->hotchar != 0 && recv_data == com->hotchar)
1971				setsofttty();
1972			ioptr = com->iptr;
1973			if (ioptr >= com->ibufend)
1974				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1975			else {
1976				if (com->do_timestamp)
1977					microtime(&com->timestamp);
1978				++com_events;
1979				schedsofttty();
1980#if 0 /* for testing input latency vs efficiency */
1981if (com->iptr - com->ibuf == 8)
1982	setsofttty();
1983#endif
1984				ioptr[0] = recv_data;
1985				ioptr[CE_INPUT_OFFSET] = line_status;
1986				com->iptr = ++ioptr;
1987				if (ioptr == com->ihighwater
1988				    && com->state & CS_RTS_IFLOW)
1989#ifdef PC98
1990					if(IS_8251(com->pc98_if_type))
1991						com_tiocm_bic(com, TIOCM_RTS);
1992					else
1993#endif
1994					outb(com->modem_ctl_port,
1995					     com->mcr_image &= ~MCR_RTS);
1996				if (line_status & LSR_OE)
1997					CE_RECORD(com, CE_OVERRUN);
1998			}
1999cont:
2000			/*
2001			 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
2002			 * jump from the top of the loop to here
2003			 */
2004#ifdef PC98
2005			if(IS_8251(com->pc98_if_type))
2006				goto status_read;
2007			else
2008#endif
2009			line_status = inb(com->line_status_port) & 0x7F;
2010		}
2011
2012		/* modem status change? (always check before doing output) */
2013#ifdef PC98
2014		if(!IS_8251(com->pc98_if_type)){
2015#endif
2016		modem_status = inb(com->modem_status_port);
2017		if (modem_status != com->last_modem_status) {
2018			if (com->do_dcd_timestamp
2019			    && !(com->last_modem_status & MSR_DCD)
2020			    && modem_status & MSR_DCD)
2021				microtime(&com->dcd_timestamp);
2022
2023			/*
2024			 * Schedule high level to handle DCD changes.  Note
2025			 * that we don't use the delta bits anywhere.  Some
2026			 * UARTs mess them up, and it's easy to remember the
2027			 * previous bits and calculate the delta.
2028			 */
2029			com->last_modem_status = modem_status;
2030			if (!(com->state & CS_CHECKMSR)) {
2031				com_events += LOTS_OF_EVENTS;
2032				com->state |= CS_CHECKMSR;
2033				setsofttty();
2034			}
2035
2036			/* handle CTS change immediately for crisp flow ctl */
2037			if (com->state & CS_CTS_OFLOW) {
2038				if (modem_status & MSR_CTS)
2039					com->state |= CS_ODEVREADY;
2040				else
2041					com->state &= ~CS_ODEVREADY;
2042			}
2043		}
2044#ifdef PC98
2045		}
2046#endif
2047
2048		/* output queued and everything ready? */
2049		if (line_status & LSR_TXRDY
2050		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2051			ioptr = com->obufq.l_head;
2052			if (com->tx_fifo_size > 1) {
2053				u_int	ocount;
2054
2055				ocount = com->obufq.l_tail - ioptr;
2056				if (ocount > com->tx_fifo_size)
2057					ocount = com->tx_fifo_size;
2058				com->bytes_out += ocount;
2059				do
2060					outb(com->data_port, *ioptr++);
2061				while (--ocount != 0);
2062			} else {
2063				outb(com->data_port, *ioptr++);
2064				++com->bytes_out;
2065			}
2066#ifdef PC98
2067			if(IS_8251(com->pc98_if_type))
2068				if ( !(pc98_check_i8251_interrupt(com) & IEN_TxFLAG) )
2069					com_int_Tx_enable(com);
2070#endif
2071			com->obufq.l_head = ioptr;
2072			if (ioptr >= com->obufq.l_tail) {
2073				struct lbq	*qp;
2074
2075				qp = com->obufq.l_next;
2076				qp->l_queued = FALSE;
2077				qp = qp->l_next;
2078				if (qp != NULL) {
2079					com->obufq.l_head = qp->l_head;
2080					com->obufq.l_tail = qp->l_tail;
2081					com->obufq.l_next = qp;
2082				} else {
2083					/* output just completed */
2084					com->state &= ~CS_BUSY;
2085#if defined(PC98)
2086					if(IS_8251(com->pc98_if_type))
2087						if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
2088							com_int_Tx_disable(com);
2089#endif
2090				}
2091				if (!(com->state & CS_ODONE)) {
2092					com_events += LOTS_OF_EVENTS;
2093					com->state |= CS_ODONE;
2094					setsofttty();	/* handle at high level ASAP */
2095				}
2096			}
2097		}
2098#ifdef PC98
2099		else if (line_status & LSR_TXRDY) {
2100			if(IS_8251(com->pc98_if_type))
2101				if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
2102					com_int_Tx_disable(com);
2103		}
2104		if(IS_8251(com->pc98_if_type))
2105			if ((tmp = inb(com->sts_port)) & STS8251_RxRDY)
2106				goto more_intr;
2107#endif
2108
2109		/* finished? */
2110#ifndef COM_MULTIPORT
2111#ifdef PC98
2112		if(IS_8251(com->pc98_if_type))
2113			return;
2114#endif
2115		if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
2116#endif /* COM_MULTIPORT */
2117			return;
2118	}
2119}
2120
2121static int
2122sioioctl(dev, cmd, data, flag, p)
2123	dev_t		dev;
2124	int		cmd;
2125	caddr_t		data;
2126	int		flag;
2127	struct proc	*p;
2128{
2129	struct com_s	*com;
2130	int		error;
2131	Port_t		iobase;
2132	int		mynor;
2133	int		s;
2134	struct tty	*tp;
2135#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2136	int		oldcmd;
2137	struct termios	term;
2138#endif
2139
2140	mynor = minor(dev);
2141	com = com_addr(MINOR_TO_UNIT(mynor));
2142	if (com->gone)
2143		return (ENODEV);
2144	iobase = com->iobase;
2145	if (mynor & CONTROL_MASK) {
2146		struct termios	*ct;
2147
2148		switch (mynor & CONTROL_MASK) {
2149		case CONTROL_INIT_STATE:
2150			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
2151			break;
2152		case CONTROL_LOCK_STATE:
2153			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
2154			break;
2155		default:
2156			return (ENODEV);	/* /dev/nodev */
2157		}
2158		switch (cmd) {
2159		case TIOCSETA:
2160			error = suser(p->p_ucred, &p->p_acflag);
2161			if (error != 0)
2162				return (error);
2163			*ct = *(struct termios *)data;
2164			return (0);
2165		case TIOCGETA:
2166			*(struct termios *)data = *ct;
2167			return (0);
2168		case TIOCGETD:
2169			*(int *)data = TTYDISC;
2170			return (0);
2171		case TIOCGWINSZ:
2172			bzero(data, sizeof(struct winsize));
2173			return (0);
2174#ifdef DSI_SOFT_MODEM
2175		/*
2176		 * Download micro-code to Digicom modem.
2177		 */
2178		case TIOCDSIMICROCODE:
2179			{
2180			u_long l;
2181			u_char *p,*pi;
2182
2183			pi = (u_char*)(*(caddr_t*)data);
2184			error = copyin(pi,&l,sizeof l);
2185			if(error)
2186				{return error;};
2187			pi += sizeof l;
2188
2189			p = malloc(l,M_TEMP,M_NOWAIT);
2190			if(!p)
2191				{return ENOBUFS;}
2192			error = copyin(pi,p,l);
2193			if(error)
2194				{free(p,M_TEMP); return error;};
2195			if(error = LoadSoftModem(
2196			    MINOR_TO_UNIT(mynor),iobase,l,p))
2197				{free(p,M_TEMP); return error;}
2198			free(p,M_TEMP);
2199			return(0);
2200			}
2201#endif /* DSI_SOFT_MODEM */
2202		default:
2203			return (ENOTTY);
2204		}
2205	}
2206	tp = com->tp;
2207#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2208	term = tp->t_termios;
2209	oldcmd = cmd;
2210	error = ttsetcompat(tp, &cmd, data, &term);
2211	if (error != 0)
2212		return (error);
2213	if (cmd != oldcmd)
2214		data = (caddr_t)&term;
2215#endif
2216	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
2217		int	cc;
2218		struct termios *dt = (struct termios *)data;
2219		struct termios *lt = mynor & CALLOUT_MASK
2220				     ? &com->lt_out : &com->lt_in;
2221
2222		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
2223			      | (dt->c_iflag & ~lt->c_iflag);
2224		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
2225			      | (dt->c_oflag & ~lt->c_oflag);
2226		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
2227			      | (dt->c_cflag & ~lt->c_cflag);
2228		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
2229			      | (dt->c_lflag & ~lt->c_lflag);
2230		for (cc = 0; cc < NCCS; ++cc)
2231			if (lt->c_cc[cc] != 0)
2232				dt->c_cc[cc] = tp->t_cc[cc];
2233		if (lt->c_ispeed != 0)
2234			dt->c_ispeed = tp->t_ispeed;
2235		if (lt->c_ospeed != 0)
2236			dt->c_ospeed = tp->t_ospeed;
2237	}
2238	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
2239	if (error >= 0)
2240		return (error);
2241	s = spltty();
2242	error = ttioctl(tp, cmd, data, flag);
2243	disc_optim(tp, &tp->t_termios, com);
2244	if (error >= 0) {
2245		splx(s);
2246		return (error);
2247	}
2248#ifdef PC98
2249	if(IS_8251(com->pc98_if_type)){
2250	switch (cmd) {
2251	case TIOCSBRK:
2252		com_send_break_on( com );
2253		break;
2254	case TIOCCBRK:
2255		com_send_break_off( com );
2256		break;
2257	case TIOCSDTR:
2258		com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS );
2259		break;
2260	case TIOCCDTR:
2261		com_tiocm_bic(com, TIOCM_DTR);
2262		break;
2263	/*
2264	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
2265	 * changes get undone on the next call to comparam().
2266	 */
2267	case TIOCMSET:
2268		com_tiocm_set( com, *(int *)data );
2269		break;
2270	case TIOCMBIS:
2271		com_tiocm_bis( com, *(int *)data );
2272		break;
2273	case TIOCMBIC:
2274		com_tiocm_bic( com, *(int *)data );
2275		break;
2276	case TIOCMGET:
2277		*(int *)data = com_tiocm_get(com);
2278		break;
2279	case TIOCMSDTRWAIT:
2280		/* must be root since the wait applies to following logins */
2281		error = suser(p->p_ucred, &p->p_acflag);
2282		if (error != 0) {
2283			splx(s);
2284			return (error);
2285		}
2286		com->dtr_wait = *(int *)data * hz / 100;
2287		break;
2288	case TIOCMGDTRWAIT:
2289		*(int *)data = com->dtr_wait * 100 / hz;
2290		break;
2291	case TIOCTIMESTAMP:
2292		com->do_timestamp = TRUE;
2293		*(struct timeval *)data = com->timestamp;
2294		break;
2295	case TIOCDCDTIMESTAMP:
2296		com->do_dcd_timestamp = TRUE;
2297		*(struct timeval *)data = com->dcd_timestamp;
2298		break;
2299	default:
2300		splx(s);
2301		return (ENOTTY);
2302	}
2303	} else {
2304#endif
2305	switch (cmd) {
2306	case TIOCSBRK:
2307		outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2308		break;
2309	case TIOCCBRK:
2310		outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2311		break;
2312	case TIOCSDTR:
2313		(void)commctl(com, TIOCM_DTR, DMBIS);
2314		break;
2315	case TIOCCDTR:
2316		(void)commctl(com, TIOCM_DTR, DMBIC);
2317		break;
2318	case TIOCMSET:
2319		(void)commctl(com, *(int *)data, DMSET);
2320		break;
2321	case TIOCMBIS:
2322		(void)commctl(com, *(int *)data, DMBIS);
2323		break;
2324	case TIOCMBIC:
2325		(void)commctl(com, *(int *)data, DMBIC);
2326		break;
2327	case TIOCMGET:
2328		*(int *)data = commctl(com, 0, DMGET);
2329		break;
2330	case TIOCMSDTRWAIT:
2331		/* must be root since the wait applies to following logins */
2332		error = suser(p->p_ucred, &p->p_acflag);
2333		if (error != 0) {
2334			splx(s);
2335			return (error);
2336		}
2337		com->dtr_wait = *(int *)data * hz / 100;
2338		break;
2339	case TIOCMGDTRWAIT:
2340		*(int *)data = com->dtr_wait * 100 / hz;
2341		break;
2342	case TIOCTIMESTAMP:
2343		com->do_timestamp = TRUE;
2344		*(struct timeval *)data = com->timestamp;
2345		break;
2346	default:
2347		splx(s);
2348		return (ENOTTY);
2349	}
2350#ifdef PC98
2351	}
2352#endif
2353	splx(s);
2354	return (0);
2355}
2356
2357void
2358siopoll()
2359{
2360	int		unit;
2361
2362	if (com_events == 0)
2363		return;
2364repeat:
2365	for (unit = 0; unit < NSIOTOT; ++unit) {
2366		u_char		*buf;
2367		struct com_s	*com;
2368		u_char		*ibuf;
2369		int		incc;
2370		struct tty	*tp;
2371#ifdef PC98
2372		int		tmp;
2373#endif
2374
2375		com = com_addr(unit);
2376		if (com == NULL)
2377			continue;
2378		if (com->gone)
2379			continue;
2380		tp = com->tp;
2381		if (tp == NULL) {
2382			/*
2383			 * XXX forget any events related to closed devices
2384			 * (actually never opened devices) so that we don't
2385			 * loop.
2386			 */
2387			disable_intr();
2388			incc = com->iptr - com->ibuf;
2389			com->iptr = com->ibuf;
2390			if (com->state & CS_CHECKMSR) {
2391				incc += LOTS_OF_EVENTS;
2392				com->state &= ~CS_CHECKMSR;
2393			}
2394			com_events -= incc;
2395			enable_intr();
2396			if (incc != 0)
2397				log(LOG_DEBUG,
2398				    "sio%d: %d events for device with no tp\n",
2399				    unit, incc);
2400			continue;
2401		}
2402
2403		/* switch the role of the low-level input buffers */
2404		if (com->iptr == (ibuf = com->ibuf)) {
2405			buf = NULL;     /* not used, but compiler can't tell */
2406			incc = 0;
2407		} else {
2408			buf = ibuf;
2409			disable_intr();
2410			incc = com->iptr - buf;
2411			com_events -= incc;
2412			if (ibuf == com->ibuf1)
2413				ibuf = com->ibuf2;
2414			else
2415				ibuf = com->ibuf1;
2416			com->ibufend = ibuf + RS_IBUFSIZE;
2417			com->ihighwater = ibuf + RS_IHIGHWATER;
2418			com->iptr = ibuf;
2419
2420			/*
2421			 * There is now room for another low-level buffer full
2422			 * of input, so enable RTS if it is now disabled and
2423			 * there is room in the high-level buffer.
2424			 */
2425#ifdef PC98
2426			if(IS_8251(com->pc98_if_type))
2427				tmp = com_tiocm_get(com) & TIOCM_RTS;
2428			else
2429				tmp = com->mcr_image & MCR_RTS;
2430#endif
2431			if ((com->state & CS_RTS_IFLOW)
2432#ifdef PC98
2433			    && !(tmp)
2434#else
2435			    && !(com->mcr_image & MCR_RTS)
2436#endif
2437			    && !(tp->t_state & TS_TBLOCK))
2438#ifdef PC98
2439				if(IS_8251(com->pc98_if_type))
2440					com_tiocm_bis(com, TIOCM_RTS);
2441				else
2442#endif
2443				outb(com->modem_ctl_port,
2444				     com->mcr_image |= MCR_RTS);
2445			enable_intr();
2446			com->ibuf = ibuf;
2447		}
2448
2449		if (com->state & CS_CHECKMSR) {
2450			u_char	delta_modem_status;
2451
2452#ifdef PC98
2453			if(!IS_8251(com->pc98_if_type)){
2454#endif
2455			disable_intr();
2456			delta_modem_status = com->last_modem_status
2457					     ^ com->prev_modem_status;
2458			com->prev_modem_status = com->last_modem_status;
2459			com_events -= LOTS_OF_EVENTS;
2460			com->state &= ~CS_CHECKMSR;
2461			enable_intr();
2462			if (delta_modem_status & MSR_DCD)
2463				(*linesw[tp->t_line].l_modem)
2464					(tp, com->prev_modem_status & MSR_DCD);
2465#ifdef PC98
2466			}
2467#endif
2468		}
2469		if (com->state & CS_ODONE) {
2470			disable_intr();
2471			com_events -= LOTS_OF_EVENTS;
2472			com->state &= ~CS_ODONE;
2473			enable_intr();
2474			if (!(com->state & CS_BUSY)
2475			    && !(com->extra_state & CSE_BUSYCHECK)) {
2476				timeout(siobusycheck, com, hz / 100);
2477				com->extra_state |= CSE_BUSYCHECK;
2478			}
2479			(*linesw[tp->t_line].l_start)(tp);
2480		}
2481		if (incc <= 0 || !(tp->t_state & TS_ISOPEN) ||
2482		    !(tp->t_cflag & CREAD))
2483			continue;
2484		/*
2485		 * Avoid the grotesquely inefficient lineswitch routine
2486		 * (ttyinput) in "raw" mode.  It usually takes about 450
2487		 * instructions (that's without canonical processing or echo!).
2488		 * slinput is reasonably fast (usually 40 instructions plus
2489		 * call overhead).
2490		 */
2491		if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
2492			if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER
2493			    && (com->state & CS_RTS_IFLOW
2494				|| tp->t_iflag & IXOFF)
2495			    && !(tp->t_state & TS_TBLOCK))
2496				ttyblock(tp);
2497			tk_nin += incc;
2498			tk_rawcc += incc;
2499			tp->t_rawcc += incc;
2500			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
2501				+= b_to_q((char *)buf, incc, &tp->t_rawq);
2502			ttwakeup(tp);
2503			if (tp->t_state & TS_TTSTOP
2504			    && (tp->t_iflag & IXANY
2505				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
2506				tp->t_state &= ~TS_TTSTOP;
2507				tp->t_lflag &= ~FLUSHO;
2508				comstart(tp);
2509			}
2510		} else {
2511			do {
2512				u_char	line_status;
2513				int	recv_data;
2514
2515				line_status = (u_char) buf[CE_INPUT_OFFSET];
2516				recv_data = (u_char) *buf++;
2517				if (line_status
2518				    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
2519					if (line_status & LSR_BI)
2520						recv_data |= TTY_BI;
2521					if (line_status & LSR_FE)
2522						recv_data |= TTY_FE;
2523					if (line_status & LSR_OE)
2524						recv_data |= TTY_OE;
2525					if (line_status & LSR_PE)
2526						recv_data |= TTY_PE;
2527				}
2528				(*linesw[tp->t_line].l_rint)(recv_data, tp);
2529			} while (--incc > 0);
2530		}
2531		if (com_events == 0)
2532			break;
2533	}
2534	if (com_events >= LOTS_OF_EVENTS)
2535		goto repeat;
2536}
2537
2538static int
2539comparam(tp, t)
2540	struct tty	*tp;
2541	struct termios	*t;
2542{
2543	u_int		cfcr;
2544	int		cflag;
2545	struct com_s	*com;
2546	int		divisor;
2547	u_char		dlbh;
2548	u_char		dlbl;
2549	int		error;
2550	Port_t		iobase;
2551	int		s;
2552	int		unit;
2553	int		txtimeout;
2554#ifdef PC98
2555	Port_t		tmp_port;
2556	int		tmp_flg;
2557#endif
2558
2559#ifdef PC98
2560	cfcr = 0;
2561	unit = DEV_TO_UNIT(tp->t_dev);
2562	com = com_addr(unit);
2563	iobase = com->iobase;
2564	if(IS_8251(com->pc98_if_type)) {
2565		divisor = pc98_ttspeedtab(com, t->c_ospeed);
2566	} else
2567#endif
2568	/* do historical conversions */
2569	if (t->c_ispeed == 0)
2570		t->c_ispeed = t->c_ospeed;
2571
2572	/* check requested parameters */
2573	divisor = ttspeedtab(t->c_ospeed, comspeedtab);
2574	if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed)
2575		return (EINVAL);
2576
2577	/* parameters are OK, convert them to the com struct and the device */
2578#ifndef PC98
2579	unit = DEV_TO_UNIT(tp->t_dev);
2580	com = com_addr(unit);
2581	iobase = com->iobase;
2582#endif
2583	s = spltty();
2584#ifdef PC98
2585	if(IS_8251(com->pc98_if_type)){
2586		if(divisor == 0){
2587			com_int_TxRx_disable( com );
2588			com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
2589		}
2590	} else {
2591#endif
2592	if (divisor == 0)
2593		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
2594	else
2595		(void)commctl(com, TIOCM_DTR, DMBIS);
2596#ifdef PC98
2597	}
2598#endif
2599	cflag = t->c_cflag;
2600#ifdef PC98
2601	if(!IS_8251(com->pc98_if_type)){
2602#endif
2603	switch (cflag & CSIZE) {
2604	case CS5:
2605		cfcr = CFCR_5BITS;
2606		break;
2607	case CS6:
2608		cfcr = CFCR_6BITS;
2609		break;
2610	case CS7:
2611		cfcr = CFCR_7BITS;
2612		break;
2613	default:
2614		cfcr = CFCR_8BITS;
2615		break;
2616	}
2617	if (cflag & PARENB) {
2618		cfcr |= CFCR_PENAB;
2619		if (!(cflag & PARODD))
2620			cfcr |= CFCR_PEVEN;
2621	}
2622	if (cflag & CSTOPB)
2623		cfcr |= CFCR_STOPB;
2624
2625	if (com->hasfifo && divisor != 0) {
2626		/*
2627		 * Use a fifo trigger level low enough so that the input
2628		 * latency from the fifo is less than about 16 msec and
2629		 * the total latency is less than about 30 msec.  These
2630		 * latencies are reasonable for humans.  Serial comms
2631		 * protocols shouldn't expect anything better since modem
2632		 * latencies are larger.
2633		 */
2634		com->fifo_image = t->c_ospeed <= 4800
2635				  ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH;
2636#ifdef COM_ESP
2637		/*
2638		 * The Hayes ESP card needs the fifo DMA mode bit set
2639		 * in compatibility mode.  If not, it will interrupt
2640		 * for each character received.
2641		 */
2642		if (com->esp)
2643			com->fifo_image |= FIFO_DMA_MODE;
2644#endif
2645		outb(iobase + com_fifo, com->fifo_image);
2646	}
2647
2648	/*
2649	 * Some UARTs lock up if the divisor latch registers are selected
2650	 * while the UART is doing output (they refuse to transmit anything
2651	 * more until given a hard reset).  Fix this by stopping filling
2652	 * the device buffers and waiting for them to drain.  Reading the
2653	 * line status port outside of siointr1() might lose some receiver
2654	 * error bits, but that is acceptable here.
2655	 */
2656#ifdef PC98
2657	}
2658#endif
2659	disable_intr();
2660retry:
2661	com->state &= ~CS_TTGO;
2662	txtimeout = tp->t_timeout;
2663	enable_intr();
2664#ifdef PC98
2665	if(IS_8251(com->pc98_if_type)){
2666		tmp_port = com->sts_port;
2667		tmp_flg = (STS8251_TxRDY|STS8251_TxEMP);
2668	} else {
2669		tmp_port = com->line_status_port;
2670		tmp_flg = (LSR_TSRE|LSR_TXRDY);
2671	}
2672	while ((inb(tmp_port) & tmp_flg) != tmp_flg) {
2673#else
2674	while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2675	       != (LSR_TSRE | LSR_TXRDY)) {
2676#endif
2677		tp->t_state |= TS_SO_OCOMPLETE;
2678		error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH,
2679				 "siotx", hz / 100);
2680		if (   txtimeout != 0
2681		    && (!error || error	== EAGAIN)
2682		    && (txtimeout -= hz	/ 100) <= 0
2683		   )
2684			error = EIO;
2685		if (com->gone)
2686			error = ENODEV;
2687		if (error != 0 && error != EAGAIN) {
2688			if (!(tp->t_state & TS_TTSTOP)) {
2689				disable_intr();
2690				com->state |= CS_TTGO;
2691				enable_intr();
2692			}
2693			splx(s);
2694			return (error);
2695		}
2696	}
2697
2698	disable_intr();		/* very important while com_data is hidden */
2699
2700	/*
2701	 * XXX - clearing CS_TTGO is not sufficient to stop further output,
2702	 * because siopoll() calls comstart() which usually sets it again
2703	 * because TS_TTSTOP is clear.  Setting TS_TTSTOP would not be
2704	 * sufficient, for similar reasons.
2705	 */
2706#ifdef PC98
2707	if ((inb(tmp_port) & tmp_flg) != tmp_flg)
2708#else
2709	if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2710	    != (LSR_TSRE | LSR_TXRDY))
2711#endif
2712		goto retry;
2713
2714#ifdef PC98
2715	if(!IS_8251(com->pc98_if_type)){
2716#endif
2717	if (divisor != 0) {
2718		outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
2719		/*
2720		 * Only set the divisor registers if they would change,
2721		 * since on some 16550 incompatibles (UMC8669F), setting
2722		 * them while input is arriving them loses sync until
2723		 * data stops arriving.
2724		 */
2725		dlbl = divisor & 0xFF;
2726		if (inb(iobase + com_dlbl) != dlbl)
2727			outb(iobase + com_dlbl, dlbl);
2728		dlbh = (u_int) divisor >> 8;
2729		if (inb(iobase + com_dlbh) != dlbh)
2730			outb(iobase + com_dlbh, dlbh);
2731	}
2732
2733
2734	outb(iobase + com_cfcr, com->cfcr_image = cfcr);
2735
2736#ifdef PC98
2737	} else
2738		com_cflag_and_speed_set(com, cflag, t->c_ospeed);
2739#endif
2740	if (!(tp->t_state & TS_TTSTOP))
2741		if (com->st16650a) {
2742			outb(iobase + com_cfcr, 0xbf);
2743			outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40);
2744		}
2745		com->state |= CS_TTGO;
2746
2747	if (cflag & CRTS_IFLOW) {
2748		com->state |= CS_RTS_IFLOW;
2749		/*
2750		 * If CS_RTS_IFLOW just changed from off to on, the change
2751		 * needs to be propagated to MCR_RTS.  This isn't urgent,
2752		 * so do it later by calling comstart() instead of repeating
2753		 * a lot of code from comstart() here.
2754		 */
2755	} else if (com->state & CS_RTS_IFLOW) {
2756		com->state &= ~CS_RTS_IFLOW;
2757		/*
2758		 * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
2759		 * on here, since comstart() won't do it later.
2760		 */
2761#ifdef PC98
2762		if(IS_8251(com->pc98_if_type))
2763			com_tiocm_bis(com, TIOCM_RTS);
2764		else
2765#endif
2766		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2767		if (com->st16650a) {
2768			outb(iobase + com_cfcr, 0xbf);
2769			outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40);
2770		}
2771	}
2772
2773
2774	/*
2775	 * Set up state to handle output flow control.
2776	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2777	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2778	 */
2779	com->state |= CS_ODEVREADY;
2780	com->state &= ~CS_CTS_OFLOW;
2781	if (cflag & CCTS_OFLOW) {
2782		com->state |= CS_CTS_OFLOW;
2783#ifdef PC98
2784		if(IS_8251(com->pc98_if_type)){
2785			if (!(pc98_get_modem_status(com) & TIOCM_CTS))
2786				com->state &= ~CS_ODEVREADY;
2787		} else {
2788#endif
2789		if (!(com->last_modem_status & MSR_CTS))
2790		if (com->st16650a) {
2791			outb(iobase + com_cfcr, 0xbf);
2792			outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80);
2793		}
2794#ifdef PC98
2795		}
2796#endif
2797	} else {
2798		if (com->st16650a) {
2799			outb(iobase + com_cfcr, 0xbf);
2800			outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80);
2801		}
2802			com->state &= ~CS_ODEVREADY;
2803	}
2804
2805
2806	outb(iobase + com_cfcr, com->cfcr_image);
2807
2808
2809	/* XXX shouldn't call functions while intrs are disabled. */
2810	disc_optim(tp, t, com);
2811	/*
2812	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
2813	 * unconditionally, but that defeated the careful discarding of
2814	 * stale input in sioopen().
2815	 */
2816	if (com->state >= (CS_BUSY | CS_TTGO))
2817		siointr1(com);
2818
2819	enable_intr();
2820	splx(s);
2821	comstart(tp);
2822	return (0);
2823}
2824
2825static void
2826comstart(tp)
2827	struct tty	*tp;
2828{
2829	struct com_s	*com;
2830	int		s;
2831	int		unit;
2832#ifdef PC98
2833	int		tmp;
2834#endif
2835
2836	unit = DEV_TO_UNIT(tp->t_dev);
2837	com = com_addr(unit);
2838	s = spltty();
2839	disable_intr();
2840	if (tp->t_state & TS_TTSTOP)
2841		com->state &= ~CS_TTGO;
2842	else
2843		com->state |= CS_TTGO;
2844	if (tp->t_state & TS_TBLOCK) {
2845#ifdef PC98
2846		if(IS_8251(com->pc98_if_type))
2847			tmp = com_tiocm_get(com) & TIOCM_RTS;
2848		else
2849			tmp = com->mcr_image & MCR_RTS;
2850		if (tmp && (com->state & CS_RTS_IFLOW))
2851#else
2852		if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2853#endif
2854#ifdef PC98
2855			if(IS_8251(com->pc98_if_type))
2856				com_tiocm_bic(com, TIOCM_RTS);
2857			else
2858#endif
2859			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2860	} else {
2861#ifdef PC98
2862		if(IS_8251(com->pc98_if_type))
2863			tmp = com_tiocm_get(com) & TIOCM_RTS;
2864		else
2865			tmp = com->mcr_image & MCR_RTS;
2866		if (!(tmp) && com->iptr < com->ihighwater
2867			&& com->state & CS_RTS_IFLOW)
2868#else
2869		if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2870		    && com->state & CS_RTS_IFLOW)
2871#endif
2872#ifdef PC98
2873			if(IS_8251(com->pc98_if_type))
2874				com_tiocm_bis(com, TIOCM_RTS);
2875			else
2876#endif
2877			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2878	}
2879	enable_intr();
2880	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2881#ifdef PC98
2882/*		if(IS_8251(com->pc98_if_type))
2883			com_int_Tx_enable(com); */
2884#endif
2885		splx(s);
2886		return;
2887	}
2888	if (tp->t_outq.c_cc != 0) {
2889		struct lbq	*qp;
2890		struct lbq	*next;
2891
2892		if (!com->obufs[0].l_queued) {
2893			com->obufs[0].l_tail
2894			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2895						  sizeof com->obuf1);
2896			com->obufs[0].l_next = NULL;
2897			com->obufs[0].l_queued = TRUE;
2898			disable_intr();
2899			if (com->state & CS_BUSY) {
2900				qp = com->obufq.l_next;
2901				while ((next = qp->l_next) != NULL)
2902					qp = next;
2903				qp->l_next = &com->obufs[0];
2904			} else {
2905				com->obufq.l_head = com->obufs[0].l_head;
2906				com->obufq.l_tail = com->obufs[0].l_tail;
2907				com->obufq.l_next = &com->obufs[0];
2908				com->state |= CS_BUSY;
2909			}
2910			enable_intr();
2911		}
2912		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2913			com->obufs[1].l_tail
2914			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2915						  sizeof com->obuf2);
2916			com->obufs[1].l_next = NULL;
2917			com->obufs[1].l_queued = TRUE;
2918			disable_intr();
2919			if (com->state & CS_BUSY) {
2920				qp = com->obufq.l_next;
2921				while ((next = qp->l_next) != NULL)
2922					qp = next;
2923				qp->l_next = &com->obufs[1];
2924			} else {
2925				com->obufq.l_head = com->obufs[1].l_head;
2926				com->obufq.l_tail = com->obufs[1].l_tail;
2927				com->obufq.l_next = &com->obufs[1];
2928				com->state |= CS_BUSY;
2929			}
2930			enable_intr();
2931		}
2932		tp->t_state |= TS_BUSY;
2933	}
2934	disable_intr();
2935	if (com->state >= (CS_BUSY | CS_TTGO))
2936		siointr1(com);	/* fake interrupt to start output */
2937	enable_intr();
2938#ifdef PC98
2939/*		if(IS_8251(com->pc98_if_type))
2940			com_int_Tx_enable(com); */
2941#endif
2942	ttwwakeup(tp);
2943	splx(s);
2944}
2945
2946static void
2947siostop(tp, rw)
2948	struct tty	*tp;
2949	int		rw;
2950{
2951	struct com_s	*com;
2952
2953	com = com_addr(DEV_TO_UNIT(tp->t_dev));
2954	if (com->gone)
2955		return;
2956	disable_intr();
2957	if (rw & FWRITE) {
2958		if (com->hasfifo)
2959#ifdef COM_ESP
2960		    /* XXX avoid h/w bug. */
2961		    if (!com->esp)
2962#endif
2963			/* XXX does this flush everything? */
2964			outb(com->iobase + com_fifo,
2965			     FIFO_XMT_RST | com->fifo_image);
2966		com->obufs[0].l_queued = FALSE;
2967		com->obufs[1].l_queued = FALSE;
2968		if (com->state & CS_ODONE)
2969			com_events -= LOTS_OF_EVENTS;
2970		com->state &= ~(CS_ODONE | CS_BUSY);
2971		com->tp->t_state &= ~TS_BUSY;
2972	}
2973	if (rw & FREAD) {
2974		if (com->hasfifo)
2975#ifdef COM_ESP
2976		    /* XXX avoid h/w bug. */
2977		    if (!com->esp)
2978#endif
2979			/* XXX does this flush everything? */
2980			outb(com->iobase + com_fifo,
2981			     FIFO_RCV_RST | com->fifo_image);
2982		com_events -= (com->iptr - com->ibuf);
2983		com->iptr = com->ibuf;
2984	}
2985	enable_intr();
2986	comstart(tp);
2987}
2988
2989static struct tty *
2990siodevtotty(dev)
2991	dev_t	dev;
2992{
2993	int	mynor;
2994	int	unit;
2995
2996	mynor = minor(dev);
2997	if (mynor & CONTROL_MASK)
2998		return (NULL);
2999	unit = MINOR_TO_UNIT(mynor);
3000	if ((u_int) unit >= NSIOTOT)
3001		return (NULL);
3002	return (&sio_tty[unit]);
3003}
3004
3005static int
3006commctl(com, bits, how)
3007	struct com_s	*com;
3008	int		bits;
3009	int		how;
3010{
3011	int	mcr;
3012	int	msr;
3013
3014	if (how == DMGET) {
3015		bits = TIOCM_LE;	/* XXX - always enabled while open */
3016		mcr = com->mcr_image;
3017		if (mcr & MCR_DTR)
3018			bits |= TIOCM_DTR;
3019		if (mcr & MCR_RTS)
3020			bits |= TIOCM_RTS;
3021		msr = com->prev_modem_status;
3022		if (msr & MSR_CTS)
3023			bits |= TIOCM_CTS;
3024		if (msr & MSR_DCD)
3025			bits |= TIOCM_CD;
3026		if (msr & MSR_DSR)
3027			bits |= TIOCM_DSR;
3028		/*
3029		 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
3030		 * more volatile by reading the modem status a lot.  Perhaps
3031		 * we should latch both bits until the status is read here.
3032		 */
3033		if (msr & (MSR_RI | MSR_TERI))
3034			bits |= TIOCM_RI;
3035		return (bits);
3036	}
3037	mcr = 0;
3038	if (bits & TIOCM_DTR)
3039		mcr |= MCR_DTR;
3040	if (bits & TIOCM_RTS)
3041		mcr |= MCR_RTS;
3042	if (com->gone)
3043		return(0);
3044	disable_intr();
3045	switch (how) {
3046	case DMSET:
3047		outb(com->modem_ctl_port,
3048		     com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
3049		break;
3050	case DMBIS:
3051		outb(com->modem_ctl_port, com->mcr_image |= mcr);
3052		break;
3053	case DMBIC:
3054		outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
3055		break;
3056	}
3057	enable_intr();
3058	return (0);
3059}
3060
3061static void
3062siosettimeout()
3063{
3064	struct com_s	*com;
3065	bool_t		someopen;
3066	int		unit;
3067
3068	/*
3069	 * Set our timeout period to 1 second if no polled devices are open.
3070	 * Otherwise set it to max(1/200, 1/hz).
3071	 * Enable timeouts iff some device is open.
3072	 */
3073	untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3074	sio_timeout = hz;
3075	someopen = FALSE;
3076	for (unit = 0; unit < NSIOTOT; ++unit) {
3077		com = com_addr(unit);
3078		if (com != NULL && com->tp != NULL
3079		    && com->tp->t_state & TS_ISOPEN && !com->gone) {
3080			someopen = TRUE;
3081			if (com->poll || com->poll_output) {
3082				sio_timeout = hz > 200 ? hz / 200 : 1;
3083				break;
3084			}
3085		}
3086	}
3087	if (someopen) {
3088		sio_timeouts_until_log = hz / sio_timeout;
3089		sio_timeout_handle = timeout(comwakeup, (void *)NULL,
3090					     sio_timeout);
3091	} else {
3092		/* Flush error messages, if any. */
3093		sio_timeouts_until_log = 1;
3094		comwakeup((void *)NULL);
3095		untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3096	}
3097}
3098
3099static void
3100comwakeup(chan)
3101	void	*chan;
3102{
3103	struct com_s	*com;
3104	int		unit;
3105
3106	sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
3107
3108	/*
3109	 * Recover from lost output interrupts.
3110	 * Poll any lines that don't use interrupts.
3111	 */
3112	for (unit = 0; unit < NSIOTOT; ++unit) {
3113		com = com_addr(unit);
3114		if (com != NULL && !com->gone
3115		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
3116			disable_intr();
3117			siointr1(com);
3118			enable_intr();
3119		}
3120	}
3121
3122	/*
3123	 * Check for and log errors, but not too often.
3124	 */
3125	if (--sio_timeouts_until_log > 0)
3126		return;
3127	sio_timeouts_until_log = hz / sio_timeout;
3128	for (unit = 0; unit < NSIOTOT; ++unit) {
3129		int	errnum;
3130
3131		com = com_addr(unit);
3132		if (com == NULL)
3133			continue;
3134		if (com->gone)
3135			continue;
3136		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
3137			u_int	delta;
3138			u_long	total;
3139
3140			disable_intr();
3141			delta = com->delta_error_counts[errnum];
3142			com->delta_error_counts[errnum] = 0;
3143			enable_intr();
3144			if (delta == 0)
3145				continue;
3146			total = com->error_counts[errnum] += delta;
3147			log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
3148			    unit, delta, error_desc[errnum],
3149			    delta == 1 ? "" : "s", total);
3150		}
3151	}
3152}
3153
3154#ifdef PC98
3155/* commint is called when modem control line changes */
3156static void
3157commint(dev_t dev)
3158{
3159	register struct tty *tp;
3160	int	stat,delta;
3161	struct com_s *com;
3162	int	mynor,unit;
3163
3164	mynor = minor(dev);
3165	unit = MINOR_TO_UNIT(mynor);
3166	com = com_addr(unit);
3167	tp = com->tp;
3168
3169	stat = com_tiocm_get(com);
3170	delta = com_tiocm_get_delta(com);
3171
3172	if (com->state & CS_CTS_OFLOW) {
3173		if (stat & TIOCM_CTS)
3174			com->state |= CS_ODEVREADY;
3175		else
3176			com->state &= ~CS_ODEVREADY;
3177	}
3178	if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) {
3179	    if (stat & TIOCM_CAR )
3180		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
3181	    else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
3182		/* negate DTR, RTS */
3183		com_tiocm_bic(com, (tp->t_cflag & HUPCL) ?
3184				TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE );
3185		/* disable IENABLE */
3186		com_int_TxRx_disable( com );
3187	    }
3188	}
3189}
3190#endif
3191
3192static void
3193disc_optim(tp, t, com)
3194	struct tty	*tp;
3195	struct termios	*t;
3196	struct com_s	*com;
3197{
3198	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
3199	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
3200	    && (!(t->c_iflag & PARMRK)
3201		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
3202	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
3203	    && linesw[tp->t_line].l_rint == ttyinput)
3204		tp->t_state |= TS_CAN_BYPASS_L_RINT;
3205	else
3206		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
3207	/*
3208	 * Prepare to reduce input latency for packet
3209	 * discplines with a end of packet character.
3210	 */
3211	if (tp->t_line == SLIPDISC)
3212		com->hotchar = 0xc0;
3213	else if (tp->t_line == PPPDISC)
3214		com->hotchar = 0x7e;
3215	else
3216		com->hotchar = 0;
3217}
3218
3219/*
3220 * Following are all routines needed for SIO to act as console
3221 */
3222#include <machine/cons.h>
3223
3224struct siocnstate {
3225	u_char	dlbl;
3226	u_char	dlbh;
3227	u_char	ier;
3228	u_char	cfcr;
3229	u_char	mcr;
3230};
3231
3232static speed_t siocngetspeed __P((Port_t, struct speedtab *));
3233static void siocnclose	__P((struct siocnstate *sp));
3234static void siocnopen	__P((struct siocnstate *sp));
3235static void siocntxwait	__P((void));
3236
3237static void
3238siocntxwait()
3239{
3240	int	timo;
3241
3242	/*
3243	 * Wait for any pending transmission to finish.  Required to avoid
3244	 * the UART lockup bug when the speed is changed, and for normal
3245	 * transmits.
3246	 */
3247	timo = 100000;
3248	while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
3249	       != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
3250		;
3251}
3252
3253/*
3254 * Read the serial port specified and try to figure out what speed
3255 * it's currently running at.  We're assuming the serial port has
3256 * been initialized and is basicly idle.  This routine is only intended
3257 * to be run at system startup.
3258 *
3259 * If the value read from the serial port doesn't make sense, return 0.
3260 */
3261
3262static speed_t
3263siocngetspeed(iobase, table)
3264	Port_t iobase;
3265	struct speedtab *table;
3266{
3267	int	code;
3268	u_char	dlbh;
3269	u_char	dlbl;
3270	u_char  cfcr;
3271
3272	cfcr = inb(iobase + com_cfcr);
3273	outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3274
3275	dlbl = inb(iobase + com_dlbl);
3276	dlbh = inb(iobase + com_dlbh);
3277
3278	outb(iobase + com_cfcr, cfcr);
3279
3280	code = dlbh << 8 | dlbl;
3281
3282	for ( ; table->sp_speed != -1; table++)
3283		if (table->sp_code == code)
3284			return (table->sp_speed);
3285
3286	return 0;	/* didn't match anything sane */
3287}
3288
3289static void
3290siocnopen(sp)
3291	struct siocnstate	*sp;
3292{
3293	int	divisor;
3294	u_char	dlbh;
3295	u_char	dlbl;
3296	Port_t	iobase;
3297
3298	/*
3299	 * Save all the device control registers except the fifo register
3300	 * and set our default ones (cs8 -parenb speed=comdefaultrate).
3301	 * We can't save the fifo register since it is read-only.
3302	 */
3303	iobase = siocniobase;
3304	sp->ier = inb(iobase + com_ier);
3305	outb(iobase + com_ier, 0);	/* spltty() doesn't stop siointr() */
3306	siocntxwait();
3307	sp->cfcr = inb(iobase + com_cfcr);
3308	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3309	sp->dlbl = inb(iobase + com_dlbl);
3310	sp->dlbh = inb(iobase + com_dlbh);
3311	/*
3312	 * Only set the divisor registers if they would change, since on
3313	 * some 16550 incompatibles (Startech), setting them clears the
3314	 * data input register.  This also reduces the effects of the
3315	 * UMC8669F bug.
3316	 */
3317	divisor = ttspeedtab(comdefaultrate, comspeedtab);
3318	dlbl = divisor & 0xFF;
3319	if (sp->dlbl != dlbl)
3320		outb(iobase + com_dlbl, dlbl);
3321	dlbh = (u_int) divisor >> 8;
3322	if (sp->dlbh != dlbh)
3323		outb(iobase + com_dlbh, dlbh);
3324	outb(iobase + com_cfcr, CFCR_8BITS);
3325	sp->mcr = inb(iobase + com_mcr);
3326	/*
3327	 * We don't want interrupts, but must be careful not to "disable"
3328	 * them by clearing the MCR_IENABLE bit, since that might cause
3329	 * an interrupt by floating the IRQ line.
3330	 */
3331	outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
3332}
3333
3334static void
3335siocnclose(sp)
3336	struct siocnstate	*sp;
3337{
3338	Port_t	iobase;
3339
3340	/*
3341	 * Restore the device control registers.
3342	 */
3343	siocntxwait();
3344	iobase = siocniobase;
3345	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3346	if (sp->dlbl != inb(iobase + com_dlbl))
3347		outb(iobase + com_dlbl, sp->dlbl);
3348	if (sp->dlbh != inb(iobase + com_dlbh))
3349		outb(iobase + com_dlbh, sp->dlbh);
3350	outb(iobase + com_cfcr, sp->cfcr);
3351	/*
3352	 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
3353	 */
3354	outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
3355	outb(iobase + com_ier, sp->ier);
3356}
3357
3358void
3359siocnprobe(cp)
3360	struct consdev	*cp;
3361{
3362	struct isa_device	*dvp;
3363	int			s;
3364	struct siocnstate	sp;
3365	speed_t			boot_speed;
3366
3367	/*
3368	 * Find our first enabled console, if any.  If it is a high-level
3369	 * console device, then initialize it and return successfully.
3370	 * If it is a low-level console device, then initialize it and
3371	 * return unsuccessfully.  It must be initialized in both cases
3372	 * for early use by console drivers and debuggers.  Initializing
3373	 * the hardware is not necessary in all cases, since the i/o
3374	 * routines initialize it on the fly, but it is necessary if
3375	 * input might arrive while the hardware is switched back to an
3376	 * uninitialized state.  We can't handle multiple console devices
3377	 * yet because our low-level routines don't take a device arg.
3378	 * We trust the user to set the console flags properly so that we
3379	 * don't need to probe.
3380	 */
3381	cp->cn_pri = CN_DEAD;
3382	for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++)
3383		if (dvp->id_driver == &siodriver && dvp->id_enabled
3384		    && COM_CONSOLE(dvp)) {
3385			siocniobase = dvp->id_iobase;
3386			s = spltty();
3387			if (boothowto & RB_SERIAL) {
3388				boot_speed = siocngetspeed(siocniobase,
3389							   comspeedtab);
3390				if (boot_speed)
3391					comdefaultrate = boot_speed;
3392			}
3393			siocnopen(&sp);
3394			splx(s);
3395			if (!COM_LLCONSOLE(dvp)) {
3396				cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit);
3397				cp->cn_pri = COM_FORCECONSOLE(dvp)
3398					     || boothowto & RB_SERIAL
3399					     ? CN_REMOTE : CN_NORMAL;
3400			}
3401			break;
3402		}
3403}
3404
3405void
3406siocninit(cp)
3407	struct consdev	*cp;
3408{
3409	comconsole = DEV_TO_UNIT(cp->cn_dev);
3410}
3411
3412int
3413siocncheckc(dev)
3414	dev_t	dev;
3415{
3416	int	c;
3417	Port_t	iobase;
3418	int	s;
3419	struct siocnstate	sp;
3420
3421	iobase = siocniobase;
3422	s = spltty();
3423	siocnopen(&sp);
3424	if (inb(iobase + com_lsr) & LSR_RXRDY)
3425		c = inb(iobase + com_data);
3426	else
3427		c = -1;
3428	siocnclose(&sp);
3429	splx(s);
3430	return (c);
3431}
3432
3433
3434int
3435siocngetc(dev)
3436	dev_t	dev;
3437{
3438	int	c;
3439	Port_t	iobase;
3440	int	s;
3441	struct siocnstate	sp;
3442
3443	iobase = siocniobase;
3444	s = spltty();
3445	siocnopen(&sp);
3446	while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3447		;
3448	c = inb(iobase + com_data);
3449	siocnclose(&sp);
3450	splx(s);
3451	return (c);
3452}
3453
3454void
3455siocnputc(dev, c)
3456	dev_t	dev;
3457	int	c;
3458{
3459	int	s;
3460	struct siocnstate	sp;
3461
3462	s = spltty();
3463	siocnopen(&sp);
3464	siocntxwait();
3465	outb(siocniobase + com_data, c);
3466	siocnclose(&sp);
3467	splx(s);
3468}
3469
3470#ifdef DSI_SOFT_MODEM
3471/*
3472 * The magic code to download microcode to a "Connection 14.4+Fax"
3473 * modem from Digicom Systems Inc.  Very magic.
3474 */
3475
3476#define DSI_ERROR(str) { ptr = str; goto error; }
3477static int
3478LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
3479{
3480    int int_c,int_k;
3481    int data_0188, data_0187;
3482
3483    /*
3484     * First see if it is a DSI SoftModem
3485     */
3486    if(!((inb(base_io+7) ^ inb(base_io+7) & 0x80)))
3487	return ENODEV;
3488
3489    data_0188 = inb(base_io+4);
3490    data_0187 = inb(base_io+3);
3491    outb(base_io+3,0x80);
3492    outb(base_io+4,0x0C);
3493    outb(base_io+0,0x31);
3494    outb(base_io+1,0x8C);
3495    outb(base_io+7,0x10);
3496    outb(base_io+7,0x19);
3497
3498    if(0x18 != (inb(base_io+7) & 0x1A))
3499	DSI_ERROR("dsp bus not granted");
3500
3501    if(0x01 != (inb(base_io+7) & 0x01)) {
3502	outb(base_io+7,0x18);
3503	outb(base_io+7,0x19);
3504	if(0x01 != (inb(base_io+7) & 0x01))
3505	    DSI_ERROR("program mem not granted");
3506    }
3507
3508    int_c = 0;
3509
3510    while(1) {
3511	if(int_c >= 7 || size <= 0x1800)
3512	    break;
3513
3514	for(int_k = 0 ; int_k < 0x800; int_k++) {
3515	    outb(base_io+0,*ptr++);
3516	    outb(base_io+1,*ptr++);
3517	    outb(base_io+2,*ptr++);
3518	}
3519
3520	size -= 0x1800;
3521	int_c++;
3522    }
3523
3524    if(size > 0x1800) {
3525 	outb(base_io+7,0x18);
3526 	outb(base_io+7,0x19);
3527	if(0x00 != (inb(base_io+7) & 0x01))
3528	    DSI_ERROR("program data not granted");
3529
3530	for(int_k = 0 ; int_k < 0x800; int_k++) {
3531	    outb(base_io+1,*ptr++);
3532	    outb(base_io+2,0);
3533	    outb(base_io+1,*ptr++);
3534	    outb(base_io+2,*ptr++);
3535	}
3536
3537	size -= 0x1800;
3538
3539	while(size > 0x1800) {
3540	    for(int_k = 0 ; int_k < 0xC00; int_k++) {
3541		outb(base_io+1,*ptr++);
3542		outb(base_io+2,*ptr++);
3543	    }
3544	    size -= 0x1800;
3545	}
3546
3547	if(size < 0x1800) {
3548	    for(int_k=0;int_k<size/2;int_k++) {
3549		outb(base_io+1,*ptr++);
3550		outb(base_io+2,*ptr++);
3551	    }
3552	}
3553
3554    } else if (size > 0) {
3555	if(int_c == 7) {
3556	    outb(base_io+7,0x18);
3557	    outb(base_io+7,0x19);
3558	    if(0x00 != (inb(base_io+7) & 0x01))
3559		DSI_ERROR("program data not granted");
3560	    for(int_k = 0 ; int_k < size/3; int_k++) {
3561		outb(base_io+1,*ptr++);
3562		outb(base_io+2,0);
3563		outb(base_io+1,*ptr++);
3564		outb(base_io+2,*ptr++);
3565	    }
3566	} else {
3567	    for(int_k = 0 ; int_k < size/3; int_k++) {
3568		outb(base_io+0,*ptr++);
3569		outb(base_io+1,*ptr++);
3570		outb(base_io+2,*ptr++);
3571	    }
3572	}
3573    }
3574    outb(base_io+7,0x11);
3575    outb(base_io+7,3);
3576
3577    outb(base_io+4,data_0188 & 0xfb);
3578
3579    outb(base_io+3,data_0187);
3580
3581    return 0;
3582error:
3583    printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr);
3584    outb(base_io+7,0x00); \
3585    outb(base_io+3,data_0187); \
3586    outb(base_io+4,data_0188);  \
3587    return EIO;
3588}
3589#endif /* DSI_SOFT_MODEM */
3590
3591/*
3592 * support PnP cards if we are using 'em
3593 */
3594
3595#if NPNP > 0
3596
3597static struct siopnp_ids {
3598	u_long vend_id;
3599	char *id_str;
3600} siopnp_ids[] = {
3601	{ 0x8113b04e, "Supra1381"},
3602	{ 0x9012b04e, "Supra1290"},
3603	{ 0x11007256, "USR0011"},
3604	{ 0 }
3605};
3606
3607static char *siopnp_probe(u_long csn, u_long vend_id);
3608static void siopnp_attach(u_long csn, u_long vend_id, char *name,
3609	struct isa_device *dev);
3610static u_long nsiopnp = NSIO;
3611
3612static struct pnp_device siopnp = {
3613	"siopnp",
3614	siopnp_probe,
3615	siopnp_attach,
3616	&nsiopnp,
3617	&tty_imask
3618};
3619DATA_SET (pnpdevice_set, siopnp);
3620
3621static char *
3622siopnp_probe(u_long csn, u_long vend_id)
3623{
3624	struct siopnp_ids *ids;
3625	char *s = NULL;
3626
3627	for(ids = siopnp_ids; ids->vend_id != 0; ids++) {
3628		if (vend_id == ids->vend_id) {
3629			s = ids->id_str;
3630			break;
3631		}
3632	}
3633
3634	if (s) {
3635		struct pnp_cinfo d;
3636		read_pnp_parms(&d, 0);
3637		if (d.enable == 0 || d.flags & 1) {
3638			printf("CSN %d is disabled.\n", csn);
3639			return (NULL);
3640		}
3641
3642	}
3643
3644	return (s);
3645}
3646
3647static void
3648siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
3649{
3650	struct pnp_cinfo d;
3651	struct isa_device *dvp;
3652
3653	if (dev->id_unit >= NSIOTOT)
3654		return;
3655
3656	if (read_pnp_parms(&d, 0) == 0) {
3657		printf("failed to read pnp parms\n");
3658		return;
3659	}
3660
3661	write_pnp_parms(&d, 0);
3662
3663	enable_pnp_card();
3664
3665	dev->id_iobase = d.port[0];
3666	dev->id_irq = (1 << d.irq[0]);
3667	dev->id_intr = siointr;
3668	dev->id_ri_flags = RI_FAST;
3669	dev->id_drq = -1;
3670
3671	if (dev->id_driver == NULL) {
3672		dev->id_driver = &siodriver;
3673		dvp = find_isadev(isa_devtab_tty, &siodriver, 0);
3674		if (dvp != NULL)
3675			dev->id_id = dvp->id_id;
3676	}
3677
3678	if ((dev->id_alive = sioprobe(dev)) != 0)
3679		sioattach(dev);
3680	else
3681		printf("sio%d: probe failed\n", dev->id_unit);
3682}
3683#endif
3684#ifdef PC98
3685/*
3686 *  pc98 local function
3687 */
3688
3689static void
3690com_tiocm_set(struct com_s *com, int msr)
3691{
3692	int	s;
3693	int	tmp = 0;
3694	int	mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS;
3695
3696	s=spltty();
3697	com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) )
3698	   | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3699	tmp |= (CMD8251_TxEN|CMD8251_RxEN);
3700	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3701	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3702	pc98_i8251_clear_or_cmd( com, mask, tmp );
3703	splx(s);
3704}
3705
3706static void
3707com_tiocm_bis(struct com_s *com, int msr)
3708{
3709	int	s;
3710	int	tmp = 0;
3711
3712	s=spltty();
3713	com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3714	tmp |= CMD8251_TxEN|CMD8251_RxEN;
3715	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3716	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3717
3718	pc98_i8251_or_cmd( com, tmp );
3719	splx(s);
3720}
3721
3722static void
3723com_tiocm_bic(struct com_s *com, int msr)
3724{
3725	int	s;
3726	int	tmp = msr;
3727
3728	s=spltty();
3729	com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3730	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3731	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3732
3733	pc98_i8251_clear_cmd( com, tmp );
3734	splx(s);
3735}
3736
3737static int
3738com_tiocm_get(struct com_s *com)
3739{
3740	return( com->pc98_prev_modem_status );
3741}
3742
3743static int
3744com_tiocm_get_delta(struct com_s *com)
3745{
3746	int	tmp;
3747
3748	tmp = com->pc98_modem_delta;
3749	com->pc98_modem_delta = 0;
3750	return( tmp );
3751}
3752
3753/* convert to TIOCM_?? ( ioctl.h ) */
3754static int
3755pc98_get_modem_status(struct com_s *com)
3756{
3757	int	stat, stat2;
3758	register int	msr;
3759
3760	stat  = inb(com->sts_port);
3761	stat2 = inb(com->in_modem_port);
3762	msr = com->pc98_prev_modem_status
3763			& ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
3764	if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR;
3765	if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI;
3766	if (   stat & STS8251_DSR ) msr |= TIOCM_DSR;
3767	if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS;
3768#if COM_CARRIER_DETECT_EMULATE
3769	if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
3770		msr |= TIOCM_CAR;
3771	}
3772#endif
3773	return(msr);
3774}
3775
3776static void
3777pc98_check_msr(void* chan)
3778{
3779	int	msr, delta;
3780	int	s;
3781	register struct tty *tp;
3782	struct	com_s *com;
3783	int	mynor;
3784	int	unit;
3785	dev_t	dev;
3786
3787	dev=(dev_t)chan;
3788	mynor = minor(dev);
3789	unit = MINOR_TO_UNIT(mynor);
3790	com = com_addr(unit);
3791	tp = com->tp;
3792
3793	s = spltty();
3794	msr = pc98_get_modem_status(com);
3795	/* make change flag */
3796	delta = msr ^ com->pc98_prev_modem_status;
3797	if ( delta & TIOCM_CAR ) {
3798	    if ( com->modem_car_chg_timer ) {
3799		if ( -- com->modem_car_chg_timer )
3800		    msr ^= TIOCM_CAR;
3801	    } else {
3802		if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ?
3803			     DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE )
3804		    msr ^= TIOCM_CAR;
3805	    }
3806	} else
3807	    com->modem_car_chg_timer = 0;
3808	delta = ( msr ^ com->pc98_prev_modem_status ) &
3809			(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
3810	com->pc98_prev_modem_status = msr;
3811	delta = ( com->pc98_modem_delta |= delta );
3812	splx(s);
3813	if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) {
3814		if ( delta ) {
3815			commint(dev);
3816		}
3817		timeout(pc98_check_msr, (caddr_t)dev,
3818					PC98_CHECK_MODEM_INTERVAL);
3819	} else {
3820		com->modem_checking = 0;
3821	}
3822}
3823
3824static void
3825pc98_msrint_start(dev_t dev)
3826{
3827	struct	com_s *com;
3828	int	mynor;
3829	int	unit;
3830	int	s = spltty();
3831
3832	mynor = minor(dev);
3833	unit = MINOR_TO_UNIT(mynor);
3834	com = com_addr(unit);
3835	/* modem control line check routine envoke interval is 1/10 sec */
3836	if ( com->modem_checking == 0 ) {
3837		com->pc98_prev_modem_status = pc98_get_modem_status(com);
3838		com->pc98_modem_delta = 0;
3839		timeout(pc98_check_msr, (caddr_t)dev,
3840					PC98_CHECK_MODEM_INTERVAL);
3841		com->modem_checking = 1;
3842	}
3843	splx(s);
3844}
3845
3846static void
3847pc98_disable_i8251_interrupt(struct com_s *com, int mod)
3848{
3849	/* disable interrupt */
3850	register int	tmp;
3851
3852	mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3853	COM_INT_DISABLE
3854	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3855	outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp );
3856	COM_INT_ENABLE
3857}
3858
3859static void
3860pc98_enable_i8251_interrupt(struct com_s *com, int mod)
3861{
3862	register int	tmp;
3863
3864	COM_INT_DISABLE
3865	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3866	outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp );
3867	COM_INT_ENABLE
3868}
3869
3870static int
3871pc98_check_i8251_interrupt(struct com_s *com)
3872{
3873	return ( com->intr_enable & 0x07 );
3874}
3875
3876static void
3877pc98_i8251_clear_cmd(struct com_s *com, int x)
3878{
3879	int	tmp;
3880
3881	COM_INT_DISABLE
3882	tmp = com->pc98_prev_siocmd & ~(x);
3883	outb(com->cmd_port, tmp);
3884	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3885	COM_INT_ENABLE
3886}
3887
3888static void
3889pc98_i8251_or_cmd(struct com_s *com, int x)
3890{
3891	int	tmp;
3892
3893	COM_INT_DISABLE
3894	tmp = com->pc98_prev_siocmd | (x);
3895	outb(com->cmd_port, tmp);
3896	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3897	COM_INT_ENABLE
3898}
3899
3900static void
3901pc98_i8251_set_cmd(struct com_s *com, int x)
3902{
3903	int	tmp;
3904
3905	COM_INT_DISABLE
3906	tmp = (x);
3907	outb(com->cmd_port, tmp);
3908	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3909	COM_INT_ENABLE
3910}
3911
3912static void
3913pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x)
3914{
3915	int	tmp;
3916	COM_INT_DISABLE
3917	tmp = com->pc98_prev_siocmd & ~(clr);
3918	tmp |= (x);
3919	outb(com->cmd_port, tmp);
3920	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
3921	COM_INT_ENABLE
3922}
3923
3924static int
3925pc98_i8251_get_cmd(struct com_s *com)
3926{
3927	return com->pc98_prev_siocmd;
3928}
3929
3930static int
3931pc98_i8251_get_mod(struct com_s *com)
3932{
3933	return com->pc98_prev_siomod;
3934}
3935
3936static void
3937pc98_i8251_reset(struct com_s *com, int mode, int command)
3938{
3939	outb(com->cmd_port, 0);	/* dummy */
3940	DELAY(2);
3941	outb(com->cmd_port, 0);	/* dummy */
3942	DELAY(2);
3943	outb(com->cmd_port, 0);	/* dummy */
3944	DELAY(2);
3945	outb(com->cmd_port, CMD8251_RESET);	/* internal reset */
3946	DELAY(2);
3947	outb(com->cmd_port, mode );	/* mode register */
3948	com->pc98_prev_siomod = mode;
3949	DELAY(2);
3950	pc98_i8251_set_cmd( com, (command|CMD8251_ER) );
3951}
3952
3953static void
3954pc98_check_sysclock(void)
3955{
3956	/* get system clock from port */
3957	if ( pc98_machine_type & M_8M ) {
3958	/* 8 MHz system & H98 */
3959		sysclock = 8;
3960	} else {
3961	/* 5 MHz system */
3962		sysclock = 5;
3963	}
3964}
3965
3966static void
3967com_cflag_and_speed_set( struct com_s *com, int cflag, int speed)
3968{
3969	int	cfcr=0, count;
3970	int	previnterrupt;
3971
3972	count = pc98_ttspeedtab( com, speed );
3973	if ( count < 0 ) return;
3974
3975	previnterrupt = pc98_check_i8251_interrupt(com);
3976	pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx );
3977
3978	switch ( cflag&CSIZE ) {
3979	  case CS5:
3980		cfcr = MOD8251_5BITS; break;
3981	  case CS6:
3982		cfcr = MOD8251_6BITS; break;
3983	  case CS7:
3984		cfcr = MOD8251_7BITS; break;
3985	  case CS8:
3986		cfcr = MOD8251_8BITS; break;
3987	}
3988	if ( cflag&PARENB ) {
3989	    if ( cflag&PARODD )
3990		cfcr |= MOD8251_PODD;
3991	    else
3992		cfcr |= MOD8251_PEVEN;
3993	} else
3994		cfcr |= MOD8251_PDISAB;
3995
3996	if ( cflag&CSTOPB )
3997		cfcr |= MOD8251_STOP2;
3998	else
3999		cfcr |= MOD8251_STOP1;
4000
4001	if ( count & 0x10000 )
4002		cfcr |= MOD8251_CLKX1;
4003	else
4004		cfcr |= MOD8251_CLKX16;
4005
4006	if (epson_machine_id != 0x20) {	/* XXX */
4007	{
4008		int	tmp;
4009		while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP))
4010			;
4011	}
4012	}
4013	/* set baud rate from ospeed */
4014	pc98_set_baud_rate( com, count );
4015
4016	if ( cfcr != pc98_i8251_get_mod(com) )
4017		pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) );
4018
4019	pc98_enable_i8251_interrupt( com, previnterrupt );
4020}
4021
4022static int
4023pc98_ttspeedtab(struct com_s *com, int speed)
4024{
4025	int	effect_sp, count=-1, mod;
4026
4027	switch ( com->pc98_if_type ) {
4028	    case COM_IF_INTERNAL:
4029		/* for *1CLK asynchronous! mode		, TEFUTEFU */
4030		effect_sp = ttspeedtab( speed, pc98speedtab );
4031		if ( effect_sp < 0 )
4032			effect_sp = ttspeedtab( (speed-1), pc98speedtab );
4033		if ( effect_sp <= 0 )
4034			return effect_sp;
4035		mod = (sysclock == 5 ? 2457600 : 1996800);
4036		if ( effect_sp == speed )
4037			mod /= 16;
4038		count = mod / effect_sp;
4039		if ( count > 65535 )
4040			return(-1);
4041		if ( effect_sp >= 2400 )
4042			if ( !(sysclock != 5 &&
4043				(effect_sp == 19200 || effect_sp == 38400)) )
4044				if ( ( mod % effect_sp ) != 0 )
4045					return(-1);
4046		if ( effect_sp != speed )
4047			count |= 0x10000;
4048		break;
4049#ifdef COM_IF_PC9861K
4050	    case COM_IF_PC9861K:
4051		effect_sp = speed;
4052		count = 1;
4053		break;
4054#endif
4055#ifdef COM_IF_PIO9032B
4056	    case COM_IF_PIO9032B:
4057		if ( speed == 0 ) return 0;
4058		count = ttspeedtab( speed, comspeedtab_pio9032b );
4059		if ( count < 0 ) return count;
4060		effect_sp = speed;
4061		break;
4062#endif
4063#ifdef COM_IF_B98_01
4064	    case COM_IF_B98_01:
4065		effect_sp=speed;
4066		count = ttspeedtab( speed, comspeedtab_b98_01 );
4067		if ( count <= 3 )
4068			return -1;         /* invalid speed/count */
4069		if ( count <= 5 )
4070			count |= 0x10000;  /* x1 mode for 76800 and 153600 */
4071		else
4072			count -= 4;        /* x16 mode for slower */
4073		break;
4074#endif
4075	}
4076	return count;
4077}
4078
4079static void
4080pc98_set_baud_rate( struct com_s *com, int count)
4081{
4082	int	s;
4083
4084	switch ( com->pc98_if_type ) {
4085	    case COM_IF_INTERNAL:
4086		if ( count < 0 ) {
4087			printf( "[ Illegal count : %d ]", count );
4088			return;
4089		} else if ( count == 0)
4090			return;
4091		/* set i8253 */
4092		s = splclock();
4093		outb( 0x77, 0xb6 );
4094		outb( 0x5f, 0);
4095		outb( 0x75, count & 0xff );
4096		outb( 0x5f, 0);
4097		outb( 0x75, (count >> 8) & 0xff );
4098		splx(s);
4099		break;
4100#if 0
4101#ifdef COM_IF_PC9861K
4102	    case COM_IF_PC9861K:
4103		break;
4104		/* ext. RS232C board: speed is determined by DIP switch */
4105#endif
4106#endif /* 0 */
4107#ifdef COM_IF_PIO9032B
4108	    case COM_IF_PIO9032B:
4109		outb( com_addr[unit], count & 0x07 );
4110		break;
4111#endif
4112#ifdef COM_IF_B98_01
4113	    case COM_IF_B98_01:
4114		outb( com->iobase,     count & 0x0f );
4115#ifdef B98_01_OLD
4116		/* some old board should be controlled in different way,
4117		   but this hasn't been tested yet.*/
4118		outb( com->iobase+2, ( count & 0x10000 ) ? 0xf0 : 0xf2 );
4119#endif
4120		break;
4121#endif
4122	}
4123}
4124static int
4125pc98_check_if_type( int iobase, struct siodev *iod)
4126{
4127	int	irr = 0, tmp = 0;
4128	int	ret = 0;
4129	static  short	irq_tab[2][8] = {
4130		{  3,  5,  6,  9, 10, 12, 13, -1},
4131		{  3, 10, 12, 13,  5,  6,  9, -1}
4132	};
4133	iod->irq = 0;
4134	switch ( iobase & 0xff ) {
4135		case IO_COM1:
4136			iod->if_type = COM_IF_INTERNAL;
4137			ret = 0; iod->irq = 4; break;
4138#ifdef COM_IF_PC9861K
4139		case IO_COM2:
4140			iod->if_type = COM_IF_PC9861K;
4141			ret = 1; irr = 0; tmp = 3; break;
4142		case IO_COM3:
4143			iod->if_type = COM_IF_PC9861K;
4144			ret = 2; irr = 1; tmp = 3; break;
4145#endif
4146#ifdef COM_IF_PIO9032B
4147	    case IO_COM_PIO9032B_2:
4148			iod->if_type = COM_IF_PIO9032B;
4149			ret = 1; irr = 0; tmp = 7; break;
4150	    case IO_COM_PIO9032B_3:
4151			iod->if_type = COM_IF_PIO9032B;
4152			ret = 2; irr = 1; tmp = 7; break;
4153#endif
4154#ifdef COM_IF_B98_01
4155	    case IO_COM_B98_01_2:
4156			iod->if_type = COM_IF_B98_01;
4157			ret = 1; irr = 0; tmp = 7;
4158			outb(iobase + 2, 0xf2);
4159			outb(iobase,     4);
4160			break;
4161	    case IO_COM_B98_01_3:
4162			iod->if_type = COM_IF_B98_01;
4163			ret = 2; irr = 1; tmp = 7;
4164			outb(iobase + 2, 0xf2);
4165			outb(iobase    , 4);
4166			break;
4167#endif
4168	    default:
4169			if((iobase & 0x0f0) == 0xd0){
4170				iod->if_type = MC16550;
4171				return 0;
4172			}
4173			return -1;
4174	}
4175
4176	iod->cmd  = ( iobase & 0xff00 )|PC98SIO_cmd_port(ret);
4177	iod->sts  = ( iobase & 0xff00 )|PC98SIO_sts_port(ret);
4178	iod->mod  = ( iobase & 0xff00 )|PC98SIO_in_modem_port(ret);
4179	iod->ctrl = ( iobase & 0xff00 )|PC98SIO_intr_ctrl_port(ret);
4180
4181	if ( iod->irq == 0 ) {
4182		tmp &= inb( iod->mod );
4183		iod->irq = irq_tab[irr][tmp];
4184		if ( iod->irq == -1 ) return -1;
4185	}
4186	return 0;
4187}
4188static int
4189pc98_set_ioport( struct com_s *com, int io_base )
4190{
4191	int	a, io, type;
4192
4193	switch ( io_base & 0xff ) {
4194	    case IO_COM1: a = 0; io = 0; type = COM_IF_INTERNAL;
4195					 pc98_check_sysclock(); break;
4196#ifdef COM_IF_PC9861K
4197	    case IO_COM2: a = 1; io = 0; type = COM_IF_PC9861K; break;
4198	    case IO_COM3: a = 2; io = 0; type = COM_IF_PC9861K; break;
4199#endif /* COM_IF_PC9861K */
4200#ifdef COM_IF_PIO9032B
4201			/* PIO9032B : I/O address is changeable */
4202	    case IO_COM_PIO9032B_2:
4203			a = 1; io = io_base & 0xff00;
4204			type = COM_IF_PIO9032B; break;
4205	    case IO_COM_PIO9032B_3:
4206			a = 2; io = io_base & 0xff00;
4207			type = COM_IF_PIO9032B; break;
4208#endif /* COM_IF_PIO9032B */
4209#ifdef COM_IF_B98_01
4210	    case IO_COM_B98_01_2:
4211			a = 1; io = 0; type = COM_IF_B98_01; break;
4212	    case IO_COM_B98_01_3:
4213			a = 2; io = 0; type = COM_IF_B98_01; break;
4214#endif /* COM_IF_B98_01*/
4215	    default:	/* i/o address not match */
4216		return -1;
4217	}
4218
4219	com->pc98_if_type	= type;
4220	com->data_port		= io | PC98SIO_data_port(a);
4221	com->cmd_port		= io | PC98SIO_cmd_port(a);
4222	com->sts_port		= io | PC98SIO_sts_port(a);
4223	com->in_modem_port	= io | PC98SIO_in_modem_port(a);
4224	com->intr_ctrl_port	= io | PC98SIO_intr_ctrl_port(a);
4225	return 0;
4226}
4227#endif /* PC98 defined */
4228