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