sio.c revision 68360
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: head/sys/pc98/cbus/sio.c 68360 2000-11-05 14:31:19Z nyan $
34 *	from: @(#)com.c	7.5 (Berkeley) 5/16/91
35 *	from: i386/isa sio.c,v 1.234
36 */
37
38#include "opt_comconsole.h"
39#include "opt_compat.h"
40#include "opt_ddb.h"
41#include "opt_sio.h"
42#include "card.h"
43#include "pci.h"
44#include "sio.h"
45
46/*
47 * Serial driver, based on 386BSD-0.1 com driver.
48 * Mostly rewritten to use pseudo-DMA.
49 * Works for National Semiconductor NS8250-NS16550AF UARTs.
50 * COM driver, based on HP dca driver.
51 *
52 * Changes for PC-Card integration:
53 *	- Added PC-Card driver table and handlers
54 */
55/*===============================================================
56 * 386BSD(98),FreeBSD-1.1x(98) com driver.
57 * -----
58 * modified for PC9801 by M.Ishii
59 *			Kyoto University Microcomputer Club (KMC)
60 * Chou "TEFUTEFU" Hirotomi
61 *			Kyoto Univ.  the faculty of medicine
62 *===============================================================
63 * FreeBSD-2.0.1(98) sio driver.
64 * -----
65 * modified for pc98 Internal i8251 and MICRO CORE MC16550II
66 *			T.Koike(hfc01340@niftyserve.or.jp)
67 * implement kernel device configuration
68 *			aizu@orient.center.nitech.ac.jp
69 *
70 * Notes.
71 * -----
72 *  PC98 localization based on 386BSD(98) com driver. Using its PC98 local
73 *  functions.
74 *  This driver is under debugging,has bugs.
75 *
76 * 1) config
77 *  options COM_MULTIPORT  #if using MC16550II
78 *  device sio0 at nec? port 0x30  tty irq 4             #internal
79 *  device sio1 at nec? port 0xd2  tty irq 5 flags 0x101 #mc1
80 *  device sio2 at nec? port 0x8d2 tty flags 0x101       #mc2
81 *                         # ~~~~~iobase        ~~multi port flag
82 *                         #                   ~  master device is sio1
83 * 2) device
84 *  cd /dev; MAKEDEV ttyd0 ttyd1 ..
85 * 3) /etc/rc.serial
86 *  57600bps is too fast for sio0(internal8251)
87 *  my ex.
88 *    #set default speed 9600
89 *    modem()
90 *       :
91 *      stty </dev/ttyid$i crtscts 9600
92 *       :                 #       ~~~~ default speed(can change after init.)
93 *    modem 0 1 2
94 * 4) COMCONSOLE
95 *  not changed.
96 * 5) PC9861K,PIO9032B,B98_01
97 *  not tested.
98 */
99/*
100 * modified for AIWA B98-01
101 * by T.Hatanou <hatanou@yasuda.comm.waseda.ac.jp>  last update: 15 Sep.1995
102 *
103 * How to configure...
104 *   # options COM_MULTIPORT         # support for MICROCORE MC16550II
105 *      ... comment-out this line, which will conflict with B98_01.
106 *   options "B98_01"                # support for AIWA B98-01
107 *   device  sio1 at nec? port 0x00d1 tty irq ?
108 *   device  sio2 at nec? port 0x00d5 tty irq ?
109 *      ... you can leave these lines `irq ?', irq will be autodetected.
110 */
111/*
112 * Modified by Y.Takahashi of Kogakuin University.
113 */
114/*
115 * modified for 8251(FIFO) by Seigo TANIMURA <tanimura@FreeBSD.org>
116 */
117
118#ifdef PC98
119#define COM_IF_INTERNAL		0x00
120#define COM_IF_PC9861K_1	0x01
121#define COM_IF_PC9861K_2	0x02
122#define COM_IF_IND_SS_1		0x03
123#define COM_IF_IND_SS_2		0x04
124#define COM_IF_PIO9032B_1	0x05
125#define COM_IF_PIO9032B_2	0x06
126#define COM_IF_B98_01_1		0x07
127#define COM_IF_B98_01_2		0x08
128#define COM_IF_END1		COM_IF_B98_01_2
129#define COM_IF_RSA98		0x10	/* same as COM_IF_NS16550 */
130#define COM_IF_NS16550		0x11
131#define COM_IF_SECOND_CCU	0x12	/* same as COM_IF_NS16550 */
132#define COM_IF_MC16550II	0x13
133#define COM_IF_MCRS98		0x14	/* same as COM_IF_MC16550II */
134#define COM_IF_RSB3000		0x15
135#define COM_IF_RSB384		0x16
136#define COM_IF_MODEM_CARD	0x17	/* same as COM_IF_NS16550 */
137#define COM_IF_RSA98III		0x18
138#define COM_IF_ESP98		0x19
139#define COM_IF_END2		COM_IF_ESP98
140#endif /* PC98 */
141
142#include <sys/param.h>
143#include <sys/bus.h>
144#include <sys/systm.h>
145#include <sys/reboot.h>
146#include <sys/malloc.h>
147#include <sys/tty.h>
148#include <sys/proc.h>
149#include <sys/module.h>
150#include <sys/conf.h>
151#include <sys/dkstat.h>
152#include <sys/fcntl.h>
153#include <sys/interrupt.h>
154#include <sys/ipl.h>
155#include <sys/kernel.h>
156#include <sys/syslog.h>
157#include <sys/sysctl.h>
158#include <sys/bus.h>
159#include <machine/bus.h>
160#include <sys/rman.h>
161#include <sys/timetc.h>
162#include <sys/timepps.h>
163
164#ifdef PC98
165#include <pc98/pc98/pc98.h>
166#include <pc98/pc98/pc98_machdep.h>
167#include <i386/isa/ic/i8251.h>
168#else
169#include <isa/isareg.h>
170#endif
171#include <isa/isavar.h>
172#if NPCI > 0
173#include <pci/pcireg.h>
174#include <pci/pcivar.h>
175#endif
176#include <machine/lock.h>
177
178#ifndef SMP
179#include <machine/lock.h>
180#endif
181#include <machine/resource.h>
182
183#include <isa/sioreg.h>
184
185#ifdef COM_ESP
186#include <i386/isa/ic/esp.h>
187#endif
188#include <i386/isa/ic/ns16550.h>
189#ifdef PC98
190#include <i386/isa/ic/rsa.h>
191#endif
192
193/* XXX - this is ok because we only do sio fast interrupts on i386 */
194#ifndef __i386__
195#define disable_intr()
196#define enable_intr()
197#endif
198
199#define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
200
201#define	CALLOUT_MASK		0x80
202#define	CONTROL_MASK		0x60
203#define	CONTROL_INIT_STATE	0x20
204#define	CONTROL_LOCK_STATE	0x40
205#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
206#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
207#define	MINOR_TO_UNIT(mynor)	((mynor) & ~MINOR_MAGIC_MASK)
208
209#ifdef COM_MULTIPORT
210/* checks in flags for multiport and which is multiport "master chip"
211 * for a given card
212 */
213#define	COM_ISMULTIPORT(flags)	((flags) & 0x01)
214#define	COM_MPMASTER(flags)	(((flags) >> 8) & 0x0ff)
215#define	COM_NOTAST4(flags)	((flags) & 0x04)
216#endif /* COM_MULTIPORT */
217
218#define	COM_CONSOLE(flags)	((flags) & 0x10)
219#define	COM_FORCECONSOLE(flags)	((flags) & 0x20)
220#define	COM_LLCONSOLE(flags)	((flags) & 0x40)
221#define	COM_DEBUGGER(flags)	((flags) & 0x80)
222#define	COM_LOSESOUTINTS(flags)	((flags) & 0x08)
223#define	COM_NOFIFO(flags)		((flags) & 0x02)
224#define COM_ST16650A(flags)	((flags) & 0x20000)
225#define COM_C_NOPROBE		(0x40000)
226#define COM_NOPROBE(flags)	((flags) & COM_C_NOPROBE)
227#define COM_C_IIR_TXRDYBUG	(0x80000)
228#define COM_IIR_TXRDYBUG(flags)	((flags) & COM_C_IIR_TXRDYBUG)
229#define	COM_FIFOSIZE(flags)	(((flags) & 0xff000000) >> 24)
230
231#ifdef PC98
232#define	com_emr		com_msr	/* Extension mode register for RSB-2000/3000 */
233#endif
234#define	com_scr		7	/* scratch register for 16450-16550 (R/W) */
235
236#define	sio_getreg(com, off) \
237	(bus_space_read_1((com)->bst, (com)->bsh, (off)))
238#define	sio_setreg(com, off, value) \
239	(bus_space_write_1((com)->bst, (com)->bsh, (off), (value)))
240
241/*
242 * com state bits.
243 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
244 * than the other bits so that they can be tested as a group without masking
245 * off the low bits.
246 *
247 * The following com and tty flags correspond closely:
248 *	CS_BUSY		= TS_BUSY (maintained by comstart(), siopoll() and
249 *				   comstop())
250 *	CS_TTGO		= ~TS_TTSTOP (maintained by comparam() and comstart())
251 *	CS_CTS_OFLOW	= CCTS_OFLOW (maintained by comparam())
252 *	CS_RTS_IFLOW	= CRTS_IFLOW (maintained by comparam())
253 * TS_FLUSH is not used.
254 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
255 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
256 */
257#define	CS_BUSY		0x80	/* output in progress */
258#define	CS_TTGO		0x40	/* output not stopped by XOFF */
259#define	CS_ODEVREADY	0x20	/* external device h/w ready (CTS) */
260#define	CS_CHECKMSR	1	/* check of MSR scheduled */
261#define	CS_CTS_OFLOW	2	/* use CTS output flow control */
262#define	CS_DTR_OFF	0x10	/* DTR held off */
263#define	CS_ODONE	4	/* output completed */
264#define	CS_RTS_IFLOW	8	/* use RTS input flow control */
265#define	CSE_BUSYCHECK	1	/* siobusycheck() scheduled */
266
267static	char const * const	error_desc[] = {
268#define	CE_OVERRUN			0
269	"silo overflow",
270#define	CE_INTERRUPT_BUF_OVERFLOW	1
271	"interrupt-level buffer overflow",
272#define	CE_TTY_BUF_OVERFLOW		2
273	"tty-level buffer overflow",
274};
275
276#define	CE_NTYPES			3
277#define	CE_RECORD(com, errnum)		(++(com)->delta_error_counts[errnum])
278
279/* types.  XXX - should be elsewhere */
280typedef u_int	Port_t;		/* hardware port */
281typedef u_char	bool_t;		/* boolean */
282
283/* queue of linear buffers */
284struct lbq {
285	u_char	*l_head;	/* next char to process */
286	u_char	*l_tail;	/* one past the last char to process */
287	struct lbq *l_next;	/* next in queue */
288	bool_t	l_queued;	/* nonzero if queued */
289};
290
291/* com device structure */
292struct com_s {
293	u_int	flags;		/* Copy isa device flags */
294	u_char	state;		/* miscellaneous flag bits */
295	bool_t  active_out;	/* nonzero if the callout device is open */
296	u_char	cfcr_image;	/* copy of value written to CFCR */
297#ifdef COM_ESP
298	bool_t	esp;		/* is this unit a hayes esp board? */
299#endif
300	u_char	extra_state;	/* more flag bits, separate for order trick */
301	u_char	fifo_image;	/* copy of value written to FIFO */
302	bool_t	hasfifo;	/* nonzero for 16550 UARTs */
303	bool_t	st16650a;	/* Is a Startech 16650A or RTS/CTS compat */
304	bool_t	loses_outints;	/* nonzero if device loses output interrupts */
305	u_char	mcr_image;	/* copy of value written to MCR */
306#ifdef COM_MULTIPORT
307	bool_t	multiport;	/* is this unit part of a multiport device? */
308#endif /* COM_MULTIPORT */
309	bool_t	no_irq;		/* nonzero if irq is not attached */
310	bool_t  gone;		/* hardware disappeared */
311	bool_t	poll;		/* nonzero if polling is required */
312	bool_t	poll_output;	/* nonzero if polling for output is required */
313	int	unit;		/* unit	number */
314	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
315	u_int	tx_fifo_size;
316	u_int	wopeners;	/* # processes waiting for DCD in open() */
317
318	/*
319	 * The high level of the driver never reads status registers directly
320	 * because there would be too many side effects to handle conveniently.
321	 * Instead, it reads copies of the registers stored here by the
322	 * interrupt handler.
323	 */
324	u_char	last_modem_status;	/* last MSR read by intr handler */
325	u_char	prev_modem_status;	/* last MSR handled by high level */
326
327	u_char	hotchar;	/* ldisc-specific char to be handled ASAP */
328	u_char	*ibuf;		/* start of input buffer */
329	u_char	*ibufend;	/* end of input buffer */
330	u_char	*ibufold;	/* old input buffer, to be freed */
331	u_char	*ihighwater;	/* threshold in input buffer */
332	u_char	*iptr;		/* next free spot in input buffer */
333	int	ibufsize;	/* size of ibuf (not include error bytes) */
334	int	ierroff;	/* offset of error bytes in ibuf */
335
336	struct lbq	obufq;	/* head of queue of output buffers */
337	struct lbq	obufs[2];	/* output buffers */
338
339	bus_space_tag_t		bst;
340	bus_space_handle_t	bsh;
341
342#ifdef PC98
343	Port_t	cmd_port;
344	Port_t	sts_port;
345	Port_t	in_modem_port;
346	Port_t	intr_ctrl_port;
347	Port_t	rsabase;	/* iobase address of a I/O-DATA RSA board */
348	int	intr_enable;
349	int	pc98_prev_modem_status;
350	int	pc98_modem_delta;
351	int	modem_car_chg_timer;
352	int	pc98_prev_siocmd;
353	int	pc98_prev_siomod;
354	int	modem_checking;
355	int	pc98_if_type;
356
357	bool_t	pc98_8251fifo;
358	bool_t	pc98_8251fifo_enable;
359#endif /* PC98 */
360	Port_t	data_port;	/* i/o ports */
361#ifdef COM_ESP
362	Port_t	esp_port;
363#endif
364	Port_t	int_id_port;
365	Port_t	modem_ctl_port;
366	Port_t	line_status_port;
367	Port_t	modem_status_port;
368	Port_t	intr_ctl_port;	/* Ports of IIR register */
369
370	struct tty	*tp;	/* cross reference */
371
372	/* Initial state. */
373	struct termios	it_in;	/* should be in struct tty */
374	struct termios	it_out;
375
376	/* Lock state. */
377	struct termios	lt_in;	/* should be in struct tty */
378	struct termios	lt_out;
379
380	bool_t	do_timestamp;
381	bool_t	do_dcd_timestamp;
382	struct timeval	timestamp;
383	struct timeval	dcd_timestamp;
384	struct	pps_state pps;
385
386	u_long	bytes_in;	/* statistics */
387	u_long	bytes_out;
388	u_int	delta_error_counts[CE_NTYPES];
389	u_long	error_counts[CE_NTYPES];
390
391	struct resource *irqres;
392	struct resource *ioportres;
393	void *cookie;
394	dev_t devs[6];
395
396	/*
397	 * Data area for output buffers.  Someday we should build the output
398	 * buffer queue without copying data.
399	 */
400#ifdef PC98
401	int	obufsize;
402 	u_char	*obuf1;
403 	u_char	*obuf2;
404#else
405	u_char	obuf1[256];
406	u_char	obuf2[256];
407#endif
408};
409
410#ifdef COM_ESP
411static	int	espattach	__P((struct com_s *com, Port_t esp_port));
412#endif
413static	int	sioattach	__P((device_t dev, int rid));
414static	int	sio_isa_attach	__P((device_t dev));
415
416static	timeout_t siobusycheck;
417static	timeout_t siodtrwakeup;
418static	void	comhardclose	__P((struct com_s *com));
419static	void	sioinput	__P((struct com_s *com));
420static	void	siointr1	__P((struct com_s *com));
421static	void	siointr		__P((void *arg));
422static	int	commctl		__P((struct com_s *com, int bits, int how));
423static	int	comparam	__P((struct tty *tp, struct termios *t));
424static	void	siopoll		__P((void *dummy));
425static	int	sioprobe	__P((device_t dev, int xrid));
426static	int	sio_isa_probe	__P((device_t dev));
427static	void	siosettimeout	__P((void));
428static	int	siosetwater	__P((struct com_s *com, speed_t speed));
429static	void	comstart	__P((struct tty *tp));
430static	void	comstop		__P((struct tty *tp, int rw));
431static	timeout_t comwakeup;
432static	void	disc_optim	__P((struct tty	*tp, struct termios *t,
433				     struct com_s *com));
434
435#if NCARD > 0
436static	int	sio_pccard_attach __P((device_t dev));
437static	int	sio_pccard_detach __P((device_t dev));
438static	int	sio_pccard_probe __P((device_t dev));
439#endif /* NCARD > 0 */
440
441#if NPCI > 0
442static	int	sio_pci_attach __P((device_t dev));
443static	void	sio_pci_kludge_unit __P((device_t dev));
444static	int	sio_pci_probe __P((device_t dev));
445#endif /* NPCI > 0 */
446
447static char driver_name[] = "sio";
448
449/* table and macro for fast conversion from a unit number to its com struct */
450static	devclass_t	sio_devclass;
451#define	com_addr(unit)	((struct com_s *) \
452			 devclass_get_softc(sio_devclass, unit))
453
454static device_method_t sio_isa_methods[] = {
455	/* Device interface */
456	DEVMETHOD(device_probe,		sio_isa_probe),
457	DEVMETHOD(device_attach,	sio_isa_attach),
458
459	{ 0, 0 }
460};
461
462static driver_t sio_isa_driver = {
463	driver_name,
464	sio_isa_methods,
465	sizeof(struct com_s),
466};
467
468#if NCARD > 0
469static device_method_t sio_pccard_methods[] = {
470	/* Device interface */
471	DEVMETHOD(device_probe,		sio_pccard_probe),
472	DEVMETHOD(device_attach,	sio_pccard_attach),
473	DEVMETHOD(device_detach,	sio_pccard_detach),
474
475	{ 0, 0 }
476};
477
478static driver_t sio_pccard_driver = {
479	driver_name,
480	sio_pccard_methods,
481	sizeof(struct com_s),
482};
483#endif /* NCARD > 0 */
484
485#if NPCI > 0
486static device_method_t sio_pci_methods[] = {
487	/* Device interface */
488	DEVMETHOD(device_probe,		sio_pci_probe),
489	DEVMETHOD(device_attach,	sio_pci_attach),
490
491	{ 0, 0 }
492};
493
494static driver_t sio_pci_driver = {
495	driver_name,
496	sio_pci_methods,
497	sizeof(struct com_s),
498};
499#endif /* NPCI > 0 */
500
501static	d_open_t	sioopen;
502static	d_close_t	sioclose;
503static	d_read_t	sioread;
504static	d_write_t	siowrite;
505static	d_ioctl_t	sioioctl;
506
507#define	CDEV_MAJOR	28
508static struct cdevsw sio_cdevsw = {
509	/* open */	sioopen,
510	/* close */	sioclose,
511	/* read */	sioread,
512	/* write */	siowrite,
513	/* ioctl */	sioioctl,
514	/* poll */	ttypoll,
515	/* mmap */	nommap,
516	/* strategy */	nostrategy,
517	/* name */	driver_name,
518	/* maj */	CDEV_MAJOR,
519	/* dump */	nodump,
520	/* psize */	nopsize,
521	/* flags */	D_TTY,
522	/* bmaj */	-1
523};
524
525int	comconsole = -1;
526static	volatile speed_t	comdefaultrate = CONSPEED;
527#ifdef __alpha__
528static	volatile speed_t	gdbdefaultrate = CONSPEED;
529#endif
530static	u_int	com_events;	/* input chars + weighted output completions */
531static	Port_t	siocniobase;
532#ifndef __alpha__
533static	int	siocnunit;
534#endif
535static	Port_t	siogdbiobase;
536static	int	siogdbunit = -1;
537static	struct intrhand *sio_slow_ih;
538static	struct intrhand *sio_fast_ih;
539static	int	sio_timeout;
540static	int	sio_timeouts_until_log;
541static	struct	callout_handle sio_timeout_handle
542    = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
543static	int	sio_numunits;
544
545#ifdef PC98
546struct	siodev	{
547	short	if_type;
548	short	irq;
549	Port_t	cmd, sts, ctrl, mod;
550};
551static	int	sysclock;
552
553#define	COM_INT_DISABLE		{int previpri; previpri=spltty();
554#define	COM_INT_ENABLE		splx(previpri);}
555#define IEN_TxFLAG		IEN_Tx
556
557#define COM_CARRIER_DETECT_EMULATE	0
558#define	PC98_CHECK_MODEM_INTERVAL	(hz/10)
559#define DCD_OFF_TOLERANCE		2
560#define DCD_ON_RECOGNITION		2
561#define GET_IFTYPE(flags)		((flags >> 24) & 0x1f)
562#define SET_IFTYPE(type)		(type << 24)
563#define IS_8251(if_type)		(!(if_type & 0x10))
564#define COM1_EXT_CLOCK			0x40000
565
566static	void	commint		__P((dev_t dev));
567static	void	com_tiocm_set	__P((struct com_s *com, int msr));
568static	void	com_tiocm_bis	__P((struct com_s *com, int msr));
569static	void	com_tiocm_bic	__P((struct com_s *com, int msr));
570static	int	com_tiocm_get	__P((struct com_s *com));
571static	int	com_tiocm_get_delta	__P((struct com_s *com));
572static	void	pc98_msrint_start	__P((dev_t dev));
573static	void	com_cflag_and_speed_set	__P((struct com_s *com, int cflag, int speed));
574static	int	pc98_ttspeedtab		__P((struct com_s *com, int speed));
575static	int	pc98_get_modem_status	__P((struct com_s *com));
576static	timeout_t	pc98_check_msr;
577static	void	pc98_set_baud_rate	__P((struct com_s *com, int count));
578static	void	pc98_i8251_reset	__P((struct com_s *com, int mode, int command));
579static	void	pc98_disable_i8251_interrupt	__P((struct com_s *com, int mod));
580static	void	pc98_enable_i8251_interrupt	__P((struct com_s *com, int mod));
581static	int	pc98_check_i8251_interrupt	__P((struct com_s *com));
582static	int	pc98_i8251_get_cmd	__P((struct com_s *com));
583static	int	pc98_i8251_get_mod	__P((struct com_s *com));
584static	void	pc98_i8251_set_cmd	__P((struct com_s *com, int x));
585static	void	pc98_i8251_or_cmd	__P((struct com_s *com, int x));
586static	void	pc98_i8251_clear_cmd	__P((struct com_s *com, int x));
587static	void	pc98_i8251_clear_or_cmd	__P((struct com_s *com, int clr, int x));
588static	int	pc98_check_if_type	__P((device_t dev, struct siodev *iod));
589static	int	pc98_check_8251vfast	__P((void));
590static	int	pc98_check_8251fifo	__P((void));
591static	void	pc98_check_sysclock	__P((void));
592static	void	pc98_set_ioport		__P((struct com_s *com));
593
594#define com_int_Tx_disable(com) \
595		pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP)
596#define com_int_Tx_enable(com) \
597		pc98_enable_i8251_interrupt(com,IEN_TxFLAG)
598#define com_int_Rx_disable(com) \
599		pc98_disable_i8251_interrupt(com,IEN_Rx)
600#define com_int_Rx_enable(com) \
601		pc98_enable_i8251_interrupt(com,IEN_Rx)
602#define com_int_TxRx_disable(com) \
603		pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx)
604#define com_int_TxRx_enable(com) \
605		pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx)
606#define com_send_break_on(com) \
607		pc98_i8251_or_cmd(com,CMD8251_SBRK)
608#define com_send_break_off(com) \
609		pc98_i8251_clear_cmd(com,CMD8251_SBRK)
610
611static struct speedtab pc98speedtab[] = {	/* internal RS232C interface */
612	{ 0,		0, },
613	{ 50,		50, },
614	{ 75,		75, },
615	{ 150,		150, },
616	{ 200,		200, },
617	{ 300,		300, },
618	{ 600,		600, },
619	{ 1200,		1200, },
620	{ 2400,		2400, },
621	{ 4800,		4800, },
622	{ 9600,		9600, },
623	{ 19200,	19200, },
624	{ 38400,	38400, },
625	{ 51200,	51200, },
626	{ 76800,	76800, },
627	{ 20800,	20800, },
628	{ 31200,	31200, },
629	{ 41600,	41600, },
630	{ 62400,	62400, },
631	{ -1,		-1 }
632};
633static struct speedtab pc98fast_speedtab[] = {
634	{ 9600,		0x80 | COMBRD(9600), },
635	{ 19200,	0x80 | COMBRD(19200), },
636	{ 38400,	0x80 | COMBRD(38400), },
637	{ 57600,	0x80 | COMBRD(57600), },
638	{ 115200,	0x80 | COMBRD(115200), },
639	{ -1,		-1 }
640};
641static struct speedtab comspeedtab_pio9032b[] = {
642	{ 300,		6, },
643	{ 600,		5, },
644	{ 1200,		4, },
645	{ 2400,		3, },
646	{ 4800,		2, },
647	{ 9600,		1, },
648	{ 19200,	0, },
649	{ 38400,	7, },
650	{ -1,		-1 }
651};
652static struct speedtab comspeedtab_b98_01[] = {
653	{ 75,		11, },
654	{ 150,		10, },
655	{ 300,		9, },
656	{ 600,		8, },
657	{ 1200,		7, },
658	{ 2400,		6, },
659	{ 4800,		5, },
660	{ 9600,		4, },
661	{ 19200,	3, },
662	{ 38400,	2, },
663	{ 76800,	1, },
664	{ 153600,	0, },
665	{ -1,		-1 }
666};
667static struct speedtab comspeedtab_mc16550[] = {
668	{ 300,		1536, },
669	{ 600,		768, },
670	{ 1200,		384, },
671	{ 2400,		192, },
672	{ 4800,		96, },
673	{ 9600,		48, },
674	{ 19200,	24, },
675	{ 38400,	12, },
676	{ 57600,	8, },
677	{ 115200,	4, },
678	{ 153600,	3, },
679	{ 230400,	2, },
680	{ 460800,	1, },
681	{ -1,		-1 }
682};
683static struct speedtab comspeedtab_rsb384[] = {
684	{ 300,		3840, },
685	{ 600,		1920, },
686	{ 1200,		960, },
687	{ 2400,		480, },
688	{ 4800,		240, },
689	{ 9600,		120, },
690	{ 19200,	60, },
691	{ 38400,	30, },
692	{ 57600,	20, },
693	{ 115200,	10, },
694	{ 128000,	9, },
695	{ 144000,	8, },
696	{ 192000,	6, },
697	{ 230400,	5, },
698	{ 288000,	4, },
699	{ 384000,	3, },
700	{ 576000,	2, },
701	{ 1152000,	1, },
702	{ -1,		-1 }
703};
704static  struct speedtab comspeedtab_rsa[] = {
705        { 0,		0 },
706	{ 50,		COMBRD_RSA(50) },
707	{ 75,		COMBRD_RSA(75) },
708	{ 110,		COMBRD_RSA(110) },
709	{ 134,		COMBRD_RSA(134) },
710	{ 150,		COMBRD_RSA(150) },
711	{ 200,		COMBRD_RSA(200) },
712	{ 300,		COMBRD_RSA(300) },
713	{ 600,		COMBRD_RSA(600) },
714	{ 1200,		COMBRD_RSA(1200) },
715	{ 1800,		COMBRD_RSA(1800) },
716	{ 2400,		COMBRD_RSA(2400) },
717	{ 4800,		COMBRD_RSA(4800) },
718	{ 9600,		COMBRD_RSA(9600) },
719	{ 19200,	COMBRD_RSA(19200) },
720	{ 38400,	COMBRD_RSA(38400) },
721	{ 57600,	COMBRD_RSA(57600) },
722	{ 115200,	COMBRD_RSA(115200) },
723	{ 230400,	COMBRD_RSA(230400) },
724	{ 460800,	COMBRD_RSA(460800) },
725	{ 921600,	COMBRD_RSA(921600) },
726	{ -1,           -1 }
727};
728#endif /* PC98 */
729
730static	struct speedtab comspeedtab[] = {
731	{ 0,		0 },
732	{ 50,		COMBRD(50) },
733	{ 75,		COMBRD(75) },
734	{ 110,		COMBRD(110) },
735	{ 134,		COMBRD(134) },
736	{ 150,		COMBRD(150) },
737	{ 200,		COMBRD(200) },
738	{ 300,		COMBRD(300) },
739	{ 600,		COMBRD(600) },
740	{ 1200,		COMBRD(1200) },
741	{ 1800,		COMBRD(1800) },
742	{ 2400,		COMBRD(2400) },
743	{ 4800,		COMBRD(4800) },
744	{ 9600,		COMBRD(9600) },
745	{ 19200,	COMBRD(19200) },
746	{ 38400,	COMBRD(38400) },
747	{ 57600,	COMBRD(57600) },
748	{ 115200,	COMBRD(115200) },
749	{ -1,		-1 }
750};
751
752#ifdef PC98
753struct {
754	char	*name;
755	short	port_table[7];
756	short	irr_mask;
757	struct speedtab	*speedtab;
758	short	check_irq;
759} if_8251_type[] = {
760	/* COM_IF_INTERNAL */
761	{ " (internal)", {0x30, 0x32, 0x32, 0x33, 0x35, -1, -1},
762	     -1, pc98speedtab, 1 },
763	/* COM_IF_PC9861K_1 */
764	{ " (PC9861K)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, -1, -1},
765	     3, NULL, 1 },
766	/* COM_IF_PC9861K_2 */
767	{ " (PC9861K)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, -1, -1},
768	      3, NULL, 1 },
769	/* COM_IF_IND_SS_1 */
770	{ " (IND-SS)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb3, -1},
771	     3, comspeedtab_mc16550, 1 },
772	/* COM_IF_IND_SS_2 */
773	{ " (IND-SS)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xbb, -1},
774	     3, comspeedtab_mc16550, 1 },
775	/* COM_IF_PIO9032B_1 */
776	{ " (PIO9032B)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb8, -1},
777	      7, comspeedtab_pio9032b, 1 },
778	/* COM_IF_PIO9032B_2 */
779	{ " (PIO9032B)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xba, -1},
780	      7, comspeedtab_pio9032b, 1 },
781	/* COM_IF_B98_01_1 */
782	{ " (B98-01)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xd1, 0xd3},
783	      7, comspeedtab_b98_01, 0 },
784	/* COM_IF_B98_01_2 */
785	{ " (B98-01)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xd5, 0xd7},
786	     7, comspeedtab_b98_01, 0 },
787};
788#define	PC98SIO_data_port(type)		(if_8251_type[type].port_table[0])
789#define	PC98SIO_cmd_port(type)		(if_8251_type[type].port_table[1])
790#define	PC98SIO_sts_port(type)		(if_8251_type[type].port_table[2])
791#define	PC98SIO_in_modem_port(type)	(if_8251_type[type].port_table[3])
792#define	PC98SIO_intr_ctrl_port(type)	(if_8251_type[type].port_table[4])
793#define	PC98SIO_baud_rate_port(type)	(if_8251_type[type].port_table[5])
794#define	PC98SIO_func_port(type)		(if_8251_type[type].port_table[6])
795
796#define	I8251F_data		0x130
797#define	I8251F_lsr		0x132
798#define	I8251F_msr		0x134
799#define	I8251F_iir		0x136
800#define	I8251F_fcr		0x138
801#define	I8251F_div		0x13a
802
803
804static bus_addr_t port_table_0[] =
805	{0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007};
806static bus_addr_t port_table_1[] =
807	{0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e};
808static bus_addr_t port_table_8[] =
809	{0x000, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700};
810static bus_addr_t port_table_rsa[] = {
811	0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
812	0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007
813};
814
815struct {
816	char		*name;
817	short		irr_read;
818	short		irr_write;
819	bus_addr_t	*iat;
820	bus_size_t	iatsz;
821	struct speedtab	*speedtab;
822} if_16550a_type[] = {
823	/* COM_IF_RSA98 */
824	{" (RSA-98)", -1, -1, port_table_0, IO_COMSIZE, comspeedtab},
825	/* COM_IF_NS16550 */
826	{"", -1, -1, port_table_0, IO_COMSIZE, comspeedtab},
827	/* COM_IF_SECOND_CCU */
828	{"", -1, -1, port_table_0, IO_COMSIZE, comspeedtab},
829	/* COM_IF_MC16550II */
830	{" (MC16550II)", -1, 0x1000, port_table_8, IO_COMSIZE,
831	 comspeedtab_mc16550},
832	/* COM_IF_MCRS98 */
833	{" (MC-RS98)", -1, 0x1000, port_table_8, IO_COMSIZE,
834	 comspeedtab_mc16550},
835	/* COM_IF_RSB3000 */
836	{" (RSB-3000)", 0xbf, -1, port_table_1, IO_COMSIZE,
837	 comspeedtab_rsb384},
838	/* COM_IF_RSB384 */
839	{" (RSB-384)", 0xbf, -1, port_table_1, IO_COMSIZE, comspeedtab_rsb384},
840	/* COM_IF_MODEM_CARD */
841	{"", -1, -1, port_table_0, IO_COMSIZE, comspeedtab},
842	/* COM_IF_RSA98III */
843	{" (RSA-98III)", -1, -1, port_table_rsa, 16, comspeedtab_rsa},
844	/* COM_IF_ESP98 */
845	{" (ESP98)", -1, -1, port_table_1, IO_COMSIZE, comspeedtab_mc16550},
846};
847#endif /* PC98 */
848
849#ifdef COM_ESP
850#ifdef PC98
851
852/* XXX configure this properly. */
853static  Port_t  likely_com_ports[] = { 0, 0xb0, 0xb1, 0 };
854static  Port_t  likely_esp_ports[] = { 0xc0d0, 0 };
855
856#define	ESP98_CMD1	(ESP_CMD1 * 0x100)
857#define	ESP98_CMD2	(ESP_CMD2 * 0x100)
858#define	ESP98_STATUS1	(ESP_STATUS1 * 0x100)
859#define	ESP98_STATUS2	(ESP_STATUS2 * 0x100)
860
861#else /* PC98 */
862
863/* XXX configure this properly. */
864static	Port_t	likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
865static	Port_t	likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
866
867#endif /* PC98 */
868#endif
869
870/*
871 * handle sysctl read/write requests for console speed
872 *
873 * In addition to setting comdefaultrate for I/O through /dev/console,
874 * also set the initial and lock values for the /dev/ttyXX device
875 * if there is one associated with the console.  Finally, if the /dev/tty
876 * device has already been open, change the speed on the open running port
877 * itself.
878 */
879
880static int
881sysctl_machdep_comdefaultrate(SYSCTL_HANDLER_ARGS)
882{
883	int error, s;
884	speed_t newspeed;
885	struct com_s *com;
886	struct tty *tp;
887
888	newspeed = comdefaultrate;
889
890	error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
891	if (error || !req->newptr)
892		return (error);
893
894	comdefaultrate = newspeed;
895
896	if (comconsole < 0)		/* serial console not selected? */
897		return (0);
898
899	com = com_addr(comconsole);
900	if (com == NULL)
901		return (ENXIO);
902
903	/*
904	 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
905	 * (note, the lock rates really are boolean -- if non-zero, disallow
906	 *  speed changes)
907	 */
908	com->it_in.c_ispeed  = com->it_in.c_ospeed =
909	com->lt_in.c_ispeed  = com->lt_in.c_ospeed =
910	com->it_out.c_ispeed = com->it_out.c_ospeed =
911	com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
912
913	/*
914	 * if we're open, change the running rate too
915	 */
916	tp = com->tp;
917	if (tp && (tp->t_state & TS_ISOPEN)) {
918		tp->t_termios.c_ispeed =
919		tp->t_termios.c_ospeed = comdefaultrate;
920		s = spltty();
921		error = comparam(tp, &tp->t_termios);
922		splx(s);
923	}
924	return error;
925}
926
927SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
928	    0, 0, sysctl_machdep_comdefaultrate, "I", "");
929
930#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
931#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
932
933#if NCARD > 0
934static int
935sio_pccard_probe(dev)
936	device_t	dev;
937{
938	/* Do not probe IRQ - pccard doesn't turn on the interrupt line */
939	/* until bus_setup_intr */
940	SET_FLAG(dev, COM_C_NOPROBE);
941
942	return (sioprobe(dev, 0));
943}
944
945static int
946sio_pccard_attach(dev)
947	device_t	dev;
948{
949	return (sioattach(dev, 0));
950}
951
952/*
953 *	sio_detach - unload the driver and clear the table.
954 *	XXX TODO:
955 *	This is usually called when the card is ejected, but
956 *	can be caused by a modunload of a controller driver.
957 *	The idea is to reset the driver's view of the device
958 *	and ensure that any driver entry points such as
959 *	read and write do not hang.
960 */
961static int
962sio_pccard_detach(dev)
963	device_t	dev;
964{
965	struct com_s	*com;
966	int i;
967
968	com = (struct com_s *) device_get_softc(dev);
969	if (com == NULL) {
970		device_printf(dev, "NULL com in siounload\n");
971		return (0);
972	}
973	com->gone = 1;
974	for (i = 0 ; i < 6; i++)
975		destroy_dev(com->devs[i]);
976	if (com->irqres) {
977		bus_teardown_intr(dev, com->irqres, com->cookie);
978		bus_release_resource(dev, SYS_RES_IRQ, 0, com->irqres);
979	}
980	if (com->ioportres)
981		bus_release_resource(dev, SYS_RES_IOPORT, 0, com->ioportres);
982	if (com->tp && (com->tp->t_state & TS_ISOPEN)) {
983		device_printf(dev, "still open, forcing close\n");
984		com->tp->t_gen++;
985		ttyclose(com->tp);
986		ttwakeup(com->tp);
987		ttwwakeup(com->tp);
988	} else {
989		if (com->ibuf != NULL)
990			free(com->ibuf, M_DEVBUF);
991	}
992	device_printf(dev, "unloaded\n");
993	return (0);
994}
995#endif /* NCARD > 0 */
996
997#if NPCI > 0
998struct pci_ids {
999	u_int32_t	type;
1000	const char	*desc;
1001	int		rid;
1002};
1003
1004static struct pci_ids pci_ids[] = {
1005	{ 0x100812b9, "3COM PCI FaxModem", 0x10 },
1006	{ 0x048011c1, "ActionTec 56k FAX PCI Modem", 0x14 },
1007	{ 0x00000000, NULL, 0 }
1008};
1009
1010static int
1011sio_pci_attach(dev)
1012	device_t	dev;
1013{
1014	u_int32_t	type;
1015	struct pci_ids	*id;
1016
1017	type = pci_get_devid(dev);
1018	id = pci_ids;
1019	while (id->type && id->type != type)
1020		id++;
1021	if (id->desc == NULL)
1022		return (ENXIO);
1023	sio_pci_kludge_unit(dev);
1024	return (sioattach(dev, id->rid));
1025}
1026
1027/*
1028 * Don't cut and paste this to other drivers.  It is a horrible kludge
1029 * which will fail to work and also be unnecessary in future versions.
1030 */
1031static void
1032sio_pci_kludge_unit(dev)
1033	device_t dev;
1034{
1035	devclass_t	dc;
1036	int		err;
1037	int		start;
1038	int		unit;
1039
1040	unit = 0;
1041	start = 0;
1042	while (resource_int_value("sio", unit, "port", &start) == 0 &&
1043	    start > 0)
1044		unit++;
1045	if (device_get_unit(dev) < unit) {
1046		dc = device_get_devclass(dev);
1047		while (devclass_get_device(dc, unit))
1048			unit++;
1049		device_printf(dev, "moving to sio%d\n", unit);
1050		err = device_set_unit(dev, unit);	/* EVIL DO NOT COPY */
1051		if (err)
1052			device_printf(dev, "error moving device %d\n", err);
1053	}
1054}
1055
1056static int
1057sio_pci_probe(dev)
1058	device_t	dev;
1059{
1060	u_int32_t	type;
1061	struct pci_ids	*id;
1062
1063	type = pci_get_devid(dev);
1064	id = pci_ids;
1065	while (id->type && id->type != type)
1066		id++;
1067	if (id->desc == NULL)
1068		return (ENXIO);
1069	device_set_desc(dev, id->desc);
1070	return (sioprobe(dev, id->rid));
1071}
1072#endif /* NPCI > 0 */
1073
1074static struct isa_pnp_id sio_ids[] = {
1075	{0x0005d041, "Standard PC COM port"},	/* PNP0500 */
1076	{0x0105d041, "16550A-compatible COM port"},	/* PNP0501 */
1077	{0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */
1078	{0x1005d041, "Generic IRDA-compatible device"},	/* PNP0510 */
1079	{0x1105d041, "Generic IRDA-compatible device"},	/* PNP0511 */
1080	/* Devices that do not have a compatid */
1081	{0x7602a904, NULL},	/* AEI0276 - 56K v.90 Fax Modem (LKT) */
1082	{0x00007905, NULL},	/* AKY0000 - 56K Plug&Play Modem */
1083	{0x01405407, NULL},	/* AZT4001 - AZT3000 PnP SOUND DEVICE, MODEM */
1084	{0x56039008, NULL},	/* BDP0356 - Best Data 56x2 */
1085	{0x36339008, NULL},	/* BDP3336 - Best Data Prods. 336F */
1086	{0x0014490a, NULL},	/* BRI1400 - Boca 33.6 PnP */
1087	{0x0015490a, NULL},	/* BRI1500 - Internal Fax Data */
1088	{0x0034490a, NULL},	/* BRI3400 - Internal ACF Modem */
1089	{0x0094490a, NULL},	/* BRI9400 - Boca K56Flex PnP */
1090	{0x00b4490a, NULL},	/* BRIB400 - Boca 56k PnP */
1091	{0x0030320d, NULL},	/* CIR3000 - Cirrus Logic V43 */
1092	{0x0100440e, NULL},	/* CRD0001 - Cardinal MVP288IV ? */
1093	{0x1200c31e, NULL},	/* GVC0012 - VF1128HV-R9 (win modem?) */
1094	{0x0303c31e, NULL},	/* GVC0303 - MaxTech 33.6 PnP D/F/V */
1095	{0x0505c31e, NULL},	/* GVC0505 - GVC 56k Faxmodem */
1096	{0x0050c31e, NULL},	/* GVC5000 - some GVC modem */
1097	{0x3800f91e, NULL},	/* GWY0038 - Telepath with v.90 */
1098	{0x9062f91e, NULL},	/* GWY6290 - Telepath with x2 Technology */
1099	{0x0000f435, NULL},	/* MOT0000 - Motorola ModemSURFR 33.6 Intern */
1100	{0x5015f435, NULL},	/* MOT1550 - Motorola ModemSURFR 56K Modem */
1101	{0xf015f435, NULL},	/* MOT15F0 - Motorola VoiceSURFR 56K Modem */
1102	{0x6045f435, NULL},	/* MOT4560 - Motorola ? */
1103	{0x61e7a338, NULL},	/* NECE761 - 33.6Modem */
1104	{0x39804f3f, NULL},	/* OZO8039 - Zoom 56k flex */
1105	{0x3024a341, NULL},	/* PMC2430 - Pace 56 Voice Internal Modem */
1106	{0x1000eb49, NULL},	/* ROK0010 - Rockwell ? */
1107	{0x5002734a, NULL},	/* RSS0250 - 5614Jx3(G) Internal Modem */
1108	{0xc100ad4d, NULL},	/* SMM00C1 - Leopard 56k PnP */
1109	{0x9012b04e, NULL},	/* SUP1290 - Supra ? */
1110	{0x1013b04e, NULL},	/* SUP1310 - SupraExpress 336i PnP */
1111	{0x8013b04e, NULL},	/* SUP1380 - SupraExpress 288i PnP Voice */
1112	{0x8113b04e, NULL},	/* SUP1381 - SupraExpress 336i PnP Voice */
1113	{0x5016b04e, NULL},	/* SUP1650 - Supra 336i Sp Intl */
1114	{0x7420b04e, NULL},	/* SUP2070 - Supra ? */
1115	{0x8020b04e, NULL},	/* SUP2080 - Supra ? */
1116	{0x8420b04e, NULL},	/* SUP2084 - SupraExpress 56i PnP */
1117	{0x7121b04e, NULL},	/* SUP2171 - SupraExpress 56i Sp? */
1118	{0x8024b04e, NULL},	/* SUP2480 - Supra ? */
1119	{0x01007256, NULL},	/* USR0001 - U.S. Robotics Inc., Sportster W */
1120	{0x02007256, NULL},	/* USR0002 - U.S. Robotics Inc. Sportster 33. */
1121	{0x04007256, NULL},	/* USR0004 - USR Sportster 14.4k */
1122	{0x06007256, NULL},	/* USR0006 - USR Sportster 33.6k */
1123	{0x11007256, NULL},	/* USR0011 - USR ? */
1124	{0x01017256, NULL},	/* USR0101 - USR ? */
1125	{0x30207256, NULL},	/* USR2030 - U.S.Robotics Inc. Sportster 560 */
1126	{0x50207256, NULL},	/* USR2050 - U.S.Robotics Inc. Sportster 33. */
1127	{0x70207256, NULL},	/* USR2070 - U.S.Robotics Inc. Sportster 560 */
1128	{0x30307256, NULL},	/* USR3030 - U.S. Robotics 56K FAX INT */
1129	{0x31307256, NULL},	/* USR3031 - U.S. Robotics 56K FAX INT */
1130	{0x50307256, NULL},	/* USR3050 - U.S. Robotics 56K FAX INT */
1131	{0x70307256, NULL},	/* USR3070 - U.S. Robotics 56K Voice INT */
1132	{0x90307256, NULL},	/* USR3090 - USR ? */
1133	{0x90917256, NULL},	/* USR9190 - USR 56k Voice INT */
1134	{0x0300695c, NULL},	/* WCI0003 - Fax/Voice/Modem/Speakphone/Asvd */
1135	{0x01a0896a, NULL},	/* ZTIA001 - Zoom Internal V90 Faxmodem */
1136	{0x61f7896a, NULL},	/* ZTIF761 - Zoom ComStar 33.6 */
1137#ifdef PC98
1138	{0x0100e4a5, "RSA-98III"},
1139#endif
1140	{0}
1141};
1142
1143
1144
1145static int
1146sio_isa_probe(dev)
1147	device_t	dev;
1148{
1149#ifdef PC98
1150	int	logical_id;
1151#endif
1152	/* Check isapnp ids */
1153	if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO)
1154		return (ENXIO);
1155#ifdef PC98
1156	logical_id = isa_get_logicalid(dev);
1157	if (logical_id == 0x0100e4a5)		/* RSA-98III */
1158		device_set_flags(dev, SET_IFTYPE(COM_IF_RSA98III));
1159#endif
1160	return (sioprobe(dev, 0));
1161}
1162
1163static int
1164sioprobe(dev, xrid)
1165	device_t	dev;
1166	int		xrid;
1167{
1168#if 0
1169	static bool_t	already_init;
1170	device_t	xdev;
1171#endif
1172	struct com_s	*com;
1173	bool_t		failures[10];
1174	int		fn;
1175	device_t	idev;
1176	Port_t		iobase;
1177	intrmask_t	irqmap[4];
1178	intrmask_t	irqs;
1179	u_char		mcr_image;
1180	int		result;
1181	u_long		xirq;
1182	u_int		flags = device_get_flags(dev);
1183	int		rid;
1184	struct resource *port;
1185	int		intrsave;
1186#ifdef PC98
1187	int		tmp;
1188	struct siodev	iod;
1189#endif
1190
1191#ifdef PC98
1192	iod.if_type = GET_IFTYPE(flags);
1193	if ((iod.if_type < 0 || iod.if_type > COM_IF_END1) &&
1194	    (iod.if_type < 0x10 || iod.if_type > COM_IF_END2))
1195		return ENXIO;
1196#endif
1197
1198	rid = xrid;
1199#ifdef PC98
1200	if (IS_8251(iod.if_type)) {
1201		port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1202					  0, ~0, 1, RF_ACTIVE);
1203	} else if (iod.if_type == COM_IF_RSA98III ||
1204		   isa_get_vendorid(dev)) {
1205		port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
1206			if_16550a_type[iod.if_type & 0x0f].iatsz, RF_ACTIVE);
1207	} else {
1208		port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
1209			if_16550a_type[iod.if_type & 0x0f].iat,
1210			if_16550a_type[iod.if_type & 0x0f].iatsz, RF_ACTIVE);
1211	}
1212#else
1213	port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1214				  0, ~0, IO_COMSIZE, RF_ACTIVE);
1215#endif
1216	if (!port)
1217		return (ENXIO);
1218#ifdef PC98
1219	if (!IS_8251(iod.if_type)) {
1220		if (isa_load_resourcev(port,
1221			if_16550a_type[iod.if_type & 0x0f].iat,
1222			if_16550a_type[iod.if_type & 0x0f].iatsz) != 0) {
1223		    bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1224		    return ENXIO;
1225		}
1226	}
1227#endif
1228
1229	com = device_get_softc(dev);
1230	com->bst = rman_get_bustag(port);
1231	com->bsh = rman_get_bushandle(port);
1232
1233#if 0
1234	/*
1235	 * XXX this is broken - when we are first called, there are no
1236	 * previously configured IO ports.  We could hard code
1237	 * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
1238	 * This code has been doing nothing since the conversion since
1239	 * "count" is zero the first time around.
1240	 */
1241	if (!already_init) {
1242		/*
1243		 * Turn off MCR_IENABLE for all likely serial ports.  An unused
1244		 * port with its MCR_IENABLE gate open will inhibit interrupts
1245		 * from any used port that shares the interrupt vector.
1246		 * XXX the gate enable is elsewhere for some multiports.
1247		 */
1248		device_t *devs;
1249		int count, i, xioport;
1250#ifdef PC98
1251		int xiftype;
1252#endif
1253
1254		devclass_get_devices(sio_devclass, &devs, &count);
1255#ifdef PC98
1256		for (i = 0; i < count; i++) {
1257			xdev = devs[i];
1258			xioport = bus_get_resource_start(xdev, SYS_RES_IOPORT, 0);
1259			xiftype = GET_IFTYPE(device_get_flags(xdev));
1260			if (device_is_enabled(xdev) && xioport > 0) {
1261			    if (IS_8251(xiftype))
1262				outb((xioport & 0xff00) | PC98SIO_cmd_port(xiftype & 0x0f), 0xf2);
1263			    else
1264				outb(xioport + if_16550a_type[xiftype & 0x0f].iat[com_mcr], 0);
1265			}
1266		}
1267#else
1268		for (i = 0; i < count; i++) {
1269			xdev = devs[i];
1270			if (device_is_enabled(xdev) &&
1271			    bus_get_resource(xdev, SYS_RES_IOPORT, 0, &xioport,
1272					     NULL) == 0)
1273				outb(xioport + com_mcr, 0);
1274		}
1275#endif
1276		free(devs, M_TEMP);
1277		already_init = TRUE;
1278	}
1279#endif
1280
1281	if (COM_LLCONSOLE(flags)) {
1282		printf("sio%d: reserved for low-level i/o\n",
1283		       device_get_unit(dev));
1284		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1285		return (ENXIO);
1286	}
1287
1288#ifdef PC98
1289	DELAY(10);
1290
1291	/*
1292	 * If the port is i8251 UART (internal, B98_01)
1293	 */
1294	if (pc98_check_if_type(dev, &iod) == -1) {
1295		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1296		return (ENXIO);
1297	}
1298	if (iod.irq > 0)
1299		bus_set_resource(dev, SYS_RES_IRQ, 0, iod.irq, 1);
1300	if (IS_8251(iod.if_type)) {
1301		outb(iod.cmd, 0);
1302		DELAY(10);
1303		outb(iod.cmd, 0);
1304		DELAY(10);
1305		outb(iod.cmd, 0);
1306		DELAY(10);
1307		outb(iod.cmd, CMD8251_RESET);
1308		DELAY(1000);		/* for a while...*/
1309		outb(iod.cmd, 0xf2);	/* MODE (dummy) */
1310		DELAY(10);
1311		outb(iod.cmd, 0x01);	/* CMD (dummy) */
1312		DELAY(1000);		/* for a while...*/
1313		if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) {
1314		    result = (ENXIO);
1315		}
1316		if (if_8251_type[iod.if_type & 0x0f].check_irq) {
1317		    COM_INT_DISABLE
1318		    tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx));
1319		    outb( iod.ctrl, tmp|IEN_TxEMP );
1320		    DELAY(10);
1321		    result = isa_irq_pending() ? 0 : ENXIO;
1322		    outb( iod.ctrl, tmp );
1323		    COM_INT_ENABLE
1324		} else {
1325		    /*
1326		     * B98_01 doesn't activate TxEMP interrupt line
1327		     * when being reset, so we can't check irq pending.
1328		     */
1329		    result = 0;
1330		}
1331		if (epson_machine_id==0x20) {	/* XXX */
1332		    result = 0;
1333		}
1334		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1335		return result;
1336	}
1337#endif /* PC98 */
1338	/*
1339	 * If the device is on a multiport card and has an AST/4
1340	 * compatible interrupt control register, initialize this
1341	 * register and prepare to leave MCR_IENABLE clear in the mcr.
1342	 * Otherwise, prepare to set MCR_IENABLE in the mcr.
1343	 * Point idev to the device struct giving the correct id_irq.
1344	 * This is the struct for the master device if there is one.
1345	 */
1346	idev = dev;
1347	mcr_image = MCR_IENABLE;
1348#ifdef COM_MULTIPORT
1349	if (COM_ISMULTIPORT(flags)) {
1350#ifndef PC98
1351		Port_t xiobase;
1352		u_long io;
1353#endif
1354
1355		idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags));
1356		if (idev == NULL) {
1357			printf("sio%d: master device %d not configured\n",
1358			       device_get_unit(dev), COM_MPMASTER(flags));
1359			idev = dev;
1360		}
1361#ifndef PC98
1362		if (!COM_NOTAST4(flags)) {
1363			if (bus_get_resource(idev, SYS_RES_IOPORT, 0, &io,
1364					     NULL) == 0) {
1365				xiobase = io;
1366				if (bus_get_resource(idev, SYS_RES_IRQ, 0,
1367				    NULL, NULL) == 0)
1368					outb(xiobase + com_scr, 0x80);
1369				else
1370					outb(xiobase + com_scr, 0);
1371			}
1372			mcr_image = 0;
1373		}
1374#endif
1375	}
1376#endif /* COM_MULTIPORT */
1377	if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) != 0)
1378		mcr_image = 0;
1379
1380	bzero(failures, sizeof failures);
1381	iobase = rman_get_start(port);
1382
1383#ifdef PC98
1384        if (iod.if_type == COM_IF_RSA98III) {
1385		mcr_image = 0;
1386
1387		outb(iobase + rsa_msr,   0x04);
1388		outb(iobase + rsa_frr,   0x00);
1389		if ((inb(iobase + rsa_srr) & 0x36) != 0x36) {
1390			bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1391			return (ENXIO);
1392		}
1393		outb(iobase + rsa_ier,   0x00);
1394		outb(iobase + rsa_frr,   0x00);
1395		outb(iobase + rsa_tivsr, 0x00);
1396		outb(iobase + rsa_tcr,   0x00);
1397	}
1398
1399	tmp = if_16550a_type[iod.if_type & 0x0f].irr_write;
1400	if (tmp != -1) {
1401	    /* MC16550II */
1402	    int	irqout;
1403	    switch (isa_get_irq(idev)) {
1404	    case 3: irqout = 4; break;
1405	    case 5: irqout = 5; break;
1406	    case 6: irqout = 6; break;
1407	    case 12: irqout = 7; break;
1408	    default:
1409		printf("sio%d: irq configuration error\n",
1410		       device_get_unit(dev));
1411		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1412		return (ENXIO);
1413	    }
1414	    outb((iobase & 0x00ff) | tmp, irqout);
1415	}
1416#endif
1417
1418	/*
1419	 * We don't want to get actual interrupts, just masked ones.
1420	 * Interrupts from this line should already be masked in the ICU,
1421	 * but mask them in the processor as well in case there are some
1422	 * (misconfigured) shared interrupts.
1423	 */
1424	intrsave = save_intr();
1425	disable_intr();
1426	COM_LOCK();
1427/* EXTRA DELAY? */
1428
1429	/*
1430	 * Initialize the speed and the word size and wait long enough to
1431	 * drain the maximum of 16 bytes of junk in device output queues.
1432	 * The speed is undefined after a master reset and must be set
1433	 * before relying on anything related to output.  There may be
1434	 * junk after a (very fast) soft reboot and (apparently) after
1435	 * master reset.
1436	 * XXX what about the UART bug avoided by waiting in comparam()?
1437	 * We don't want to to wait long enough to drain at 2 bps.
1438	 */
1439	if (iobase == siocniobase)
1440		DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
1441	else {
1442#ifdef PC98
1443		tmp = ttspeedtab(SIO_TEST_SPEED,
1444				 if_16550a_type[iod.if_type & 0x0f].speedtab);
1445		sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS);
1446		sio_setreg(com, com_dlbl, tmp & 0xff);
1447		sio_setreg(com, com_dlbh, (tmp >> 8) & 0xff);
1448		sio_setreg(com, com_cfcr, CFCR_8BITS);
1449#else
1450		sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS);
1451		sio_setreg(com, com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff);
1452		sio_setreg(com, com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8);
1453		sio_setreg(com, com_cfcr, CFCR_8BITS);
1454#endif
1455		DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
1456	}
1457
1458	/*
1459	 * Enable the interrupt gate and disable device interupts.  This
1460	 * should leave the device driving the interrupt line low and
1461	 * guarantee an edge trigger if an interrupt can be generated.
1462	 */
1463/* EXTRA DELAY? */
1464	sio_setreg(com, com_mcr, mcr_image);
1465	sio_setreg(com, com_ier, 0);
1466	DELAY(1000);		/* XXX */
1467	irqmap[0] = isa_irq_pending();
1468
1469	/*
1470	 * Attempt to set loopback mode so that we can send a null byte
1471	 * without annoying any external device.
1472	 */
1473/* EXTRA DELAY? */
1474	sio_setreg(com, com_mcr, mcr_image | MCR_LOOPBACK);
1475
1476	/*
1477	 * Attempt to generate an output interrupt.  On 8250's, setting
1478	 * IER_ETXRDY generates an interrupt independent of the current
1479	 * setting and independent of whether the THR is empty.  On 16450's,
1480	 * setting IER_ETXRDY generates an interrupt independent of the
1481	 * current setting.  On 16550A's, setting IER_ETXRDY only
1482	 * generates an interrupt when IER_ETXRDY is not already set.
1483	 */
1484	sio_setreg(com, com_ier, IER_ETXRDY);
1485#ifdef PC98
1486        if (iod.if_type == COM_IF_RSA98III)
1487		outb(iobase + rsa_ier, 0x04);
1488#endif
1489
1490	/*
1491	 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
1492	 * an interrupt.  They'd better generate one for actually doing
1493	 * output.  Loopback may be broken on the same incompatibles but
1494	 * it's unlikely to do more than allow the null byte out.
1495	 */
1496	sio_setreg(com, com_data, 0);
1497	DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
1498
1499	/*
1500	 * Turn off loopback mode so that the interrupt gate works again
1501	 * (MCR_IENABLE was hidden).  This should leave the device driving
1502	 * an interrupt line high.  It doesn't matter if the interrupt
1503	 * line oscillates while we are not looking at it, since interrupts
1504	 * are disabled.
1505	 */
1506/* EXTRA DELAY? */
1507	sio_setreg(com, com_mcr, mcr_image);
1508
1509	/*
1510	 * Some pcmcia cards have the "TXRDY bug", so we check everyone
1511	 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
1512	 */
1513	if (COM_NOPROBE(flags)) {
1514		/* Reading IIR register twice */
1515		for (fn = 0; fn < 2; fn ++) {
1516			DELAY(10000);
1517			failures[6] = sio_getreg(com, com_iir);
1518		}
1519		/* Check IIR_TXRDY clear ? */
1520		result = 0;
1521		if (failures[6] & IIR_TXRDY) {
1522			/* Nop, Double check with clearing IER */
1523			sio_setreg(com, com_ier, 0);
1524			if (sio_getreg(com, com_iir) & IIR_NOPEND) {
1525				/* Ok. we're familia this gang */
1526				SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
1527			} else {
1528				/* Unknown, Just omit this chip.. XXX */
1529				result = ENXIO;
1530			}
1531		} else {
1532			/* OK. this is well-known guys */
1533			CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
1534		}
1535		sio_setreg(com, com_cfcr, CFCR_8BITS);
1536		COM_UNLOCK();
1537		restore_intr(intrsave);
1538		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1539		return (iobase == siocniobase ? 0 : result);
1540	}
1541
1542	/*
1543	 * Check that
1544	 *	o the CFCR, IER and MCR in UART hold the values written to them
1545	 *	  (the values happen to be all distinct - this is good for
1546	 *	  avoiding false positive tests from bus echoes).
1547	 *	o an output interrupt is generated and its vector is correct.
1548	 *	o the interrupt goes away when the IIR in the UART is read.
1549	 */
1550/* EXTRA DELAY? */
1551	failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
1552	failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
1553	failures[2] = sio_getreg(com, com_mcr) - mcr_image;
1554	DELAY(10000);		/* Some internal modems need this time */
1555	irqmap[1] = isa_irq_pending();
1556	failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY;
1557#ifdef PC98
1558        if (iod.if_type == COM_IF_RSA98III)
1559		inb(iobase + rsa_srr);
1560#endif
1561	DELAY(1000);		/* XXX */
1562	irqmap[2] = isa_irq_pending();
1563	failures[6] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
1564#ifdef PC98
1565        if (iod.if_type == COM_IF_RSA98III)
1566		inb(iobase + rsa_srr);
1567#endif
1568
1569	/*
1570	 * Turn off all device interrupts and check that they go off properly.
1571	 * Leave MCR_IENABLE alone.  For ports without a master port, it gates
1572	 * the OUT2 output of the UART to
1573	 * the ICU input.  Closing the gate would give a floating ICU input
1574	 * (unless there is another device driving it) and spurious interrupts.
1575	 * (On the system that this was first tested on, the input floats high
1576	 * and gives a (masked) interrupt as soon as the gate is closed.)
1577	 */
1578	sio_setreg(com, com_ier, 0);
1579	sio_setreg(com, com_cfcr, CFCR_8BITS);	/* dummy to avoid bus echo */
1580	failures[7] = sio_getreg(com, com_ier);
1581#ifdef PC98
1582        if (iod.if_type == COM_IF_RSA98III)
1583		outb(iobase + rsa_ier, 0x00);
1584#endif
1585	DELAY(1000);		/* XXX */
1586	irqmap[3] = isa_irq_pending();
1587	failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
1588#ifdef PC98
1589        if (iod.if_type == COM_IF_RSA98III) {
1590		inb(iobase + rsa_srr);
1591		outb(iobase + rsa_frr, 0x00);
1592	}
1593#endif
1594
1595	COM_UNLOCK();
1596	restore_intr(intrsave);
1597
1598	irqs = irqmap[1] & ~irqmap[0];
1599	if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
1600	    ((1 << xirq) & irqs) == 0)
1601		printf(
1602		"sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
1603		    device_get_unit(dev), xirq, irqs);
1604	if (bootverbose)
1605		printf("sio%d: irq maps: %#x %#x %#x %#x\n",
1606		    device_get_unit(dev),
1607		    irqmap[0], irqmap[1], irqmap[2], irqmap[3]);
1608
1609	result = 0;
1610	for (fn = 0; fn < sizeof failures; ++fn)
1611		if (failures[fn]) {
1612			sio_setreg(com, com_mcr, 0);
1613			result = ENXIO;
1614			if (bootverbose) {
1615				printf("sio%d: probe failed test(s):",
1616				    device_get_unit(dev));
1617				for (fn = 0; fn < sizeof failures; ++fn)
1618					if (failures[fn])
1619						printf(" %d", fn);
1620				printf("\n");
1621			}
1622			break;
1623		}
1624	bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1625	return (iobase == siocniobase ? 0 : result);
1626}
1627
1628#ifdef COM_ESP
1629static int
1630espattach(com, esp_port)
1631	struct com_s		*com;
1632	Port_t			esp_port;
1633{
1634	u_char	dips;
1635	u_char	val;
1636
1637	/*
1638	 * Check the ESP-specific I/O port to see if we're an ESP
1639	 * card.  If not, return failure immediately.
1640	 */
1641	if ((inb(esp_port) & 0xf3) == 0) {
1642		printf(" port 0x%x is not an ESP board?\n", esp_port);
1643		return (0);
1644	}
1645
1646	/*
1647	 * We've got something that claims to be a Hayes ESP card.
1648	 * Let's hope so.
1649	 */
1650
1651	/* Get the dip-switch configuration */
1652#ifdef PC98
1653	outb(esp_port + ESP98_CMD1, ESP_GETDIPS);
1654	dips = inb(esp_port + ESP98_STATUS1);
1655#else
1656	outb(esp_port + ESP_CMD1, ESP_GETDIPS);
1657	dips = inb(esp_port + ESP_STATUS1);
1658#endif
1659
1660	/*
1661	 * Bits 0,1 of dips say which COM port we are.
1662	 */
1663#ifdef PC98
1664	if ((rman_get_start(com->ioportres) & 0xff) ==
1665	    likely_com_ports[dips & 0x03])
1666#else
1667	if (rman_get_start(com->ioportres) == likely_com_ports[dips & 0x03])
1668#endif
1669		printf(" : ESP");
1670	else {
1671		printf(" esp_port has com %d\n", dips & 0x03);
1672		return (0);
1673	}
1674
1675	/*
1676	 * Check for ESP version 2.0 or later:  bits 4,5,6 = 010.
1677	 */
1678#ifdef PC98
1679	outb(esp_port + ESP98_CMD1, ESP_GETTEST);
1680	val = inb(esp_port + ESP98_STATUS1);	/* clear reg 1 */
1681	val = inb(esp_port + ESP98_STATUS2);
1682#else
1683	outb(esp_port + ESP_CMD1, ESP_GETTEST);
1684	val = inb(esp_port + ESP_STATUS1);	/* clear reg 1 */
1685	val = inb(esp_port + ESP_STATUS2);
1686#endif
1687	if ((val & 0x70) < 0x20) {
1688		printf("-old (%o)", val & 0x70);
1689		return (0);
1690	}
1691
1692	/*
1693	 * Check for ability to emulate 16550:  bit 7 == 1
1694	 */
1695	if ((dips & 0x80) == 0) {
1696		printf(" slave");
1697		return (0);
1698	}
1699
1700	/*
1701	 * Okay, we seem to be a Hayes ESP card.  Whee.
1702	 */
1703	com->esp = TRUE;
1704	com->esp_port = esp_port;
1705	return (1);
1706}
1707#endif /* COM_ESP */
1708
1709static int
1710sio_isa_attach(dev)
1711	device_t	dev;
1712{
1713	return (sioattach(dev, 0));
1714}
1715
1716static int
1717sioattach(dev, xrid)
1718	device_t	dev;
1719	int		xrid;
1720{
1721	struct com_s	*com;
1722#ifdef COM_ESP
1723	Port_t		*espp;
1724#endif
1725	Port_t		iobase;
1726	int		unit;
1727	u_int		flags;
1728	int		rid;
1729	struct resource *port;
1730	int		ret;
1731	int		intrstate;
1732#ifdef PC98
1733	u_char		*obuf;
1734	u_long		obufsize;
1735	int		if_type = GET_IFTYPE(device_get_flags(dev));
1736#endif
1737
1738	rid = xrid;
1739#ifdef PC98
1740	if (IS_8251(if_type)) {
1741		port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1742					  0, ~0, 1, RF_ACTIVE);
1743	} else if (if_type == COM_IF_RSA98III ||
1744		   isa_get_vendorid(dev)) {
1745		port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
1746			if_16550a_type[if_type & 0x0f].iatsz, RF_ACTIVE);
1747	} else {
1748		port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
1749			if_16550a_type[if_type & 0x0f].iat,
1750			if_16550a_type[if_type & 0x0f].iatsz, RF_ACTIVE);
1751	}
1752#else
1753	port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1754				  0, ~0, IO_COMSIZE, RF_ACTIVE);
1755#endif
1756	if (!port)
1757		return (ENXIO);
1758#ifdef PC98
1759	if (!IS_8251(if_type)) {
1760		if (isa_load_resourcev(port,
1761			if_16550a_type[if_type & 0x0f].iat,
1762			if_16550a_type[if_type & 0x0f].iatsz) != 0) {
1763		    bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1764		    return ENXIO;
1765		}
1766	}
1767#endif
1768
1769	iobase = rman_get_start(port);
1770	unit = device_get_unit(dev);
1771	com = device_get_softc(dev);
1772	flags = device_get_flags(dev);
1773
1774	if (unit >= sio_numunits)
1775		sio_numunits = unit + 1;
1776
1777#ifdef PC98
1778	obufsize = 256;
1779	if (if_type == COM_IF_RSA98III)
1780		obufsize = 2048;
1781	if ((obuf = malloc(obufsize * 2, M_DEVBUF, M_NOWAIT)) == NULL) {
1782		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1783		return ENXIO;
1784	}
1785	bzero(obuf, obufsize * 2);
1786#endif
1787
1788	/*
1789	 * sioprobe() has initialized the device registers as follows:
1790	 *	o cfcr = CFCR_8BITS.
1791	 *	  It is most important that CFCR_DLAB is off, so that the
1792	 *	  data port is not hidden when we enable interrupts.
1793	 *	o ier = 0.
1794	 *	  Interrupts are only enabled when the line is open.
1795	 *	o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
1796	 *	  interrupt control register or the config specifies no irq.
1797	 *	  Keeping MCR_DTR and MCR_RTS off might stop the external
1798	 *	  device from sending before we are ready.
1799	 */
1800	bzero(com, sizeof *com);
1801	com->unit = unit;
1802	com->ioportres = port;
1803	com->bst = rman_get_bustag(port);
1804	com->bsh = rman_get_bushandle(port);
1805	com->cfcr_image = CFCR_8BITS;
1806	com->dtr_wait = 3 * hz;
1807	com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
1808	com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
1809	com->tx_fifo_size = 1;
1810#ifdef PC98
1811	com->obufsize = obufsize;
1812	com->obuf1 = obuf;
1813	com->obuf2 = obuf + obufsize;
1814#endif
1815	com->obufs[0].l_head = com->obuf1;
1816	com->obufs[1].l_head = com->obuf2;
1817
1818#ifdef PC98
1819	com->pc98_if_type = if_type;
1820
1821	if (IS_8251(if_type)) {
1822	    pc98_set_ioport(com);
1823
1824	    if (if_type == COM_IF_INTERNAL && pc98_check_8251fifo()) {
1825		com->pc98_8251fifo = 1;
1826		com->pc98_8251fifo_enable = 0;
1827	    }
1828	} else {
1829	    bus_addr_t	*iat = if_16550a_type[if_type & 0x0f].iat;
1830
1831	    com->data_port = iobase + iat[com_data];
1832	    com->int_id_port = iobase + iat[com_iir];
1833	    com->modem_ctl_port = iobase + iat[com_mcr];
1834	    com->mcr_image = inb(com->modem_ctl_port);
1835	    com->line_status_port = iobase + iat[com_lsr];
1836	    com->modem_status_port = iobase + iat[com_msr];
1837	    com->intr_ctl_port = iobase + iat[com_ier];
1838	}
1839#else /* not PC98 */
1840	com->data_port = iobase + com_data;
1841	com->int_id_port = iobase + com_iir;
1842	com->modem_ctl_port = iobase + com_mcr;
1843	com->mcr_image = inb(com->modem_ctl_port);
1844	com->line_status_port = iobase + com_lsr;
1845	com->modem_status_port = iobase + com_msr;
1846	com->intr_ctl_port = iobase + com_ier;
1847#endif
1848
1849	/*
1850	 * We don't use all the flags from <sys/ttydefaults.h> since they
1851	 * are only relevant for logins.  It's important to have echo off
1852	 * initially so that the line doesn't start blathering before the
1853	 * echo flag can be turned off.
1854	 */
1855	com->it_in.c_iflag = 0;
1856	com->it_in.c_oflag = 0;
1857	com->it_in.c_cflag = TTYDEF_CFLAG;
1858	com->it_in.c_lflag = 0;
1859	if (unit == comconsole) {
1860#ifdef PC98
1861		if (IS_8251(com->pc98_if_type))
1862			DELAY(100000);
1863#endif
1864		com->it_in.c_iflag = TTYDEF_IFLAG;
1865		com->it_in.c_oflag = TTYDEF_OFLAG;
1866		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
1867		com->it_in.c_lflag = TTYDEF_LFLAG;
1868		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
1869		com->lt_out.c_ispeed = com->lt_out.c_ospeed =
1870		com->lt_in.c_ispeed = com->lt_in.c_ospeed =
1871		com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
1872	} else
1873		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1874	intrstate = save_intr();
1875	if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1876		COM_UNLOCK();
1877		restore_intr(intrstate);
1878		/*
1879		 * Leave i/o resources allocated if this is a `cn'-level
1880		 * console, so that other devices can't snarf them.
1881		 */
1882		if (iobase != siocniobase)
1883			bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1884		return (ENOMEM);
1885	}
1886	COM_UNLOCK();
1887	restore_intr(intrstate);
1888	termioschars(&com->it_in);
1889	com->it_out = com->it_in;
1890
1891	/* attempt to determine UART type */
1892	printf("sio%d: type", unit);
1893
1894
1895#ifndef PC98
1896#ifdef COM_MULTIPORT
1897	if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags))
1898#else
1899	if (!COM_IIR_TXRDYBUG(flags))
1900#endif
1901	{
1902		u_char	scr;
1903		u_char	scr1;
1904		u_char	scr2;
1905
1906		scr = sio_getreg(com, com_scr);
1907		sio_setreg(com, com_scr, 0xa5);
1908		scr1 = sio_getreg(com, com_scr);
1909		sio_setreg(com, com_scr, 0x5a);
1910		scr2 = sio_getreg(com, com_scr);
1911		sio_setreg(com, com_scr, scr);
1912		if (scr1 != 0xa5 || scr2 != 0x5a) {
1913			printf(" 8250");
1914			goto determined_type;
1915		}
1916	}
1917#endif /* !PC98 */
1918#ifdef PC98
1919	if (IS_8251(com->pc98_if_type)) {
1920	    if (com->pc98_8251fifo && !COM_NOFIFO(flags))
1921		com->tx_fifo_size = 16;
1922	    com_int_TxRx_disable( com );
1923	    com_cflag_and_speed_set( com, com->it_in.c_cflag, comdefaultrate );
1924	    com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
1925	    com_send_break_off( com );
1926
1927	    if (com->pc98_if_type == COM_IF_INTERNAL) {
1928		printf(" (internal%s%s)",
1929		       com->pc98_8251fifo ? " fifo" : "",
1930		       PC98SIO_baud_rate_port(com->pc98_if_type) != -1 ?
1931		       " v-fast" : "");
1932	    } else {
1933		printf(" 8251%s", if_8251_type[com->pc98_if_type & 0x0f].name);
1934	    }
1935	} else {
1936#endif /* PC98 */
1937	sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1938	DELAY(100);
1939	com->st16650a = 0;
1940	switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1941	case FIFO_RX_LOW:
1942		printf(" 16450");
1943		break;
1944	case FIFO_RX_MEDL:
1945		printf(" 16450?");
1946		break;
1947	case FIFO_RX_MEDH:
1948		printf(" 16550?");
1949		break;
1950	case FIFO_RX_HIGH:
1951		if (COM_NOFIFO(flags)) {
1952			printf(" 16550A fifo disabled");
1953		} else {
1954			com->hasfifo = TRUE;
1955#ifdef PC98
1956			com->tx_fifo_size = 0;	/* XXX flag conflicts. */
1957			printf(" 16550A");
1958#else
1959			if (COM_ST16650A(flags)) {
1960				com->st16650a = 1;
1961				com->tx_fifo_size = 32;
1962				printf(" ST16650A");
1963			} else {
1964				com->tx_fifo_size = COM_FIFOSIZE(flags);
1965				printf(" 16550A");
1966			}
1967#endif
1968		}
1969#ifdef PC98
1970		if (com->pc98_if_type == COM_IF_RSA98III) {
1971			com->tx_fifo_size = 2048;
1972			com->rsabase = iobase;
1973			outb(com->rsabase + rsa_ier, 0x00);
1974			outb(com->rsabase + rsa_frr, 0x00);
1975		}
1976#endif
1977
1978#ifdef COM_ESP
1979#ifdef PC98
1980		if (com->pc98_if_type == COM_IF_ESP98)
1981#endif
1982		for (espp = likely_esp_ports; *espp != 0; espp++)
1983			if (espattach(com, *espp)) {
1984				com->tx_fifo_size = 1024;
1985				break;
1986			}
1987#endif
1988		if (!com->st16650a) {
1989			if (!com->tx_fifo_size)
1990				com->tx_fifo_size = 16;
1991			else
1992				printf(" lookalike with %d bytes FIFO",
1993				    com->tx_fifo_size);
1994		}
1995
1996		break;
1997	}
1998
1999#ifdef PC98
2000	if (com->pc98_if_type == COM_IF_RSB3000) {
2001	    /* Set RSB-2000/3000 Extended Buffer mode. */
2002	    u_char lcr;
2003	    lcr = sio_getreg(com, com_cfcr);
2004	    sio_setreg(com, com_cfcr, lcr | CFCR_DLAB);
2005	    sio_setreg(com, com_emr, EMR_EXBUFF | EMR_EFMODE);
2006	    sio_setreg(com, com_cfcr, lcr);
2007	}
2008#endif
2009
2010#ifdef COM_ESP
2011	if (com->esp) {
2012		/*
2013		 * Set 16550 compatibility mode.
2014		 * We don't use the ESP_MODE_SCALE bit to increase the
2015		 * fifo trigger levels because we can't handle large
2016		 * bursts of input.
2017		 * XXX flow control should be set in comparam(), not here.
2018		 */
2019#ifdef PC98
2020		outb(com->esp_port + ESP98_CMD1, ESP_SETMODE);
2021		outb(com->esp_port + ESP98_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
2022#else
2023		outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
2024		outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
2025#endif
2026
2027		/* Set RTS/CTS flow control. */
2028#ifdef PC98
2029		outb(com->esp_port + ESP98_CMD1, ESP_SETFLOWTYPE);
2030		outb(com->esp_port + ESP98_CMD2, ESP_FLOW_RTS);
2031		outb(com->esp_port + ESP98_CMD2, ESP_FLOW_CTS);
2032#else
2033		outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
2034		outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
2035		outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
2036#endif
2037
2038		/* Set flow-control levels. */
2039#ifdef PC98
2040		outb(com->esp_port + ESP98_CMD1, ESP_SETRXFLOW);
2041		outb(com->esp_port + ESP98_CMD2, HIBYTE(768));
2042		outb(com->esp_port + ESP98_CMD2, LOBYTE(768));
2043		outb(com->esp_port + ESP98_CMD2, HIBYTE(512));
2044		outb(com->esp_port + ESP98_CMD2, LOBYTE(512));
2045#else
2046		outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
2047		outb(com->esp_port + ESP_CMD2, HIBYTE(768));
2048		outb(com->esp_port + ESP_CMD2, LOBYTE(768));
2049		outb(com->esp_port + ESP_CMD2, HIBYTE(512));
2050		outb(com->esp_port + ESP_CMD2, LOBYTE(512));
2051#endif
2052
2053#ifdef PC98
2054                /* Set UART clock prescaler. */
2055                outb(com->esp_port + ESP98_CMD1, ESP_SETCLOCK);
2056                outb(com->esp_port + ESP98_CMD2, 2);	/* 4 times */
2057#endif
2058	}
2059#endif /* COM_ESP */
2060	sio_setreg(com, com_fifo, 0);
2061#ifdef PC98
2062	printf("%s", if_16550a_type[com->pc98_if_type & 0x0f].name);
2063#else
2064determined_type: ;
2065#endif
2066
2067#ifdef COM_MULTIPORT
2068	if (COM_ISMULTIPORT(flags)) {
2069		device_t masterdev;
2070
2071		com->multiport = TRUE;
2072		printf(" (multiport");
2073		if (unit == COM_MPMASTER(flags))
2074			printf(" master");
2075		printf(")");
2076		masterdev = devclass_get_device(sio_devclass,
2077		    COM_MPMASTER(flags));
2078		com->no_irq = (masterdev == NULL || bus_get_resource(masterdev,
2079		    SYS_RES_IRQ, 0, NULL, NULL) != 0);
2080	 }
2081#endif /* COM_MULTIPORT */
2082#ifdef PC98
2083	}
2084#endif
2085	if (unit == comconsole)
2086		printf(", console");
2087	if (COM_IIR_TXRDYBUG(flags))
2088		printf(" with a bogus IIR_TXRDY register");
2089	printf("\n");
2090
2091	if (sio_fast_ih == NULL) {
2092		sio_fast_ih = sinthand_add("tty:sio", &tty_ithd, siopoll,
2093		    NULL, SWI_TTY, 0);
2094		sio_slow_ih = sinthand_add("tty:sio", &clk_ithd, siopoll,
2095		    NULL, SWI_TTY, 0);
2096	}
2097	com->devs[0] = make_dev(&sio_cdevsw, unit,
2098	    UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit);
2099	com->devs[1] = make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE,
2100	    UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit);
2101	com->devs[2] = make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE,
2102	    UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit);
2103	com->devs[3] = make_dev(&sio_cdevsw, unit | CALLOUT_MASK,
2104	    UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit);
2105	com->devs[4] = make_dev(&sio_cdevsw,
2106	    unit | CALLOUT_MASK | CONTROL_INIT_STATE,
2107	    UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit);
2108	com->devs[5] = make_dev(&sio_cdevsw,
2109	    unit | CALLOUT_MASK | CONTROL_LOCK_STATE,
2110	    UID_UUCP, GID_DIALER, 0660, "cuala%r", unit);
2111	com->flags = flags;
2112	com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
2113	pps_init(&com->pps);
2114
2115	rid = 0;
2116	com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
2117	    RF_ACTIVE);
2118	if (com->irqres) {
2119		ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres,
2120				     INTR_TYPE_TTY | INTR_FAST,
2121				     siointr, com, &com->cookie);
2122		if (ret) {
2123			ret = BUS_SETUP_INTR(device_get_parent(dev), dev,
2124					     com->irqres, INTR_TYPE_TTY,
2125					     siointr, com, &com->cookie);
2126			if (ret == 0)
2127				device_printf(dev, "unable to activate interrupt in fast mode - using normal mode");
2128		}
2129		if (ret)
2130			device_printf(dev, "could not activate interrupt\n");
2131	}
2132
2133	return (0);
2134}
2135
2136static int
2137sioopen(dev, flag, mode, p)
2138	dev_t		dev;
2139	int		flag;
2140	int		mode;
2141	struct proc	*p;
2142{
2143	struct com_s	*com;
2144	int		error;
2145	int		mynor;
2146	int		s;
2147	struct tty	*tp;
2148	int		unit;
2149
2150	mynor = minor(dev);
2151	unit = MINOR_TO_UNIT(mynor);
2152	com = com_addr(unit);
2153	if (com == NULL)
2154		return (ENXIO);
2155	if (com->gone)
2156		return (ENXIO);
2157	if (mynor & CONTROL_MASK)
2158		return (0);
2159	tp = dev->si_tty = com->tp = ttymalloc(com->tp);
2160	s = spltty();
2161	/*
2162	 * We jump to this label after all non-interrupted sleeps to pick
2163	 * up any changes of the device state.
2164	 */
2165open_top:
2166	while (com->state & CS_DTR_OFF) {
2167		error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0);
2168		if (com_addr(unit) == NULL)
2169			return (ENXIO);
2170		if (error != 0 || com->gone)
2171			goto out;
2172	}
2173	if (tp->t_state & TS_ISOPEN) {
2174		/*
2175		 * The device is open, so everything has been initialized.
2176		 * Handle conflicts.
2177		 */
2178		if (mynor & CALLOUT_MASK) {
2179			if (!com->active_out) {
2180				error = EBUSY;
2181				goto out;
2182			}
2183		} else {
2184			if (com->active_out) {
2185				if (flag & O_NONBLOCK) {
2186					error = EBUSY;
2187					goto out;
2188				}
2189				error =	tsleep(&com->active_out,
2190					       TTIPRI | PCATCH, "siobi", 0);
2191				if (com_addr(unit) == NULL)
2192					return (ENXIO);
2193				if (error != 0 || com->gone)
2194					goto out;
2195				goto open_top;
2196			}
2197		}
2198		if (tp->t_state & TS_XCLUDE &&
2199		    suser(p)) {
2200			error = EBUSY;
2201			goto out;
2202		}
2203	} else {
2204		int	intrsave;
2205
2206		/*
2207		 * The device isn't open, so there are no conflicts.
2208		 * Initialize it.  Initialization is done twice in many
2209		 * cases: to preempt sleeping callin opens if we are
2210		 * callout, and to complete a callin open after DCD rises.
2211		 */
2212		tp->t_oproc = comstart;
2213		tp->t_param = comparam;
2214		tp->t_stop = comstop;
2215		tp->t_dev = dev;
2216		tp->t_termios = mynor & CALLOUT_MASK
2217				? com->it_out : com->it_in;
2218#ifdef PC98
2219		if (!IS_8251(com->pc98_if_type))
2220#endif
2221		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
2222		com->poll = com->no_irq;
2223		com->poll_output = com->loses_outints;
2224		++com->wopeners;
2225		error = comparam(tp, &tp->t_termios);
2226		--com->wopeners;
2227		if (error != 0)
2228			goto out;
2229#ifdef PC98
2230		if (IS_8251(com->pc98_if_type)) {
2231			com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS);
2232			pc98_msrint_start(dev);
2233			if (com->pc98_8251fifo) {
2234			    com->pc98_8251fifo_enable = 1;
2235			    outb(I8251F_fcr, CTRL8251F_ENABLE |
2236				 CTRL8251F_XMT_RST | CTRL8251F_RCV_RST);
2237			}
2238		}
2239#endif
2240		/*
2241		 * XXX we should goto open_top if comparam() slept.
2242		 */
2243		if (com->hasfifo) {
2244			/*
2245			 * (Re)enable and drain fifos.
2246			 *
2247			 * Certain SMC chips cause problems if the fifos
2248			 * are enabled while input is ready.  Turn off the
2249			 * fifo if necessary to clear the input.  We test
2250			 * the input ready bit after enabling the fifos
2251			 * since we've already enabled them in comparam()
2252			 * and to handle races between enabling and fresh
2253			 * input.
2254			 */
2255			while (TRUE) {
2256				sio_setreg(com, com_fifo,
2257					   FIFO_RCV_RST | FIFO_XMT_RST
2258					   | com->fifo_image);
2259#ifdef PC98
2260				if (com->pc98_if_type == COM_IF_RSA98III)
2261					outb(com->rsabase + rsa_frr , 0x00);
2262#endif
2263				/*
2264				 * XXX the delays are for superstitious
2265				 * historical reasons.  It must be less than
2266				 * the character time at the maximum
2267				 * supported speed (87 usec at 115200 bps
2268				 * 8N1).  Otherwise we might loop endlessly
2269				 * if data is streaming in.  We used to use
2270				 * delays of 100.  That usually worked
2271				 * because DELAY(100) used to usually delay
2272				 * for about 85 usec instead of 100.
2273				 */
2274				DELAY(50);
2275#ifdef PC98
2276				if (com->pc98_if_type == COM_IF_RSA98III ?
2277				    !(inb(com->rsabase + rsa_srr) & 0x08) :
2278				    !(inb(com->line_status_port) & LSR_RXRDY))
2279					break;
2280#else
2281				if (!(inb(com->line_status_port) & LSR_RXRDY))
2282					break;
2283#endif
2284				sio_setreg(com, com_fifo, 0);
2285				DELAY(50);
2286				(void) inb(com->data_port);
2287			}
2288		}
2289
2290		intrsave = save_intr();
2291		disable_intr();
2292		COM_LOCK();
2293#ifdef PC98
2294		if (IS_8251(com->pc98_if_type)) {
2295		    com_tiocm_bis(com, TIOCM_LE);
2296		    com->pc98_prev_modem_status = pc98_get_modem_status(com);
2297		    com_int_Rx_enable(com);
2298		} else {
2299#endif
2300		(void) inb(com->line_status_port);
2301		(void) inb(com->data_port);
2302		com->prev_modem_status = com->last_modem_status
2303		    = inb(com->modem_status_port);
2304		if (COM_IIR_TXRDYBUG(com->flags)) {
2305			outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
2306						| IER_EMSC);
2307		} else {
2308			outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
2309						| IER_ERLS | IER_EMSC);
2310		}
2311#ifdef PC98
2312		if (com->pc98_if_type == COM_IF_RSA98III) {
2313			outb(com->rsabase + rsa_ier, 0x1d);
2314			outb(com->intr_ctl_port, IER_ERLS | IER_EMSC);
2315		}
2316#endif
2317#ifdef PC98
2318		}
2319#endif
2320		COM_UNLOCK();
2321		restore_intr(intrsave);
2322		/*
2323		 * Handle initial DCD.  Callout devices get a fake initial
2324		 * DCD (trapdoor DCD).  If we are callout, then any sleeping
2325		 * callin opens get woken up and resume sleeping on "siobi"
2326		 * instead of "siodcd".
2327		 */
2328		/*
2329		 * XXX `mynor & CALLOUT_MASK' should be
2330		 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
2331		 * TRAPDOOR_CARRIER is the default initial state for callout
2332		 * devices and SOFT_CARRIER is like CLOCAL except it hides
2333		 * the true carrier.
2334		 */
2335#ifdef PC98
2336		if ((IS_8251(com->pc98_if_type) &&
2337			(pc98_get_modem_status(com) & TIOCM_CAR)) ||
2338		    (!IS_8251(com->pc98_if_type) &&
2339			(com->prev_modem_status & MSR_DCD)) ||
2340		    mynor & CALLOUT_MASK)
2341			(*linesw[tp->t_line].l_modem)(tp, 1);
2342#else
2343		if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
2344			(*linesw[tp->t_line].l_modem)(tp, 1);
2345#endif
2346	}
2347	/*
2348	 * Wait for DCD if necessary.
2349	 */
2350	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
2351	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
2352		++com->wopeners;
2353		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
2354		if (com_addr(unit) == NULL)
2355			return (ENXIO);
2356		--com->wopeners;
2357		if (error != 0 || com->gone)
2358			goto out;
2359		goto open_top;
2360	}
2361	error =	(*linesw[tp->t_line].l_open)(dev, tp);
2362	disc_optim(tp, &tp->t_termios, com);
2363	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
2364		com->active_out = TRUE;
2365	siosettimeout();
2366out:
2367	splx(s);
2368	if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
2369		comhardclose(com);
2370	return (error);
2371}
2372
2373static int
2374sioclose(dev, flag, mode, p)
2375	dev_t		dev;
2376	int		flag;
2377	int		mode;
2378	struct proc	*p;
2379{
2380	struct com_s	*com;
2381	int		mynor;
2382	int		s;
2383	struct tty	*tp;
2384
2385	mynor = minor(dev);
2386	if (mynor & CONTROL_MASK)
2387		return (0);
2388	com = com_addr(MINOR_TO_UNIT(mynor));
2389	if (com == NULL)
2390		return (ENODEV);
2391	tp = com->tp;
2392	s = spltty();
2393	(*linesw[tp->t_line].l_close)(tp, flag);
2394#ifdef PC98
2395	com->modem_checking = 0;
2396#endif
2397	disc_optim(tp, &tp->t_termios, com);
2398	comstop(tp, FREAD | FWRITE);
2399	comhardclose(com);
2400	ttyclose(tp);
2401	siosettimeout();
2402	splx(s);
2403	if (com->gone) {
2404		printf("sio%d: gone\n", com->unit);
2405		s = spltty();
2406		if (com->ibuf != NULL)
2407			free(com->ibuf, M_DEVBUF);
2408		bzero(tp, sizeof *tp);
2409		splx(s);
2410	}
2411	return (0);
2412}
2413
2414static void
2415comhardclose(com)
2416	struct com_s	*com;
2417{
2418	int		s;
2419	struct tty	*tp;
2420	int		unit;
2421
2422	unit = com->unit;
2423	s = spltty();
2424	com->poll = FALSE;
2425	com->poll_output = FALSE;
2426	com->do_timestamp = FALSE;
2427	com->do_dcd_timestamp = FALSE;
2428	com->pps.ppsparam.mode = 0;
2429#ifdef PC98
2430	if (IS_8251(com->pc98_if_type))
2431		com_send_break_off(com);
2432	else
2433#endif
2434	sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2435	{
2436#ifdef PC98
2437		int tmp;
2438		if (IS_8251(com->pc98_if_type))
2439			com_int_TxRx_disable(com);
2440		else
2441			sio_setreg(com, com_ier, 0);
2442		if (com->pc98_if_type == COM_IF_RSA98III)
2443			outb(com->rsabase + rsa_ier, 0x00);
2444#else
2445		sio_setreg(com, com_ier, 0);
2446#endif
2447		tp = com->tp;
2448#ifdef PC98
2449		if (IS_8251(com->pc98_if_type))
2450			tmp = pc98_get_modem_status(com) & TIOCM_CAR;
2451		else
2452			tmp = com->prev_modem_status & MSR_DCD;
2453#endif
2454		if (tp->t_cflag & HUPCL
2455		    /*
2456		     * XXX we will miss any carrier drop between here and the
2457		     * next open.  Perhaps we should watch DCD even when the
2458		     * port is closed; it is not sufficient to check it at
2459		     * the next open because it might go up and down while
2460		     * we're not watching.
2461		     */
2462		    || (!com->active_out
2463#ifdef PC98
2464			&& !(tmp)
2465#else
2466		        && !(com->prev_modem_status & MSR_DCD)
2467#endif
2468		        && !(com->it_in.c_cflag & CLOCAL))
2469		    || !(tp->t_state & TS_ISOPEN)) {
2470#ifdef PC98
2471			if (IS_8251(com->pc98_if_type))
2472			    com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
2473			else
2474#endif
2475			(void)commctl(com, TIOCM_DTR, DMBIC);
2476			if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
2477				timeout(siodtrwakeup, com, com->dtr_wait);
2478				com->state |= CS_DTR_OFF;
2479			}
2480		}
2481#ifdef PC98
2482		else {
2483			if (IS_8251(com->pc98_if_type))
2484				com_tiocm_bic(com, TIOCM_LE);
2485		}
2486#endif
2487	}
2488#ifdef PC98
2489	if (com->pc98_8251fifo)	{
2490	    if (com->pc98_8251fifo_enable)
2491		outb(I8251F_fcr, CTRL8251F_XMT_RST | CTRL8251F_RCV_RST);
2492	    com->pc98_8251fifo_enable = 0;
2493	}
2494#endif
2495	if (com->hasfifo) {
2496		/*
2497		 * Disable fifos so that they are off after controlled
2498		 * reboots.  Some BIOSes fail to detect 16550s when the
2499		 * fifos are enabled.
2500		 */
2501		sio_setreg(com, com_fifo, 0);
2502	}
2503	com->active_out = FALSE;
2504	wakeup(&com->active_out);
2505	wakeup(TSA_CARR_ON(tp));	/* restart any wopeners */
2506	splx(s);
2507}
2508
2509static int
2510sioread(dev, uio, flag)
2511	dev_t		dev;
2512	struct uio	*uio;
2513	int		flag;
2514{
2515	int		mynor;
2516	struct com_s	*com;
2517
2518	mynor = minor(dev);
2519	if (mynor & CONTROL_MASK)
2520		return (ENODEV);
2521	com = com_addr(MINOR_TO_UNIT(mynor));
2522	if (com == NULL || com->gone)
2523		return (ENODEV);
2524	return ((*linesw[com->tp->t_line].l_read)(com->tp, uio, flag));
2525}
2526
2527static int
2528siowrite(dev, uio, flag)
2529	dev_t		dev;
2530	struct uio	*uio;
2531	int		flag;
2532{
2533	int		mynor;
2534	struct com_s	*com;
2535	int		unit;
2536
2537	mynor = minor(dev);
2538	if (mynor & CONTROL_MASK)
2539		return (ENODEV);
2540
2541	unit = MINOR_TO_UNIT(mynor);
2542	com = com_addr(unit);
2543	if (com == NULL || com->gone)
2544		return (ENODEV);
2545	/*
2546	 * (XXX) We disallow virtual consoles if the physical console is
2547	 * a serial port.  This is in case there is a display attached that
2548	 * is not the console.  In that situation we don't need/want the X
2549	 * server taking over the console.
2550	 */
2551	if (constty != NULL && unit == comconsole)
2552		constty = NULL;
2553	return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag));
2554}
2555
2556static void
2557siobusycheck(chan)
2558	void	*chan;
2559{
2560	struct com_s	*com;
2561	int		s;
2562
2563	com = (struct com_s *)chan;
2564
2565	/*
2566	 * Clear TS_BUSY if low-level output is complete.
2567	 * spl locking is sufficient because siointr1() does not set CS_BUSY.
2568	 * If siointr1() clears CS_BUSY after we look at it, then we'll get
2569	 * called again.  Reading the line status port outside of siointr1()
2570	 * is safe because CS_BUSY is clear so there are no output interrupts
2571	 * to lose.
2572	 */
2573	s = spltty();
2574	if (com->state & CS_BUSY)
2575		com->extra_state &= ~CSE_BUSYCHECK;	/* False alarm. */
2576#ifdef	PC98
2577	else if ((IS_8251(com->pc98_if_type) &&
2578		  ((com->pc98_8251fifo_enable &&
2579		    (inb(I8251F_lsr) & (STS8251F_TxRDY | STS8251F_TxEMP))
2580		    == (STS8251F_TxRDY | STS8251F_TxEMP)) ||
2581		   (!com->pc98_8251fifo_enable &&
2582		    (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP))
2583		    == (STS8251_TxRDY | STS8251_TxEMP)))) ||
2584		 ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2585		  == (LSR_TSRE | LSR_TXRDY))) {
2586#else
2587	else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2588	    == (LSR_TSRE | LSR_TXRDY)) {
2589#endif
2590		com->tp->t_state &= ~TS_BUSY;
2591		ttwwakeup(com->tp);
2592		com->extra_state &= ~CSE_BUSYCHECK;
2593	} else
2594		timeout(siobusycheck, com, hz / 100);
2595	splx(s);
2596}
2597
2598static void
2599siodtrwakeup(chan)
2600	void	*chan;
2601{
2602	struct com_s	*com;
2603
2604	com = (struct com_s *)chan;
2605	com->state &= ~CS_DTR_OFF;
2606	wakeup(&com->dtr_wait);
2607}
2608
2609/*
2610 * Call this function with COM_LOCK.  It will return with the lock still held.
2611 */
2612static void
2613sioinput(com)
2614	struct com_s	*com;
2615{
2616	u_char		*buf;
2617	int		incc;
2618	u_char		line_status;
2619	int		recv_data;
2620	struct tty	*tp;
2621	int		intrsave;
2622
2623	buf = com->ibuf;
2624	tp = com->tp;
2625	if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
2626		com_events -= (com->iptr - com->ibuf);
2627		com->iptr = com->ibuf;
2628		return;
2629	}
2630	if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
2631		/*
2632		 * Avoid the grotesquely inefficient lineswitch routine
2633		 * (ttyinput) in "raw" mode.  It usually takes about 450
2634		 * instructions (that's without canonical processing or echo!).
2635		 * slinput is reasonably fast (usually 40 instructions plus
2636		 * call overhead).
2637		 */
2638		do {
2639			/*
2640			 * This may look odd, but it is using save-and-enable
2641			 * semantics instead of the save-and-disable semantics
2642			 * that are used everywhere else.
2643			 */
2644			intrsave = save_intr();
2645			COM_UNLOCK();
2646			enable_intr();
2647			incc = com->iptr - buf;
2648			if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
2649			    && (com->state & CS_RTS_IFLOW
2650				|| tp->t_iflag & IXOFF)
2651			    && !(tp->t_state & TS_TBLOCK))
2652				ttyblock(tp);
2653			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
2654				+= b_to_q((char *)buf, incc, &tp->t_rawq);
2655			buf += incc;
2656			tk_nin += incc;
2657			tk_rawcc += incc;
2658			tp->t_rawcc += incc;
2659			ttwakeup(tp);
2660			if (tp->t_state & TS_TTSTOP
2661			    && (tp->t_iflag & IXANY
2662				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
2663				tp->t_state &= ~TS_TTSTOP;
2664				tp->t_lflag &= ~FLUSHO;
2665				comstart(tp);
2666			}
2667			restore_intr(intrsave);
2668			COM_LOCK();
2669		} while (buf < com->iptr);
2670	} else {
2671		do {
2672			/*
2673			 * This may look odd, but it is using save-and-enable
2674			 * semantics instead of the save-and-disable semantics
2675			 * that are used everywhere else.
2676			 */
2677			intrsave = save_intr();
2678			COM_UNLOCK();
2679			enable_intr();
2680			line_status = buf[com->ierroff];
2681			recv_data = *buf++;
2682			if (line_status
2683			    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
2684				if (line_status & LSR_BI)
2685					recv_data |= TTY_BI;
2686				if (line_status & LSR_FE)
2687					recv_data |= TTY_FE;
2688				if (line_status & LSR_OE)
2689					recv_data |= TTY_OE;
2690				if (line_status & LSR_PE)
2691					recv_data |= TTY_PE;
2692			}
2693			(*linesw[tp->t_line].l_rint)(recv_data, tp);
2694			restore_intr(intrsave);
2695			COM_LOCK();
2696		} while (buf < com->iptr);
2697	}
2698	com_events -= (com->iptr - com->ibuf);
2699	com->iptr = com->ibuf;
2700
2701	/*
2702	 * There is now room for another low-level buffer full of input,
2703	 * so enable RTS if it is now disabled and there is room in the
2704	 * high-level buffer.
2705	 */
2706#ifdef PC98
2707	if (IS_8251(com->pc98_if_type)) {
2708		if ((com->state & CS_RTS_IFLOW) &&
2709		    !(com_tiocm_get(com) & TIOCM_RTS) &&
2710		    !(tp->t_state & TS_TBLOCK))
2711			com_tiocm_bis(com, TIOCM_RTS);
2712	} else {
2713		if ((com->state & CS_RTS_IFLOW) &&
2714		    !(com->mcr_image & MCR_RTS) &&
2715		    !(tp->t_state & TS_TBLOCK))
2716			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2717	}
2718#else
2719	if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
2720	    !(tp->t_state & TS_TBLOCK))
2721		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2722#endif
2723}
2724
2725void
2726siointr(arg)
2727	void		*arg;
2728{
2729#ifndef COM_MULTIPORT
2730	COM_LOCK();
2731	siointr1((struct com_s *) arg);
2732	COM_UNLOCK();
2733#else /* COM_MULTIPORT */
2734	bool_t		possibly_more_intrs;
2735	int		unit;
2736	struct com_s	*com;
2737#ifdef PC98
2738	u_char		rsa_buf_status;
2739#endif
2740
2741	/*
2742	 * Loop until there is no activity on any port.  This is necessary
2743	 * to get an interrupt edge more than to avoid another interrupt.
2744	 * If the IRQ signal is just an OR of the IRQ signals from several
2745	 * devices, then the edge from one may be lost because another is
2746	 * on.
2747	 */
2748	COM_LOCK();
2749	do {
2750		possibly_more_intrs = FALSE;
2751		for (unit = 0; unit < sio_numunits; ++unit) {
2752			com = com_addr(unit);
2753			/*
2754			 * XXX COM_LOCK();
2755			 * would it work here, or be counter-productive?
2756			 */
2757#ifdef PC98
2758			if (com != NULL
2759			    && !com->gone
2760			    && IS_8251(com->pc98_if_type)) {
2761				siointr1(com);
2762			} else if (com != NULL
2763			    && !com->gone
2764			    && com->pc98_if_type == COM_IF_RSA98III) {
2765				rsa_buf_status =
2766				    inb(com->rsabase + rsa_srr) & 0xc9;
2767				if ((rsa_buf_status & 0xc8)
2768				    || !(rsa_buf_status & 0x01)) {
2769				    siointr1(com);
2770				    if (rsa_buf_status !=
2771					(inb(com->rsabase + rsa_srr) & 0xc9))
2772					possibly_more_intrs = TRUE;
2773				}
2774			} else
2775#endif
2776			if (com != NULL
2777			    && !com->gone
2778			    && (inb(com->int_id_port) & IIR_IMASK)
2779			       != IIR_NOPEND) {
2780				siointr1(com);
2781				possibly_more_intrs = TRUE;
2782			}
2783			/* XXX COM_UNLOCK(); */
2784		}
2785	} while (possibly_more_intrs);
2786	COM_UNLOCK();
2787#endif /* COM_MULTIPORT */
2788}
2789
2790static void
2791siointr1(com)
2792	struct com_s	*com;
2793{
2794	u_char	line_status;
2795	u_char	modem_status;
2796	u_char	*ioptr;
2797	u_char	recv_data;
2798	u_char	int_ctl;
2799	u_char	int_ctl_new;
2800	struct	timecounter *tc;
2801	u_int	count;
2802
2803#ifdef PC98
2804	u_char	tmp = 0;
2805	u_char	rsa_buf_status = 0;
2806	int	rsa_tx_fifo_size = 0;
2807#endif /* PC98 */
2808
2809	int_ctl = inb(com->intr_ctl_port);
2810	int_ctl_new = int_ctl;
2811
2812	while (!com->gone) {
2813#ifdef PC98
2814status_read:;
2815		if (IS_8251(com->pc98_if_type)) {
2816			if (com->pc98_8251fifo_enable)
2817				tmp = inb(I8251F_lsr);
2818			else
2819				tmp = inb(com->sts_port);
2820more_intr:
2821			line_status = 0;
2822			if (com->pc98_8251fifo_enable) {
2823			    if (tmp & STS8251F_TxRDY) line_status |= LSR_TXRDY;
2824			    if (tmp & STS8251F_RxRDY) line_status |= LSR_RXRDY;
2825			    if (tmp & STS8251F_TxEMP) line_status |= LSR_TSRE;
2826			    if (tmp & STS8251F_PE)    line_status |= LSR_PE;
2827			    if (tmp & STS8251F_OE)    line_status |= LSR_OE;
2828			    if (tmp & STS8251F_BD_SD) line_status |= LSR_BI;
2829			} else {
2830			    if (tmp & STS8251_TxRDY)  line_status |= LSR_TXRDY;
2831			    if (tmp & STS8251_RxRDY)  line_status |= LSR_RXRDY;
2832			    if (tmp & STS8251_TxEMP)  line_status |= LSR_TSRE;
2833			    if (tmp & STS8251_PE)     line_status |= LSR_PE;
2834			    if (tmp & STS8251_OE)     line_status |= LSR_OE;
2835			    if (tmp & STS8251_FE)     line_status |= LSR_FE;
2836			    if (tmp & STS8251_BD_SD)  line_status |= LSR_BI;
2837			}
2838		} else {
2839#endif /* PC98 */
2840		if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) {
2841			modem_status = inb(com->modem_status_port);
2842		        if ((modem_status ^ com->last_modem_status) & MSR_DCD) {
2843				tc = timecounter;
2844				count = tc->tc_get_timecount(tc);
2845				pps_event(&com->pps, tc, count,
2846				    (modem_status & MSR_DCD) ?
2847				    PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
2848			}
2849		}
2850		line_status = inb(com->line_status_port);
2851#ifdef PC98
2852		}
2853		if (com->pc98_if_type == COM_IF_RSA98III)
2854			rsa_buf_status = inb(com->rsabase + rsa_srr);
2855#endif /* PC98 */
2856
2857		/* input event? (check first to help avoid overruns) */
2858#ifndef PC98
2859		while (line_status & LSR_RCV_MASK) {
2860#else
2861		while ((line_status & LSR_RCV_MASK)
2862		       || (com->pc98_if_type == COM_IF_RSA98III
2863			   && (rsa_buf_status & 0x08))) {
2864#endif /* PC98 */
2865			/* break/unnattached error bits or real input? */
2866#ifdef PC98
2867			if (IS_8251(com->pc98_if_type)) {
2868				if (com->pc98_8251fifo_enable) {
2869				    recv_data = inb(I8251F_data);
2870				    if (tmp & (STS8251F_PE | STS8251F_OE |
2871					       STS8251F_BD_SD)) {
2872					pc98_i8251_or_cmd(com, CMD8251_ER);
2873					recv_data = 0;
2874				    }
2875				} else {
2876				    recv_data = inb(com->data_port);
2877				    if (tmp & (STS8251_PE | STS8251_OE |
2878					       STS8251_FE | STS8251_BD_SD)) {
2879					pc98_i8251_or_cmd(com, CMD8251_ER);
2880					recv_data = 0;
2881				    }
2882				}
2883			} else if (com->pc98_if_type == COM_IF_RSA98III) {
2884				if (!(rsa_buf_status & 0x08))
2885					recv_data = 0;
2886				else
2887					recv_data = inb(com->data_port);
2888			} else
2889#endif
2890			if (!(line_status & LSR_RXRDY))
2891				recv_data = 0;
2892			else
2893				recv_data = inb(com->data_port);
2894			if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
2895				/*
2896				 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
2897				 * Otherwise, push the work to a higher level
2898				 * (to handle PARMRK) if we're bypassing.
2899				 * Otherwise, convert BI/FE and PE+INPCK to 0.
2900				 *
2901				 * This makes bypassing work right in the
2902				 * usual "raw" case (IGNBRK set, and IGNPAR
2903				 * and INPCK clear).
2904				 *
2905				 * Note: BI together with FE/PE means just BI.
2906				 */
2907				if (line_status & LSR_BI) {
2908#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
2909					if (com->unit == comconsole) {
2910						breakpoint();
2911						goto cont;
2912					}
2913#endif
2914					if (com->tp == NULL
2915					    || com->tp->t_iflag & IGNBRK)
2916						goto cont;
2917				} else {
2918					if (com->tp == NULL
2919					    || com->tp->t_iflag & IGNPAR)
2920						goto cont;
2921				}
2922				if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
2923				    && (line_status & (LSR_BI | LSR_FE)
2924					|| com->tp->t_iflag & INPCK))
2925					recv_data = 0;
2926			}
2927			++com->bytes_in;
2928			if (com->hotchar != 0 && recv_data == com->hotchar)
2929				sched_swi(sio_fast_ih, SWI_NOSWITCH);
2930			ioptr = com->iptr;
2931			if (ioptr >= com->ibufend)
2932				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
2933			else {
2934				if (com->do_timestamp)
2935					microtime(&com->timestamp);
2936				++com_events;
2937				sched_swi(sio_slow_ih, SWI_DELAY);
2938#if 0 /* for testing input latency vs efficiency */
2939if (com->iptr - com->ibuf == 8)
2940	sched_swi(sio_fast_ih, SWI_NOSWITCH);
2941#endif
2942				ioptr[0] = recv_data;
2943				ioptr[com->ierroff] = line_status;
2944				com->iptr = ++ioptr;
2945				if (ioptr == com->ihighwater
2946				    && com->state & CS_RTS_IFLOW)
2947#ifdef PC98
2948					IS_8251(com->pc98_if_type) ?
2949						com_tiocm_bic(com, TIOCM_RTS) :
2950#endif
2951					outb(com->modem_ctl_port,
2952					     com->mcr_image &= ~MCR_RTS);
2953				if (line_status & LSR_OE)
2954					CE_RECORD(com, CE_OVERRUN);
2955			}
2956cont:
2957			/*
2958			 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
2959			 * jump from the top of the loop to here
2960			 */
2961#ifdef PC98
2962			if (IS_8251(com->pc98_if_type))
2963				goto status_read;
2964			else
2965#endif
2966			line_status = inb(com->line_status_port) & 0x7F;
2967#ifdef PC98
2968			if (com->pc98_if_type == COM_IF_RSA98III)
2969				rsa_buf_status = inb(com->rsabase + rsa_srr);
2970#endif /* PC98 */
2971		}
2972
2973		/* modem status change? (always check before doing output) */
2974#ifdef PC98
2975		if (!IS_8251(com->pc98_if_type)) {
2976#endif
2977		modem_status = inb(com->modem_status_port);
2978		if (modem_status != com->last_modem_status) {
2979			if (com->do_dcd_timestamp
2980			    && !(com->last_modem_status & MSR_DCD)
2981			    && modem_status & MSR_DCD)
2982				microtime(&com->dcd_timestamp);
2983
2984			/*
2985			 * Schedule high level to handle DCD changes.  Note
2986			 * that we don't use the delta bits anywhere.  Some
2987			 * UARTs mess them up, and it's easy to remember the
2988			 * previous bits and calculate the delta.
2989			 */
2990			com->last_modem_status = modem_status;
2991			if (!(com->state & CS_CHECKMSR)) {
2992				com_events += LOTS_OF_EVENTS;
2993				com->state |= CS_CHECKMSR;
2994				sched_swi(sio_fast_ih, SWI_NOSWITCH);
2995			}
2996
2997			/* handle CTS change immediately for crisp flow ctl */
2998			if (com->state & CS_CTS_OFLOW) {
2999				if (modem_status & MSR_CTS)
3000					com->state |= CS_ODEVREADY;
3001				else
3002					com->state &= ~CS_ODEVREADY;
3003			}
3004		}
3005#ifdef PC98
3006		}
3007#endif
3008
3009		/* output queued and everything ready? */
3010#ifndef PC98
3011		if (line_status & LSR_TXRDY
3012		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
3013#else
3014		if (((com->pc98_if_type == COM_IF_RSA98III)
3015		     ? (rsa_buf_status & 0x02)
3016		     : (line_status & LSR_TXRDY))
3017		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
3018#endif
3019#ifdef PC98
3020			Port_t	tmp_data_port;
3021
3022			if (IS_8251(com->pc98_if_type) &&
3023			    com->pc98_8251fifo_enable)
3024				tmp_data_port = I8251F_data;
3025			else
3026				tmp_data_port = com->data_port;
3027#endif
3028
3029			ioptr = com->obufq.l_head;
3030			if (com->tx_fifo_size > 1) {
3031				u_int	ocount;
3032
3033				ocount = com->obufq.l_tail - ioptr;
3034#ifdef PC98
3035				if (com->pc98_if_type == COM_IF_RSA98III) {
3036				  rsa_buf_status = inb(com->rsabase + rsa_srr);
3037				  rsa_tx_fifo_size = 1024;
3038				  if (!(rsa_buf_status & 0x01))
3039				      rsa_tx_fifo_size = 2048;
3040				  if (ocount > rsa_tx_fifo_size)
3041				      ocount = rsa_tx_fifo_size;
3042				} else
3043#endif
3044				if (ocount > com->tx_fifo_size)
3045					ocount = com->tx_fifo_size;
3046				com->bytes_out += ocount;
3047				do
3048#ifdef PC98
3049					outb(tmp_data_port, *ioptr++);
3050#else
3051					outb(com->data_port, *ioptr++);
3052#endif
3053				while (--ocount != 0);
3054			} else {
3055#ifdef PC98
3056				outb(tmp_data_port, *ioptr++);
3057#else
3058				outb(com->data_port, *ioptr++);
3059#endif
3060				++com->bytes_out;
3061			}
3062#ifdef PC98
3063			if (IS_8251(com->pc98_if_type))
3064			    if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG))
3065				com_int_Tx_enable(com);
3066#endif
3067			com->obufq.l_head = ioptr;
3068			if (COM_IIR_TXRDYBUG(com->flags)) {
3069				int_ctl_new = int_ctl | IER_ETXRDY;
3070			}
3071			if (ioptr >= com->obufq.l_tail) {
3072				struct lbq	*qp;
3073
3074				qp = com->obufq.l_next;
3075				qp->l_queued = FALSE;
3076				qp = qp->l_next;
3077				if (qp != NULL) {
3078					com->obufq.l_head = qp->l_head;
3079					com->obufq.l_tail = qp->l_tail;
3080					com->obufq.l_next = qp;
3081				} else {
3082					/* output just completed */
3083					if (COM_IIR_TXRDYBUG(com->flags)) {
3084						int_ctl_new = int_ctl & ~IER_ETXRDY;
3085					}
3086					com->state &= ~CS_BUSY;
3087#if defined(PC98)
3088					if (IS_8251(com->pc98_if_type) &&
3089					    pc98_check_i8251_interrupt(com) & IEN_TxFLAG)
3090						com_int_Tx_disable(com);
3091#endif
3092				}
3093				if (!(com->state & CS_ODONE)) {
3094					com_events += LOTS_OF_EVENTS;
3095					com->state |= CS_ODONE;
3096					/* handle at high level ASAP */
3097					sched_swi(sio_fast_ih, SWI_NOSWITCH);
3098				}
3099			}
3100			if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) {
3101#ifdef PC98
3102				if (com->pc98_if_type == COM_IF_RSA98III) {
3103				    int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY);
3104				    outb(com->intr_ctl_port, int_ctl_new);
3105				    outb(com->rsabase + rsa_ier, 0x1d);
3106				} else
3107#endif
3108				outb(com->intr_ctl_port, int_ctl_new);
3109			}
3110		}
3111#ifdef PC98
3112		else if (line_status & LSR_TXRDY) {
3113		    if (IS_8251(com->pc98_if_type))
3114			if (pc98_check_i8251_interrupt(com) & IEN_TxFLAG)
3115			    com_int_Tx_disable(com);
3116		}
3117		if (IS_8251(com->pc98_if_type)) {
3118		    if (com->pc98_8251fifo_enable) {
3119			if ((tmp = inb(I8251F_lsr)) & STS8251F_RxRDY)
3120			    goto more_intr;
3121		    } else {
3122			if ((tmp = inb(com->sts_port)) & STS8251_RxRDY)
3123			    goto more_intr;
3124		    }
3125		}
3126#endif
3127
3128		/* finished? */
3129#ifndef COM_MULTIPORT
3130#ifdef PC98
3131		if (IS_8251(com->pc98_if_type))
3132			return;
3133#endif
3134		if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
3135#endif /* COM_MULTIPORT */
3136			return;
3137	}
3138}
3139
3140static int
3141sioioctl(dev, cmd, data, flag, p)
3142	dev_t		dev;
3143	u_long		cmd;
3144	caddr_t		data;
3145	int		flag;
3146	struct proc	*p;
3147{
3148	struct com_s	*com;
3149	int		error;
3150	int		mynor;
3151	int		s;
3152	struct tty	*tp;
3153#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
3154	u_long		oldcmd;
3155	struct termios	term;
3156#endif
3157
3158	mynor = minor(dev);
3159	com = com_addr(MINOR_TO_UNIT(mynor));
3160	if (com == NULL || com->gone)
3161		return (ENODEV);
3162	if (mynor & CONTROL_MASK) {
3163		struct termios	*ct;
3164
3165		switch (mynor & CONTROL_MASK) {
3166		case CONTROL_INIT_STATE:
3167			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
3168			break;
3169		case CONTROL_LOCK_STATE:
3170			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
3171			break;
3172		default:
3173			return (ENODEV);	/* /dev/nodev */
3174		}
3175		switch (cmd) {
3176		case TIOCSETA:
3177			error = suser(p);
3178			if (error != 0)
3179				return (error);
3180			*ct = *(struct termios *)data;
3181			return (0);
3182		case TIOCGETA:
3183			*(struct termios *)data = *ct;
3184			return (0);
3185		case TIOCGETD:
3186			*(int *)data = TTYDISC;
3187			return (0);
3188		case TIOCGWINSZ:
3189			bzero(data, sizeof(struct winsize));
3190			return (0);
3191		default:
3192			return (ENOTTY);
3193		}
3194	}
3195	tp = com->tp;
3196#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
3197	term = tp->t_termios;
3198	oldcmd = cmd;
3199	error = ttsetcompat(tp, &cmd, data, &term);
3200	if (error != 0)
3201		return (error);
3202	if (cmd != oldcmd)
3203		data = (caddr_t)&term;
3204#endif
3205	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
3206		int	cc;
3207		struct termios *dt = (struct termios *)data;
3208		struct termios *lt = mynor & CALLOUT_MASK
3209				     ? &com->lt_out : &com->lt_in;
3210
3211		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
3212			      | (dt->c_iflag & ~lt->c_iflag);
3213		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
3214			      | (dt->c_oflag & ~lt->c_oflag);
3215		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
3216			      | (dt->c_cflag & ~lt->c_cflag);
3217		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
3218			      | (dt->c_lflag & ~lt->c_lflag);
3219		for (cc = 0; cc < NCCS; ++cc)
3220			if (lt->c_cc[cc] != 0)
3221				dt->c_cc[cc] = tp->t_cc[cc];
3222		if (lt->c_ispeed != 0)
3223			dt->c_ispeed = tp->t_ispeed;
3224		if (lt->c_ospeed != 0)
3225			dt->c_ospeed = tp->t_ospeed;
3226	}
3227	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
3228	if (error != ENOIOCTL)
3229		return (error);
3230	s = spltty();
3231	error = ttioctl(tp, cmd, data, flag);
3232	disc_optim(tp, &tp->t_termios, com);
3233	if (error != ENOIOCTL) {
3234		splx(s);
3235		return (error);
3236	}
3237#ifdef PC98
3238	if (IS_8251(com->pc98_if_type)) {
3239	    switch (cmd) {
3240	    case TIOCSBRK:
3241		com_send_break_on(com);
3242		break;
3243	    case TIOCCBRK:
3244		com_send_break_off(com);
3245		break;
3246	    case TIOCSDTR:
3247		com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS);
3248		break;
3249	    case TIOCCDTR:
3250		com_tiocm_bic(com, TIOCM_DTR);
3251		break;
3252	/*
3253	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
3254	 * changes get undone on the next call to comparam().
3255	 */
3256	    case TIOCMSET:
3257		com_tiocm_set(com, *(int *)data);
3258		break;
3259	    case TIOCMBIS:
3260		com_tiocm_bis(com, *(int *)data);
3261		break;
3262	    case TIOCMBIC:
3263		com_tiocm_bic(com, *(int *)data);
3264		break;
3265	    case TIOCMGET:
3266		*(int *)data = com_tiocm_get(com);
3267		break;
3268	    case TIOCMSDTRWAIT:
3269		/* must be root since the wait applies to following logins */
3270		error = suser(p);
3271		if (error != 0) {
3272			splx(s);
3273			return (error);
3274		}
3275		com->dtr_wait = *(int *)data * hz / 100;
3276		break;
3277	    case TIOCMGDTRWAIT:
3278		*(int *)data = com->dtr_wait * 100 / hz;
3279		break;
3280	    case TIOCTIMESTAMP:
3281		com->do_timestamp = TRUE;
3282		*(struct timeval *)data = com->timestamp;
3283		break;
3284	    case TIOCDCDTIMESTAMP:
3285		com->do_dcd_timestamp = TRUE;
3286		*(struct timeval *)data = com->dcd_timestamp;
3287		break;
3288	    default:
3289		splx(s);
3290		error = pps_ioctl(cmd, data, &com->pps);
3291		if (error == ENODEV)
3292			error = ENOTTY;
3293		return (error);
3294	    }
3295	} else {
3296#endif
3297	switch (cmd) {
3298	case TIOCSBRK:
3299		sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK);
3300		break;
3301	case TIOCCBRK:
3302		sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
3303		break;
3304	case TIOCSDTR:
3305		(void)commctl(com, TIOCM_DTR, DMBIS);
3306		break;
3307	case TIOCCDTR:
3308		(void)commctl(com, TIOCM_DTR, DMBIC);
3309		break;
3310	/*
3311	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
3312	 * changes get undone on the next call to comparam().
3313	 */
3314	case TIOCMSET:
3315		(void)commctl(com, *(int *)data, DMSET);
3316		break;
3317	case TIOCMBIS:
3318		(void)commctl(com, *(int *)data, DMBIS);
3319		break;
3320	case TIOCMBIC:
3321		(void)commctl(com, *(int *)data, DMBIC);
3322		break;
3323	case TIOCMGET:
3324		*(int *)data = commctl(com, 0, DMGET);
3325		break;
3326	case TIOCMSDTRWAIT:
3327		/* must be root since the wait applies to following logins */
3328		error = suser(p);
3329		if (error != 0) {
3330			splx(s);
3331			return (error);
3332		}
3333		com->dtr_wait = *(int *)data * hz / 100;
3334		break;
3335	case TIOCMGDTRWAIT:
3336		*(int *)data = com->dtr_wait * 100 / hz;
3337		break;
3338	case TIOCTIMESTAMP:
3339		com->do_timestamp = TRUE;
3340		*(struct timeval *)data = com->timestamp;
3341		break;
3342	case TIOCDCDTIMESTAMP:
3343		com->do_dcd_timestamp = TRUE;
3344		*(struct timeval *)data = com->dcd_timestamp;
3345		break;
3346	default:
3347		splx(s);
3348		error = pps_ioctl(cmd, data, &com->pps);
3349		if (error == ENODEV)
3350			error = ENOTTY;
3351		return (error);
3352	}
3353#ifdef PC98
3354	}
3355#endif
3356	splx(s);
3357	return (0);
3358}
3359
3360/* software interrupt handler for SWI_TTY */
3361static void
3362siopoll(void *dummy)
3363{
3364	int		unit;
3365	int		intrsave;
3366
3367	if (com_events == 0)
3368		return;
3369repeat:
3370	for (unit = 0; unit < sio_numunits; ++unit) {
3371		struct com_s	*com;
3372		int		incc;
3373		struct tty	*tp;
3374
3375		com = com_addr(unit);
3376		if (com == NULL)
3377			continue;
3378		tp = com->tp;
3379		if (tp == NULL || com->gone) {
3380			/*
3381			 * Discard any events related to never-opened or
3382			 * going-away devices.
3383			 */
3384			intrsave = save_intr();
3385			disable_intr();
3386			COM_LOCK();
3387			incc = com->iptr - com->ibuf;
3388			com->iptr = com->ibuf;
3389			if (com->state & CS_CHECKMSR) {
3390				incc += LOTS_OF_EVENTS;
3391				com->state &= ~CS_CHECKMSR;
3392			}
3393			com_events -= incc;
3394			COM_UNLOCK();
3395			restore_intr(intrsave);
3396			continue;
3397		}
3398		if (com->iptr != com->ibuf) {
3399			intrsave = save_intr();
3400			disable_intr();
3401			COM_LOCK();
3402			sioinput(com);
3403			COM_UNLOCK();
3404			restore_intr(intrsave);
3405		}
3406		if (com->state & CS_CHECKMSR) {
3407			u_char	delta_modem_status;
3408
3409#ifdef PC98
3410			if (!IS_8251(com->pc98_if_type)) {
3411#endif
3412			intrsave = save_intr();
3413			disable_intr();
3414			COM_LOCK();
3415			delta_modem_status = com->last_modem_status
3416					     ^ com->prev_modem_status;
3417			com->prev_modem_status = com->last_modem_status;
3418			com_events -= LOTS_OF_EVENTS;
3419			com->state &= ~CS_CHECKMSR;
3420			COM_UNLOCK();
3421			restore_intr(intrsave);
3422			if (delta_modem_status & MSR_DCD)
3423				(*linesw[tp->t_line].l_modem)
3424					(tp, com->prev_modem_status & MSR_DCD);
3425#ifdef PC98
3426			}
3427#endif
3428		}
3429		if (com->state & CS_ODONE) {
3430			intrsave = save_intr();
3431			disable_intr();
3432			COM_LOCK();
3433			com_events -= LOTS_OF_EVENTS;
3434			com->state &= ~CS_ODONE;
3435			COM_UNLOCK();
3436			restore_intr(intrsave);
3437			if (!(com->state & CS_BUSY)
3438			    && !(com->extra_state & CSE_BUSYCHECK)) {
3439				timeout(siobusycheck, com, hz / 100);
3440				com->extra_state |= CSE_BUSYCHECK;
3441			}
3442			(*linesw[tp->t_line].l_start)(tp);
3443		}
3444		if (com_events == 0)
3445			break;
3446	}
3447	if (com_events >= LOTS_OF_EVENTS)
3448		goto repeat;
3449}
3450
3451static int
3452comparam(tp, t)
3453	struct tty	*tp;
3454	struct termios	*t;
3455{
3456	u_int		cfcr;
3457	int		cflag;
3458	struct com_s	*com;
3459	int		divisor;
3460	u_char		dlbh;
3461	u_char		dlbl;
3462	int		s;
3463	int		unit;
3464	int		intrsave;
3465#ifdef PC98
3466	u_char		param = 0;
3467#endif
3468
3469#ifdef PC98
3470	unit = DEV_TO_UNIT(tp->t_dev);
3471	com = com_addr(unit);
3472
3473	cfcr = 0;
3474	if (IS_8251(com->pc98_if_type)) {
3475	    divisor = pc98_ttspeedtab(com, t->c_ospeed);
3476	} else {
3477	    /* do historical conversions */
3478	    if (t->c_ispeed == 0)
3479		t->c_ispeed = t->c_ospeed;
3480
3481	    /* check requested parameters */
3482	    divisor = ttspeedtab(t->c_ospeed,
3483			if_16550a_type[com->pc98_if_type & 0x0f].speedtab);
3484	}
3485#else
3486	/* do historical conversions */
3487	if (t->c_ispeed == 0)
3488		t->c_ispeed = t->c_ospeed;
3489
3490	/* check requested parameters */
3491	divisor = ttspeedtab(t->c_ospeed, comspeedtab);
3492#endif
3493	if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed))
3494		return (EINVAL);
3495
3496#ifndef PC98
3497	/* parameters are OK, convert them to the com struct and the device */
3498	unit = DEV_TO_UNIT(tp->t_dev);
3499	com = com_addr(unit);
3500	if (com == NULL)
3501		return (ENODEV);
3502#endif
3503	s = spltty();
3504#ifdef PC98
3505	if (IS_8251(com->pc98_if_type)) {
3506		if (divisor == 0)
3507			com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
3508		else
3509			com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
3510	} else
3511#endif
3512	if (divisor == 0)
3513		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
3514	else
3515		(void)commctl(com, TIOCM_DTR, DMBIS);
3516	cflag = t->c_cflag;
3517#ifdef PC98
3518	if (!IS_8251(com->pc98_if_type)) {
3519#endif
3520	switch (cflag & CSIZE) {
3521	case CS5:
3522		cfcr = CFCR_5BITS;
3523		break;
3524	case CS6:
3525		cfcr = CFCR_6BITS;
3526		break;
3527	case CS7:
3528		cfcr = CFCR_7BITS;
3529		break;
3530	default:
3531		cfcr = CFCR_8BITS;
3532		break;
3533	}
3534	if (cflag & PARENB) {
3535		cfcr |= CFCR_PENAB;
3536		if (!(cflag & PARODD))
3537			cfcr |= CFCR_PEVEN;
3538	}
3539	if (cflag & CSTOPB)
3540		cfcr |= CFCR_STOPB;
3541
3542	if (com->hasfifo && divisor != 0) {
3543		/*
3544		 * Use a fifo trigger level low enough so that the input
3545		 * latency from the fifo is less than about 16 msec and
3546		 * the total latency is less than about 30 msec.  These
3547		 * latencies are reasonable for humans.  Serial comms
3548		 * protocols shouldn't expect anything better since modem
3549		 * latencies are larger.
3550		 */
3551		com->fifo_image = t->c_ospeed <= 4800
3552				  ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH;
3553#ifdef COM_ESP
3554		/*
3555		 * The Hayes ESP card needs the fifo DMA mode bit set
3556		 * in compatibility mode.  If not, it will interrupt
3557		 * for each character received.
3558		 */
3559		if (com->esp)
3560			com->fifo_image |= FIFO_DMA_MODE;
3561#endif
3562		sio_setreg(com, com_fifo, com->fifo_image);
3563	}
3564#ifdef PC98
3565	}
3566#endif
3567
3568	/*
3569	 * This returns with interrupts disabled so that we can complete
3570	 * the speed change atomically.  Keeping interrupts disabled is
3571	 * especially important while com_data is hidden.
3572	 */
3573	intrsave = save_intr();
3574	(void) siosetwater(com, t->c_ispeed);
3575
3576#ifdef PC98
3577	if (IS_8251(com->pc98_if_type))
3578		com_cflag_and_speed_set(com, cflag, t->c_ospeed);
3579	else {
3580#endif
3581	if (divisor != 0) {
3582		sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
3583		/*
3584		 * Only set the divisor registers if they would change,
3585		 * since on some 16550 incompatibles (UMC8669F), setting
3586		 * them while input is arriving them loses sync until
3587		 * data stops arriving.
3588		 */
3589		dlbl = divisor & 0xFF;
3590		if (sio_getreg(com, com_dlbl) != dlbl)
3591			sio_setreg(com, com_dlbl, dlbl);
3592		dlbh = (u_int) divisor >> 8;
3593		if (sio_getreg(com, com_dlbh) != dlbh)
3594			sio_setreg(com, com_dlbh, dlbh);
3595	}
3596
3597	sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
3598#ifdef PC98
3599	}
3600#endif
3601
3602	if (!(tp->t_state & TS_TTSTOP))
3603		com->state |= CS_TTGO;
3604
3605	if (cflag & CRTS_IFLOW) {
3606#ifndef PC98
3607		if (com->st16650a) {
3608			sio_setreg(com, com_cfcr, 0xbf);
3609			sio_setreg(com, com_fifo,
3610				   sio_getreg(com, com_fifo) | 0x40);
3611		}
3612#endif
3613		com->state |= CS_RTS_IFLOW;
3614		/*
3615		 * If CS_RTS_IFLOW just changed from off to on, the change
3616		 * needs to be propagated to MCR_RTS.  This isn't urgent,
3617		 * so do it later by calling comstart() instead of repeating
3618		 * a lot of code from comstart() here.
3619		 */
3620	} else if (com->state & CS_RTS_IFLOW) {
3621		com->state &= ~CS_RTS_IFLOW;
3622		/*
3623		 * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
3624		 * on here, since comstart() won't do it later.
3625		 */
3626#ifdef PC98
3627		if (IS_8251(com->pc98_if_type))
3628			com_tiocm_bis(com, TIOCM_RTS);
3629		else
3630			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3631#else
3632		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3633		if (com->st16650a) {
3634			sio_setreg(com, com_cfcr, 0xbf);
3635			sio_setreg(com, com_fifo,
3636				   sio_getreg(com, com_fifo) & ~0x40);
3637		}
3638#endif
3639	}
3640
3641
3642	/*
3643	 * Set up state to handle output flow control.
3644	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
3645	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
3646	 */
3647	com->state |= CS_ODEVREADY;
3648	com->state &= ~CS_CTS_OFLOW;
3649#ifdef PC98
3650	if (com->pc98_if_type == COM_IF_RSA98III) {
3651		param = inb(com->rsabase + rsa_msr);
3652		outb(com->rsabase + rsa_msr, param & 0x14);
3653	}
3654#endif
3655	if (cflag & CCTS_OFLOW) {
3656		com->state |= CS_CTS_OFLOW;
3657#ifdef PC98
3658		if (IS_8251(com->pc98_if_type)) {
3659			if (!(pc98_get_modem_status(com) & TIOCM_CTS))
3660				com->state &= ~CS_ODEVREADY;
3661		} else {
3662			if (com->pc98_if_type == COM_IF_RSA98III) {
3663				/* Set automatic flow control mode */
3664				outb(com->rsabase + rsa_msr, param | 0x08);
3665			} else
3666#endif
3667		if (!(com->last_modem_status & MSR_CTS))
3668			com->state &= ~CS_ODEVREADY;
3669#ifdef PC98
3670		}
3671#else
3672		if (com->st16650a) {
3673			sio_setreg(com, com_cfcr, 0xbf);
3674			sio_setreg(com, com_fifo,
3675				   sio_getreg(com, com_fifo) | 0x80);
3676		}
3677	} else {
3678		if (com->st16650a) {
3679			sio_setreg(com, com_cfcr, 0xbf);
3680			sio_setreg(com, com_fifo,
3681				   sio_getreg(com, com_fifo) & ~0x80);
3682		}
3683#endif
3684	}
3685
3686#ifdef PC98
3687	if (!IS_8251(com->pc98_if_type))
3688#endif
3689	sio_setreg(com, com_cfcr, com->cfcr_image);
3690
3691	/* XXX shouldn't call functions while intrs are disabled. */
3692	disc_optim(tp, t, com);
3693	/*
3694	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
3695	 * unconditionally, but that defeated the careful discarding of
3696	 * stale input in sioopen().
3697	 */
3698	if (com->state >= (CS_BUSY | CS_TTGO))
3699		siointr1(com);
3700
3701	COM_UNLOCK();
3702	restore_intr(intrsave);
3703	splx(s);
3704	comstart(tp);
3705	if (com->ibufold != NULL) {
3706		free(com->ibufold, M_DEVBUF);
3707		com->ibufold = NULL;
3708	}
3709	return (0);
3710}
3711
3712/*
3713 * This function must be called with interrupts enabled and the com_lock
3714 * unlocked.  It will return with interrupts disabled and the com_lock locked.
3715 */
3716static int
3717siosetwater(com, speed)
3718	struct com_s	*com;
3719	speed_t		speed;
3720{
3721	int		cp4ticks;
3722	u_char		*ibuf;
3723	int		ibufsize;
3724	struct tty	*tp;
3725
3726	/*
3727	 * Make the buffer size large enough to handle a softtty interrupt
3728	 * latency of about 2 ticks without loss of throughput or data
3729	 * (about 3 ticks if input flow control is not used or not honoured,
3730	 * but a bit less for CS5-CS7 modes).
3731	 */
3732	cp4ticks = speed / 10 / hz * 4;
3733	for (ibufsize = 128; ibufsize < cp4ticks;)
3734		ibufsize <<= 1;
3735#ifdef PC98
3736	if (com->pc98_if_type == COM_IF_RSA98III)
3737		ibufsize = 2048;
3738#endif
3739	if (ibufsize == com->ibufsize) {
3740		disable_intr();
3741		COM_LOCK();
3742		return (0);
3743	}
3744
3745	/*
3746	 * Allocate input buffer.  The extra factor of 2 in the size is
3747	 * to allow for an error byte for each input byte.
3748	 */
3749	ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
3750	if (ibuf == NULL) {
3751		disable_intr();
3752		COM_LOCK();
3753		return (ENOMEM);
3754	}
3755
3756	/* Initialize non-critical variables. */
3757	com->ibufold = com->ibuf;
3758	com->ibufsize = ibufsize;
3759	tp = com->tp;
3760	if (tp != NULL) {
3761		tp->t_ififosize = 2 * ibufsize;
3762		tp->t_ispeedwat = (speed_t)-1;
3763		tp->t_ospeedwat = (speed_t)-1;
3764	}
3765
3766	/*
3767	 * Read current input buffer, if any.  Continue with interrupts
3768	 * disabled.
3769	 */
3770	disable_intr();
3771	COM_LOCK();
3772	if (com->iptr != com->ibuf)
3773		sioinput(com);
3774
3775	/*-
3776	 * Initialize critical variables, including input buffer watermarks.
3777	 * The external device is asked to stop sending when the buffer
3778	 * exactly reaches high water, or when the high level requests it.
3779	 * The high level is notified immediately (rather than at a later
3780	 * clock tick) when this watermark is reached.
3781	 * The buffer size is chosen so the watermark should almost never
3782	 * be reached.
3783	 * The low watermark is invisibly 0 since the buffer is always
3784	 * emptied all at once.
3785	 */
3786	com->iptr = com->ibuf = ibuf;
3787	com->ibufend = ibuf + ibufsize;
3788	com->ierroff = ibufsize;
3789	com->ihighwater = ibuf + 3 * ibufsize / 4;
3790	return (0);
3791}
3792
3793static void
3794comstart(tp)
3795	struct tty	*tp;
3796{
3797	struct com_s	*com;
3798	int		s;
3799	int		unit;
3800	int		intrsave;
3801
3802	unit = DEV_TO_UNIT(tp->t_dev);
3803	com = com_addr(unit);
3804	if (com == NULL)
3805		return;
3806	s = spltty();
3807	intrsave = save_intr();
3808	disable_intr();
3809	COM_LOCK();
3810	if (tp->t_state & TS_TTSTOP)
3811		com->state &= ~CS_TTGO;
3812	else
3813		com->state |= CS_TTGO;
3814	if (tp->t_state & TS_TBLOCK) {
3815#ifdef PC98
3816		if (IS_8251(com->pc98_if_type)) {
3817		    if ((com_tiocm_get(com) & TIOCM_RTS) &&
3818			(com->state & CS_RTS_IFLOW))
3819			com_tiocm_bic(com, TIOCM_RTS);
3820		} else {
3821		    if ((com->mcr_image & MCR_RTS) &&
3822			(com->state & CS_RTS_IFLOW))
3823			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
3824		}
3825#else
3826		if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
3827			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
3828#endif
3829	} else {
3830#ifdef PC98
3831		if (IS_8251(com->pc98_if_type)) {
3832		    if (!(com_tiocm_get(com) & TIOCM_RTS) &&
3833			com->iptr < com->ihighwater &&
3834			com->state & CS_RTS_IFLOW)
3835			com_tiocm_bis(com, TIOCM_RTS);
3836		} else {
3837		    if (!(com->mcr_image & MCR_RTS) &&
3838			com->iptr < com->ihighwater &&
3839			com->state & CS_RTS_IFLOW)
3840			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3841		}
3842#else
3843		if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
3844		    && com->state & CS_RTS_IFLOW)
3845			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3846#endif
3847	}
3848	COM_UNLOCK();
3849	restore_intr(intrsave);
3850	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
3851		ttwwakeup(tp);
3852		splx(s);
3853		return;
3854	}
3855	if (tp->t_outq.c_cc != 0) {
3856		struct lbq	*qp;
3857		struct lbq	*next;
3858
3859		if (!com->obufs[0].l_queued) {
3860			com->obufs[0].l_tail
3861			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
3862#ifdef PC98
3863						  com->obufsize);
3864#else
3865						  sizeof com->obuf1);
3866#endif
3867			com->obufs[0].l_next = NULL;
3868			com->obufs[0].l_queued = TRUE;
3869			intrsave = save_intr();
3870			disable_intr();
3871			COM_LOCK();
3872			if (com->state & CS_BUSY) {
3873				qp = com->obufq.l_next;
3874				while ((next = qp->l_next) != NULL)
3875					qp = next;
3876				qp->l_next = &com->obufs[0];
3877			} else {
3878				com->obufq.l_head = com->obufs[0].l_head;
3879				com->obufq.l_tail = com->obufs[0].l_tail;
3880				com->obufq.l_next = &com->obufs[0];
3881				com->state |= CS_BUSY;
3882			}
3883			COM_UNLOCK();
3884			restore_intr(intrsave);
3885		}
3886		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
3887			com->obufs[1].l_tail
3888			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
3889#ifdef PC98
3890						  com->obufsize);
3891#else
3892						  sizeof com->obuf2);
3893#endif
3894			com->obufs[1].l_next = NULL;
3895			com->obufs[1].l_queued = TRUE;
3896			intrsave = save_intr();
3897			disable_intr();
3898			COM_LOCK();
3899			if (com->state & CS_BUSY) {
3900				qp = com->obufq.l_next;
3901				while ((next = qp->l_next) != NULL)
3902					qp = next;
3903				qp->l_next = &com->obufs[1];
3904			} else {
3905				com->obufq.l_head = com->obufs[1].l_head;
3906				com->obufq.l_tail = com->obufs[1].l_tail;
3907				com->obufq.l_next = &com->obufs[1];
3908				com->state |= CS_BUSY;
3909			}
3910			COM_UNLOCK();
3911			restore_intr(intrsave);
3912		}
3913		tp->t_state |= TS_BUSY;
3914	}
3915	intrsave = save_intr();
3916	disable_intr();
3917	COM_LOCK();
3918	if (com->state >= (CS_BUSY | CS_TTGO))
3919		siointr1(com);	/* fake interrupt to start output */
3920	COM_UNLOCK();
3921	restore_intr(intrsave);
3922	ttwwakeup(tp);
3923	splx(s);
3924}
3925
3926static void
3927comstop(tp, rw)
3928	struct tty	*tp;
3929	int		rw;
3930{
3931	struct com_s	*com;
3932	int		intrsave;
3933#ifdef PC98
3934	int		rsa98_tmp  = 0;
3935#endif
3936
3937	com = com_addr(DEV_TO_UNIT(tp->t_dev));
3938	if (com == NULL || com->gone)
3939		return;
3940	intrsave = save_intr();
3941	disable_intr();
3942	COM_LOCK();
3943	if (rw & FWRITE) {
3944#ifdef PC98
3945		if (!IS_8251(com->pc98_if_type)) {
3946#endif
3947		if (com->hasfifo)
3948#ifdef COM_ESP
3949		    /* XXX avoid h/w bug. */
3950		    if (!com->esp)
3951#endif
3952			sio_setreg(com, com_fifo,
3953				   FIFO_XMT_RST | com->fifo_image);
3954#ifdef PC98
3955		if (com->pc98_if_type == COM_IF_RSA98III)
3956		    for (rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3957			sio_setreg(com, com_fifo,
3958				   FIFO_XMT_RST | com->fifo_image);
3959		}
3960#endif
3961		com->obufs[0].l_queued = FALSE;
3962		com->obufs[1].l_queued = FALSE;
3963		if (com->state & CS_ODONE)
3964			com_events -= LOTS_OF_EVENTS;
3965		com->state &= ~(CS_ODONE | CS_BUSY);
3966		com->tp->t_state &= ~TS_BUSY;
3967	}
3968	if (rw & FREAD) {
3969#ifdef PC98
3970		if (!IS_8251(com->pc98_if_type)) {
3971		    if (com->pc98_if_type == COM_IF_RSA98III)
3972			for (rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3973			    sio_getreg(com, com_data);
3974#endif
3975		if (com->hasfifo)
3976#ifdef COM_ESP
3977		    /* XXX avoid h/w bug. */
3978		    if (!com->esp)
3979#endif
3980			sio_setreg(com, com_fifo,
3981				   FIFO_RCV_RST | com->fifo_image);
3982#ifdef PC98
3983		}
3984#endif
3985		com_events -= (com->iptr - com->ibuf);
3986		com->iptr = com->ibuf;
3987	}
3988	COM_UNLOCK();
3989	restore_intr(intrsave);
3990	comstart(tp);
3991}
3992
3993static int
3994commctl(com, bits, how)
3995	struct com_s	*com;
3996	int		bits;
3997	int		how;
3998{
3999	int	mcr;
4000	int	msr;
4001	int	intrsave;
4002
4003	if (how == DMGET) {
4004		bits = TIOCM_LE;	/* XXX - always enabled while open */
4005		mcr = com->mcr_image;
4006		if (mcr & MCR_DTR)
4007			bits |= TIOCM_DTR;
4008		if (mcr & MCR_RTS)
4009			bits |= TIOCM_RTS;
4010		msr = com->prev_modem_status;
4011		if (msr & MSR_CTS)
4012			bits |= TIOCM_CTS;
4013		if (msr & MSR_DCD)
4014			bits |= TIOCM_CD;
4015		if (msr & MSR_DSR)
4016			bits |= TIOCM_DSR;
4017		/*
4018		 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
4019		 * more volatile by reading the modem status a lot.  Perhaps
4020		 * we should latch both bits until the status is read here.
4021		 */
4022		if (msr & (MSR_RI | MSR_TERI))
4023			bits |= TIOCM_RI;
4024		return (bits);
4025	}
4026	mcr = 0;
4027	if (bits & TIOCM_DTR)
4028		mcr |= MCR_DTR;
4029	if (bits & TIOCM_RTS)
4030		mcr |= MCR_RTS;
4031	if (com->gone)
4032		return(0);
4033	intrsave = save_intr();
4034	disable_intr();
4035	COM_LOCK();
4036	switch (how) {
4037	case DMSET:
4038		outb(com->modem_ctl_port,
4039		     com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
4040		break;
4041	case DMBIS:
4042		outb(com->modem_ctl_port, com->mcr_image |= mcr);
4043		break;
4044	case DMBIC:
4045		outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
4046		break;
4047	}
4048	COM_UNLOCK();
4049	restore_intr(intrsave);
4050	return (0);
4051}
4052
4053static void
4054siosettimeout()
4055{
4056	struct com_s	*com;
4057	bool_t		someopen;
4058	int		unit;
4059
4060	/*
4061	 * Set our timeout period to 1 second if no polled devices are open.
4062	 * Otherwise set it to max(1/200, 1/hz).
4063	 * Enable timeouts iff some device is open.
4064	 */
4065	untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
4066	sio_timeout = hz;
4067	someopen = FALSE;
4068	for (unit = 0; unit < sio_numunits; ++unit) {
4069		com = com_addr(unit);
4070		if (com != NULL && com->tp != NULL
4071		    && com->tp->t_state & TS_ISOPEN && !com->gone) {
4072			someopen = TRUE;
4073			if (com->poll || com->poll_output) {
4074				sio_timeout = hz > 200 ? hz / 200 : 1;
4075				break;
4076			}
4077		}
4078	}
4079	if (someopen) {
4080		sio_timeouts_until_log = hz / sio_timeout;
4081		sio_timeout_handle = timeout(comwakeup, (void *)NULL,
4082					     sio_timeout);
4083	} else {
4084		/* Flush error messages, if any. */
4085		sio_timeouts_until_log = 1;
4086		comwakeup((void *)NULL);
4087		untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
4088	}
4089}
4090
4091static void
4092comwakeup(chan)
4093	void	*chan;
4094{
4095	struct com_s	*com;
4096	int		unit;
4097	int		intrsave;
4098
4099	sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
4100
4101	/*
4102	 * Recover from lost output interrupts.
4103	 * Poll any lines that don't use interrupts.
4104	 */
4105	for (unit = 0; unit < sio_numunits; ++unit) {
4106		com = com_addr(unit);
4107		if (com != NULL && !com->gone
4108		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
4109			intrsave = save_intr();
4110			disable_intr();
4111			COM_LOCK();
4112			siointr1(com);
4113			COM_UNLOCK();
4114			restore_intr(intrsave);
4115		}
4116	}
4117
4118	/*
4119	 * Check for and log errors, but not too often.
4120	 */
4121	if (--sio_timeouts_until_log > 0)
4122		return;
4123	sio_timeouts_until_log = hz / sio_timeout;
4124	for (unit = 0; unit < sio_numunits; ++unit) {
4125		int	errnum;
4126
4127		com = com_addr(unit);
4128		if (com == NULL)
4129			continue;
4130		if (com->gone)
4131			continue;
4132		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
4133			u_int	delta;
4134			u_long	total;
4135
4136			intrsave = save_intr();
4137			disable_intr();
4138			COM_LOCK();
4139			delta = com->delta_error_counts[errnum];
4140			com->delta_error_counts[errnum] = 0;
4141			COM_UNLOCK();
4142			restore_intr(intrsave);
4143			if (delta == 0)
4144				continue;
4145			total = com->error_counts[errnum] += delta;
4146			log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
4147			    unit, delta, error_desc[errnum],
4148			    delta == 1 ? "" : "s", total);
4149		}
4150	}
4151}
4152
4153#ifdef PC98
4154/* commint is called when modem control line changes */
4155static void
4156commint(dev_t dev)
4157{
4158	register struct tty *tp;
4159	int	stat,delta;
4160	struct com_s *com;
4161	int	mynor,unit;
4162
4163	mynor = minor(dev);
4164	unit = MINOR_TO_UNIT(mynor);
4165	com = com_addr(unit);
4166	tp = com->tp;
4167
4168	stat = com_tiocm_get(com);
4169	delta = com_tiocm_get_delta(com);
4170
4171	if (com->state & CS_CTS_OFLOW) {
4172		if (stat & TIOCM_CTS)
4173			com->state |= CS_ODEVREADY;
4174		else
4175			com->state &= ~CS_ODEVREADY;
4176	}
4177	if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) {
4178	    if (stat & TIOCM_CAR )
4179		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
4180	    else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
4181		/* negate DTR, RTS */
4182		com_tiocm_bic(com, (tp->t_cflag & HUPCL) ?
4183				TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE );
4184		/* disable IENABLE */
4185		com_int_TxRx_disable( com );
4186	    }
4187	}
4188}
4189#endif
4190
4191static void
4192disc_optim(tp, t, com)
4193	struct tty	*tp;
4194	struct termios	*t;
4195	struct com_s	*com;
4196{
4197	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
4198	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
4199	    && (!(t->c_iflag & PARMRK)
4200		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
4201	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
4202	    && linesw[tp->t_line].l_rint == ttyinput)
4203		tp->t_state |= TS_CAN_BYPASS_L_RINT;
4204	else
4205		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
4206	com->hotchar = linesw[tp->t_line].l_hotchar;
4207}
4208
4209/*
4210 * Following are all routines needed for SIO to act as console
4211 */
4212#include <sys/cons.h>
4213
4214struct siocnstate {
4215	u_char	dlbl;
4216	u_char	dlbh;
4217	u_char	ier;
4218	u_char	cfcr;
4219	u_char	mcr;
4220};
4221
4222#ifndef __alpha__
4223static speed_t siocngetspeed __P((Port_t, struct speedtab *));
4224#endif
4225static void siocnclose	__P((struct siocnstate *sp, Port_t iobase));
4226static void siocnopen	__P((struct siocnstate *sp, Port_t iobase, int speed));
4227static void siocntxwait	__P((Port_t iobase));
4228
4229#ifdef __alpha__
4230int siocnattach __P((int port, int speed));
4231int siogdbattach __P((int port, int speed));
4232int siogdbgetc __P((void));
4233void siogdbputc __P((int c));
4234#else
4235static cn_probe_t siocnprobe;
4236static cn_init_t siocninit;
4237#endif
4238static cn_checkc_t siocncheckc;
4239static cn_getc_t siocngetc;
4240static cn_putc_t siocnputc;
4241
4242#ifdef __i386__
4243CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc,
4244	    siocnputc, NULL);
4245#endif
4246
4247/* To get the GDB related variables */
4248#if DDB > 0
4249#include <ddb/ddb.h>
4250#endif
4251
4252static void
4253siocntxwait(iobase)
4254	Port_t	iobase;
4255{
4256	int	timo;
4257
4258	/*
4259	 * Wait for any pending transmission to finish.  Required to avoid
4260	 * the UART lockup bug when the speed is changed, and for normal
4261	 * transmits.
4262	 */
4263	timo = 100000;
4264	while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
4265	       != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
4266		;
4267}
4268
4269#ifndef __alpha__
4270
4271/*
4272 * Read the serial port specified and try to figure out what speed
4273 * it's currently running at.  We're assuming the serial port has
4274 * been initialized and is basicly idle.  This routine is only intended
4275 * to be run at system startup.
4276 *
4277 * If the value read from the serial port doesn't make sense, return 0.
4278 */
4279
4280static speed_t
4281siocngetspeed(iobase, table)
4282	Port_t iobase;
4283	struct speedtab *table;
4284{
4285	int	code;
4286	u_char	dlbh;
4287	u_char	dlbl;
4288	u_char  cfcr;
4289
4290	cfcr = inb(iobase + com_cfcr);
4291	outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
4292
4293	dlbl = inb(iobase + com_dlbl);
4294	dlbh = inb(iobase + com_dlbh);
4295
4296	outb(iobase + com_cfcr, cfcr);
4297
4298	code = dlbh << 8 | dlbl;
4299
4300	for (; table->sp_speed != -1; table++)
4301		if (table->sp_code == code)
4302			return (table->sp_speed);
4303
4304	return (0);	/* didn't match anything sane */
4305}
4306
4307#endif
4308
4309static void
4310siocnopen(sp, iobase, speed)
4311	struct siocnstate	*sp;
4312	Port_t			iobase;
4313	int			speed;
4314{
4315	int	divisor;
4316	u_char	dlbh;
4317	u_char	dlbl;
4318
4319	/*
4320	 * Save all the device control registers except the fifo register
4321	 * and set our default ones (cs8 -parenb speed=comdefaultrate).
4322	 * We can't save the fifo register since it is read-only.
4323	 */
4324	sp->ier = inb(iobase + com_ier);
4325	outb(iobase + com_ier, 0);	/* spltty() doesn't stop siointr() */
4326	siocntxwait(iobase);
4327	sp->cfcr = inb(iobase + com_cfcr);
4328	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
4329	sp->dlbl = inb(iobase + com_dlbl);
4330	sp->dlbh = inb(iobase + com_dlbh);
4331	/*
4332	 * Only set the divisor registers if they would change, since on
4333	 * some 16550 incompatibles (Startech), setting them clears the
4334	 * data input register.  This also reduces the effects of the
4335	 * UMC8669F bug.
4336	 */
4337	divisor = ttspeedtab(speed, comspeedtab);
4338	dlbl = divisor & 0xFF;
4339	if (sp->dlbl != dlbl)
4340		outb(iobase + com_dlbl, dlbl);
4341	dlbh = (u_int) divisor >> 8;
4342	if (sp->dlbh != dlbh)
4343		outb(iobase + com_dlbh, dlbh);
4344	outb(iobase + com_cfcr, CFCR_8BITS);
4345	sp->mcr = inb(iobase + com_mcr);
4346	/*
4347	 * We don't want interrupts, but must be careful not to "disable"
4348	 * them by clearing the MCR_IENABLE bit, since that might cause
4349	 * an interrupt by floating the IRQ line.
4350	 */
4351	outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
4352}
4353
4354static void
4355siocnclose(sp, iobase)
4356	struct siocnstate	*sp;
4357	Port_t			iobase;
4358{
4359	/*
4360	 * Restore the device control registers.
4361	 */
4362	siocntxwait(iobase);
4363	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
4364	if (sp->dlbl != inb(iobase + com_dlbl))
4365		outb(iobase + com_dlbl, sp->dlbl);
4366	if (sp->dlbh != inb(iobase + com_dlbh))
4367		outb(iobase + com_dlbh, sp->dlbh);
4368	outb(iobase + com_cfcr, sp->cfcr);
4369	/*
4370	 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
4371	 */
4372	outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
4373	outb(iobase + com_ier, sp->ier);
4374}
4375
4376#ifndef __alpha__
4377
4378static void
4379siocnprobe(cp)
4380	struct consdev	*cp;
4381{
4382	speed_t			boot_speed;
4383	u_char			cfcr;
4384	int			s, unit;
4385	struct siocnstate	sp;
4386
4387	/*
4388	 * Find our first enabled console, if any.  If it is a high-level
4389	 * console device, then initialize it and return successfully.
4390	 * If it is a low-level console device, then initialize it and
4391	 * return unsuccessfully.  It must be initialized in both cases
4392	 * for early use by console drivers and debuggers.  Initializing
4393	 * the hardware is not necessary in all cases, since the i/o
4394	 * routines initialize it on the fly, but it is necessary if
4395	 * input might arrive while the hardware is switched back to an
4396	 * uninitialized state.  We can't handle multiple console devices
4397	 * yet because our low-level routines don't take a device arg.
4398	 * We trust the user to set the console flags properly so that we
4399	 * don't need to probe.
4400	 */
4401	cp->cn_pri = CN_DEAD;
4402
4403	for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
4404		int flags;
4405		int disabled;
4406		if (resource_int_value("sio", unit, "disabled", &disabled) == 0) {
4407			if (disabled)
4408				continue;
4409		}
4410		if (resource_int_value("sio", unit, "flags", &flags))
4411			continue;
4412		if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) {
4413			int port;
4414			Port_t iobase;
4415
4416			if (resource_int_value("sio", unit, "port", &port))
4417				continue;
4418			iobase = port;
4419			s = spltty();
4420			if (boothowto & RB_SERIAL) {
4421				boot_speed = siocngetspeed(iobase, comspeedtab);
4422				if (boot_speed)
4423					comdefaultrate = boot_speed;
4424			}
4425
4426			/*
4427			 * Initialize the divisor latch.  We can't rely on
4428			 * siocnopen() to do this the first time, since it
4429			 * avoids writing to the latch if the latch appears
4430			 * to have the correct value.  Also, if we didn't
4431			 * just read the speed from the hardware, then we
4432			 * need to set the speed in hardware so that
4433			 * switching it later is null.
4434			 */
4435			cfcr = inb(iobase + com_cfcr);
4436			outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
4437			outb(iobase + com_dlbl,
4438			     COMBRD(comdefaultrate) & 0xff);
4439			outb(iobase + com_dlbh,
4440			     (u_int) COMBRD(comdefaultrate) >> 8);
4441			outb(iobase + com_cfcr, cfcr);
4442
4443			siocnopen(&sp, iobase, comdefaultrate);
4444
4445			splx(s);
4446			if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) {
4447				cp->cn_dev = makedev(CDEV_MAJOR, unit);
4448				cp->cn_pri = COM_FORCECONSOLE(flags)
4449					     || boothowto & RB_SERIAL
4450					     ? CN_REMOTE : CN_NORMAL;
4451				siocniobase = iobase;
4452				siocnunit = unit;
4453			}
4454			if (COM_DEBUGGER(flags)) {
4455				printf("sio%d: gdb debugging port\n", unit);
4456				siogdbiobase = iobase;
4457				siogdbunit = unit;
4458#if DDB > 0
4459				gdbdev = makedev(CDEV_MAJOR, unit);
4460				gdb_getc = siocngetc;
4461				gdb_putc = siocnputc;
4462#endif
4463			}
4464		}
4465	}
4466#ifdef	__i386__
4467#if DDB > 0
4468	/*
4469	 * XXX Ugly Compatability.
4470	 * If no gdb port has been specified, set it to be the console
4471	 * as some configuration files don't specify the gdb port.
4472	 */
4473	if (gdbdev == NODEV && (boothowto & RB_GDB)) {
4474		printf("Warning: no GDB port specified. Defaulting to sio%d.\n",
4475			siocnunit);
4476		printf("Set flag 0x80 on desired GDB port in your\n");
4477		printf("configuration file (currently sio only).\n");
4478		siogdbiobase = siocniobase;
4479		siogdbunit = siocnunit;
4480		gdbdev = makedev(CDEV_MAJOR, siocnunit);
4481		gdb_getc = siocngetc;
4482		gdb_putc = siocnputc;
4483	}
4484#endif
4485#endif
4486}
4487
4488static void
4489siocninit(cp)
4490	struct consdev	*cp;
4491{
4492	comconsole = DEV_TO_UNIT(cp->cn_dev);
4493}
4494
4495#endif
4496
4497#ifdef __alpha__
4498
4499CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc, NULL);
4500
4501int
4502siocnattach(port, speed)
4503	int port;
4504	int speed;
4505{
4506	int			s;
4507	u_char			cfcr;
4508	struct siocnstate	sp;
4509
4510	siocniobase = port;
4511	comdefaultrate = speed;
4512	sio_consdev.cn_pri = CN_NORMAL;
4513	sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0);
4514
4515	s = spltty();
4516
4517	/*
4518	 * Initialize the divisor latch.  We can't rely on
4519	 * siocnopen() to do this the first time, since it
4520	 * avoids writing to the latch if the latch appears
4521	 * to have the correct value.  Also, if we didn't
4522	 * just read the speed from the hardware, then we
4523	 * need to set the speed in hardware so that
4524	 * switching it later is null.
4525	 */
4526	cfcr = inb(siocniobase + com_cfcr);
4527	outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr);
4528	outb(siocniobase + com_dlbl,
4529	     COMBRD(comdefaultrate) & 0xff);
4530	outb(siocniobase + com_dlbh,
4531	     (u_int) COMBRD(comdefaultrate) >> 8);
4532	outb(siocniobase + com_cfcr, cfcr);
4533
4534	siocnopen(&sp, siocniobase, comdefaultrate);
4535	splx(s);
4536
4537	cn_tab = &sio_consdev;
4538	return (0);
4539}
4540
4541int
4542siogdbattach(port, speed)
4543	int port;
4544	int speed;
4545{
4546	int			s;
4547	u_char			cfcr;
4548	struct siocnstate	sp;
4549	int			unit = 1;	/* XXX !!! */
4550
4551	siogdbiobase = port;
4552	gdbdefaultrate = speed;
4553
4554	printf("sio%d: gdb debugging port\n", unit);
4555	siogdbunit = unit;
4556#if DDB > 0
4557	gdbdev = makedev(CDEV_MAJOR, unit);
4558	gdb_getc = siocngetc;
4559	gdb_putc = siocnputc;
4560#endif
4561
4562	s = spltty();
4563
4564	/*
4565	 * Initialize the divisor latch.  We can't rely on
4566	 * siocnopen() to do this the first time, since it
4567	 * avoids writing to the latch if the latch appears
4568	 * to have the correct value.  Also, if we didn't
4569	 * just read the speed from the hardware, then we
4570	 * need to set the speed in hardware so that
4571	 * switching it later is null.
4572	 */
4573	cfcr = inb(siogdbiobase + com_cfcr);
4574	outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr);
4575	outb(siogdbiobase + com_dlbl,
4576	     COMBRD(gdbdefaultrate) & 0xff);
4577	outb(siogdbiobase + com_dlbh,
4578	     (u_int) COMBRD(gdbdefaultrate) >> 8);
4579	outb(siogdbiobase + com_cfcr, cfcr);
4580
4581	siocnopen(&sp, siogdbiobase, gdbdefaultrate);
4582	splx(s);
4583
4584	return (0);
4585}
4586
4587#endif
4588
4589static int
4590siocncheckc(dev)
4591	dev_t	dev;
4592{
4593	int	c;
4594	Port_t	iobase;
4595	int	s;
4596	struct siocnstate	sp;
4597
4598	if (minor(dev) == siogdbunit)
4599		iobase = siogdbiobase;
4600	else
4601		iobase = siocniobase;
4602	s = spltty();
4603	siocnopen(&sp, iobase, comdefaultrate);
4604	if (inb(iobase + com_lsr) & LSR_RXRDY)
4605		c = inb(iobase + com_data);
4606	else
4607		c = -1;
4608	siocnclose(&sp, iobase);
4609	splx(s);
4610	return (c);
4611}
4612
4613
4614int
4615siocngetc(dev)
4616	dev_t	dev;
4617{
4618	int	c;
4619	Port_t	iobase;
4620	int	s;
4621	struct siocnstate	sp;
4622
4623	if (minor(dev) == siogdbunit)
4624		iobase = siogdbiobase;
4625	else
4626		iobase = siocniobase;
4627	s = spltty();
4628	siocnopen(&sp, iobase, comdefaultrate);
4629	while (!(inb(iobase + com_lsr) & LSR_RXRDY))
4630		;
4631	c = inb(iobase + com_data);
4632	siocnclose(&sp, iobase);
4633	splx(s);
4634	return (c);
4635}
4636
4637void
4638siocnputc(dev, c)
4639	dev_t	dev;
4640	int	c;
4641{
4642	int	s;
4643	struct siocnstate	sp;
4644	Port_t	iobase;
4645
4646	if (minor(dev) == siogdbunit)
4647		iobase = siogdbiobase;
4648	else
4649		iobase = siocniobase;
4650	s = spltty();
4651	siocnopen(&sp, iobase, comdefaultrate);
4652	siocntxwait(iobase);
4653	outb(iobase + com_data, c);
4654	siocnclose(&sp, iobase);
4655	splx(s);
4656}
4657
4658#ifdef __alpha__
4659int
4660siogdbgetc()
4661{
4662	int	c;
4663	Port_t	iobase;
4664	int	s;
4665	struct siocnstate	sp;
4666
4667	iobase = siogdbiobase;
4668	s = spltty();
4669	siocnopen(&sp, iobase, gdbdefaultrate);
4670	while (!(inb(iobase + com_lsr) & LSR_RXRDY))
4671		;
4672	c = inb(iobase + com_data);
4673	siocnclose(&sp, iobase);
4674	splx(s);
4675	return (c);
4676}
4677
4678void
4679siogdbputc(c)
4680	int	c;
4681{
4682	int	s;
4683	struct siocnstate	sp;
4684
4685	s = spltty();
4686	siocnopen(&sp, siogdbiobase, gdbdefaultrate);
4687	siocntxwait(siogdbiobase);
4688	outb(siogdbiobase + com_data, c);
4689	siocnclose(&sp, siogdbiobase);
4690	splx(s);
4691}
4692#endif
4693
4694DRIVER_MODULE(sio, isa, sio_isa_driver, sio_devclass, 0, 0);
4695#if NCARD > 0
4696DRIVER_MODULE(sio, pccard, sio_pccard_driver, sio_devclass, 0, 0);
4697#endif
4698#if NPCI > 0
4699DRIVER_MODULE(sio, pci, sio_pci_driver, sio_devclass, 0, 0);
4700#endif
4701
4702#ifdef PC98
4703/*
4704 *  pc98 local function
4705 */
4706
4707static void
4708com_tiocm_set(struct com_s *com, int msr)
4709{
4710	int	s;
4711	int	tmp = 0;
4712	int	mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS;
4713
4714	s=spltty();
4715	com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) )
4716	   | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4717	tmp |= (CMD8251_TxEN|CMD8251_RxEN);
4718	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4719	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4720	pc98_i8251_clear_or_cmd( com, mask, tmp );
4721	splx(s);
4722}
4723
4724static void
4725com_tiocm_bis(struct com_s *com, int msr)
4726{
4727	int	s;
4728	int	tmp = 0;
4729
4730	s=spltty();
4731	com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4732	tmp |= CMD8251_TxEN|CMD8251_RxEN;
4733	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4734	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4735
4736	pc98_i8251_or_cmd( com, tmp );
4737	splx(s);
4738}
4739
4740static void
4741com_tiocm_bic(struct com_s *com, int msr)
4742{
4743	int	s;
4744	int	tmp = msr;
4745
4746	s=spltty();
4747	com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4748	if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4749	if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4750
4751	pc98_i8251_clear_cmd( com, tmp );
4752	splx(s);
4753}
4754
4755static int
4756com_tiocm_get(struct com_s *com)
4757{
4758	return( com->pc98_prev_modem_status );
4759}
4760
4761static int
4762com_tiocm_get_delta(struct com_s *com)
4763{
4764	int	tmp;
4765
4766	tmp = com->pc98_modem_delta;
4767	com->pc98_modem_delta = 0;
4768	return( tmp );
4769}
4770
4771/* convert to TIOCM_?? ( ioctl.h ) */
4772static int
4773pc98_get_modem_status(struct com_s *com)
4774{
4775	register int	msr;
4776
4777	msr = com->pc98_prev_modem_status
4778			& ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4779	if (com->pc98_8251fifo_enable) {
4780		int	stat2;
4781
4782		stat2 = inb(I8251F_msr);
4783		if ( stat2 & CICSCDF_CD ) msr |= TIOCM_CAR;
4784		if ( stat2 & CICSCDF_CI ) msr |= TIOCM_RI;
4785		if ( stat2 & CICSCDF_DR ) msr |= TIOCM_DSR;
4786		if ( stat2 & CICSCDF_CS ) msr |= TIOCM_CTS;
4787#if COM_CARRIER_DETECT_EMULATE
4788		if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
4789			msr |= TIOCM_CAR;
4790		}
4791#endif
4792	} else {
4793		int	stat, stat2;
4794
4795		stat  = inb(com->sts_port);
4796		stat2 = inb(com->in_modem_port);
4797		if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR;
4798		if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI;
4799		if (   stat & STS8251_DSR ) msr |= TIOCM_DSR;
4800		if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS;
4801#if COM_CARRIER_DETECT_EMULATE
4802		if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
4803			msr |= TIOCM_CAR;
4804		}
4805#endif
4806	}
4807	return(msr);
4808}
4809
4810static void
4811pc98_check_msr(void* chan)
4812{
4813	int	msr, delta;
4814	int	s;
4815	register struct tty *tp;
4816	struct	com_s *com;
4817	int	mynor;
4818	int	unit;
4819	dev_t	dev;
4820
4821	dev=(dev_t)chan;
4822	mynor = minor(dev);
4823	unit = MINOR_TO_UNIT(mynor);
4824	com = com_addr(unit);
4825	tp = com->tp;
4826
4827	s = spltty();
4828	msr = pc98_get_modem_status(com);
4829	/* make change flag */
4830	delta = msr ^ com->pc98_prev_modem_status;
4831	if ( delta & TIOCM_CAR ) {
4832	    if ( com->modem_car_chg_timer ) {
4833		if ( -- com->modem_car_chg_timer )
4834		    msr ^= TIOCM_CAR;
4835	    } else {
4836		if ((com->modem_car_chg_timer = (msr & TIOCM_CAR) ?
4837		     DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE) != 0)
4838		    msr ^= TIOCM_CAR;
4839	    }
4840	} else
4841	    com->modem_car_chg_timer = 0;
4842	delta = ( msr ^ com->pc98_prev_modem_status ) &
4843			(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4844	com->pc98_prev_modem_status = msr;
4845	delta = ( com->pc98_modem_delta |= delta );
4846	splx(s);
4847	if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) {
4848		if ( delta ) {
4849			commint(dev);
4850		}
4851		timeout(pc98_check_msr, (caddr_t)dev,
4852					PC98_CHECK_MODEM_INTERVAL);
4853	} else {
4854		com->modem_checking = 0;
4855	}
4856}
4857
4858static void
4859pc98_msrint_start(dev_t dev)
4860{
4861	struct	com_s *com;
4862	int	mynor;
4863	int	unit;
4864	int	s = spltty();
4865
4866	mynor = minor(dev);
4867	unit = MINOR_TO_UNIT(mynor);
4868	com = com_addr(unit);
4869	/* modem control line check routine envoke interval is 1/10 sec */
4870	if ( com->modem_checking == 0 ) {
4871		com->pc98_prev_modem_status = pc98_get_modem_status(com);
4872		com->pc98_modem_delta = 0;
4873		timeout(pc98_check_msr, (caddr_t)dev,
4874					PC98_CHECK_MODEM_INTERVAL);
4875		com->modem_checking = 1;
4876	}
4877	splx(s);
4878}
4879
4880static void
4881pc98_disable_i8251_interrupt(struct com_s *com, int mod)
4882{
4883	/* disable interrupt */
4884	register int	tmp;
4885
4886	mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4887	COM_INT_DISABLE
4888	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4889	outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp );
4890	COM_INT_ENABLE
4891}
4892
4893static void
4894pc98_enable_i8251_interrupt(struct com_s *com, int mod)
4895{
4896	register int	tmp;
4897
4898	COM_INT_DISABLE
4899	tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4900	outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp );
4901	COM_INT_ENABLE
4902}
4903
4904static int
4905pc98_check_i8251_interrupt(struct com_s *com)
4906{
4907	return ( com->intr_enable & 0x07 );
4908}
4909
4910static void
4911pc98_i8251_clear_cmd(struct com_s *com, int x)
4912{
4913	int	tmp;
4914
4915	COM_INT_DISABLE
4916	tmp = com->pc98_prev_siocmd & ~(x);
4917	if (com->pc98_8251fifo_enable)
4918	    outb(I8251F_fcr, 0);
4919	outb(com->cmd_port, tmp);
4920	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4921	if (com->pc98_8251fifo_enable)
4922	    outb(I8251F_fcr, CTRL8251F_ENABLE);
4923	COM_INT_ENABLE
4924}
4925
4926static void
4927pc98_i8251_or_cmd(struct com_s *com, int x)
4928{
4929	int	tmp;
4930
4931	COM_INT_DISABLE
4932	if (com->pc98_8251fifo_enable)
4933	    outb(I8251F_fcr, 0);
4934	tmp = com->pc98_prev_siocmd | (x);
4935	outb(com->cmd_port, tmp);
4936	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4937	if (com->pc98_8251fifo_enable)
4938	    outb(I8251F_fcr, CTRL8251F_ENABLE);
4939	COM_INT_ENABLE
4940}
4941
4942static void
4943pc98_i8251_set_cmd(struct com_s *com, int x)
4944{
4945	int	tmp;
4946
4947	COM_INT_DISABLE
4948	if (com->pc98_8251fifo_enable)
4949	    outb(I8251F_fcr, 0);
4950	tmp = (x);
4951	outb(com->cmd_port, tmp);
4952	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4953	if (com->pc98_8251fifo_enable)
4954	    outb(I8251F_fcr, CTRL8251F_ENABLE);
4955	COM_INT_ENABLE
4956}
4957
4958static void
4959pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x)
4960{
4961	int	tmp;
4962	COM_INT_DISABLE
4963	if (com->pc98_8251fifo_enable)
4964	    outb(I8251F_fcr, 0);
4965	tmp = com->pc98_prev_siocmd & ~(clr);
4966	tmp |= (x);
4967	outb(com->cmd_port, tmp);
4968	com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4969	if (com->pc98_8251fifo_enable)
4970	    outb(I8251F_fcr, CTRL8251F_ENABLE);
4971	COM_INT_ENABLE
4972}
4973
4974static int
4975pc98_i8251_get_cmd(struct com_s *com)
4976{
4977	return com->pc98_prev_siocmd;
4978}
4979
4980static int
4981pc98_i8251_get_mod(struct com_s *com)
4982{
4983	return com->pc98_prev_siomod;
4984}
4985
4986static void
4987pc98_i8251_reset(struct com_s *com, int mode, int command)
4988{
4989	if (com->pc98_8251fifo_enable)
4990	    outb(I8251F_fcr, 0);
4991	outb(com->cmd_port, 0);	/* dummy */
4992	DELAY(2);
4993	outb(com->cmd_port, 0);	/* dummy */
4994	DELAY(2);
4995	outb(com->cmd_port, 0);	/* dummy */
4996	DELAY(2);
4997	outb(com->cmd_port, CMD8251_RESET);	/* internal reset */
4998	DELAY(2);
4999	outb(com->cmd_port, mode );	/* mode register */
5000	com->pc98_prev_siomod = mode;
5001	DELAY(2);
5002	pc98_i8251_set_cmd( com, (command|CMD8251_ER) );
5003	DELAY(10);
5004	if (com->pc98_8251fifo_enable)
5005	    outb(I8251F_fcr, CTRL8251F_ENABLE |
5006		 CTRL8251F_XMT_RST | CTRL8251F_RCV_RST);
5007}
5008
5009static void
5010pc98_check_sysclock(void)
5011{
5012	/* get system clock from port */
5013	if ( pc98_machine_type & M_8M ) {
5014	/* 8 MHz system & H98 */
5015		sysclock = 8;
5016	} else {
5017	/* 5 MHz system */
5018		sysclock = 5;
5019	}
5020}
5021
5022static void
5023com_cflag_and_speed_set( struct com_s *com, int cflag, int speed)
5024{
5025	int	cfcr=0, count;
5026	int	previnterrupt;
5027
5028	count = pc98_ttspeedtab( com, speed );
5029	if ( count < 0 ) return;
5030
5031	previnterrupt = pc98_check_i8251_interrupt(com);
5032	pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx );
5033
5034	switch ( cflag&CSIZE ) {
5035	  case CS5:
5036		cfcr = MOD8251_5BITS; break;
5037	  case CS6:
5038		cfcr = MOD8251_6BITS; break;
5039	  case CS7:
5040		cfcr = MOD8251_7BITS; break;
5041	  case CS8:
5042		cfcr = MOD8251_8BITS; break;
5043	}
5044	if ( cflag&PARENB ) {
5045	    if ( cflag&PARODD )
5046		cfcr |= MOD8251_PODD;
5047	    else
5048		cfcr |= MOD8251_PEVEN;
5049	} else
5050		cfcr |= MOD8251_PDISAB;
5051
5052	if ( cflag&CSTOPB )
5053		cfcr |= MOD8251_STOP2;
5054	else
5055		cfcr |= MOD8251_STOP1;
5056
5057	if ( count & 0x10000 )
5058		cfcr |= MOD8251_CLKX1;
5059	else
5060		cfcr |= MOD8251_CLKX16;
5061
5062	if (epson_machine_id != 0x20) {	/* XXX */
5063		int	tmp;
5064		while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP))
5065			;
5066	}
5067	/* set baud rate from ospeed */
5068	pc98_set_baud_rate( com, count );
5069
5070	if ( cfcr != pc98_i8251_get_mod(com) )
5071		pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) );
5072
5073	pc98_enable_i8251_interrupt( com, previnterrupt );
5074}
5075
5076static int
5077pc98_ttspeedtab(struct com_s *com, int speed)
5078{
5079	int	if_type, effect_sp, count = -1, mod;
5080
5081	if_type = com->pc98_if_type & 0x0f;
5082
5083	switch (com->pc98_if_type) {
5084	case COM_IF_INTERNAL:
5085	    if (PC98SIO_baud_rate_port(if_type) != -1) {
5086		count = ttspeedtab(speed, if_8251_type[if_type].speedtab);
5087		if (count > 0) {
5088		    count |= COM1_EXT_CLOCK;
5089		    break;
5090		}
5091	    }
5092
5093	    /* for *1CLK asynchronous! mode, TEFUTEFU */
5094	    mod = (sysclock == 5) ? 2457600 : 1996800;
5095	    effect_sp = ttspeedtab( speed, pc98speedtab );
5096	    if ( effect_sp < 0 )	/* XXX */
5097		effect_sp = ttspeedtab( (speed - 1), pc98speedtab );
5098	    if ( effect_sp <= 0 )
5099		return effect_sp;
5100	    if ( effect_sp == speed )
5101		mod /= 16;
5102	    if ( mod % effect_sp )
5103		return(-1);
5104	    count = mod / effect_sp;
5105	    if ( count > 65535 )
5106		return(-1);
5107	    if ( effect_sp != speed )
5108		count |= 0x10000;
5109	    break;
5110	case COM_IF_PC9861K_1:
5111	case COM_IF_PC9861K_2:
5112	    count = 1;
5113	    break;
5114	case COM_IF_IND_SS_1:
5115	case COM_IF_IND_SS_2:
5116	case COM_IF_PIO9032B_1:
5117	case COM_IF_PIO9032B_2:
5118	    if ( speed == 0 ) return 0;
5119	    count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
5120	    break;
5121	case COM_IF_B98_01_1:
5122	case COM_IF_B98_01_2:
5123	    if ( speed == 0 ) return 0;
5124	    count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
5125#ifdef B98_01_OLD
5126	    if (count == 0 || count == 1) {
5127		count += 4;
5128		count |= 0x20000;  /* x1 mode for 76800 and 153600 */
5129	    }
5130#endif
5131	    break;
5132	}
5133
5134	return count;
5135}
5136
5137static void
5138pc98_set_baud_rate( struct com_s *com, int count )
5139{
5140	int	if_type, io, s;
5141
5142	if_type = com->pc98_if_type & 0x0f;
5143	io = rman_get_start(com->ioportres) & 0xff00;
5144
5145	switch (com->pc98_if_type) {
5146	case COM_IF_INTERNAL:
5147	    if (PC98SIO_baud_rate_port(if_type) != -1) {
5148		if (count & COM1_EXT_CLOCK) {
5149		    outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff);
5150		    break;
5151		} else {
5152		    outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09);
5153		}
5154	    }
5155
5156	    if ( count < 0 ) {
5157		printf( "[ Illegal count : %d ]", count );
5158		return;
5159	    } else if ( count == 0 )
5160		return;
5161	    /* set i8253 */
5162	    s = splclock();
5163	    if (count != 3)
5164		outb( 0x77, 0xb6 );
5165	    else
5166		outb( 0x77, 0xb4 );
5167	    outb( 0x5f, 0);
5168	    outb( 0x75, count & 0xff );
5169	    outb( 0x5f, 0);
5170	    outb( 0x75, (count >> 8) & 0xff );
5171	    splx(s);
5172	    break;
5173	case COM_IF_IND_SS_1:
5174	case COM_IF_IND_SS_2:
5175	    outb(io | PC98SIO_intr_ctrl_port(if_type), 0);
5176	    outb(io | PC98SIO_baud_rate_port(if_type), 0);
5177	    outb(io | PC98SIO_baud_rate_port(if_type), 0xc0);
5178	    outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80);
5179	    outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff);
5180	    break;
5181	case COM_IF_PIO9032B_1:
5182	case COM_IF_PIO9032B_2:
5183	    outb(io | PC98SIO_baud_rate_port(if_type), count);
5184	    break;
5185	case COM_IF_B98_01_1:
5186	case COM_IF_B98_01_2:
5187	    outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f);
5188#ifdef B98_01_OLD
5189	    /*
5190	     * Some old B98_01 board should be controlled
5191	     * in different way, but this hasn't been tested yet.
5192	     */
5193	    outb(io | PC98SIO_func_port(if_type),
5194		 (count & 0x20000) ? 0xf0 : 0xf2);
5195#endif
5196	    break;
5197	}
5198}
5199static int
5200pc98_check_if_type(device_t dev, struct siodev *iod)
5201{
5202	int	irr, io, if_type, tmp;
5203	static  short	irq_tab[2][8] = {
5204		{  3,  5,  6,  9, 10, 12, 13, -1},
5205		{  3, 10, 12, 13,  5,  6,  9, -1}
5206	};
5207
5208	if_type = iod->if_type & 0x0f;
5209	iod->irq = 0;
5210	io = isa_get_port(dev) & 0xff00;
5211
5212	if (IS_8251(iod->if_type)) {
5213	    if (PC98SIO_func_port(if_type) != -1) {
5214		outb(io | PC98SIO_func_port(if_type), 0xf2);
5215		tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab);
5216		if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1)
5217		    outb(io | PC98SIO_baud_rate_port(if_type), tmp);
5218	    }
5219
5220	    iod->cmd  = io | PC98SIO_cmd_port(if_type);
5221	    iod->sts  = io | PC98SIO_sts_port(if_type);
5222	    iod->mod  = io | PC98SIO_in_modem_port(if_type);
5223	    iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type);
5224
5225	    if (iod->if_type == COM_IF_INTERNAL) {
5226		iod->irq = 4;
5227
5228		if (pc98_check_8251vfast()) {
5229			PC98SIO_baud_rate_port(if_type) = I8251F_div;
5230			if_8251_type[if_type].speedtab = pc98fast_speedtab;
5231		}
5232	    } else {
5233		tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask;
5234		if ((isa_get_port(dev) & 0xff) == IO_COM2)
5235		    iod->irq = irq_tab[0][tmp];
5236		else
5237		    iod->irq = irq_tab[1][tmp];
5238	    }
5239	} else {
5240	    irr = if_16550a_type[if_type].irr_read;
5241#ifdef COM_MULTIPORT
5242	    if (!COM_ISMULTIPORT(device_get_flags(dev)) ||
5243		    device_get_unit(dev) == COM_MPMASTER(device_get_flags(dev)))
5244#endif
5245	    if (irr != -1) {
5246		tmp = inb(io | irr);
5247		if (isa_get_port(dev) & 0x01)	/* XXX depend on RSB-384 */
5248		    iod->irq = irq_tab[1][tmp >> 3];
5249		else
5250		    iod->irq = irq_tab[0][tmp & 0x07];
5251	    }
5252	}
5253	if ( iod->irq == -1 ) return -1;
5254
5255	return 0;
5256}
5257static void
5258pc98_set_ioport(struct com_s *com)
5259{
5260	int	if_type = com->pc98_if_type & 0x0f;
5261	Port_t	io = rman_get_start(com->ioportres) & 0xff00;
5262
5263	pc98_check_sysclock();
5264	com->data_port		= io | PC98SIO_data_port(if_type);
5265	com->cmd_port		= io | PC98SIO_cmd_port(if_type);
5266	com->sts_port		= io | PC98SIO_sts_port(if_type);
5267	com->in_modem_port	= io | PC98SIO_in_modem_port(if_type);
5268	com->intr_ctrl_port	= io | PC98SIO_intr_ctrl_port(if_type);
5269}
5270static int
5271pc98_check_8251vfast(void)
5272{
5273    int	i;
5274
5275    outb(I8251F_div, 0x8c);
5276    DELAY(10);
5277    for (i = 0; i < 100; i++) {
5278	if ((inb(I8251F_div) & 0x80) != 0) {
5279	    i = 0;
5280	    break;
5281	}
5282	DELAY(1);
5283    }
5284    outb(I8251F_div, 0);
5285    DELAY(10);
5286    for (; i < 100; i++) {
5287	if ((inb(I8251F_div) & 0x80) == 0)
5288	    return 1;
5289	DELAY(1);
5290    }
5291
5292    return 0;
5293}
5294static int
5295pc98_check_8251fifo(void)
5296{
5297    u_char	tmp1, tmp2;
5298
5299    tmp1 = inb(I8251F_iir);
5300    DELAY(10);
5301    tmp2 = inb(I8251F_iir);
5302    if (((tmp1 ^ tmp2) & 0x40) != 0 && ((tmp1 | tmp2) & 0x20) == 0)
5303	return 1;
5304
5305    return 0;
5306}
5307#endif /* PC98 defined */
5308