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