sio.c revision 58848
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/dev/sio/sio.c 58848 2000-03-31 07:09:08Z peter $
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 "sio.h"
44
45/*
46 * Serial driver, based on 386BSD-0.1 com driver.
47 * Mostly rewritten to use pseudo-DMA.
48 * Works for National Semiconductor NS8250-NS16550AF UARTs.
49 * COM driver, based on HP dca driver.
50 *
51 * Changes for PC-Card integration:
52 *	- Added PC-Card driver table and handlers
53 */
54#include <sys/param.h>
55#include <sys/systm.h>
56#include <sys/reboot.h>
57#include <sys/malloc.h>
58#include <sys/tty.h>
59#include <sys/proc.h>
60#include <sys/module.h>
61#include <sys/conf.h>
62#include <sys/dkstat.h>
63#include <sys/fcntl.h>
64#include <sys/interrupt.h>
65#include <sys/kernel.h>
66#include <sys/syslog.h>
67#include <sys/sysctl.h>
68#include <sys/bus.h>
69#include <machine/bus.h>
70#include <sys/rman.h>
71#include <sys/timetc.h>
72#include <sys/timepps.h>
73
74#include <isa/isareg.h>
75#include <isa/isavar.h>
76#include <machine/lock.h>
77
78#include <machine/clock.h>
79#include <machine/ipl.h>
80#ifndef SMP
81#include <machine/lock.h>
82#endif
83#include <machine/resource.h>
84
85#include <isa/sioreg.h>
86
87#ifdef COM_ESP
88#include <isa/ic/esp.h>
89#endif
90#include <isa/ic/ns16550.h>
91
92#ifndef __i386__
93#define disable_intr()
94#define enable_intr()
95#endif
96
97#ifdef SMP
98#define disable_intr()	COM_DISABLE_INTR()
99#define enable_intr()	COM_ENABLE_INTR()
100#endif /* SMP */
101
102#define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
103
104#define	CALLOUT_MASK		0x80
105#define	CONTROL_MASK		0x60
106#define	CONTROL_INIT_STATE	0x20
107#define	CONTROL_LOCK_STATE	0x40
108#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
109#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
110#define	MINOR_TO_UNIT(mynor)	((mynor) & ~MINOR_MAGIC_MASK)
111
112#ifdef COM_MULTIPORT
113/* checks in flags for multiport and which is multiport "master chip"
114 * for a given card
115 */
116#define	COM_ISMULTIPORT(flags)	((flags) & 0x01)
117#define	COM_MPMASTER(flags)	(((flags) >> 8) & 0x0ff)
118#define	COM_NOTAST4(flags)	((flags) & 0x04)
119#endif /* COM_MULTIPORT */
120
121#define	COM_CONSOLE(flags)	((flags) & 0x10)
122#define	COM_FORCECONSOLE(flags)	((flags) & 0x20)
123#define	COM_LLCONSOLE(flags)	((flags) & 0x40)
124#define	COM_DEBUGGER(flags)	((flags) & 0x80)
125#define	COM_LOSESOUTINTS(flags)	((flags) & 0x08)
126#define	COM_NOFIFO(flags)		((flags) & 0x02)
127#define COM_ST16650A(flags)	((flags) & 0x20000)
128#define COM_C_NOPROBE		(0x40000)
129#define COM_NOPROBE(flags)	((flags) & COM_C_NOPROBE)
130#define COM_C_IIR_TXRDYBUG	(0x80000)
131#define COM_IIR_TXRDYBUG(flags)	((flags) & COM_C_IIR_TXRDYBUG)
132#define	COM_FIFOSIZE(flags)	(((flags) & 0xff000000) >> 24)
133
134#define	com_scr		7	/* scratch register for 16450-16550 (R/W) */
135
136/*
137 * com state bits.
138 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
139 * than the other bits so that they can be tested as a group without masking
140 * off the low bits.
141 *
142 * The following com and tty flags correspond closely:
143 *	CS_BUSY		= TS_BUSY (maintained by comstart(), siopoll() and
144 *				   comstop())
145 *	CS_TTGO		= ~TS_TTSTOP (maintained by comparam() and comstart())
146 *	CS_CTS_OFLOW	= CCTS_OFLOW (maintained by comparam())
147 *	CS_RTS_IFLOW	= CRTS_IFLOW (maintained by comparam())
148 * TS_FLUSH is not used.
149 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
150 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
151 */
152#define	CS_BUSY		0x80	/* output in progress */
153#define	CS_TTGO		0x40	/* output not stopped by XOFF */
154#define	CS_ODEVREADY	0x20	/* external device h/w ready (CTS) */
155#define	CS_CHECKMSR	1	/* check of MSR scheduled */
156#define	CS_CTS_OFLOW	2	/* use CTS output flow control */
157#define	CS_DTR_OFF	0x10	/* DTR held off */
158#define	CS_ODONE	4	/* output completed */
159#define	CS_RTS_IFLOW	8	/* use RTS input flow control */
160#define	CSE_BUSYCHECK	1	/* siobusycheck() scheduled */
161
162static	char const * const	error_desc[] = {
163#define	CE_OVERRUN			0
164	"silo overflow",
165#define	CE_INTERRUPT_BUF_OVERFLOW	1
166	"interrupt-level buffer overflow",
167#define	CE_TTY_BUF_OVERFLOW		2
168	"tty-level buffer overflow",
169};
170
171#define	CE_NTYPES			3
172#define	CE_RECORD(com, errnum)		(++(com)->delta_error_counts[errnum])
173
174/* types.  XXX - should be elsewhere */
175typedef u_int	Port_t;		/* hardware port */
176typedef u_char	bool_t;		/* boolean */
177
178/* queue of linear buffers */
179struct lbq {
180	u_char	*l_head;	/* next char to process */
181	u_char	*l_tail;	/* one past the last char to process */
182	struct lbq *l_next;	/* next in queue */
183	bool_t	l_queued;	/* nonzero if queued */
184};
185
186/* com device structure */
187struct com_s {
188	u_int	flags;		/* Copy isa device flags */
189	u_char	state;		/* miscellaneous flag bits */
190	bool_t  active_out;	/* nonzero if the callout device is open */
191	u_char	cfcr_image;	/* copy of value written to CFCR */
192#ifdef COM_ESP
193	bool_t	esp;		/* is this unit a hayes esp board? */
194#endif
195	u_char	extra_state;	/* more flag bits, separate for order trick */
196	u_char	fifo_image;	/* copy of value written to FIFO */
197	bool_t	hasfifo;	/* nonzero for 16550 UARTs */
198	bool_t	st16650a;	/* Is a Startech 16650A or RTS/CTS compat */
199	bool_t	loses_outints;	/* nonzero if device loses output interrupts */
200	u_char	mcr_image;	/* copy of value written to MCR */
201#ifdef COM_MULTIPORT
202	bool_t	multiport;	/* is this unit part of a multiport device? */
203#endif /* COM_MULTIPORT */
204	bool_t	no_irq;		/* nonzero if irq is not attached */
205	bool_t  gone;		/* hardware disappeared */
206	bool_t	poll;		/* nonzero if polling is required */
207	bool_t	poll_output;	/* nonzero if polling for output is required */
208	int	unit;		/* unit	number */
209	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
210	u_int	tx_fifo_size;
211	u_int	wopeners;	/* # processes waiting for DCD in open() */
212
213	/*
214	 * The high level of the driver never reads status registers directly
215	 * because there would be too many side effects to handle conveniently.
216	 * Instead, it reads copies of the registers stored here by the
217	 * interrupt handler.
218	 */
219	u_char	last_modem_status;	/* last MSR read by intr handler */
220	u_char	prev_modem_status;	/* last MSR handled by high level */
221
222	u_char	hotchar;	/* ldisc-specific char to be handled ASAP */
223	u_char	*ibuf;		/* start of input buffer */
224	u_char	*ibufend;	/* end of input buffer */
225	u_char	*ibufold;	/* old input buffer, to be freed */
226	u_char	*ihighwater;	/* threshold in input buffer */
227	u_char	*iptr;		/* next free spot in input buffer */
228	int	ibufsize;	/* size of ibuf (not include error bytes) */
229	int	ierroff;	/* offset of error bytes in ibuf */
230
231	struct lbq	obufq;	/* head of queue of output buffers */
232	struct lbq	obufs[2];	/* output buffers */
233
234	Port_t	data_port;	/* i/o ports */
235#ifdef COM_ESP
236	Port_t	esp_port;
237#endif
238	Port_t	int_id_port;
239	Port_t	iobase;
240	Port_t	modem_ctl_port;
241	Port_t	line_status_port;
242	Port_t	modem_status_port;
243	Port_t	intr_ctl_port;	/* Ports of IIR register */
244
245	struct tty	*tp;	/* cross reference */
246
247	/* Initial state. */
248	struct termios	it_in;	/* should be in struct tty */
249	struct termios	it_out;
250
251	/* Lock state. */
252	struct termios	lt_in;	/* should be in struct tty */
253	struct termios	lt_out;
254
255	bool_t	do_timestamp;
256	bool_t	do_dcd_timestamp;
257	struct timeval	timestamp;
258	struct timeval	dcd_timestamp;
259	struct	pps_state pps;
260
261	u_long	bytes_in;	/* statistics */
262	u_long	bytes_out;
263	u_int	delta_error_counts[CE_NTYPES];
264	u_long	error_counts[CE_NTYPES];
265
266	struct resource *irqres;
267	struct resource *ioportres;
268	void *cookie;
269
270	/*
271	 * Data area for output buffers.  Someday we should build the output
272	 * buffer queue without copying data.
273	 */
274	u_char	obuf1[256];
275	u_char	obuf2[256];
276};
277
278#ifdef COM_ESP
279static	int	espattach	__P((struct com_s *com, Port_t esp_port));
280#endif
281static	int	sioattach	__P((device_t dev));
282static	int	sio_isa_attach	__P((device_t dev));
283
284static	timeout_t siobusycheck;
285static	timeout_t siodtrwakeup;
286static	void	comhardclose	__P((struct com_s *com));
287static	void	sioinput	__P((struct com_s *com));
288static	void	siointr1	__P((struct com_s *com));
289static	void	siointr		__P((void *arg));
290static	int	commctl		__P((struct com_s *com, int bits, int how));
291static	int	comparam	__P((struct tty *tp, struct termios *t));
292static	swihand_t siopoll;
293static	int	sioprobe	__P((device_t dev));
294static	int	sio_isa_probe	__P((device_t dev));
295static	void	siosettimeout	__P((void));
296static	int	siosetwater	__P((struct com_s *com, speed_t speed));
297static	void	comstart	__P((struct tty *tp));
298static	void	comstop		__P((struct tty *tp, int rw));
299static	timeout_t comwakeup;
300static	void	disc_optim	__P((struct tty	*tp, struct termios *t,
301				     struct com_s *com));
302
303#if NCARD > 0
304static	int	sio_pccard_attach __P((device_t dev));
305static	int	sio_pccard_detach __P((device_t dev));
306static	int	sio_pccard_probe __P((device_t dev));
307#endif /* NCARD > 0 */
308
309static char driver_name[] = "sio";
310
311/* table and macro for fast conversion from a unit number to its com struct */
312static	devclass_t	sio_devclass;
313#define	com_addr(unit)	((struct com_s *) \
314			 devclass_get_softc(sio_devclass, unit))
315
316static device_method_t sio_isa_methods[] = {
317	/* Device interface */
318	DEVMETHOD(device_probe,		sio_isa_probe),
319	DEVMETHOD(device_attach,	sio_isa_attach),
320
321	{ 0, 0 }
322};
323
324static driver_t sio_isa_driver = {
325	driver_name,
326	sio_isa_methods,
327	sizeof(struct com_s),
328};
329
330#if NCARD > 0
331static device_method_t sio_pccard_methods[] = {
332	/* Device interface */
333	DEVMETHOD(device_probe,		sio_pccard_probe),
334	DEVMETHOD(device_attach,	sio_pccard_attach),
335	DEVMETHOD(device_detach,	sio_pccard_detach),
336
337	{ 0, 0 }
338};
339
340static driver_t sio_pccard_driver = {
341	driver_name,
342	sio_pccard_methods,
343	sizeof(struct com_s),
344};
345#endif (NCARD > 0)
346
347static	d_open_t	sioopen;
348static	d_close_t	sioclose;
349static	d_read_t	sioread;
350static	d_write_t	siowrite;
351static	d_ioctl_t	sioioctl;
352
353#define	CDEV_MAJOR	28
354static struct cdevsw sio_cdevsw = {
355	/* open */	sioopen,
356	/* close */	sioclose,
357	/* read */	sioread,
358	/* write */	siowrite,
359	/* ioctl */	sioioctl,
360	/* poll */	ttypoll,
361	/* mmap */	nommap,
362	/* strategy */	nostrategy,
363	/* name */	driver_name,
364	/* maj */	CDEV_MAJOR,
365	/* dump */	nodump,
366	/* psize */	nopsize,
367	/* flags */	D_TTY,
368	/* bmaj */	-1
369};
370
371int	comconsole = -1;
372static	volatile speed_t	comdefaultrate = CONSPEED;
373#ifdef __alpha__
374static	volatile speed_t	gdbdefaultrate = CONSPEED;
375#endif
376static	u_int	com_events;	/* input chars + weighted output completions */
377static	Port_t	siocniobase;
378static	int	siocnunit;
379static	Port_t	siogdbiobase;
380static	int	siogdbunit = -1;
381static	bool_t	sio_registered;
382static	int	sio_timeout;
383static	int	sio_timeouts_until_log;
384static	struct	callout_handle sio_timeout_handle
385    = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
386static	int	sio_numunits;
387
388static	struct speedtab comspeedtab[] = {
389	{ 0,		0 },
390	{ 50,		COMBRD(50) },
391	{ 75,		COMBRD(75) },
392	{ 110,		COMBRD(110) },
393	{ 134,		COMBRD(134) },
394	{ 150,		COMBRD(150) },
395	{ 200,		COMBRD(200) },
396	{ 300,		COMBRD(300) },
397	{ 600,		COMBRD(600) },
398	{ 1200,		COMBRD(1200) },
399	{ 1800,		COMBRD(1800) },
400	{ 2400,		COMBRD(2400) },
401	{ 4800,		COMBRD(4800) },
402	{ 9600,		COMBRD(9600) },
403	{ 19200,	COMBRD(19200) },
404	{ 38400,	COMBRD(38400) },
405	{ 57600,	COMBRD(57600) },
406	{ 115200,	COMBRD(115200) },
407	{ -1,		-1 }
408};
409
410#ifdef COM_ESP
411/* XXX configure this properly. */
412static	Port_t	likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
413static	Port_t	likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
414#endif
415
416/*
417 * handle sysctl read/write requests for console speed
418 *
419 * In addition to setting comdefaultrate for I/O through /dev/console,
420 * also set the initial and lock values for the /dev/ttyXX device
421 * if there is one associated with the console.  Finally, if the /dev/tty
422 * device has already been open, change the speed on the open running port
423 * itself.
424 */
425
426static int
427sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS
428{
429	int error, s;
430	speed_t newspeed;
431	struct com_s *com;
432	struct tty *tp;
433
434	newspeed = comdefaultrate;
435
436	error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
437	if (error || !req->newptr)
438		return (error);
439
440	comdefaultrate = newspeed;
441
442	if (comconsole < 0)		/* serial console not selected? */
443		return (0);
444
445	com = com_addr(comconsole);
446	if (com == NULL)
447		return (ENXIO);
448
449	/*
450	 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
451	 * (note, the lock rates really are boolean -- if non-zero, disallow
452	 *  speed changes)
453	 */
454	com->it_in.c_ispeed  = com->it_in.c_ospeed =
455	com->lt_in.c_ispeed  = com->lt_in.c_ospeed =
456	com->it_out.c_ispeed = com->it_out.c_ospeed =
457	com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
458
459	/*
460	 * if we're open, change the running rate too
461	 */
462	tp = com->tp;
463	if (tp && (tp->t_state & TS_ISOPEN)) {
464		tp->t_termios.c_ispeed =
465		tp->t_termios.c_ospeed = comdefaultrate;
466		s = spltty();
467		error = comparam(tp, &tp->t_termios);
468		splx(s);
469	}
470	return error;
471}
472
473SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
474	    0, 0, sysctl_machdep_comdefaultrate, "I", "");
475
476#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
477#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
478
479#if NCARD > 0
480static int
481sio_pccard_probe(dev)
482	device_t	dev;
483{
484	/* Do not probe IRQ - pccard doesn't turn on the interrupt line */
485	/* until bus_setup_intr */
486	SET_FLAG(dev, COM_C_NOPROBE);
487
488	return (sioprobe(dev));
489}
490
491static int
492sio_pccard_attach(dev)
493	device_t	dev;
494{
495	return (sioattach(dev));
496}
497
498/*
499 *	sio_detach - unload the driver and clear the table.
500 *	XXX TODO:
501 *	This is usually called when the card is ejected, but
502 *	can be caused by a modunload of a controller driver.
503 *	The idea is to reset the driver's view of the device
504 *	and ensure that any driver entry points such as
505 *	read and write do not hang.
506 */
507static int
508sio_pccard_detach(dev)
509	device_t	dev;
510{
511	struct com_s	*com;
512
513	com = (struct com_s *) device_get_softc(dev);
514	if (com == NULL) {
515		device_printf(dev, "NULL com in siounload\n");
516		return (0);
517	}
518	if (com->iobase == 0) {
519		device_printf(dev, "already unloaded!\n");
520		return (0);
521	}
522	com->gone = 1;
523	if (com->irqres) {
524		bus_teardown_intr(dev, com->irqres, com->cookie);
525		bus_release_resource(dev, SYS_RES_IRQ, 0, com->irqres);
526	}
527	if (com->ioportres)
528		bus_release_resource(dev, SYS_RES_IOPORT, 0, com->ioportres);
529	if (com->tp && (com->tp->t_state & TS_ISOPEN)) {
530		device_printf(dev, "still open, forcing close\n");
531		com->tp->t_gen++;
532		ttyclose(com->tp);
533		ttwakeup(com->tp);
534		ttwwakeup(com->tp);
535	} else {
536		if (com->ibuf != NULL)
537			free(com->ibuf, M_DEVBUF);
538	}
539	device_printf(dev, "unloaded\n");
540	return (0);
541}
542#endif /* NCARD > 0 */
543
544
545static struct isa_pnp_id sio_ids[] = {
546	{0x0005d041, "Standard PC COM port"},	/* PNP0500 */
547	{0x0105d041, "16550A-compatible COM port"},	/* PNP0501 */
548	{0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */
549	{0x1005d041, "Generic IRDA-compatible device"},	/* PNP0510 */
550	{0x1105d041, "Generic IRDA-compatible device"},	/* PNP0511 */
551	/* Devices that do not have a compatid */
552	{0x7602a904, NULL},	/* AEI0276 - 56K v.90 Fax Modem (LKT) */
553	{0x00007905, NULL},	/* AKY0000 - 56K Plug&Play Modem */
554	{0x01405407, NULL},	/* AZT4001 - AZT3000 PnP SOUND DEVICE, MODEM */
555	{0x56039008, NULL},	/* BDP0356 - Best Data 56x2 */
556	{0x36339008, NULL},	/* BDP3336 - Best Data Prods. 336F */
557	{0x0014490a, NULL},	/* BRI1400 - Boca 33.6 PnP */
558	{0x0015490a, NULL},	/* BRI1500 - Internal Fax Data */
559	{0x0034490a, NULL},	/* BRI3400 - Internal ACF Modem */
560	{0x00b4490a, NULL},	/* BRIB400 - Boca 56k PnP */
561	{0x0030320d, NULL},	/* CIR3000 - Cirrus Logic V43 */
562	{0x0100440e, NULL},	/* CRD0001 - Cardinal MVP288IV ? */
563	{0x1200c31e, NULL},	/* GVC0012 - VF1128HV-R9 (win modem?) */
564	{0x0303c31e, NULL},	/* GVC0303 - MaxTech 33.6 PnP D/F/V */
565	{0x0505c31e, NULL},	/* GVC0505 - GVC 56k Faxmodem */
566	{0x0050c31e, NULL},	/* GVC5000 - some GVC modem */
567	{0x3800f91e, NULL},	/* GWY0038 - Telepath with v.90 */
568	{0x9062f91e, NULL},	/* GWY6290 - Telepath with x2 Technology */
569	{0x0000f435, NULL},	/* MOT0000 - Motorola ModemSURFR 33.6 Intern */
570	{0x5015f435, NULL},	/* MOT1550 - Motorola ModemSURFR 56K Modem */
571	{0xf015f435, NULL},	/* MOT15F0 - Motorola VoiceSURFR 56K Modem */
572	{0x6045f435, NULL},	/* MOT4560 - Motorola ? */
573	{0x61e7a338, NULL},	/* NECE761 - 33.6Modem */
574	{0x39804f3f, NULL},	/* OZO8039 - Zoom 56k flex */
575	{0x3024a341, NULL},	/* PMC2430 - Pace 56 Voice Internal Modem */
576	{0x1000eb49, NULL},	/* ROK0010 - Rockwell ? */
577	{0x5002734a, NULL},	/* RSS0250 - 5614Jx3(G) Internal Modem */
578	{0xc100ad4d, NULL},	/* SMM00C1 - Leopard 56k PnP */
579	{0x9012b04e, NULL},	/* SUP1290 - Supra ? */
580	{0x1013b04e, NULL},	/* SUP1310 - SupraExpress 336i PnP */
581	{0x8013b04e, NULL},	/* SUP1380 - SupraExpress 288i PnP Voice */
582	{0x8113b04e, NULL},	/* SUP1381 - SupraExpress 336i PnP Voice */
583	{0x5016b04e, NULL},	/* SUP1650 - Supra 336i Sp Intl */
584	{0x7420b04e, NULL},	/* SUP2070 - Supra ? */
585	{0x8020b04e, NULL},	/* SUP2080 - Supra ? */
586	{0x8420b04e, NULL},	/* SUP2084 - SupraExpress 56i PnP */
587	{0x7121b04e, NULL},	/* SUP2171 - SupraExpress 56i Sp? */
588	{0x8024b04e, NULL},	/* SUP2480 - Supra ? */
589	{0x01007256, NULL},	/* USR0001 - U.S. Robotics Inc., Sportster W */
590	{0x02007256, NULL},	/* USR0002 - U.S. Robotics Inc. Sportster 33. */
591	{0x04007256, NULL},	/* USR0004 - USR Sportster 14.4k */
592	{0x06007256, NULL},	/* USR0006 - USR Sportster 33.6k */
593	{0x11007256, NULL},	/* USR0011 - USR ? */
594	{0x01017256, NULL},	/* USR0101 - USR ? */
595	{0x30207256, NULL},	/* USR2030 - U.S.Robotics Inc. Sportster 560 */
596	{0x50207256, NULL},	/* USR2050 - U.S.Robotics Inc. Sportster 33. */
597	{0x70207256, NULL},	/* USR2070 - U.S.Robotics Inc. Sportster 560 */
598	{0x30307256, NULL},	/* USR3030 - U.S. Robotics 56K FAX INT */
599	{0x31307256, NULL},	/* USR3031 - U.S. Robotics 56K FAX INT */
600	{0x50307256, NULL},	/* USR3050 - U.S. Robotics 56K FAX INT */
601	{0x70307256, NULL},	/* USR3070 - U.S. Robotics 56K Voice INT */
602	{0x90307256, NULL},	/* USR3090 - USR ? */
603	{0x90917256, NULL},	/* USR9190 - USR 56k Voice INT */
604	{0x0300695c, NULL},	/* WCI0003 - Fax/Voice/Modem/Speakphone/Asvd */
605	{0x61f7896a, NULL},	/* ZTIF761 - Zoom ComStar 33.6 */
606	{0}
607};
608
609
610
611static int
612sio_isa_probe(dev)
613	device_t	dev;
614{
615	/* Check isapnp ids */
616	if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO)
617		return (ENXIO);
618	return (sioprobe(dev));
619}
620
621static int
622sioprobe(dev)
623	device_t	dev;
624{
625#if 0
626	static bool_t	already_init;
627	device_t	xdev;
628#endif
629	bool_t		failures[10];
630	int		fn;
631	device_t	idev;
632	Port_t		iobase;
633	intrmask_t	irqmap[4];
634	intrmask_t	irqs;
635	u_char		mcr_image;
636	int		result;
637	u_long		xirq;
638	u_int		flags = device_get_flags(dev);
639	int		rid;
640	struct resource *port;
641
642	rid = 0;
643	port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
644				  0, ~0, IO_COMSIZE, RF_ACTIVE);
645	if (!port)
646		return (ENXIO);
647
648#if 0
649	/*
650	 * XXX this is broken - when we are first called, there are no
651	 * previously configured IO ports.  We could hard code
652	 * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
653	 * This code has been doing nothing since the conversion since
654	 * "count" is zero the first time around.
655	 */
656	if (!already_init) {
657		/*
658		 * Turn off MCR_IENABLE for all likely serial ports.  An unused
659		 * port with its MCR_IENABLE gate open will inhibit interrupts
660		 * from any used port that shares the interrupt vector.
661		 * XXX the gate enable is elsewhere for some multiports.
662		 */
663		device_t *devs;
664		int count, i, xioport;
665
666		devclass_get_devices(sio_devclass, &devs, &count);
667		for (i = 0; i < count; i++) {
668			xdev = devs[i];
669			if (device_is_enabled(xdev) &&
670			    bus_get_resource(xdev, SYS_RES_IOPORT, 0, &xioport,
671					     NULL) == 0)
672				outb(xioport + com_mcr, 0);
673		}
674		free(devs, M_TEMP);
675		already_init = TRUE;
676	}
677#endif
678
679	if (COM_LLCONSOLE(flags)) {
680		printf("sio%d: reserved for low-level i/o\n",
681		       device_get_unit(dev));
682		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
683		return (ENXIO);
684	}
685
686	/*
687	 * If the device is on a multiport card and has an AST/4
688	 * compatible interrupt control register, initialize this
689	 * register and prepare to leave MCR_IENABLE clear in the mcr.
690	 * Otherwise, prepare to set MCR_IENABLE in the mcr.
691	 * Point idev to the device struct giving the correct id_irq.
692	 * This is the struct for the master device if there is one.
693	 */
694	idev = dev;
695	mcr_image = MCR_IENABLE;
696#ifdef COM_MULTIPORT
697	if (COM_ISMULTIPORT(flags)) {
698		Port_t xiobase;
699		u_long io;
700
701		idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags));
702		if (idev == NULL) {
703			printf("sio%d: master device %d not configured\n",
704			       device_get_unit(dev), COM_MPMASTER(flags));
705			idev = dev;
706		}
707		if (!COM_NOTAST4(flags)) {
708			if (bus_get_resource(idev, SYS_RES_IOPORT, 0, &io,
709					     NULL) == 0) {
710				xiobase = io;
711				if (bus_get_resource(idev, SYS_RES_IRQ, 0,
712				    NULL, NULL) == 0)
713					outb(xiobase + com_scr, 0x80);
714				else
715					outb(xiobase + com_scr, 0);
716			}
717			mcr_image = 0;
718		}
719	}
720#endif /* COM_MULTIPORT */
721	if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) != 0)
722		mcr_image = 0;
723
724	bzero(failures, sizeof failures);
725	iobase = rman_get_start(port);
726
727	/*
728	 * We don't want to get actual interrupts, just masked ones.
729	 * Interrupts from this line should already be masked in the ICU,
730	 * but mask them in the processor as well in case there are some
731	 * (misconfigured) shared interrupts.
732	 */
733	disable_intr();
734/* EXTRA DELAY? */
735
736	/*
737	 * Initialize the speed and the word size and wait long enough to
738	 * drain the maximum of 16 bytes of junk in device output queues.
739	 * The speed is undefined after a master reset and must be set
740	 * before relying on anything related to output.  There may be
741	 * junk after a (very fast) soft reboot and (apparently) after
742	 * master reset.
743	 * XXX what about the UART bug avoided by waiting in comparam()?
744	 * We don't want to to wait long enough to drain at 2 bps.
745	 */
746	if (iobase == siocniobase)
747		DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
748	else {
749		outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
750		outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff);
751		outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8);
752		outb(iobase + com_cfcr, CFCR_8BITS);
753		DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
754	}
755
756	/*
757	 * Enable the interrupt gate and disable device interupts.  This
758	 * should leave the device driving the interrupt line low and
759	 * guarantee an edge trigger if an interrupt can be generated.
760	 */
761/* EXTRA DELAY? */
762	outb(iobase + com_mcr, mcr_image);
763	outb(iobase + com_ier, 0);
764	DELAY(1000);		/* XXX */
765	irqmap[0] = isa_irq_pending();
766
767	/*
768	 * Attempt to set loopback mode so that we can send a null byte
769	 * without annoying any external device.
770	 */
771/* EXTRA DELAY? */
772	outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK);
773
774	/*
775	 * Attempt to generate an output interrupt.  On 8250's, setting
776	 * IER_ETXRDY generates an interrupt independent of the current
777	 * setting and independent of whether the THR is empty.  On 16450's,
778	 * setting IER_ETXRDY generates an interrupt independent of the
779	 * current setting.  On 16550A's, setting IER_ETXRDY only
780	 * generates an interrupt when IER_ETXRDY is not already set.
781	 */
782	outb(iobase + com_ier, IER_ETXRDY);
783
784	/*
785	 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
786	 * an interrupt.  They'd better generate one for actually doing
787	 * output.  Loopback may be broken on the same incompatibles but
788	 * it's unlikely to do more than allow the null byte out.
789	 */
790	outb(iobase + com_data, 0);
791	DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
792
793	/*
794	 * Turn off loopback mode so that the interrupt gate works again
795	 * (MCR_IENABLE was hidden).  This should leave the device driving
796	 * an interrupt line high.  It doesn't matter if the interrupt
797	 * line oscillates while we are not looking at it, since interrupts
798	 * are disabled.
799	 */
800/* EXTRA DELAY? */
801	outb(iobase + com_mcr, mcr_image);
802
803	/*
804	 * Some pcmcia cards have the "TXRDY bug", so we check everyone
805	 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
806	 */
807	if (COM_NOPROBE(flags)) {
808		/* Reading IIR register twice */
809		for (fn = 0; fn < 2; fn ++) {
810			DELAY(10000);
811			failures[6] = inb(iobase + com_iir);
812		}
813		/* Check IIR_TXRDY clear ? */
814		result = 0;
815		if (failures[6] & IIR_TXRDY) {
816			/* Nop, Double check with clearing IER */
817			outb(iobase + com_ier, 0);
818			if (inb(iobase + com_iir) & IIR_NOPEND) {
819				/* Ok. we're familia this gang */
820				SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
821			} else {
822				/* Unknown, Just omit this chip.. XXX */
823				result = ENXIO;
824			}
825		} else {
826			/* OK. this is well-known guys */
827			CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
828		}
829		outb(iobase + com_cfcr, CFCR_8BITS);
830		enable_intr();
831		bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
832		return (iobase == siocniobase ? 0 : result);
833	}
834
835	/*
836	 * Check that
837	 *	o the CFCR, IER and MCR in UART hold the values written to them
838	 *	  (the values happen to be all distinct - this is good for
839	 *	  avoiding false positive tests from bus echoes).
840	 *	o an output interrupt is generated and its vector is correct.
841	 *	o the interrupt goes away when the IIR in the UART is read.
842	 */
843/* EXTRA DELAY? */
844	failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS;
845	failures[1] = inb(iobase + com_ier) - IER_ETXRDY;
846	failures[2] = inb(iobase + com_mcr) - mcr_image;
847	DELAY(10000);		/* Some internal modems need this time */
848	irqmap[1] = isa_irq_pending();
849	failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY;
850	DELAY(1000);		/* XXX */
851	irqmap[2] = isa_irq_pending();
852	failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
853
854	/*
855	 * Turn off all device interrupts and check that they go off properly.
856	 * Leave MCR_IENABLE alone.  For ports without a master port, it gates
857	 * the OUT2 output of the UART to
858	 * the ICU input.  Closing the gate would give a floating ICU input
859	 * (unless there is another device driving it) and spurious interrupts.
860	 * (On the system that this was first tested on, the input floats high
861	 * and gives a (masked) interrupt as soon as the gate is closed.)
862	 */
863	outb(iobase + com_ier, 0);
864	outb(iobase + com_cfcr, CFCR_8BITS);	/* dummy to avoid bus echo */
865	failures[7] = inb(iobase + com_ier);
866	DELAY(1000);		/* XXX */
867	irqmap[3] = isa_irq_pending();
868	failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
869
870	enable_intr();
871
872	irqs = irqmap[1] & ~irqmap[0];
873	if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
874	    ((1 << xirq) & irqs) == 0)
875		printf(
876		"sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
877		    device_get_unit(dev), xirq, irqs);
878	if (bootverbose)
879		printf("sio%d: irq maps: %#x %#x %#x %#x\n",
880		    device_get_unit(dev),
881		    irqmap[0], irqmap[1], irqmap[2], irqmap[3]);
882
883	result = 0;
884	for (fn = 0; fn < sizeof failures; ++fn)
885		if (failures[fn]) {
886			outb(iobase + com_mcr, 0);
887			result = ENXIO;
888			if (bootverbose) {
889				printf("sio%d: probe failed test(s):",
890				    device_get_unit(dev));
891				for (fn = 0; fn < sizeof failures; ++fn)
892					if (failures[fn])
893						printf(" %d", fn);
894				printf("\n");
895			}
896			break;
897		}
898	bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
899	return (iobase == siocniobase ? 0 : result);
900}
901
902#ifdef COM_ESP
903static int
904espattach(com, esp_port)
905	struct com_s		*com;
906	Port_t			esp_port;
907{
908	u_char	dips;
909	u_char	val;
910
911	/*
912	 * Check the ESP-specific I/O port to see if we're an ESP
913	 * card.  If not, return failure immediately.
914	 */
915	if ((inb(esp_port) & 0xf3) == 0) {
916		printf(" port 0x%x is not an ESP board?\n", esp_port);
917		return (0);
918	}
919
920	/*
921	 * We've got something that claims to be a Hayes ESP card.
922	 * Let's hope so.
923	 */
924
925	/* Get the dip-switch configuration */
926	outb(esp_port + ESP_CMD1, ESP_GETDIPS);
927	dips = inb(esp_port + ESP_STATUS1);
928
929	/*
930	 * Bits 0,1 of dips say which COM port we are.
931	 */
932	if (com->iobase == likely_com_ports[dips & 0x03])
933		printf(" : ESP");
934	else {
935		printf(" esp_port has com %d\n", dips & 0x03);
936		return (0);
937	}
938
939	/*
940	 * Check for ESP version 2.0 or later:  bits 4,5,6 = 010.
941	 */
942	outb(esp_port + ESP_CMD1, ESP_GETTEST);
943	val = inb(esp_port + ESP_STATUS1);	/* clear reg 1 */
944	val = inb(esp_port + ESP_STATUS2);
945	if ((val & 0x70) < 0x20) {
946		printf("-old (%o)", val & 0x70);
947		return (0);
948	}
949
950	/*
951	 * Check for ability to emulate 16550:  bit 7 == 1
952	 */
953	if ((dips & 0x80) == 0) {
954		printf(" slave");
955		return (0);
956	}
957
958	/*
959	 * Okay, we seem to be a Hayes ESP card.  Whee.
960	 */
961	com->esp = TRUE;
962	com->esp_port = esp_port;
963	return (1);
964}
965#endif /* COM_ESP */
966
967static int
968sio_isa_attach(dev)
969	device_t	dev;
970{
971	return (sioattach(dev));
972}
973
974static int
975sioattach(dev)
976	device_t	dev;
977{
978	struct com_s	*com;
979#ifdef COM_ESP
980	Port_t		*espp;
981#endif
982	Port_t		iobase;
983	int		unit;
984	u_int		flags;
985	int		rid;
986	struct resource *port;
987	int		ret;
988
989	rid = 0;
990	port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
991				  0, ~0, IO_COMSIZE, RF_ACTIVE);
992	if (!port)
993		return (ENXIO);
994
995	iobase = rman_get_start(port);
996	unit = device_get_unit(dev);
997	com = device_get_softc(dev);
998	flags = device_get_flags(dev);
999
1000	if (unit >= sio_numunits)
1001		sio_numunits = unit + 1;
1002	/*
1003	 * sioprobe() has initialized the device registers as follows:
1004	 *	o cfcr = CFCR_8BITS.
1005	 *	  It is most important that CFCR_DLAB is off, so that the
1006	 *	  data port is not hidden when we enable interrupts.
1007	 *	o ier = 0.
1008	 *	  Interrupts are only enabled when the line is open.
1009	 *	o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
1010	 *	  interrupt control register or the config specifies no irq.
1011	 *	  Keeping MCR_DTR and MCR_RTS off might stop the external
1012	 *	  device from sending before we are ready.
1013	 */
1014	bzero(com, sizeof *com);
1015	com->unit = unit;
1016	com->ioportres = port;
1017	com->cfcr_image = CFCR_8BITS;
1018	com->dtr_wait = 3 * hz;
1019	com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
1020	com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
1021	com->tx_fifo_size = 1;
1022	com->obufs[0].l_head = com->obuf1;
1023	com->obufs[1].l_head = com->obuf2;
1024
1025	com->iobase = iobase;
1026	com->data_port = iobase + com_data;
1027	com->int_id_port = iobase + com_iir;
1028	com->modem_ctl_port = iobase + com_mcr;
1029	com->mcr_image = inb(com->modem_ctl_port);
1030	com->line_status_port = iobase + com_lsr;
1031	com->modem_status_port = iobase + com_msr;
1032	com->intr_ctl_port = iobase + com_ier;
1033
1034	/*
1035	 * We don't use all the flags from <sys/ttydefaults.h> since they
1036	 * are only relevant for logins.  It's important to have echo off
1037	 * initially so that the line doesn't start blathering before the
1038	 * echo flag can be turned off.
1039	 */
1040	com->it_in.c_iflag = 0;
1041	com->it_in.c_oflag = 0;
1042	com->it_in.c_cflag = TTYDEF_CFLAG;
1043	com->it_in.c_lflag = 0;
1044	if (unit == comconsole) {
1045		com->it_in.c_iflag = TTYDEF_IFLAG;
1046		com->it_in.c_oflag = TTYDEF_OFLAG;
1047		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
1048		com->it_in.c_lflag = TTYDEF_LFLAG;
1049		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
1050		com->lt_out.c_ispeed = com->lt_out.c_ospeed =
1051		com->lt_in.c_ispeed = com->lt_in.c_ospeed =
1052		com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
1053	} else
1054		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1055	if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1056		enable_intr();
1057		/*
1058		 * Leave i/o resources allocated if this is a `cn'-level
1059		 * console, so that other devices can't snarf them.
1060		 */
1061		if (iobase != siocniobase)
1062			bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1063		return (ENOMEM);
1064	}
1065	enable_intr();
1066	termioschars(&com->it_in);
1067	com->it_out = com->it_in;
1068
1069	/* attempt to determine UART type */
1070	printf("sio%d: type", unit);
1071
1072
1073#ifdef COM_MULTIPORT
1074	if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags))
1075#else
1076	if (!COM_IIR_TXRDYBUG(flags))
1077#endif
1078	{
1079		u_char	scr;
1080		u_char	scr1;
1081		u_char	scr2;
1082
1083		scr = inb(iobase + com_scr);
1084		outb(iobase + com_scr, 0xa5);
1085		scr1 = inb(iobase + com_scr);
1086		outb(iobase + com_scr, 0x5a);
1087		scr2 = inb(iobase + com_scr);
1088		outb(iobase + com_scr, scr);
1089		if (scr1 != 0xa5 || scr2 != 0x5a) {
1090			printf(" 8250");
1091			goto determined_type;
1092		}
1093	}
1094	outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1095	DELAY(100);
1096	com->st16650a = 0;
1097	switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1098	case FIFO_RX_LOW:
1099		printf(" 16450");
1100		break;
1101	case FIFO_RX_MEDL:
1102		printf(" 16450?");
1103		break;
1104	case FIFO_RX_MEDH:
1105		printf(" 16550?");
1106		break;
1107	case FIFO_RX_HIGH:
1108		if (COM_NOFIFO(flags)) {
1109			printf(" 16550A fifo disabled");
1110		} else {
1111			com->hasfifo = TRUE;
1112			if (COM_ST16650A(flags)) {
1113				com->st16650a = 1;
1114				com->tx_fifo_size = 32;
1115				printf(" ST16650A");
1116			} else {
1117				com->tx_fifo_size = COM_FIFOSIZE(flags);
1118				printf(" 16550A");
1119			}
1120		}
1121#ifdef COM_ESP
1122		for (espp = likely_esp_ports; *espp != 0; espp++)
1123			if (espattach(com, *espp)) {
1124				com->tx_fifo_size = 1024;
1125				break;
1126			}
1127#endif
1128		if (!com->st16650a) {
1129			if (!com->tx_fifo_size)
1130				com->tx_fifo_size = 16;
1131			else
1132				printf(" lookalike with %d bytes FIFO",
1133				    com->tx_fifo_size);
1134		}
1135
1136		break;
1137	}
1138
1139#ifdef COM_ESP
1140	if (com->esp) {
1141		/*
1142		 * Set 16550 compatibility mode.
1143		 * We don't use the ESP_MODE_SCALE bit to increase the
1144		 * fifo trigger levels because we can't handle large
1145		 * bursts of input.
1146		 * XXX flow control should be set in comparam(), not here.
1147		 */
1148		outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
1149		outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1150
1151		/* Set RTS/CTS flow control. */
1152		outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
1153		outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
1154		outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
1155
1156		/* Set flow-control levels. */
1157		outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
1158		outb(com->esp_port + ESP_CMD2, HIBYTE(768));
1159		outb(com->esp_port + ESP_CMD2, LOBYTE(768));
1160		outb(com->esp_port + ESP_CMD2, HIBYTE(512));
1161		outb(com->esp_port + ESP_CMD2, LOBYTE(512));
1162	}
1163#endif /* COM_ESP */
1164	outb(iobase + com_fifo, 0);
1165determined_type: ;
1166
1167#ifdef COM_MULTIPORT
1168	if (COM_ISMULTIPORT(flags)) {
1169		device_t masterdev;
1170
1171		com->multiport = TRUE;
1172		printf(" (multiport");
1173		if (unit == COM_MPMASTER(flags))
1174			printf(" master");
1175		printf(")");
1176		masterdev = devclass_get_device(sio_devclass,
1177		    COM_MPMASTER(flags));
1178		com->no_irq = (masterdev == NULL || bus_get_resource(masterdev,
1179		    SYS_RES_IRQ, 0, NULL, NULL) != 0);
1180	 }
1181#endif /* COM_MULTIPORT */
1182	if (unit == comconsole)
1183		printf(", console");
1184	if (COM_IIR_TXRDYBUG(flags))
1185		printf(" with a bogus IIR_TXRDY register");
1186	printf("\n");
1187
1188	if (!sio_registered) {
1189		register_swi(SWI_TTY, siopoll);
1190		sio_registered = TRUE;
1191	}
1192	make_dev(&sio_cdevsw, unit,
1193	    UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit);
1194	make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE,
1195	    UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit);
1196	make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE,
1197	    UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit);
1198	make_dev(&sio_cdevsw, unit | CALLOUT_MASK,
1199	    UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit);
1200	make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE,
1201	    UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit);
1202	make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE,
1203	    UID_UUCP, GID_DIALER, 0660, "cuala%r", unit);
1204	com->flags = flags;
1205	com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1206	pps_init(&com->pps);
1207
1208	rid = 0;
1209	com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
1210	    RF_ACTIVE);
1211	if (com->irqres) {
1212		ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres,
1213				     INTR_TYPE_TTY | INTR_TYPE_FAST,
1214				     siointr, com, &com->cookie);
1215		if (ret) {
1216			ret = BUS_SETUP_INTR(device_get_parent(dev), dev,
1217					     com->irqres, INTR_TYPE_TTY,
1218					     siointr, com, &com->cookie);
1219			if (ret == 0)
1220				device_printf(dev, "unable to activate interrupt in fast mode - using normal mode");
1221		}
1222		if (ret)
1223			device_printf(dev, "could not activate interrupt\n");
1224	}
1225
1226	return (0);
1227}
1228
1229static int
1230sioopen(dev, flag, mode, p)
1231	dev_t		dev;
1232	int		flag;
1233	int		mode;
1234	struct proc	*p;
1235{
1236	struct com_s	*com;
1237	int		error;
1238	Port_t		iobase;
1239	int		mynor;
1240	int		s;
1241	struct tty	*tp;
1242	int		unit;
1243
1244	mynor = minor(dev);
1245	unit = MINOR_TO_UNIT(mynor);
1246	com = com_addr(unit);
1247	if (com == NULL)
1248		return (ENXIO);
1249	if (com->gone)
1250		return (ENXIO);
1251	if (mynor & CONTROL_MASK)
1252		return (0);
1253	tp = dev->si_tty = com->tp = ttymalloc(com->tp);
1254	s = spltty();
1255	/*
1256	 * We jump to this label after all non-interrupted sleeps to pick
1257	 * up any changes of the device state.
1258	 */
1259open_top:
1260	while (com->state & CS_DTR_OFF) {
1261		error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0);
1262		if (com_addr(unit) == NULL)
1263			return (ENXIO);
1264		if (error != 0 || com->gone)
1265			goto out;
1266	}
1267	if (tp->t_state & TS_ISOPEN) {
1268		/*
1269		 * The device is open, so everything has been initialized.
1270		 * Handle conflicts.
1271		 */
1272		if (mynor & CALLOUT_MASK) {
1273			if (!com->active_out) {
1274				error = EBUSY;
1275				goto out;
1276			}
1277		} else {
1278			if (com->active_out) {
1279				if (flag & O_NONBLOCK) {
1280					error = EBUSY;
1281					goto out;
1282				}
1283				error =	tsleep(&com->active_out,
1284					       TTIPRI | PCATCH, "siobi", 0);
1285				if (com_addr(unit) == NULL)
1286					return (ENXIO);
1287				if (error != 0 || com->gone)
1288					goto out;
1289				goto open_top;
1290			}
1291		}
1292		if (tp->t_state & TS_XCLUDE &&
1293		    suser(p)) {
1294			error = EBUSY;
1295			goto out;
1296		}
1297	} else {
1298		/*
1299		 * The device isn't open, so there are no conflicts.
1300		 * Initialize it.  Initialization is done twice in many
1301		 * cases: to preempt sleeping callin opens if we are
1302		 * callout, and to complete a callin open after DCD rises.
1303		 */
1304		tp->t_oproc = comstart;
1305		tp->t_param = comparam;
1306		tp->t_stop = comstop;
1307		tp->t_dev = dev;
1308		tp->t_termios = mynor & CALLOUT_MASK
1309				? com->it_out : com->it_in;
1310		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
1311		com->poll = com->no_irq;
1312		com->poll_output = com->loses_outints;
1313		++com->wopeners;
1314		error = comparam(tp, &tp->t_termios);
1315		--com->wopeners;
1316		if (error != 0)
1317			goto out;
1318		/*
1319		 * XXX we should goto open_top if comparam() slept.
1320		 */
1321		iobase = com->iobase;
1322		if (com->hasfifo) {
1323			/*
1324			 * (Re)enable and drain fifos.
1325			 *
1326			 * Certain SMC chips cause problems if the fifos
1327			 * are enabled while input is ready.  Turn off the
1328			 * fifo if necessary to clear the input.  We test
1329			 * the input ready bit after enabling the fifos
1330			 * since we've already enabled them in comparam()
1331			 * and to handle races between enabling and fresh
1332			 * input.
1333			 */
1334			while (TRUE) {
1335				outb(iobase + com_fifo,
1336				     FIFO_RCV_RST | FIFO_XMT_RST
1337				     | com->fifo_image);
1338				/*
1339				 * XXX the delays are for superstitious
1340				 * historical reasons.  It must be less than
1341				 * the character time at the maximum
1342				 * supported speed (87 usec at 115200 bps
1343				 * 8N1).  Otherwise we might loop endlessly
1344				 * if data is streaming in.  We used to use
1345				 * delays of 100.  That usually worked
1346				 * because DELAY(100) used to usually delay
1347				 * for about 85 usec instead of 100.
1348				 */
1349				DELAY(50);
1350				if (!(inb(com->line_status_port) & LSR_RXRDY))
1351					break;
1352				outb(iobase + com_fifo, 0);
1353				DELAY(50);
1354				(void) inb(com->data_port);
1355			}
1356		}
1357
1358		disable_intr();
1359		(void) inb(com->line_status_port);
1360		(void) inb(com->data_port);
1361		com->prev_modem_status = com->last_modem_status
1362		    = inb(com->modem_status_port);
1363		if (COM_IIR_TXRDYBUG(com->flags)) {
1364			outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
1365						| IER_EMSC);
1366		} else {
1367			outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
1368						| IER_ERLS | IER_EMSC);
1369		}
1370		enable_intr();
1371		/*
1372		 * Handle initial DCD.  Callout devices get a fake initial
1373		 * DCD (trapdoor DCD).  If we are callout, then any sleeping
1374		 * callin opens get woken up and resume sleeping on "siobi"
1375		 * instead of "siodcd".
1376		 */
1377		/*
1378		 * XXX `mynor & CALLOUT_MASK' should be
1379		 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
1380		 * TRAPDOOR_CARRIER is the default initial state for callout
1381		 * devices and SOFT_CARRIER is like CLOCAL except it hides
1382		 * the true carrier.
1383		 */
1384		if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
1385			(*linesw[tp->t_line].l_modem)(tp, 1);
1386	}
1387	/*
1388	 * Wait for DCD if necessary.
1389	 */
1390	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
1391	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
1392		++com->wopeners;
1393		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
1394		if (com_addr(unit) == NULL)
1395			return (ENXIO);
1396		--com->wopeners;
1397		if (error != 0 || com->gone)
1398			goto out;
1399		goto open_top;
1400	}
1401	error =	(*linesw[tp->t_line].l_open)(dev, tp);
1402	disc_optim(tp, &tp->t_termios, com);
1403	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
1404		com->active_out = TRUE;
1405	siosettimeout();
1406out:
1407	splx(s);
1408	if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
1409		comhardclose(com);
1410	return (error);
1411}
1412
1413static int
1414sioclose(dev, flag, mode, p)
1415	dev_t		dev;
1416	int		flag;
1417	int		mode;
1418	struct proc	*p;
1419{
1420	struct com_s	*com;
1421	int		mynor;
1422	int		s;
1423	struct tty	*tp;
1424
1425	mynor = minor(dev);
1426	if (mynor & CONTROL_MASK)
1427		return (0);
1428	com = com_addr(MINOR_TO_UNIT(mynor));
1429	if (com == NULL)
1430		return (ENODEV);
1431	tp = com->tp;
1432	s = spltty();
1433	(*linesw[tp->t_line].l_close)(tp, flag);
1434	disc_optim(tp, &tp->t_termios, com);
1435	comstop(tp, FREAD | FWRITE);
1436	comhardclose(com);
1437	ttyclose(tp);
1438	siosettimeout();
1439	splx(s);
1440	if (com->gone) {
1441		printf("sio%d: gone\n", com->unit);
1442		s = spltty();
1443		if (com->ibuf != NULL)
1444			free(com->ibuf, M_DEVBUF);
1445		bzero(tp, sizeof *tp);
1446		splx(s);
1447	}
1448	return (0);
1449}
1450
1451static void
1452comhardclose(com)
1453	struct com_s	*com;
1454{
1455	Port_t		iobase;
1456	int		s;
1457	struct tty	*tp;
1458	int		unit;
1459
1460	unit = com->unit;
1461	iobase = com->iobase;
1462	s = spltty();
1463	com->poll = FALSE;
1464	com->poll_output = FALSE;
1465	com->do_timestamp = FALSE;
1466	com->do_dcd_timestamp = FALSE;
1467	com->pps.ppsparam.mode = 0;
1468	outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1469	{
1470		outb(iobase + com_ier, 0);
1471		tp = com->tp;
1472		if (tp->t_cflag & HUPCL
1473		    /*
1474		     * XXX we will miss any carrier drop between here and the
1475		     * next open.  Perhaps we should watch DCD even when the
1476		     * port is closed; it is not sufficient to check it at
1477		     * the next open because it might go up and down while
1478		     * we're not watching.
1479		     */
1480		    || (!com->active_out
1481		        && !(com->prev_modem_status & MSR_DCD)
1482		        && !(com->it_in.c_cflag & CLOCAL))
1483		    || !(tp->t_state & TS_ISOPEN)) {
1484			(void)commctl(com, TIOCM_DTR, DMBIC);
1485			if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
1486				timeout(siodtrwakeup, com, com->dtr_wait);
1487				com->state |= CS_DTR_OFF;
1488			}
1489		}
1490	}
1491	if (com->hasfifo) {
1492		/*
1493		 * Disable fifos so that they are off after controlled
1494		 * reboots.  Some BIOSes fail to detect 16550s when the
1495		 * fifos are enabled.
1496		 */
1497		outb(iobase + com_fifo, 0);
1498	}
1499	com->active_out = FALSE;
1500	wakeup(&com->active_out);
1501	wakeup(TSA_CARR_ON(tp));	/* restart any wopeners */
1502	splx(s);
1503}
1504
1505static int
1506sioread(dev, uio, flag)
1507	dev_t		dev;
1508	struct uio	*uio;
1509	int		flag;
1510{
1511	int		mynor;
1512	struct com_s	*com;
1513
1514	mynor = minor(dev);
1515	if (mynor & CONTROL_MASK)
1516		return (ENODEV);
1517	com = com_addr(MINOR_TO_UNIT(mynor));
1518	if (com == NULL || com->gone)
1519		return (ENODEV);
1520	return ((*linesw[com->tp->t_line].l_read)(com->tp, uio, flag));
1521}
1522
1523static int
1524siowrite(dev, uio, flag)
1525	dev_t		dev;
1526	struct uio	*uio;
1527	int		flag;
1528{
1529	int		mynor;
1530	struct com_s	*com;
1531	int		unit;
1532
1533	mynor = minor(dev);
1534	if (mynor & CONTROL_MASK)
1535		return (ENODEV);
1536
1537	unit = MINOR_TO_UNIT(mynor);
1538	com = com_addr(unit);
1539	if (com == NULL || com->gone)
1540		return (ENODEV);
1541	/*
1542	 * (XXX) We disallow virtual consoles if the physical console is
1543	 * a serial port.  This is in case there is a display attached that
1544	 * is not the console.  In that situation we don't need/want the X
1545	 * server taking over the console.
1546	 */
1547	if (constty != NULL && unit == comconsole)
1548		constty = NULL;
1549	return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag));
1550}
1551
1552static void
1553siobusycheck(chan)
1554	void	*chan;
1555{
1556	struct com_s	*com;
1557	int		s;
1558
1559	com = (struct com_s *)chan;
1560
1561	/*
1562	 * Clear TS_BUSY if low-level output is complete.
1563	 * spl locking is sufficient because siointr1() does not set CS_BUSY.
1564	 * If siointr1() clears CS_BUSY after we look at it, then we'll get
1565	 * called again.  Reading the line status port outside of siointr1()
1566	 * is safe because CS_BUSY is clear so there are no output interrupts
1567	 * to lose.
1568	 */
1569	s = spltty();
1570	if (com->state & CS_BUSY)
1571		com->extra_state &= ~CSE_BUSYCHECK;	/* False alarm. */
1572	else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
1573	    == (LSR_TSRE | LSR_TXRDY)) {
1574		com->tp->t_state &= ~TS_BUSY;
1575		ttwwakeup(com->tp);
1576		com->extra_state &= ~CSE_BUSYCHECK;
1577	} else
1578		timeout(siobusycheck, com, hz / 100);
1579	splx(s);
1580}
1581
1582static void
1583siodtrwakeup(chan)
1584	void	*chan;
1585{
1586	struct com_s	*com;
1587
1588	com = (struct com_s *)chan;
1589	com->state &= ~CS_DTR_OFF;
1590	wakeup(&com->dtr_wait);
1591}
1592
1593static void
1594sioinput(com)
1595	struct com_s	*com;
1596{
1597	u_char		*buf;
1598	int		incc;
1599	u_char		line_status;
1600	int		recv_data;
1601	struct tty	*tp;
1602
1603	buf = com->ibuf;
1604	tp = com->tp;
1605	if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
1606		com_events -= (com->iptr - com->ibuf);
1607		com->iptr = com->ibuf;
1608		return;
1609	}
1610	if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1611		/*
1612		 * Avoid the grotesquely inefficient lineswitch routine
1613		 * (ttyinput) in "raw" mode.  It usually takes about 450
1614		 * instructions (that's without canonical processing or echo!).
1615		 * slinput is reasonably fast (usually 40 instructions plus
1616		 * call overhead).
1617		 */
1618		do {
1619			enable_intr();
1620			incc = com->iptr - buf;
1621			if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1622			    && (com->state & CS_RTS_IFLOW
1623				|| tp->t_iflag & IXOFF)
1624			    && !(tp->t_state & TS_TBLOCK))
1625				ttyblock(tp);
1626			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1627				+= b_to_q((char *)buf, incc, &tp->t_rawq);
1628			buf += incc;
1629			tk_nin += incc;
1630			tk_rawcc += incc;
1631			tp->t_rawcc += incc;
1632			ttwakeup(tp);
1633			if (tp->t_state & TS_TTSTOP
1634			    && (tp->t_iflag & IXANY
1635				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1636				tp->t_state &= ~TS_TTSTOP;
1637				tp->t_lflag &= ~FLUSHO;
1638				comstart(tp);
1639			}
1640			disable_intr();
1641		} while (buf < com->iptr);
1642	} else {
1643		do {
1644			enable_intr();
1645			line_status = buf[com->ierroff];
1646			recv_data = *buf++;
1647			if (line_status
1648			    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1649				if (line_status & LSR_BI)
1650					recv_data |= TTY_BI;
1651				if (line_status & LSR_FE)
1652					recv_data |= TTY_FE;
1653				if (line_status & LSR_OE)
1654					recv_data |= TTY_OE;
1655				if (line_status & LSR_PE)
1656					recv_data |= TTY_PE;
1657			}
1658			(*linesw[tp->t_line].l_rint)(recv_data, tp);
1659			disable_intr();
1660		} while (buf < com->iptr);
1661	}
1662	com_events -= (com->iptr - com->ibuf);
1663	com->iptr = com->ibuf;
1664
1665	/*
1666	 * There is now room for another low-level buffer full of input,
1667	 * so enable RTS if it is now disabled and there is room in the
1668	 * high-level buffer.
1669	 */
1670	if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
1671	    !(tp->t_state & TS_TBLOCK))
1672		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
1673}
1674
1675void
1676siointr(arg)
1677	void		*arg;
1678{
1679#ifndef COM_MULTIPORT
1680	COM_LOCK();
1681	siointr1((struct com_s *) arg);
1682	COM_UNLOCK();
1683#else /* COM_MULTIPORT */
1684	bool_t		possibly_more_intrs;
1685	int		unit;
1686	struct com_s	*com;
1687
1688	/*
1689	 * Loop until there is no activity on any port.  This is necessary
1690	 * to get an interrupt edge more than to avoid another interrupt.
1691	 * If the IRQ signal is just an OR of the IRQ signals from several
1692	 * devices, then the edge from one may be lost because another is
1693	 * on.
1694	 */
1695	COM_LOCK();
1696	do {
1697		possibly_more_intrs = FALSE;
1698		for (unit = 0; unit < sio_numunits; ++unit) {
1699			com = com_addr(unit);
1700			/*
1701			 * XXX COM_LOCK();
1702			 * would it work here, or be counter-productive?
1703			 */
1704			if (com != NULL
1705			    && !com->gone
1706			    && (inb(com->int_id_port) & IIR_IMASK)
1707			       != IIR_NOPEND) {
1708				siointr1(com);
1709				possibly_more_intrs = TRUE;
1710			}
1711			/* XXX COM_UNLOCK(); */
1712		}
1713	} while (possibly_more_intrs);
1714	COM_UNLOCK();
1715#endif /* COM_MULTIPORT */
1716}
1717
1718static void
1719siointr1(com)
1720	struct com_s	*com;
1721{
1722	u_char	line_status;
1723	u_char	modem_status;
1724	u_char	*ioptr;
1725	u_char	recv_data;
1726	u_char	int_ctl;
1727	u_char	int_ctl_new;
1728	struct	timecounter *tc;
1729	u_int	count;
1730
1731	int_ctl = inb(com->intr_ctl_port);
1732	int_ctl_new = int_ctl;
1733
1734	while (!com->gone) {
1735		if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) {
1736			modem_status = inb(com->modem_status_port);
1737		        if ((modem_status ^ com->last_modem_status) & MSR_DCD) {
1738				tc = timecounter;
1739				count = tc->tc_get_timecount(tc);
1740				pps_event(&com->pps, tc, count,
1741				    (modem_status & MSR_DCD) ?
1742				    PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
1743			}
1744		}
1745		line_status = inb(com->line_status_port);
1746
1747		/* input event? (check first to help avoid overruns) */
1748		while (line_status & LSR_RCV_MASK) {
1749			/* break/unnattached error bits or real input? */
1750			if (!(line_status & LSR_RXRDY))
1751				recv_data = 0;
1752			else
1753				recv_data = inb(com->data_port);
1754			if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
1755				/*
1756				 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
1757				 * Otherwise, push the work to a higher level
1758				 * (to handle PARMRK) if we're bypassing.
1759				 * Otherwise, convert BI/FE and PE+INPCK to 0.
1760				 *
1761				 * This makes bypassing work right in the
1762				 * usual "raw" case (IGNBRK set, and IGNPAR
1763				 * and INPCK clear).
1764				 *
1765				 * Note: BI together with FE/PE means just BI.
1766				 */
1767				if (line_status & LSR_BI) {
1768#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
1769					if (com->unit == comconsole) {
1770						breakpoint();
1771						goto cont;
1772					}
1773#endif
1774					if (com->tp == NULL
1775					    || com->tp->t_iflag & IGNBRK)
1776						goto cont;
1777				} else {
1778					if (com->tp == NULL
1779					    || com->tp->t_iflag & IGNPAR)
1780						goto cont;
1781				}
1782				if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
1783				    && (line_status & (LSR_BI | LSR_FE)
1784					|| com->tp->t_iflag & INPCK))
1785					recv_data = 0;
1786			}
1787			++com->bytes_in;
1788			if (com->hotchar != 0 && recv_data == com->hotchar)
1789				setsofttty();
1790			ioptr = com->iptr;
1791			if (ioptr >= com->ibufend)
1792				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1793			else {
1794				if (com->do_timestamp)
1795					microtime(&com->timestamp);
1796				++com_events;
1797				schedsofttty();
1798#if 0 /* for testing input latency vs efficiency */
1799if (com->iptr - com->ibuf == 8)
1800	setsofttty();
1801#endif
1802				ioptr[0] = recv_data;
1803				ioptr[com->ierroff] = line_status;
1804				com->iptr = ++ioptr;
1805				if (ioptr == com->ihighwater
1806				    && com->state & CS_RTS_IFLOW)
1807					outb(com->modem_ctl_port,
1808					     com->mcr_image &= ~MCR_RTS);
1809				if (line_status & LSR_OE)
1810					CE_RECORD(com, CE_OVERRUN);
1811			}
1812cont:
1813			/*
1814			 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
1815			 * jump from the top of the loop to here
1816			 */
1817			line_status = inb(com->line_status_port) & 0x7F;
1818		}
1819
1820		/* modem status change? (always check before doing output) */
1821		modem_status = inb(com->modem_status_port);
1822		if (modem_status != com->last_modem_status) {
1823			if (com->do_dcd_timestamp
1824			    && !(com->last_modem_status & MSR_DCD)
1825			    && modem_status & MSR_DCD)
1826				microtime(&com->dcd_timestamp);
1827
1828			/*
1829			 * Schedule high level to handle DCD changes.  Note
1830			 * that we don't use the delta bits anywhere.  Some
1831			 * UARTs mess them up, and it's easy to remember the
1832			 * previous bits and calculate the delta.
1833			 */
1834			com->last_modem_status = modem_status;
1835			if (!(com->state & CS_CHECKMSR)) {
1836				com_events += LOTS_OF_EVENTS;
1837				com->state |= CS_CHECKMSR;
1838				setsofttty();
1839			}
1840
1841			/* handle CTS change immediately for crisp flow ctl */
1842			if (com->state & CS_CTS_OFLOW) {
1843				if (modem_status & MSR_CTS)
1844					com->state |= CS_ODEVREADY;
1845				else
1846					com->state &= ~CS_ODEVREADY;
1847			}
1848		}
1849
1850		/* output queued and everything ready? */
1851		if (line_status & LSR_TXRDY
1852		    && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1853			ioptr = com->obufq.l_head;
1854			if (com->tx_fifo_size > 1) {
1855				u_int	ocount;
1856
1857				ocount = com->obufq.l_tail - ioptr;
1858				if (ocount > com->tx_fifo_size)
1859					ocount = com->tx_fifo_size;
1860				com->bytes_out += ocount;
1861				do
1862					outb(com->data_port, *ioptr++);
1863				while (--ocount != 0);
1864			} else {
1865				outb(com->data_port, *ioptr++);
1866				++com->bytes_out;
1867			}
1868			com->obufq.l_head = ioptr;
1869			if (COM_IIR_TXRDYBUG(com->flags)) {
1870				int_ctl_new = int_ctl | IER_ETXRDY;
1871			}
1872			if (ioptr >= com->obufq.l_tail) {
1873				struct lbq	*qp;
1874
1875				qp = com->obufq.l_next;
1876				qp->l_queued = FALSE;
1877				qp = qp->l_next;
1878				if (qp != NULL) {
1879					com->obufq.l_head = qp->l_head;
1880					com->obufq.l_tail = qp->l_tail;
1881					com->obufq.l_next = qp;
1882				} else {
1883					/* output just completed */
1884					if (COM_IIR_TXRDYBUG(com->flags)) {
1885						int_ctl_new = int_ctl & ~IER_ETXRDY;
1886					}
1887					com->state &= ~CS_BUSY;
1888				}
1889				if (!(com->state & CS_ODONE)) {
1890					com_events += LOTS_OF_EVENTS;
1891					com->state |= CS_ODONE;
1892					setsofttty();	/* handle at high level ASAP */
1893				}
1894			}
1895			if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) {
1896				outb(com->intr_ctl_port, int_ctl_new);
1897			}
1898		}
1899
1900		/* finished? */
1901#ifndef COM_MULTIPORT
1902		if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
1903#endif /* COM_MULTIPORT */
1904			return;
1905	}
1906}
1907
1908static int
1909sioioctl(dev, cmd, data, flag, p)
1910	dev_t		dev;
1911	u_long		cmd;
1912	caddr_t		data;
1913	int		flag;
1914	struct proc	*p;
1915{
1916	struct com_s	*com;
1917	int		error;
1918	Port_t		iobase;
1919	int		mynor;
1920	int		s;
1921	struct tty	*tp;
1922#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1923	u_long		oldcmd;
1924	struct termios	term;
1925#endif
1926
1927	mynor = minor(dev);
1928	com = com_addr(MINOR_TO_UNIT(mynor));
1929	if (com == NULL || com->gone)
1930		return (ENODEV);
1931	iobase = com->iobase;
1932	if (mynor & CONTROL_MASK) {
1933		struct termios	*ct;
1934
1935		switch (mynor & CONTROL_MASK) {
1936		case CONTROL_INIT_STATE:
1937			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
1938			break;
1939		case CONTROL_LOCK_STATE:
1940			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
1941			break;
1942		default:
1943			return (ENODEV);	/* /dev/nodev */
1944		}
1945		switch (cmd) {
1946		case TIOCSETA:
1947			error = suser(p);
1948			if (error != 0)
1949				return (error);
1950			*ct = *(struct termios *)data;
1951			return (0);
1952		case TIOCGETA:
1953			*(struct termios *)data = *ct;
1954			return (0);
1955		case TIOCGETD:
1956			*(int *)data = TTYDISC;
1957			return (0);
1958		case TIOCGWINSZ:
1959			bzero(data, sizeof(struct winsize));
1960			return (0);
1961		default:
1962			return (ENOTTY);
1963		}
1964	}
1965	tp = com->tp;
1966#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1967	term = tp->t_termios;
1968	oldcmd = cmd;
1969	error = ttsetcompat(tp, &cmd, data, &term);
1970	if (error != 0)
1971		return (error);
1972	if (cmd != oldcmd)
1973		data = (caddr_t)&term;
1974#endif
1975	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1976		int	cc;
1977		struct termios *dt = (struct termios *)data;
1978		struct termios *lt = mynor & CALLOUT_MASK
1979				     ? &com->lt_out : &com->lt_in;
1980
1981		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1982			      | (dt->c_iflag & ~lt->c_iflag);
1983		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1984			      | (dt->c_oflag & ~lt->c_oflag);
1985		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1986			      | (dt->c_cflag & ~lt->c_cflag);
1987		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1988			      | (dt->c_lflag & ~lt->c_lflag);
1989		for (cc = 0; cc < NCCS; ++cc)
1990			if (lt->c_cc[cc] != 0)
1991				dt->c_cc[cc] = tp->t_cc[cc];
1992		if (lt->c_ispeed != 0)
1993			dt->c_ispeed = tp->t_ispeed;
1994		if (lt->c_ospeed != 0)
1995			dt->c_ospeed = tp->t_ospeed;
1996	}
1997	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1998	if (error != ENOIOCTL)
1999		return (error);
2000	s = spltty();
2001	error = ttioctl(tp, cmd, data, flag);
2002	disc_optim(tp, &tp->t_termios, com);
2003	if (error != ENOIOCTL) {
2004		splx(s);
2005		return (error);
2006	}
2007	switch (cmd) {
2008	case TIOCSBRK:
2009		outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2010		break;
2011	case TIOCCBRK:
2012		outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2013		break;
2014	case TIOCSDTR:
2015		(void)commctl(com, TIOCM_DTR, DMBIS);
2016		break;
2017	case TIOCCDTR:
2018		(void)commctl(com, TIOCM_DTR, DMBIC);
2019		break;
2020	/*
2021	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
2022	 * changes get undone on the next call to comparam().
2023	 */
2024	case TIOCMSET:
2025		(void)commctl(com, *(int *)data, DMSET);
2026		break;
2027	case TIOCMBIS:
2028		(void)commctl(com, *(int *)data, DMBIS);
2029		break;
2030	case TIOCMBIC:
2031		(void)commctl(com, *(int *)data, DMBIC);
2032		break;
2033	case TIOCMGET:
2034		*(int *)data = commctl(com, 0, DMGET);
2035		break;
2036	case TIOCMSDTRWAIT:
2037		/* must be root since the wait applies to following logins */
2038		error = suser(p);
2039		if (error != 0) {
2040			splx(s);
2041			return (error);
2042		}
2043		com->dtr_wait = *(int *)data * hz / 100;
2044		break;
2045	case TIOCMGDTRWAIT:
2046		*(int *)data = com->dtr_wait * 100 / hz;
2047		break;
2048	case TIOCTIMESTAMP:
2049		com->do_timestamp = TRUE;
2050		*(struct timeval *)data = com->timestamp;
2051		break;
2052	case TIOCDCDTIMESTAMP:
2053		com->do_dcd_timestamp = TRUE;
2054		*(struct timeval *)data = com->dcd_timestamp;
2055		break;
2056	default:
2057		splx(s);
2058		error = pps_ioctl(cmd, data, &com->pps);
2059		if (error == ENODEV)
2060			error = ENOTTY;
2061		return (error);
2062	}
2063	splx(s);
2064	return (0);
2065}
2066
2067static void
2068siopoll()
2069{
2070	int		unit;
2071
2072	if (com_events == 0)
2073		return;
2074repeat:
2075	for (unit = 0; unit < sio_numunits; ++unit) {
2076		struct com_s	*com;
2077		int		incc;
2078		struct tty	*tp;
2079
2080		com = com_addr(unit);
2081		if (com == NULL)
2082			continue;
2083		tp = com->tp;
2084		if (tp == NULL || com->gone) {
2085			/*
2086			 * Discard any events related to never-opened or
2087			 * going-away devices.
2088			 */
2089			disable_intr();
2090			incc = com->iptr - com->ibuf;
2091			com->iptr = com->ibuf;
2092			if (com->state & CS_CHECKMSR) {
2093				incc += LOTS_OF_EVENTS;
2094				com->state &= ~CS_CHECKMSR;
2095			}
2096			com_events -= incc;
2097			enable_intr();
2098			continue;
2099		}
2100		if (com->iptr != com->ibuf) {
2101			disable_intr();
2102			sioinput(com);
2103			enable_intr();
2104		}
2105		if (com->state & CS_CHECKMSR) {
2106			u_char	delta_modem_status;
2107
2108			disable_intr();
2109			delta_modem_status = com->last_modem_status
2110					     ^ com->prev_modem_status;
2111			com->prev_modem_status = com->last_modem_status;
2112			com_events -= LOTS_OF_EVENTS;
2113			com->state &= ~CS_CHECKMSR;
2114			enable_intr();
2115			if (delta_modem_status & MSR_DCD)
2116				(*linesw[tp->t_line].l_modem)
2117					(tp, com->prev_modem_status & MSR_DCD);
2118		}
2119		if (com->state & CS_ODONE) {
2120			disable_intr();
2121			com_events -= LOTS_OF_EVENTS;
2122			com->state &= ~CS_ODONE;
2123			enable_intr();
2124			if (!(com->state & CS_BUSY)
2125			    && !(com->extra_state & CSE_BUSYCHECK)) {
2126				timeout(siobusycheck, com, hz / 100);
2127				com->extra_state |= CSE_BUSYCHECK;
2128			}
2129			(*linesw[tp->t_line].l_start)(tp);
2130		}
2131		if (com_events == 0)
2132			break;
2133	}
2134	if (com_events >= LOTS_OF_EVENTS)
2135		goto repeat;
2136}
2137
2138static int
2139comparam(tp, t)
2140	struct tty	*tp;
2141	struct termios	*t;
2142{
2143	u_int		cfcr;
2144	int		cflag;
2145	struct com_s	*com;
2146	int		divisor;
2147	u_char		dlbh;
2148	u_char		dlbl;
2149	Port_t		iobase;
2150	int		s;
2151	int		unit;
2152
2153	/* do historical conversions */
2154	if (t->c_ispeed == 0)
2155		t->c_ispeed = t->c_ospeed;
2156
2157	/* check requested parameters */
2158	divisor = ttspeedtab(t->c_ospeed, comspeedtab);
2159	if (divisor < 0 || (divisor > 0 && t->c_ispeed != t->c_ospeed))
2160		return (EINVAL);
2161
2162	/* parameters are OK, convert them to the com struct and the device */
2163	unit = DEV_TO_UNIT(tp->t_dev);
2164	com = com_addr(unit);
2165	if (com == NULL)
2166		return (ENODEV);
2167	iobase = com->iobase;
2168	s = spltty();
2169	if (divisor == 0)
2170		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
2171	else
2172		(void)commctl(com, TIOCM_DTR, DMBIS);
2173	cflag = t->c_cflag;
2174	switch (cflag & CSIZE) {
2175	case CS5:
2176		cfcr = CFCR_5BITS;
2177		break;
2178	case CS6:
2179		cfcr = CFCR_6BITS;
2180		break;
2181	case CS7:
2182		cfcr = CFCR_7BITS;
2183		break;
2184	default:
2185		cfcr = CFCR_8BITS;
2186		break;
2187	}
2188	if (cflag & PARENB) {
2189		cfcr |= CFCR_PENAB;
2190		if (!(cflag & PARODD))
2191			cfcr |= CFCR_PEVEN;
2192	}
2193	if (cflag & CSTOPB)
2194		cfcr |= CFCR_STOPB;
2195
2196	if (com->hasfifo && divisor != 0) {
2197		/*
2198		 * Use a fifo trigger level low enough so that the input
2199		 * latency from the fifo is less than about 16 msec and
2200		 * the total latency is less than about 30 msec.  These
2201		 * latencies are reasonable for humans.  Serial comms
2202		 * protocols shouldn't expect anything better since modem
2203		 * latencies are larger.
2204		 */
2205		com->fifo_image = t->c_ospeed <= 4800
2206				  ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH;
2207#ifdef COM_ESP
2208		/*
2209		 * The Hayes ESP card needs the fifo DMA mode bit set
2210		 * in compatibility mode.  If not, it will interrupt
2211		 * for each character received.
2212		 */
2213		if (com->esp)
2214			com->fifo_image |= FIFO_DMA_MODE;
2215#endif
2216		outb(iobase + com_fifo, com->fifo_image);
2217	}
2218
2219	/*
2220	 * This returns with interrupts disabled so that we can complete
2221	 * the speed change atomically.  Keeping interrupts disabled is
2222	 * especially important while com_data is hidden.
2223	 */
2224	(void) siosetwater(com, t->c_ispeed);
2225
2226	if (divisor != 0) {
2227		outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
2228		/*
2229		 * Only set the divisor registers if they would change,
2230		 * since on some 16550 incompatibles (UMC8669F), setting
2231		 * them while input is arriving them loses sync until
2232		 * data stops arriving.
2233		 */
2234		dlbl = divisor & 0xFF;
2235		if (inb(iobase + com_dlbl) != dlbl)
2236			outb(iobase + com_dlbl, dlbl);
2237		dlbh = (u_int) divisor >> 8;
2238		if (inb(iobase + com_dlbh) != dlbh)
2239			outb(iobase + com_dlbh, dlbh);
2240	}
2241
2242
2243	outb(iobase + com_cfcr, com->cfcr_image = cfcr);
2244
2245	if (!(tp->t_state & TS_TTSTOP))
2246		com->state |= CS_TTGO;
2247
2248	if (cflag & CRTS_IFLOW) {
2249		if (com->st16650a) {
2250			outb(iobase + com_cfcr, 0xbf);
2251			outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40);
2252		}
2253		com->state |= CS_RTS_IFLOW;
2254		/*
2255		 * If CS_RTS_IFLOW just changed from off to on, the change
2256		 * needs to be propagated to MCR_RTS.  This isn't urgent,
2257		 * so do it later by calling comstart() instead of repeating
2258		 * a lot of code from comstart() here.
2259		 */
2260	} else if (com->state & CS_RTS_IFLOW) {
2261		com->state &= ~CS_RTS_IFLOW;
2262		/*
2263		 * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
2264		 * on here, since comstart() won't do it later.
2265		 */
2266		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2267		if (com->st16650a) {
2268			outb(iobase + com_cfcr, 0xbf);
2269			outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40);
2270		}
2271	}
2272
2273
2274	/*
2275	 * Set up state to handle output flow control.
2276	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2277	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2278	 */
2279	com->state |= CS_ODEVREADY;
2280	com->state &= ~CS_CTS_OFLOW;
2281	if (cflag & CCTS_OFLOW) {
2282		com->state |= CS_CTS_OFLOW;
2283		if (!(com->last_modem_status & MSR_CTS))
2284			com->state &= ~CS_ODEVREADY;
2285		if (com->st16650a) {
2286			outb(iobase + com_cfcr, 0xbf);
2287			outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80);
2288		}
2289	} else {
2290		if (com->st16650a) {
2291			outb(iobase + com_cfcr, 0xbf);
2292			outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80);
2293		}
2294	}
2295
2296
2297	outb(iobase + com_cfcr, com->cfcr_image);
2298
2299
2300	/* XXX shouldn't call functions while intrs are disabled. */
2301	disc_optim(tp, t, com);
2302	/*
2303	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
2304	 * unconditionally, but that defeated the careful discarding of
2305	 * stale input in sioopen().
2306	 */
2307	if (com->state >= (CS_BUSY | CS_TTGO))
2308		siointr1(com);
2309
2310	enable_intr();
2311	splx(s);
2312	comstart(tp);
2313	if (com->ibufold != NULL) {
2314		free(com->ibufold, M_DEVBUF);
2315		com->ibufold = NULL;
2316	}
2317	return (0);
2318}
2319
2320static int
2321siosetwater(com, speed)
2322	struct com_s	*com;
2323	speed_t		speed;
2324{
2325	int		cp4ticks;
2326	u_char		*ibuf;
2327	int		ibufsize;
2328	struct tty	*tp;
2329
2330	/*
2331	 * Make the buffer size large enough to handle a softtty interrupt
2332	 * latency of about 2 ticks without loss of throughput or data
2333	 * (about 3 ticks if input flow control is not used or not honoured,
2334	 * but a bit less for CS5-CS7 modes).
2335	 */
2336	cp4ticks = speed / 10 / hz * 4;
2337	for (ibufsize = 128; ibufsize < cp4ticks;)
2338		ibufsize <<= 1;
2339	if (ibufsize == com->ibufsize) {
2340		disable_intr();
2341		return (0);
2342	}
2343
2344	/*
2345	 * Allocate input buffer.  The extra factor of 2 in the size is
2346	 * to allow for an error byte for each input byte.
2347	 */
2348	ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
2349	if (ibuf == NULL) {
2350		disable_intr();
2351		return (ENOMEM);
2352	}
2353
2354	/* Initialize non-critical variables. */
2355	com->ibufold = com->ibuf;
2356	com->ibufsize = ibufsize;
2357	tp = com->tp;
2358	if (tp != NULL) {
2359		tp->t_ififosize = 2 * ibufsize;
2360		tp->t_ispeedwat = (speed_t)-1;
2361		tp->t_ospeedwat = (speed_t)-1;
2362	}
2363
2364	/*
2365	 * Read current input buffer, if any.  Continue with interrupts
2366	 * disabled.
2367	 */
2368	disable_intr();
2369	if (com->iptr != com->ibuf)
2370		sioinput(com);
2371
2372	/*-
2373	 * Initialize critical variables, including input buffer watermarks.
2374	 * The external device is asked to stop sending when the buffer
2375	 * exactly reaches high water, or when the high level requests it.
2376	 * The high level is notified immediately (rather than at a later
2377	 * clock tick) when this watermark is reached.
2378	 * The buffer size is chosen so the watermark should almost never
2379	 * be reached.
2380	 * The low watermark is invisibly 0 since the buffer is always
2381	 * emptied all at once.
2382	 */
2383	com->iptr = com->ibuf = ibuf;
2384	com->ibufend = ibuf + ibufsize;
2385	com->ierroff = ibufsize;
2386	com->ihighwater = ibuf + 3 * ibufsize / 4;
2387	return (0);
2388}
2389
2390static void
2391comstart(tp)
2392	struct tty	*tp;
2393{
2394	struct com_s	*com;
2395	int		s;
2396	int		unit;
2397
2398	unit = DEV_TO_UNIT(tp->t_dev);
2399	com = com_addr(unit);
2400	if (com == NULL)
2401		return;
2402	s = spltty();
2403	disable_intr();
2404	if (tp->t_state & TS_TTSTOP)
2405		com->state &= ~CS_TTGO;
2406	else
2407		com->state |= CS_TTGO;
2408	if (tp->t_state & TS_TBLOCK) {
2409		if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2410			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2411	} else {
2412		if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2413		    && com->state & CS_RTS_IFLOW)
2414			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2415	}
2416	enable_intr();
2417	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2418		ttwwakeup(tp);
2419		splx(s);
2420		return;
2421	}
2422	if (tp->t_outq.c_cc != 0) {
2423		struct lbq	*qp;
2424		struct lbq	*next;
2425
2426		if (!com->obufs[0].l_queued) {
2427			com->obufs[0].l_tail
2428			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2429						  sizeof com->obuf1);
2430			com->obufs[0].l_next = NULL;
2431			com->obufs[0].l_queued = TRUE;
2432			disable_intr();
2433			if (com->state & CS_BUSY) {
2434				qp = com->obufq.l_next;
2435				while ((next = qp->l_next) != NULL)
2436					qp = next;
2437				qp->l_next = &com->obufs[0];
2438			} else {
2439				com->obufq.l_head = com->obufs[0].l_head;
2440				com->obufq.l_tail = com->obufs[0].l_tail;
2441				com->obufq.l_next = &com->obufs[0];
2442				com->state |= CS_BUSY;
2443			}
2444			enable_intr();
2445		}
2446		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2447			com->obufs[1].l_tail
2448			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2449						  sizeof com->obuf2);
2450			com->obufs[1].l_next = NULL;
2451			com->obufs[1].l_queued = TRUE;
2452			disable_intr();
2453			if (com->state & CS_BUSY) {
2454				qp = com->obufq.l_next;
2455				while ((next = qp->l_next) != NULL)
2456					qp = next;
2457				qp->l_next = &com->obufs[1];
2458			} else {
2459				com->obufq.l_head = com->obufs[1].l_head;
2460				com->obufq.l_tail = com->obufs[1].l_tail;
2461				com->obufq.l_next = &com->obufs[1];
2462				com->state |= CS_BUSY;
2463			}
2464			enable_intr();
2465		}
2466		tp->t_state |= TS_BUSY;
2467	}
2468	disable_intr();
2469	if (com->state >= (CS_BUSY | CS_TTGO))
2470		siointr1(com);	/* fake interrupt to start output */
2471	enable_intr();
2472	ttwwakeup(tp);
2473	splx(s);
2474}
2475
2476static void
2477comstop(tp, rw)
2478	struct tty	*tp;
2479	int		rw;
2480{
2481	struct com_s	*com;
2482
2483	com = com_addr(DEV_TO_UNIT(tp->t_dev));
2484	if (com == NULL || com->gone)
2485		return;
2486	disable_intr();
2487	if (rw & FWRITE) {
2488		if (com->hasfifo)
2489#ifdef COM_ESP
2490		    /* XXX avoid h/w bug. */
2491		    if (!com->esp)
2492#endif
2493			outb(com->iobase + com_fifo,
2494			     FIFO_XMT_RST | com->fifo_image);
2495		com->obufs[0].l_queued = FALSE;
2496		com->obufs[1].l_queued = FALSE;
2497		if (com->state & CS_ODONE)
2498			com_events -= LOTS_OF_EVENTS;
2499		com->state &= ~(CS_ODONE | CS_BUSY);
2500		com->tp->t_state &= ~TS_BUSY;
2501	}
2502	if (rw & FREAD) {
2503		if (com->hasfifo)
2504#ifdef COM_ESP
2505		    /* XXX avoid h/w bug. */
2506		    if (!com->esp)
2507#endif
2508			outb(com->iobase + com_fifo,
2509			     FIFO_RCV_RST | com->fifo_image);
2510		com_events -= (com->iptr - com->ibuf);
2511		com->iptr = com->ibuf;
2512	}
2513	enable_intr();
2514	comstart(tp);
2515}
2516
2517static int
2518commctl(com, bits, how)
2519	struct com_s	*com;
2520	int		bits;
2521	int		how;
2522{
2523	int	mcr;
2524	int	msr;
2525
2526	if (how == DMGET) {
2527		bits = TIOCM_LE;	/* XXX - always enabled while open */
2528		mcr = com->mcr_image;
2529		if (mcr & MCR_DTR)
2530			bits |= TIOCM_DTR;
2531		if (mcr & MCR_RTS)
2532			bits |= TIOCM_RTS;
2533		msr = com->prev_modem_status;
2534		if (msr & MSR_CTS)
2535			bits |= TIOCM_CTS;
2536		if (msr & MSR_DCD)
2537			bits |= TIOCM_CD;
2538		if (msr & MSR_DSR)
2539			bits |= TIOCM_DSR;
2540		/*
2541		 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
2542		 * more volatile by reading the modem status a lot.  Perhaps
2543		 * we should latch both bits until the status is read here.
2544		 */
2545		if (msr & (MSR_RI | MSR_TERI))
2546			bits |= TIOCM_RI;
2547		return (bits);
2548	}
2549	mcr = 0;
2550	if (bits & TIOCM_DTR)
2551		mcr |= MCR_DTR;
2552	if (bits & TIOCM_RTS)
2553		mcr |= MCR_RTS;
2554	if (com->gone)
2555		return(0);
2556	disable_intr();
2557	switch (how) {
2558	case DMSET:
2559		outb(com->modem_ctl_port,
2560		     com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
2561		break;
2562	case DMBIS:
2563		outb(com->modem_ctl_port, com->mcr_image |= mcr);
2564		break;
2565	case DMBIC:
2566		outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
2567		break;
2568	}
2569	enable_intr();
2570	return (0);
2571}
2572
2573static void
2574siosettimeout()
2575{
2576	struct com_s	*com;
2577	bool_t		someopen;
2578	int		unit;
2579
2580	/*
2581	 * Set our timeout period to 1 second if no polled devices are open.
2582	 * Otherwise set it to max(1/200, 1/hz).
2583	 * Enable timeouts iff some device is open.
2584	 */
2585	untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2586	sio_timeout = hz;
2587	someopen = FALSE;
2588	for (unit = 0; unit < sio_numunits; ++unit) {
2589		com = com_addr(unit);
2590		if (com != NULL && com->tp != NULL
2591		    && com->tp->t_state & TS_ISOPEN && !com->gone) {
2592			someopen = TRUE;
2593			if (com->poll || com->poll_output) {
2594				sio_timeout = hz > 200 ? hz / 200 : 1;
2595				break;
2596			}
2597		}
2598	}
2599	if (someopen) {
2600		sio_timeouts_until_log = hz / sio_timeout;
2601		sio_timeout_handle = timeout(comwakeup, (void *)NULL,
2602					     sio_timeout);
2603	} else {
2604		/* Flush error messages, if any. */
2605		sio_timeouts_until_log = 1;
2606		comwakeup((void *)NULL);
2607		untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2608	}
2609}
2610
2611static void
2612comwakeup(chan)
2613	void	*chan;
2614{
2615	struct com_s	*com;
2616	int		unit;
2617
2618	sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
2619
2620	/*
2621	 * Recover from lost output interrupts.
2622	 * Poll any lines that don't use interrupts.
2623	 */
2624	for (unit = 0; unit < sio_numunits; ++unit) {
2625		com = com_addr(unit);
2626		if (com != NULL && !com->gone
2627		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2628			disable_intr();
2629			siointr1(com);
2630			enable_intr();
2631		}
2632	}
2633
2634	/*
2635	 * Check for and log errors, but not too often.
2636	 */
2637	if (--sio_timeouts_until_log > 0)
2638		return;
2639	sio_timeouts_until_log = hz / sio_timeout;
2640	for (unit = 0; unit < sio_numunits; ++unit) {
2641		int	errnum;
2642
2643		com = com_addr(unit);
2644		if (com == NULL)
2645			continue;
2646		if (com->gone)
2647			continue;
2648		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2649			u_int	delta;
2650			u_long	total;
2651
2652			disable_intr();
2653			delta = com->delta_error_counts[errnum];
2654			com->delta_error_counts[errnum] = 0;
2655			enable_intr();
2656			if (delta == 0)
2657				continue;
2658			total = com->error_counts[errnum] += delta;
2659			log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
2660			    unit, delta, error_desc[errnum],
2661			    delta == 1 ? "" : "s", total);
2662		}
2663	}
2664}
2665
2666static void
2667disc_optim(tp, t, com)
2668	struct tty	*tp;
2669	struct termios	*t;
2670	struct com_s	*com;
2671{
2672	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2673	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2674	    && (!(t->c_iflag & PARMRK)
2675		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2676	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2677	    && linesw[tp->t_line].l_rint == ttyinput)
2678		tp->t_state |= TS_CAN_BYPASS_L_RINT;
2679	else
2680		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2681	com->hotchar = linesw[tp->t_line].l_hotchar;
2682}
2683
2684/*
2685 * Following are all routines needed for SIO to act as console
2686 */
2687#include <sys/cons.h>
2688
2689struct siocnstate {
2690	u_char	dlbl;
2691	u_char	dlbh;
2692	u_char	ier;
2693	u_char	cfcr;
2694	u_char	mcr;
2695};
2696
2697static speed_t siocngetspeed __P((Port_t, struct speedtab *));
2698static void siocnclose	__P((struct siocnstate *sp, Port_t iobase));
2699static void siocnopen	__P((struct siocnstate *sp, Port_t iobase, int speed));
2700static void siocntxwait	__P((Port_t iobase));
2701
2702static cn_probe_t siocnprobe;
2703static cn_init_t siocninit;
2704static cn_checkc_t siocncheckc;
2705static cn_getc_t siocngetc;
2706static cn_putc_t siocnputc;
2707
2708#ifdef __i386__
2709CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc,
2710	    siocnputc, NULL);
2711#endif
2712
2713/* To get the GDB related variables */
2714#if DDB > 0
2715#include <ddb/ddb.h>
2716#endif
2717
2718static void
2719siocntxwait(iobase)
2720	Port_t	iobase;
2721{
2722	int	timo;
2723
2724	/*
2725	 * Wait for any pending transmission to finish.  Required to avoid
2726	 * the UART lockup bug when the speed is changed, and for normal
2727	 * transmits.
2728	 */
2729	timo = 100000;
2730	while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
2731	       != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
2732		;
2733}
2734
2735/*
2736 * Read the serial port specified and try to figure out what speed
2737 * it's currently running at.  We're assuming the serial port has
2738 * been initialized and is basicly idle.  This routine is only intended
2739 * to be run at system startup.
2740 *
2741 * If the value read from the serial port doesn't make sense, return 0.
2742 */
2743
2744static speed_t
2745siocngetspeed(iobase, table)
2746	Port_t iobase;
2747	struct speedtab *table;
2748{
2749	int	code;
2750	u_char	dlbh;
2751	u_char	dlbl;
2752	u_char  cfcr;
2753
2754	cfcr = inb(iobase + com_cfcr);
2755	outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
2756
2757	dlbl = inb(iobase + com_dlbl);
2758	dlbh = inb(iobase + com_dlbh);
2759
2760	outb(iobase + com_cfcr, cfcr);
2761
2762	code = dlbh << 8 | dlbl;
2763
2764	for (; table->sp_speed != -1; table++)
2765		if (table->sp_code == code)
2766			return (table->sp_speed);
2767
2768	return 0;	/* didn't match anything sane */
2769}
2770
2771static void
2772siocnopen(sp, iobase, speed)
2773	struct siocnstate	*sp;
2774	Port_t			iobase;
2775	int			speed;
2776{
2777	int	divisor;
2778	u_char	dlbh;
2779	u_char	dlbl;
2780
2781	/*
2782	 * Save all the device control registers except the fifo register
2783	 * and set our default ones (cs8 -parenb speed=comdefaultrate).
2784	 * We can't save the fifo register since it is read-only.
2785	 */
2786	sp->ier = inb(iobase + com_ier);
2787	outb(iobase + com_ier, 0);	/* spltty() doesn't stop siointr() */
2788	siocntxwait(iobase);
2789	sp->cfcr = inb(iobase + com_cfcr);
2790	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2791	sp->dlbl = inb(iobase + com_dlbl);
2792	sp->dlbh = inb(iobase + com_dlbh);
2793	/*
2794	 * Only set the divisor registers if they would change, since on
2795	 * some 16550 incompatibles (Startech), setting them clears the
2796	 * data input register.  This also reduces the effects of the
2797	 * UMC8669F bug.
2798	 */
2799	divisor = ttspeedtab(speed, comspeedtab);
2800	dlbl = divisor & 0xFF;
2801	if (sp->dlbl != dlbl)
2802		outb(iobase + com_dlbl, dlbl);
2803	dlbh = (u_int) divisor >> 8;
2804	if (sp->dlbh != dlbh)
2805		outb(iobase + com_dlbh, dlbh);
2806	outb(iobase + com_cfcr, CFCR_8BITS);
2807	sp->mcr = inb(iobase + com_mcr);
2808	/*
2809	 * We don't want interrupts, but must be careful not to "disable"
2810	 * them by clearing the MCR_IENABLE bit, since that might cause
2811	 * an interrupt by floating the IRQ line.
2812	 */
2813	outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
2814}
2815
2816static void
2817siocnclose(sp, iobase)
2818	struct siocnstate	*sp;
2819	Port_t			iobase;
2820{
2821	/*
2822	 * Restore the device control registers.
2823	 */
2824	siocntxwait(iobase);
2825	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2826	if (sp->dlbl != inb(iobase + com_dlbl))
2827		outb(iobase + com_dlbl, sp->dlbl);
2828	if (sp->dlbh != inb(iobase + com_dlbh))
2829		outb(iobase + com_dlbh, sp->dlbh);
2830	outb(iobase + com_cfcr, sp->cfcr);
2831	/*
2832	 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
2833	 */
2834	outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
2835	outb(iobase + com_ier, sp->ier);
2836}
2837
2838static void
2839siocnprobe(cp)
2840	struct consdev	*cp;
2841{
2842	speed_t			boot_speed;
2843	u_char			cfcr;
2844	int			s, unit;
2845	struct siocnstate	sp;
2846
2847	/*
2848	 * Find our first enabled console, if any.  If it is a high-level
2849	 * console device, then initialize it and return successfully.
2850	 * If it is a low-level console device, then initialize it and
2851	 * return unsuccessfully.  It must be initialized in both cases
2852	 * for early use by console drivers and debuggers.  Initializing
2853	 * the hardware is not necessary in all cases, since the i/o
2854	 * routines initialize it on the fly, but it is necessary if
2855	 * input might arrive while the hardware is switched back to an
2856	 * uninitialized state.  We can't handle multiple console devices
2857	 * yet because our low-level routines don't take a device arg.
2858	 * We trust the user to set the console flags properly so that we
2859	 * don't need to probe.
2860	 */
2861	cp->cn_pri = CN_DEAD;
2862
2863	for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
2864		int flags;
2865		int disabled;
2866		if (resource_int_value("sio", unit, "disabled", &disabled) == 0) {
2867			if (disabled)
2868				continue;
2869		}
2870		if (resource_int_value("sio", unit, "flags", &flags))
2871			continue;
2872		if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) {
2873			int port;
2874			Port_t iobase;
2875
2876			if (resource_int_value("sio", unit, "port", &port))
2877				continue;
2878			iobase = port;
2879			s = spltty();
2880			if (boothowto & RB_SERIAL) {
2881				boot_speed = siocngetspeed(iobase, comspeedtab);
2882				if (boot_speed)
2883					comdefaultrate = boot_speed;
2884			}
2885
2886			/*
2887			 * Initialize the divisor latch.  We can't rely on
2888			 * siocnopen() to do this the first time, since it
2889			 * avoids writing to the latch if the latch appears
2890			 * to have the correct value.  Also, if we didn't
2891			 * just read the speed from the hardware, then we
2892			 * need to set the speed in hardware so that
2893			 * switching it later is null.
2894			 */
2895			cfcr = inb(iobase + com_cfcr);
2896			outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
2897			outb(iobase + com_dlbl,
2898			     COMBRD(comdefaultrate) & 0xff);
2899			outb(iobase + com_dlbh,
2900			     (u_int) COMBRD(comdefaultrate) >> 8);
2901			outb(iobase + com_cfcr, cfcr);
2902
2903			siocnopen(&sp, iobase, comdefaultrate);
2904
2905			splx(s);
2906			if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) {
2907				cp->cn_dev = makedev(CDEV_MAJOR, unit);
2908				cp->cn_pri = COM_FORCECONSOLE(flags)
2909					     || boothowto & RB_SERIAL
2910					     ? CN_REMOTE : CN_NORMAL;
2911				siocniobase = iobase;
2912				siocnunit = unit;
2913			}
2914			if (COM_DEBUGGER(flags)) {
2915				printf("sio%d: gdb debugging port\n", unit);
2916				siogdbiobase = iobase;
2917				siogdbunit = unit;
2918#if DDB > 0
2919				gdbdev = makedev(CDEV_MAJOR, unit);
2920				gdb_getc = siocngetc;
2921				gdb_putc = siocnputc;
2922#endif
2923			}
2924		}
2925	}
2926#ifdef	__i386__
2927#if DDB > 0
2928	/*
2929	 * XXX Ugly Compatability.
2930	 * If no gdb port has been specified, set it to be the console
2931	 * as some configuration files don't specify the gdb port.
2932	 */
2933	if (gdbdev == NODEV && (boothowto & RB_GDB)) {
2934		printf("Warning: no GDB port specified. Defaulting to sio%d.\n",
2935			siocnunit);
2936		printf("Set flag 0x80 on desired GDB port in your\n");
2937		printf("configuration file (currently sio only).\n");
2938		siogdbiobase = siocniobase;
2939		siogdbunit = siocnunit;
2940		gdbdev = makedev(CDEV_MAJOR, siocnunit);
2941		gdb_getc = siocngetc;
2942		gdb_putc = siocnputc;
2943	}
2944#endif
2945#endif
2946}
2947
2948#ifdef __alpha__
2949
2950CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc, NULL);
2951
2952int
2953siocnattach(port, speed)
2954	int port;
2955	int speed;
2956{
2957	int			s;
2958	u_char			cfcr;
2959	struct siocnstate	sp;
2960
2961	siocniobase = port;
2962	comdefaultrate = speed;
2963	sio_consdev.cn_pri = CN_NORMAL;
2964	sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0);
2965
2966	s = spltty();
2967
2968	/*
2969	 * Initialize the divisor latch.  We can't rely on
2970	 * siocnopen() to do this the first time, since it
2971	 * avoids writing to the latch if the latch appears
2972	 * to have the correct value.  Also, if we didn't
2973	 * just read the speed from the hardware, then we
2974	 * need to set the speed in hardware so that
2975	 * switching it later is null.
2976	 */
2977	cfcr = inb(siocniobase + com_cfcr);
2978	outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr);
2979	outb(siocniobase + com_dlbl,
2980	     COMBRD(comdefaultrate) & 0xff);
2981	outb(siocniobase + com_dlbh,
2982	     (u_int) COMBRD(comdefaultrate) >> 8);
2983	outb(siocniobase + com_cfcr, cfcr);
2984
2985	siocnopen(&sp, siocniobase, comdefaultrate);
2986	splx(s);
2987
2988	cn_tab = &sio_consdev;
2989	return 0;
2990}
2991
2992int
2993siogdbattach(port, speed)
2994	int port;
2995	int speed;
2996{
2997	int			s;
2998	u_char			cfcr;
2999	struct siocnstate	sp;
3000
3001	siogdbiobase = port;
3002	gdbdefaultrate = speed;
3003
3004	s = spltty();
3005
3006	/*
3007	 * Initialize the divisor latch.  We can't rely on
3008	 * siocnopen() to do this the first time, since it
3009	 * avoids writing to the latch if the latch appears
3010	 * to have the correct value.  Also, if we didn't
3011	 * just read the speed from the hardware, then we
3012	 * need to set the speed in hardware so that
3013	 * switching it later is null.
3014	 */
3015	cfcr = inb(siogdbiobase + com_cfcr);
3016	outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr);
3017	outb(siogdbiobase + com_dlbl,
3018	     COMBRD(gdbdefaultrate) & 0xff);
3019	outb(siogdbiobase + com_dlbh,
3020	     (u_int) COMBRD(gdbdefaultrate) >> 8);
3021	outb(siogdbiobase + com_cfcr, cfcr);
3022
3023	siocnopen(&sp, siogdbiobase, gdbdefaultrate);
3024	splx(s);
3025
3026	return 0;
3027}
3028
3029#endif
3030
3031static void
3032siocninit(cp)
3033	struct consdev	*cp;
3034{
3035	comconsole = DEV_TO_UNIT(cp->cn_dev);
3036}
3037
3038static int
3039siocncheckc(dev)
3040	dev_t	dev;
3041{
3042	int	c;
3043	Port_t	iobase;
3044	int	s;
3045	struct siocnstate	sp;
3046
3047	if (minor(dev) == siogdbunit)
3048		iobase = siogdbiobase;
3049	else
3050		iobase = siocniobase;
3051	s = spltty();
3052	siocnopen(&sp, iobase, comdefaultrate);
3053	if (inb(iobase + com_lsr) & LSR_RXRDY)
3054		c = inb(iobase + com_data);
3055	else
3056		c = -1;
3057	siocnclose(&sp, iobase);
3058	splx(s);
3059	return (c);
3060}
3061
3062
3063int
3064siocngetc(dev)
3065	dev_t	dev;
3066{
3067	int	c;
3068	Port_t	iobase;
3069	int	s;
3070	struct siocnstate	sp;
3071
3072	if (minor(dev) == siogdbunit)
3073		iobase = siogdbiobase;
3074	else
3075		iobase = siocniobase;
3076	s = spltty();
3077	siocnopen(&sp, iobase, comdefaultrate);
3078	while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3079		;
3080	c = inb(iobase + com_data);
3081	siocnclose(&sp, iobase);
3082	splx(s);
3083	return (c);
3084}
3085
3086void
3087siocnputc(dev, c)
3088	dev_t	dev;
3089	int	c;
3090{
3091	int	s;
3092	struct siocnstate	sp;
3093	Port_t	iobase;
3094
3095	if (minor(dev) == siogdbunit)
3096		iobase = siogdbiobase;
3097	else
3098		iobase = siocniobase;
3099	s = spltty();
3100	siocnopen(&sp, iobase, comdefaultrate);
3101	siocntxwait(iobase);
3102	outb(iobase + com_data, c);
3103	siocnclose(&sp, iobase);
3104	splx(s);
3105}
3106
3107#ifdef __alpha__
3108int
3109siogdbgetc()
3110{
3111	int	c;
3112	Port_t	iobase;
3113	int	s;
3114	struct siocnstate	sp;
3115
3116	iobase = siogdbiobase;
3117	s = spltty();
3118	siocnopen(&sp, iobase, gdbdefaultrate);
3119	while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3120		;
3121	c = inb(iobase + com_data);
3122	siocnclose(&sp, iobase);
3123	splx(s);
3124	return (c);
3125}
3126
3127void
3128siogdbputc(c)
3129	int	c;
3130{
3131	int	s;
3132	struct siocnstate	sp;
3133
3134	s = spltty();
3135	siocnopen(&sp, siogdbiobase, gdbdefaultrate);
3136	siocntxwait(siogdbiobase);
3137	outb(siogdbiobase + com_data, c);
3138	siocnclose(&sp, siogdbiobase);
3139	splx(s);
3140}
3141#endif
3142
3143DRIVER_MODULE(sio, isa, sio_isa_driver, sio_devclass, 0, 0);
3144#if NCARD > 0
3145DRIVER_MODULE(sio, pccard, sio_pccard_driver, sio_devclass, 0, 0);
3146#endif
3147