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