cy_isa.c revision 72242
1/*-
2 * cyclades cyclom-y serial driver
3 *	Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
4 *
5 * Copyright (c) 1993 Andrew Herbert.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. The name Andrew Herbert may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
22 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD: head/sys/dev/cy/cy_isa.c 72242 2001-02-09 17:55:32Z jhb $
31 */
32
33#include "opt_compat.h"
34#include "cy.h"
35
36/*
37 * TODO:
38 * Atomic COR change.
39 * Consoles.
40 */
41
42/*
43 * Temporary compile-time configuration options.
44 */
45#define	RxFifoThreshold	(CD1400_RX_FIFO_SIZE / 2)
46			/* Number of chars in the receiver FIFO before an
47			 * an interrupt is generated.  Should depend on
48			 * line speed.  Needs to be about 6 on a 486DX33
49			 * for 4 active ports at 115200 bps.  Why doesn't
50			 * 10 work?
51			 */
52#define	PollMode	/* Use polling-based irq service routine, not the
53			 * hardware svcack lines.  Must be defined for
54			 * Cyclom-16Y boards.  Less efficient for Cyclom-8Ys,
55			 * and stops 4 * 115200 bps from working.
56			 */
57#undef	Smarts		/* Enable slightly more CD1400 intelligence.  Mainly
58			 * the output CR/LF processing, plus we can avoid a
59			 * few checks usually done in ttyinput().
60			 *
61			 * XXX not fully implemented, and not particularly
62			 * worthwhile.
63			 */
64#undef	CyDebug		/* Include debugging code (not very expensive). */
65
66/* These will go away. */
67#undef	SOFT_CTS_OFLOW
68#define	SOFT_HOTCHAR
69
70#include <sys/param.h>
71#include <sys/systm.h>
72#include <sys/tty.h>
73#include <sys/conf.h>
74#include <sys/dkstat.h>
75#include <sys/fcntl.h>
76#include <sys/bus.h>
77#include <sys/interrupt.h>
78#include <sys/ipl.h>
79#include <sys/kernel.h>
80#include <sys/malloc.h>
81#include <sys/mutex.h>
82#include <sys/syslog.h>
83#include <machine/lock.h>
84#include <machine/psl.h>
85
86#include <i386/isa/isa_device.h>
87#include <i386/isa/cyreg.h>
88#include <i386/isa/ic/cd1400.h>
89
90#ifndef COMPAT_OLDISA
91#error "The cy device requires the old isa compatibility shims"
92#endif
93
94/*
95 * Dictionary so that I can name everything *sio* or *com* to compare with
96 * sio.c.  There is also lots of ugly formatting and unnecessary ifdefs to
97 * simplify the comparision.  These will go away.
98 */
99#define	LSR_BI		CD1400_RDSR_BREAK
100#define	LSR_FE		CD1400_RDSR_FE
101#define	LSR_OE		CD1400_RDSR_OE
102#define	LSR_PE		CD1400_RDSR_PE
103#define	MCR_DTR		CD1400_MSVR2_DTR
104#define	MCR_RTS		CD1400_MSVR1_RTS
105#define	MSR_CTS		CD1400_MSVR2_CTS
106#define	MSR_DCD		CD1400_MSVR2_CD
107#define	MSR_DSR		CD1400_MSVR2_DSR
108#define	MSR_RI		CD1400_MSVR2_RI
109#define	NSIO		(NCY * CY_MAX_PORTS)
110#define	comconsole	cyconsole
111#define	comdefaultrate	cydefaultrate
112#define	com_events	cy_events
113#define	comhardclose	cyhardclose
114#define	commctl		cymctl
115#define	comparam	cyparam
116#define	comspeed	cyspeed
117#define	comstart	cystart
118#define	comwakeup	cywakeup
119#define	nsio_tty	ncy_tty
120#define	p_com_addr	p_cy_addr
121#define	sioattach	cyattach
122#define	sioclose	cyclose
123#define	siodriver	cydriver
124#define	siodtrwakeup	cydtrwakeup
125#define	sioinput	cyinput
126#define	siointr		cyintr
127#define	siointr1	cyintr1
128#define	sioioctl	cyioctl
129#define	sioopen		cyopen
130#define	siopoll		cypoll
131#define	sioprobe	cyprobe
132#define	siosettimeout	cysettimeout
133#define	siosetwater	cysetwater
134#define	comstop		cystop
135#define	siowrite	cywrite
136#define	sio_ih		cy_ih
137#define	sio_irec	cy_irec
138#define	sio_lock	cy_lock
139#define	sio_inited	cy_inited
140#define	sio_timeout	cy_timeout
141#define	sio_timeout_handle cy_timeout_handle
142#define	sio_timeouts_until_log	cy_timeouts_until_log
143#define	sio_tty		cy_tty
144
145#define	CY_MAX_PORTS		(CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s)
146
147/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
148#define	CD1400_xIVR_CHAN_SHIFT	3
149#define	CD1400_xIVR_CHAN	0x1F
150
151/*
152 * ETC states.  com->etc may also contain a hardware ETC command value,
153 * meaning that execution of that command is pending.
154 */
155#define	ETC_NONE		0	/* we depend on bzero() setting this */
156#define	ETC_BREAK_STARTING	1
157#define	ETC_BREAK_STARTED	2
158#define	ETC_BREAK_ENDING	3
159#define	ETC_BREAK_ENDED		4
160
161#define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
162
163#define	CALLOUT_MASK		0x80
164#define	CONTROL_MASK		0x60
165#define	CONTROL_INIT_STATE	0x20
166#define	CONTROL_LOCK_STATE	0x40
167#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
168#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
169#define	MINOR_TO_UNIT(mynor)	(((mynor) >> 16) * CY_MAX_PORTS \
170				 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK))
171
172/*
173 * com state bits.
174 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
175 * than the other bits so that they can be tested as a group without masking
176 * off the low bits.
177 *
178 * The following com and tty flags correspond closely:
179 *	CS_BUSY		= TS_BUSY (maintained by comstart(), siopoll() and
180 *				   comstop())
181 *	CS_TTGO		= ~TS_TTSTOP (maintained by comparam() and comstart())
182 *	CS_CTS_OFLOW	= CCTS_OFLOW (maintained by comparam())
183 *	CS_RTS_IFLOW	= CRTS_IFLOW (maintained by comparam())
184 * TS_FLUSH is not used.
185 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
186 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
187 */
188#define	CS_BUSY		0x80	/* output in progress */
189#define	CS_TTGO		0x40	/* output not stopped by XOFF */
190#define	CS_ODEVREADY	0x20	/* external device h/w ready (CTS) */
191#define	CS_CHECKMSR	1	/* check of MSR scheduled */
192#define	CS_CTS_OFLOW	2	/* use CTS output flow control */
193#define	CS_DTR_OFF	0x10	/* DTR held off */
194#define	CS_ODONE	4	/* output completed */
195#define	CS_RTS_IFLOW	8	/* use RTS input flow control */
196#define	CSE_ODONE	1	/* output transmitted */
197
198static	char const * const	error_desc[] = {
199#define	CE_OVERRUN			0
200	"silo overflow",
201#define	CE_INTERRUPT_BUF_OVERFLOW	1
202	"interrupt-level buffer overflow",
203#define	CE_TTY_BUF_OVERFLOW		2
204	"tty-level buffer overflow",
205};
206
207#define	CE_NTYPES			3
208#define	CE_RECORD(com, errnum)		(++(com)->delta_error_counts[errnum])
209
210/* types.  XXX - should be elsewhere */
211typedef u_char	bool_t;		/* boolean */
212typedef u_char volatile *cy_addr;
213
214/* queue of linear buffers */
215struct lbq {
216	u_char	*l_head;	/* next char to process */
217	u_char	*l_tail;	/* one past the last char to process */
218	struct lbq *l_next;	/* next in queue */
219	bool_t	l_queued;	/* nonzero if queued */
220};
221
222/* com device structure */
223struct com_s {
224	u_char	state;		/* miscellaneous flag bits */
225	bool_t  active_out;	/* nonzero if the callout device is open */
226#if 0
227	u_char	cfcr_image;	/* copy of value written to CFCR */
228#endif
229	u_char	etc;		/* pending Embedded Transmit Command */
230	u_char	extra_state;	/* more flag bits, separate for order trick */
231#if 0
232	u_char	fifo_image;	/* copy of value written to FIFO */
233#endif
234	u_char	gfrcr_image;	/* copy of value read from GFRCR */
235#if 0
236	bool_t	hasfifo;	/* nonzero for 16550 UARTs */
237	bool_t	loses_outints;	/* nonzero if device loses output interrupts */
238#endif
239	u_char	mcr_dtr;	/* MCR bit that is wired to DTR */
240	u_char	mcr_image;	/* copy of value written to MCR */
241	u_char	mcr_rts;	/* MCR bit that is wired to RTS */
242#if 0
243#ifdef COM_MULTIPORT
244	bool_t	multiport;	/* is this unit part of a multiport device? */
245#endif /* COM_MULTIPORT */
246	bool_t	no_irq;		/* nonzero if irq is not attached */
247	bool_t	poll;		/* nonzero if polling is required */
248	bool_t	poll_output;	/* nonzero if polling for output is required */
249#endif
250	int	unit;		/* unit	number */
251	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
252#if 0
253	u_int	tx_fifo_size;
254#endif
255	u_int	wopeners;	/* # processes waiting for DCD in open() */
256
257	/*
258	 * The high level of the driver never reads status registers directly
259	 * because there would be too many side effects to handle conveniently.
260	 * Instead, it reads copies of the registers stored here by the
261	 * interrupt handler.
262	 */
263	u_char	last_modem_status;	/* last MSR read by intr handler */
264	u_char	prev_modem_status;	/* last MSR handled by high level */
265
266	u_char	hotchar;	/* ldisc-specific char to be handled ASAP */
267	u_char	*ibuf;		/* start of input buffer */
268	u_char	*ibufend;	/* end of input buffer */
269	u_char	*ibufold;	/* old input buffer, to be freed */
270	u_char	*ihighwater;	/* threshold in input buffer */
271	u_char	*iptr;		/* next free spot in input buffer */
272	int	ibufsize;	/* size of ibuf (not include error bytes) */
273	int	ierroff;	/* offset of error bytes in ibuf */
274
275	struct lbq	obufq;	/* head of queue of output buffers */
276	struct lbq	obufs[2];	/* output buffers */
277
278	int	cy_align;	/* index for register alignment */
279	cy_addr	cy_iobase;	/* base address of this port's cyclom */
280	cy_addr	iobase;		/* base address of this port's cd1400 */
281	int	mcr_rts_reg;	/* cd1400 reg number of reg holding mcr_rts */
282
283	struct tty	*tp;	/* cross reference */
284
285	/* Initial state. */
286	struct termios	it_in;	/* should be in struct tty */
287	struct termios	it_out;
288
289	/* Lock state. */
290	struct termios	lt_in;	/* should be in struct tty */
291	struct termios	lt_out;
292
293	bool_t	do_timestamp;
294	bool_t	do_dcd_timestamp;
295	struct timeval	timestamp;
296	struct timeval	dcd_timestamp;
297
298	u_long	bytes_in;	/* statistics */
299	u_long	bytes_out;
300	u_int	delta_error_counts[CE_NTYPES];
301	u_long	error_counts[CE_NTYPES];
302
303	u_int	recv_exception;	/* exception chars received */
304	u_int	mdm;		/* modem signal changes */
305#ifdef CyDebug
306	u_int	start_count;	/* no. of calls to comstart() */
307	u_int	start_real;	/* no. of calls that did something */
308#endif
309	u_char	car;		/* CD1400 CAR shadow (if first unit in cd) */
310	u_char	channel_control;/* CD1400 CCR control command shadow */
311	u_char	cor[3];		/* CD1400 COR1-3 shadows */
312	u_char	intr_enable;	/* CD1400 SRER shadow */
313
314	/*
315	 * Data area for output buffers.  Someday we should build the output
316	 * buffer queue without copying data.
317	 */
318	u_char	obuf1[256];
319	u_char	obuf2[256];
320};
321
322/* PCI driver entry point. */
323int	cyattach_common		__P((cy_addr cy_iobase, int cy_align));
324ointhand2_t	siointr;
325
326static	int	cy_units	__P((cy_addr cy_iobase, int cy_align));
327static	int	sioattach	__P((struct isa_device *dev));
328static	void	cd1400_channel_cmd __P((struct com_s *com, int cmd));
329static	void	cd1400_channel_cmd_wait __P((struct com_s *com));
330static	void	cd_etc		__P((struct com_s *com, int etc));
331static	int	cd_getreg	__P((struct com_s *com, int reg));
332static	void	cd_setreg	__P((struct com_s *com, int reg, int val));
333static	timeout_t siodtrwakeup;
334static	void	comhardclose	__P((struct com_s *com));
335static	void	sioinput	__P((struct com_s *com));
336#if 0
337static	void	siointr1	__P((struct com_s *com));
338#endif
339static	int	commctl		__P((struct com_s *com, int bits, int how));
340static	int	comparam	__P((struct tty *tp, struct termios *t));
341static	void	siopoll		__P((void *arg));
342static	int	sioprobe	__P((struct isa_device *dev));
343static	void	siosettimeout	__P((void));
344static	int	siosetwater	__P((struct com_s *com, speed_t speed));
345static	int	comspeed	__P((speed_t speed, u_long cy_clock,
346				     int *prescaler_io));
347static	void	comstart	__P((struct tty *tp));
348static	void	comstop		__P((struct tty *tp, int rw));
349static	timeout_t comwakeup;
350static	void	disc_optim	__P((struct tty	*tp, struct termios *t,
351				     struct com_s *com));
352
353#ifdef CyDebug
354void	cystatus	__P((int unit));
355#endif
356
357static char	driver_name[] = "cy";
358static struct	mtx sio_lock;
359static int	sio_inited;
360
361/* table and macro for fast conversion from a unit number to its com struct */
362static	struct com_s	*p_com_addr[NSIO];
363#define	com_addr(unit)	(p_com_addr[unit])
364
365struct isa_driver	siodriver = {
366	INTR_TYPE_TTY | INTR_FAST,
367	sioprobe,
368	sioattach,
369	driver_name
370};
371COMPAT_ISA_DRIVER(cy, cydriver);	/* XXX */
372
373static	d_open_t	sioopen;
374static	d_close_t	sioclose;
375static	d_write_t	siowrite;
376static	d_ioctl_t	sioioctl;
377
378#define	CDEV_MAJOR	48
379static struct cdevsw sio_cdevsw = {
380	/* open */	sioopen,
381	/* close */	sioclose,
382	/* read */	ttyread,
383	/* write */	siowrite,
384	/* ioctl */	sioioctl,
385	/* poll */	ttypoll,
386	/* mmap */	nommap,
387	/* strategy */	nostrategy,
388	/* name */	driver_name,
389	/* maj */	CDEV_MAJOR,
390	/* dump */	nodump,
391	/* psize */	nopsize,
392	/* flags */	D_TTY,
393	/* bmaj */	-1
394};
395
396static	int	comconsole = -1;
397static	speed_t	comdefaultrate = TTYDEF_SPEED;
398static	u_int	com_events;	/* input chars + weighted output completions */
399static	void	*sio_ih;
400static	int	sio_timeout;
401static	int	sio_timeouts_until_log;
402static	struct	callout_handle sio_timeout_handle
403    = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
404#if 0 /* XXX */
405static struct tty	*sio_tty[NSIO];
406#else
407static struct tty	sio_tty[NSIO];
408#endif
409static	const int	nsio_tty = NSIO;
410
411#ifdef CyDebug
412static	u_int	cd_inbs;
413static	u_int	cy_inbs;
414static	u_int	cd_outbs;
415static	u_int	cy_outbs;
416static	u_int	cy_svrr_probes;
417static	u_int	cy_timeouts;
418#endif
419
420static	int	cy_chip_offset[] = {
421	0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00,
422};
423static	int	cy_nr_cd1400s[NCY];
424static	int	cy_total_devices;
425#undef	RxFifoThreshold
426static	int	volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
427
428static int
429sioprobe(dev)
430	struct isa_device	*dev;
431{
432	cy_addr	iobase;
433
434	iobase = (cy_addr)dev->id_maddr;
435
436	if (atomic_cmpset_int(&sio_inited, 0, 1))
437		mtx_init(&sio_lock, driver_name, MTX_SPIN);
438
439	/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
440	cy_inb(iobase, CY16_RESET, 0);	/* XXX? */
441	DELAY(500);	/* wait for the board to get its act together */
442
443	/* this is needed to get the board out of reset */
444	cy_outb(iobase, CY_CLEAR_INTR, 0, 0);
445	DELAY(500);
446
447	return (cy_units(iobase, 0) == 0 ? 0 : -1);
448}
449
450static int
451cy_units(cy_iobase, cy_align)
452	cy_addr	cy_iobase;
453	int	cy_align;
454{
455	int	cyu;
456	u_char	firmware_version;
457	int	i;
458	cy_addr	iobase;
459
460	for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) {
461		iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align);
462
463		/* wait for chip to become ready for new command */
464		for (i = 0; i < 10; i++) {
465			DELAY(50);
466			if (!cd_inb(iobase, CD1400_CCR, cy_align))
467				break;
468		}
469
470		/* clear the GFRCR register */
471		cd_outb(iobase, CD1400_GFRCR, cy_align, 0);
472
473		/* issue a reset command */
474		cd_outb(iobase, CD1400_CCR, cy_align,
475			CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
476
477		/* wait for the CD1400 to initialize itself */
478		for (i = 0; i < 200; i++) {
479			DELAY(50);
480
481			/* retrieve firmware version */
482			firmware_version = cd_inb(iobase, CD1400_GFRCR,
483						  cy_align);
484			if ((firmware_version & 0xf0) == 0x40)
485				break;
486		}
487
488		/*
489		 * Anything in the 0x40-0x4F range is fine.
490		 * If one CD1400 is bad then we don't support higher
491		 * numbered good ones on this board.
492		 */
493		if ((firmware_version & 0xf0) != 0x40)
494			break;
495	}
496	return (cyu);
497}
498
499static int
500sioattach(isdp)
501	struct isa_device	*isdp;
502{
503	int	adapter;
504
505	adapter = cyattach_common((cy_addr) isdp->id_maddr, 0);
506	if (adapter < 0)
507		return (0);
508
509	/*
510	 * XXX
511	 * This kludge is to allow ISA/PCI device specifications in the
512	 * kernel config file to be in any order.
513	 */
514	if (isdp->id_unit != adapter) {
515		printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter);
516		isdp->id_unit = adapter;	/* XXX */
517	}
518	isdp->id_ointr = siointr;
519	/* isdp->id_ri_flags |= RI_FAST; XXX unimplemented - use newbus! */
520	return (1);
521}
522
523int
524cyattach_common(cy_iobase, cy_align)
525	cy_addr	cy_iobase;
526	int	cy_align;
527{
528	int	adapter;
529	int	cyu;
530	u_char	firmware_version;
531	cy_addr	iobase;
532	int	ncyu;
533	int	unit;
534
535	adapter = cy_total_devices;
536	if ((u_int)adapter >= NCY) {
537		printf(
538	"cy%d: can't attach adapter: insufficient cy devices configured\n",
539		       adapter);
540		return (-1);
541	}
542	ncyu = cy_units(cy_iobase, cy_align);
543	if (ncyu == 0)
544		return (-1);
545	cy_nr_cd1400s[adapter] = ncyu;
546	cy_total_devices++;
547
548	unit = adapter * CY_MAX_PORTS;
549	for (cyu = 0; cyu < ncyu; ++cyu) {
550		int	cdu;
551
552		iobase = (cy_addr) (cy_iobase
553				    + (cy_chip_offset[cyu] << cy_align));
554		firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align);
555
556		/* Set up a receive timeout period of than 1+ ms. */
557		cd_outb(iobase, CD1400_PPR, cy_align,
558			howmany(CY_CLOCK(firmware_version)
559				/ CD1400_PPR_PRESCALER, 1000));
560
561		for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
562			struct com_s	*com;
563			int		s;
564
565	com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO);
566	if (com == NULL)
567		break;
568	com->unit = unit;
569			com->gfrcr_image = firmware_version;
570			if (CY_RTS_DTR_SWAPPED(firmware_version)) {
571				com->mcr_dtr = MCR_RTS;
572				com->mcr_rts = MCR_DTR;
573				com->mcr_rts_reg = CD1400_MSVR2;
574			} else {
575				com->mcr_dtr = MCR_DTR;
576				com->mcr_rts = MCR_RTS;
577				com->mcr_rts_reg = CD1400_MSVR1;
578			}
579	com->dtr_wait = 3 * hz;
580	com->obufs[0].l_head = com->obuf1;
581	com->obufs[1].l_head = com->obuf2;
582
583			com->cy_align = cy_align;
584			com->cy_iobase = cy_iobase;
585	com->iobase = iobase;
586			com->car = ~CD1400_CAR_CHAN;
587
588	/*
589	 * We don't use all the flags from <sys/ttydefaults.h> since they
590	 * are only relevant for logins.  It's important to have echo off
591	 * initially so that the line doesn't start blathering before the
592	 * echo flag can be turned off.
593	 */
594	com->it_in.c_iflag = 0;
595	com->it_in.c_oflag = 0;
596	com->it_in.c_cflag = TTYDEF_CFLAG;
597	com->it_in.c_lflag = 0;
598	if (unit == comconsole) {
599		com->it_in.c_iflag = TTYDEF_IFLAG;
600		com->it_in.c_oflag = TTYDEF_OFLAG;
601		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
602		com->it_in.c_lflag = TTYDEF_LFLAG;
603		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
604	}
605	if (siosetwater(com, com->it_in.c_ispeed) != 0) {
606		mtx_unlock_spin(&sio_lock);
607		free(com, M_DEVBUF);
608		return (0);
609	}
610	mtx_unlock_spin(&sio_lock);
611	termioschars(&com->it_in);
612	com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
613	com->it_out = com->it_in;
614
615	s = spltty();
616	com_addr(unit) = com;
617	splx(s);
618
619	if (sio_ih == NULL) {
620		cdevsw_add(&sio_cdevsw);
621		swi_add(&tty_ithd, "tty:cy", siopoll, NULL, SWI_TTY, 0,
622		    &sio_ih);
623	}
624	make_dev(&sio_cdevsw, unit,
625		UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter,
626		unit % CY_MAX_PORTS);
627	make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE,
628		UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter,
629		unit % CY_MAX_PORTS);
630	make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE,
631		UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter,
632		unit % CY_MAX_PORTS);
633	make_dev(&sio_cdevsw, unit | CALLOUT_MASK,
634		UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter,
635		unit % CY_MAX_PORTS);
636	make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE,
637		UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter,
638		unit % CY_MAX_PORTS);
639	make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE,
640		UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter,
641		unit % CY_MAX_PORTS);
642		}
643	}
644
645	/* ensure an edge for the next interrupt */
646	cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
647
648	return (adapter);
649}
650
651static int
652sioopen(dev, flag, mode, p)
653	dev_t		dev;
654	int		flag;
655	int		mode;
656	struct proc	*p;
657{
658	struct com_s	*com;
659	int		error;
660	int		mynor;
661	int		s;
662	struct tty	*tp;
663	int		unit;
664
665	mynor = minor(dev);
666	unit = MINOR_TO_UNIT(mynor);
667	if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
668		return (ENXIO);
669	if (mynor & CONTROL_MASK)
670		return (0);
671#if 0 /* XXX */
672	tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]);
673#else
674	tp = com->tp = &sio_tty[unit];
675#endif
676	dev->si_tty = tp;
677	s = spltty();
678	/*
679	 * We jump to this label after all non-interrupted sleeps to pick
680	 * up any changes of the device state.
681	 */
682open_top:
683	while (com->state & CS_DTR_OFF) {
684		error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0);
685		if (error != 0)
686			goto out;
687	}
688	if (tp->t_state & TS_ISOPEN) {
689		/*
690		 * The device is open, so everything has been initialized.
691		 * Handle conflicts.
692		 */
693		if (mynor & CALLOUT_MASK) {
694			if (!com->active_out) {
695				error = EBUSY;
696				goto out;
697			}
698		} else {
699			if (com->active_out) {
700				if (flag & O_NONBLOCK) {
701					error = EBUSY;
702					goto out;
703				}
704				error =	tsleep(&com->active_out,
705					       TTIPRI | PCATCH, "cybi", 0);
706				if (error != 0)
707					goto out;
708				goto open_top;
709			}
710		}
711		if (tp->t_state & TS_XCLUDE &&
712		    suser(p)) {
713			error = EBUSY;
714			goto out;
715		}
716	} else {
717		/*
718		 * The device isn't open, so there are no conflicts.
719		 * Initialize it.  Initialization is done twice in many
720		 * cases: to preempt sleeping callin opens if we are
721		 * callout, and to complete a callin open after DCD rises.
722		 */
723		tp->t_oproc = comstart;
724		tp->t_stop = comstop;
725		tp->t_param = comparam;
726		tp->t_dev = dev;
727		tp->t_termios = mynor & CALLOUT_MASK
728				? com->it_out : com->it_in;
729
730		/* Encode per-board unit in LIVR for access in intr routines. */
731		cd_setreg(com, CD1400_LIVR,
732			  (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
733
734		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
735#if 0
736		com->poll = com->no_irq;
737		com->poll_output = com->loses_outints;
738#endif
739		++com->wopeners;
740		error = comparam(tp, &tp->t_termios);
741		--com->wopeners;
742		if (error != 0)
743			goto out;
744#if 0
745		if (com->hasfifo) {
746			/*
747			 * (Re)enable and flush fifos.
748			 *
749			 * Certain SMC chips cause problems if the fifos
750			 * are enabled while input is ready.  Turn off the
751			 * fifo if necessary to clear the input.  We test
752			 * the input ready bit after enabling the fifos
753			 * since we've already enabled them in comparam()
754			 * and to handle races between enabling and fresh
755			 * input.
756			 */
757			while (TRUE) {
758				outb(iobase + com_fifo,
759				     FIFO_RCV_RST | FIFO_XMT_RST
760				     | com->fifo_image);
761				DELAY(100);
762				if (!(inb(com->line_status_port) & LSR_RXRDY))
763					break;
764				outb(iobase + com_fifo, 0);
765				DELAY(100);
766				(void) inb(com->data_port);
767			}
768		}
769
770		mtx_lock_spin(&sio_lock);
771		(void) inb(com->line_status_port);
772		(void) inb(com->data_port);
773		com->prev_modem_status = com->last_modem_status
774		    = inb(com->modem_status_port);
775		outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
776				       | IER_EMSC);
777		mtx_unlock_spin(&sio_lock);
778#else /* !0 */
779		/*
780		 * Flush fifos.  This requires a full channel reset which
781		 * also disables the transmitter and receiver.  Recover
782		 * from this.
783		 */
784		cd1400_channel_cmd(com,
785				   CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET);
786		cd1400_channel_cmd(com, com->channel_control);
787
788		mtx_lock_spin(&sio_lock);
789		com->prev_modem_status = com->last_modem_status
790		    = cd_getreg(com, CD1400_MSVR2);
791		cd_setreg(com, CD1400_SRER,
792			  com->intr_enable
793			  = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
794		mtx_unlock_spin(&sio_lock);
795#endif /* 0 */
796		/*
797		 * Handle initial DCD.  Callout devices get a fake initial
798		 * DCD (trapdoor DCD).  If we are callout, then any sleeping
799		 * callin opens get woken up and resume sleeping on "cybi"
800		 * instead of "cydcd".
801		 */
802		/*
803		 * XXX `mynor & CALLOUT_MASK' should be
804		 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
805		 * TRAPDOOR_CARRIER is the default initial state for callout
806		 * devices and SOFT_CARRIER is like CLOCAL except it hides
807		 * the true carrier.
808		 */
809		if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
810			(*linesw[tp->t_line].l_modem)(tp, 1);
811	}
812	/*
813	 * Wait for DCD if necessary.
814	 */
815	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
816	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
817		++com->wopeners;
818		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0);
819		--com->wopeners;
820		if (error != 0)
821			goto out;
822		goto open_top;
823	}
824	error =	(*linesw[tp->t_line].l_open)(dev, tp);
825	disc_optim(tp, &tp->t_termios, com);
826	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
827		com->active_out = TRUE;
828	siosettimeout();
829out:
830	splx(s);
831	if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
832		comhardclose(com);
833	return (error);
834}
835
836static int
837sioclose(dev, flag, mode, p)
838	dev_t		dev;
839	int		flag;
840	int		mode;
841	struct proc	*p;
842{
843	struct com_s	*com;
844	int		mynor;
845	int		s;
846	struct tty	*tp;
847
848	mynor = minor(dev);
849	if (mynor & CONTROL_MASK)
850		return (0);
851	com = com_addr(MINOR_TO_UNIT(mynor));
852	tp = com->tp;
853	s = spltty();
854	cd_etc(com, CD1400_ETC_STOPBREAK);
855	(*linesw[tp->t_line].l_close)(tp, flag);
856	disc_optim(tp, &tp->t_termios, com);
857	comstop(tp, FREAD | FWRITE);
858	comhardclose(com);
859	ttyclose(tp);
860	siosettimeout();
861	splx(s);
862#ifdef broken /* session holds a ref to the tty; can't deallocate */
863	ttyfree(tp);
864	com->tp = sio_tty[unit] = NULL;
865#endif
866	return (0);
867}
868
869static void
870comhardclose(com)
871	struct com_s	*com;
872{
873	cy_addr		iobase;
874	int		s;
875	struct tty	*tp;
876	int		unit;
877
878	unit = com->unit;
879	iobase = com->iobase;
880	s = spltty();
881#if 0
882	com->poll = FALSE;
883	com->poll_output = FALSE;
884#endif
885	com->do_timestamp = 0;
886#if 0
887	outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
888#else
889	/* XXX */
890	mtx_lock_spin(&sio_lock);
891	com->etc = ETC_NONE;
892	cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC);
893	mtx_unlock_spin(&sio_lock);
894	cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
895#endif
896
897	{
898#if 0
899		outb(iobase + com_ier, 0);
900#else
901		mtx_lock_spin(&sio_lock);
902		cd_setreg(com, CD1400_SRER, com->intr_enable = 0);
903		mtx_unlock_spin(&sio_lock);
904#endif
905		tp = com->tp;
906		if ((tp->t_cflag & HUPCL)
907		    /*
908		     * XXX we will miss any carrier drop between here and the
909		     * next open.  Perhaps we should watch DCD even when the
910		     * port is closed; it is not sufficient to check it at
911		     * the next open because it might go up and down while
912		     * we're not watching.
913		     */
914		    || (!com->active_out
915		       && !(com->prev_modem_status & MSR_DCD)
916		       && !(com->it_in.c_cflag & CLOCAL))
917		    || !(tp->t_state & TS_ISOPEN)) {
918			(void)commctl(com, TIOCM_DTR, DMBIC);
919
920			/* Disable receiver (leave transmitter enabled). */
921			com->channel_control = CD1400_CCR_CMDCHANCTL
922					       | CD1400_CCR_XMTEN
923					       | CD1400_CCR_RCVDIS;
924			cd1400_channel_cmd(com, com->channel_control);
925
926			if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
927				timeout(siodtrwakeup, com, com->dtr_wait);
928				com->state |= CS_DTR_OFF;
929			}
930		}
931	}
932#if 0
933	if (com->hasfifo) {
934		/*
935		 * Disable fifos so that they are off after controlled
936		 * reboots.  Some BIOSes fail to detect 16550s when the
937		 * fifos are enabled.
938		 */
939		outb(iobase + com_fifo, 0);
940	}
941#endif
942	com->active_out = FALSE;
943	wakeup(&com->active_out);
944	wakeup(TSA_CARR_ON(tp));	/* restart any wopeners */
945	splx(s);
946}
947
948static int
949siowrite(dev, uio, flag)
950	dev_t		dev;
951	struct uio	*uio;
952	int		flag;
953{
954	int		mynor;
955	struct tty	*tp;
956	int		unit;
957
958	mynor = minor(dev);
959	if (mynor & CONTROL_MASK)
960		return (ENODEV);
961
962	unit = MINOR_TO_UNIT(mynor);
963	tp = com_addr(unit)->tp;
964	/*
965	 * (XXX) We disallow virtual consoles if the physical console is
966	 * a serial port.  This is in case there is a display attached that
967	 * is not the console.  In that situation we don't need/want the X
968	 * server taking over the console.
969	 */
970	if (constty != NULL && unit == comconsole)
971		constty = NULL;
972#ifdef Smarts
973	/* XXX duplicate ttwrite(), but without so much output processing on
974	 * CR & LF chars.  Hardly worth the effort, given that high-throughput
975	 * sessions are raw anyhow.
976	 */
977#else
978	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
979#endif
980}
981
982static void
983siodtrwakeup(chan)
984	void	*chan;
985{
986	struct com_s	*com;
987
988	com = (struct com_s *)chan;
989	com->state &= ~CS_DTR_OFF;
990	wakeup(&com->dtr_wait);
991}
992
993/*
994 * Call this function with the sio_lock mutex held.  It will return with the
995 * lock still held.
996 */
997static void
998sioinput(com)
999	struct com_s	*com;
1000{
1001	u_char		*buf;
1002	int		incc;
1003	u_char		line_status;
1004	int		recv_data;
1005	struct tty	*tp;
1006
1007	buf = com->ibuf;
1008	tp = com->tp;
1009	if (!(tp->t_state & TS_ISOPEN)) {
1010		com_events -= (com->iptr - com->ibuf);
1011		com->iptr = com->ibuf;
1012		return;
1013	}
1014	if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1015		/*
1016		 * Avoid the grotesquely inefficient lineswitch routine
1017		 * (ttyinput) in "raw" mode.  It usually takes about 450
1018		 * instructions (that's without canonical processing or echo!).
1019		 * slinput is reasonably fast (usually 40 instructions plus
1020		 * call overhead).
1021		 */
1022
1023		do {
1024			/*
1025			 * This may look odd, but it is using save-and-enable
1026			 * semantics instead of the save-and-disable semantics
1027			 * that are used everywhere else.
1028			 */
1029			mtx_unlock_spin(&sio_lock);
1030			incc = com->iptr - buf;
1031			if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1032			    && (com->state & CS_RTS_IFLOW
1033				|| tp->t_iflag & IXOFF)
1034			    && !(tp->t_state & TS_TBLOCK))
1035				ttyblock(tp);
1036			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1037				+= b_to_q((char *)buf, incc, &tp->t_rawq);
1038			buf += incc;
1039			tk_nin += incc;
1040			tk_rawcc += incc;
1041			tp->t_rawcc += incc;
1042			ttwakeup(tp);
1043			if (tp->t_state & TS_TTSTOP
1044			    && (tp->t_iflag & IXANY
1045				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1046				tp->t_state &= ~TS_TTSTOP;
1047				tp->t_lflag &= ~FLUSHO;
1048				comstart(tp);
1049			}
1050			mtx_lock_spin(&sio_lock);
1051		} while (buf < com->iptr);
1052	} else {
1053		do {
1054			/*
1055			 * This may look odd, but it is using save-and-enable
1056			 * semantics instead of the save-and-disable semantics
1057			 * that are used everywhere else.
1058			 */
1059			mtx_unlock_spin(&sio_lock);
1060			line_status = buf[com->ierroff];
1061			recv_data = *buf++;
1062			if (line_status
1063			    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1064				if (line_status & LSR_BI)
1065					recv_data |= TTY_BI;
1066				if (line_status & LSR_FE)
1067					recv_data |= TTY_FE;
1068				if (line_status & LSR_OE)
1069					recv_data |= TTY_OE;
1070				if (line_status & LSR_PE)
1071					recv_data |= TTY_PE;
1072			}
1073			(*linesw[tp->t_line].l_rint)(recv_data, tp);
1074			mtx_lock_spin(&sio_lock);
1075		} while (buf < com->iptr);
1076	}
1077	com_events -= (com->iptr - com->ibuf);
1078	com->iptr = com->ibuf;
1079
1080	/*
1081	 * There is now room for another low-level buffer full of input,
1082	 * so enable RTS if it is now disabled and there is room in the
1083	 * high-level buffer.
1084	 */
1085	if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) &&
1086	    !(tp->t_state & TS_TBLOCK))
1087#if 0
1088		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
1089#else
1090		cd_setreg(com, com->mcr_rts_reg,
1091			  com->mcr_image |= com->mcr_rts);
1092#endif
1093}
1094
1095void
1096siointr(unit)
1097	int	unit;
1098{
1099	int	baseu;
1100	int	cy_align;
1101	cy_addr	cy_iobase;
1102	int	cyu;
1103	cy_addr	iobase;
1104	u_char	status;
1105
1106	mtx_lock_spin(&sio_lock);	/* XXX could this be placed down lower in the loop? */
1107
1108	baseu = unit * CY_MAX_PORTS;
1109	cy_align = com_addr(baseu)->cy_align;
1110	cy_iobase = com_addr(baseu)->cy_iobase;
1111
1112	/* check each CD1400 in turn */
1113	for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) {
1114		iobase = (cy_addr) (cy_iobase
1115				    + (cy_chip_offset[cyu] << cy_align));
1116		/* poll to see if it has any work */
1117		status = cd_inb(iobase, CD1400_SVRR, cy_align);
1118		if (status == 0)
1119			continue;
1120#ifdef CyDebug
1121		++cy_svrr_probes;
1122#endif
1123		/* service requests as appropriate, giving priority to RX */
1124		if (status & CD1400_SVRR_RXRDY) {
1125			struct com_s	*com;
1126			u_int		count;
1127			u_char		*ioptr;
1128			u_char		line_status;
1129			u_char		recv_data;
1130			u_char		serv_type;
1131#ifdef PollMode
1132			u_char		save_rir;
1133#endif
1134
1135#ifdef PollMode
1136			save_rir = cd_inb(iobase, CD1400_RIR, cy_align);
1137
1138			/* enter rx service */
1139			cd_outb(iobase, CD1400_CAR, cy_align, save_rir);
1140			com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
1141			= save_rir & CD1400_CAR_CHAN;
1142
1143			serv_type = cd_inb(iobase, CD1400_RIVR, cy_align);
1144			com = com_addr(baseu
1145				       + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
1146					  & CD1400_xIVR_CHAN));
1147#else
1148			/* ack receive service */
1149			serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align);
1150
1151			com = com_addr(baseu +
1152				       + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
1153					  & CD1400_xIVR_CHAN));
1154#endif
1155
1156		if (serv_type & CD1400_RIVR_EXCEPTION) {
1157			++com->recv_exception;
1158			line_status = cd_inb(iobase, CD1400_RDSR, cy_align);
1159			/* break/unnattached error bits or real input? */
1160			recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
1161#ifndef SOFT_HOTCHAR
1162			if (line_status & CD1400_RDSR_SPECIAL
1163			    && com->hotchar != 0)
1164				swi_sched(sio_ih, SWI_NOSWITCH);
1165
1166#endif
1167#if 1 /* XXX "intelligent" PFO error handling would break O error handling */
1168			if (line_status & (LSR_PE|LSR_FE|LSR_BI)) {
1169				/*
1170				  Don't store PE if IGNPAR and BI if IGNBRK,
1171				  this hack allows "raw" tty optimization
1172				  works even if IGN* is set.
1173				*/
1174				if (   com->tp == NULL
1175				    || !(com->tp->t_state & TS_ISOPEN)
1176				    || ((line_status & (LSR_PE|LSR_FE))
1177				    &&  (com->tp->t_iflag & IGNPAR))
1178				    || ((line_status & LSR_BI)
1179				    &&  (com->tp->t_iflag & IGNBRK)))
1180					goto cont;
1181				if (   (line_status & (LSR_PE|LSR_FE))
1182				    && (com->tp->t_state & TS_CAN_BYPASS_L_RINT)
1183				    && ((line_status & LSR_FE)
1184				    ||  ((line_status & LSR_PE)
1185				    &&  (com->tp->t_iflag & INPCK))))
1186					recv_data = 0;
1187			}
1188#endif /* 1 */
1189			++com->bytes_in;
1190#ifdef SOFT_HOTCHAR
1191			if (com->hotchar != 0 && recv_data == com->hotchar)
1192				swi_sched(sio_ih, SWI_NOSWITCH);
1193#endif
1194			ioptr = com->iptr;
1195			if (ioptr >= com->ibufend)
1196				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1197			else {
1198				if (com->do_timestamp)
1199					microtime(&com->timestamp);
1200				++com_events;
1201				ioptr[0] = recv_data;
1202				ioptr[com->ierroff] = line_status;
1203				com->iptr = ++ioptr;
1204				if (ioptr == com->ihighwater
1205				    && com->state & CS_RTS_IFLOW)
1206#if 0
1207					outb(com->modem_ctl_port,
1208					     com->mcr_image &= ~MCR_RTS);
1209#else
1210					cd_outb(iobase, com->mcr_rts_reg,
1211						cy_align,
1212						com->mcr_image &=
1213						~com->mcr_rts);
1214#endif
1215				if (line_status & LSR_OE)
1216					CE_RECORD(com, CE_OVERRUN);
1217			}
1218			goto cont;
1219		} else {
1220			int	ifree;
1221
1222			count = cd_inb(iobase, CD1400_RDCR, cy_align);
1223			if (!count)
1224				goto cont;
1225			com->bytes_in += count;
1226			ioptr = com->iptr;
1227			ifree = com->ibufend - ioptr;
1228			if (count > ifree) {
1229				count -= ifree;
1230				com_events += ifree;
1231				if (ifree != 0) {
1232					if (com->do_timestamp)
1233						microtime(&com->timestamp);
1234					do {
1235						recv_data = cd_inb(iobase,
1236								   CD1400_RDSR,
1237								   cy_align);
1238#ifdef SOFT_HOTCHAR
1239						if (com->hotchar != 0
1240						    && recv_data
1241						       == com->hotchar)
1242							swi_sched(sio_ih, SWI_NOSWITCH);
1243#endif
1244						ioptr[0] = recv_data;
1245						ioptr[com->ierroff] = 0;
1246						++ioptr;
1247					} while (--ifree != 0);
1248				}
1249				com->delta_error_counts
1250				    [CE_INTERRUPT_BUF_OVERFLOW] += count;
1251				do {
1252					recv_data = cd_inb(iobase, CD1400_RDSR,
1253							   cy_align);
1254#ifdef SOFT_HOTCHAR
1255					if (com->hotchar != 0
1256					    && recv_data == com->hotchar)
1257						swi_sched(sio_ih, SWI_NOSWITCH);
1258#endif
1259				} while (--count != 0);
1260			} else {
1261				if (com->do_timestamp)
1262					microtime(&com->timestamp);
1263				if (ioptr <= com->ihighwater
1264				    && ioptr + count > com->ihighwater
1265				    && com->state & CS_RTS_IFLOW)
1266#if 0
1267					outb(com->modem_ctl_port,
1268					     com->mcr_image &= ~MCR_RTS);
1269#else
1270					cd_outb(iobase, com->mcr_rts_reg,
1271						cy_align,
1272						com->mcr_image
1273						&= ~com->mcr_rts);
1274#endif
1275				com_events += count;
1276				do {
1277					recv_data = cd_inb(iobase, CD1400_RDSR,
1278							   cy_align);
1279#ifdef SOFT_HOTCHAR
1280					if (com->hotchar != 0
1281					    && recv_data == com->hotchar)
1282						swi_sched(sio_ih, SWI_NOSWITCH);
1283#endif
1284					ioptr[0] = recv_data;
1285					ioptr[com->ierroff] = 0;
1286					++ioptr;
1287				} while (--count != 0);
1288			}
1289			com->iptr = ioptr;
1290		}
1291cont:
1292
1293			/* terminate service context */
1294#ifdef PollMode
1295			cd_outb(iobase, CD1400_RIR, cy_align,
1296				save_rir
1297				& ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
1298#else
1299			cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
1300#endif
1301		}
1302		if (status & CD1400_SVRR_MDMCH) {
1303			struct com_s	*com;
1304			u_char	modem_status;
1305#ifdef PollMode
1306			u_char	save_mir;
1307#else
1308			u_char	vector;
1309#endif
1310
1311#ifdef PollMode
1312			save_mir = cd_inb(iobase, CD1400_MIR, cy_align);
1313
1314			/* enter modem service */
1315			cd_outb(iobase, CD1400_CAR, cy_align, save_mir);
1316			com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
1317			= save_mir & CD1400_CAR_CHAN;
1318
1319			com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
1320				       + (save_mir & CD1400_MIR_CHAN));
1321#else
1322			/* ack modem service */
1323			vector = cy_inb(iobase, CY8_SVCACKM, cy_align);
1324
1325			com = com_addr(baseu
1326				       + ((vector >> CD1400_xIVR_CHAN_SHIFT)
1327					  & CD1400_xIVR_CHAN));
1328#endif
1329			++com->mdm;
1330			modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align);
1331		if (modem_status != com->last_modem_status) {
1332			if (com->do_dcd_timestamp
1333			    && !(com->last_modem_status & MSR_DCD)
1334			    && modem_status & MSR_DCD)
1335				microtime(&com->dcd_timestamp);
1336
1337			/*
1338			 * Schedule high level to handle DCD changes.  Note
1339			 * that we don't use the delta bits anywhere.  Some
1340			 * UARTs mess them up, and it's easy to remember the
1341			 * previous bits and calculate the delta.
1342			 */
1343			com->last_modem_status = modem_status;
1344			if (!(com->state & CS_CHECKMSR)) {
1345				com_events += LOTS_OF_EVENTS;
1346				com->state |= CS_CHECKMSR;
1347				swi_sched(sio_ih, SWI_NOSWITCH);
1348			}
1349
1350#ifdef SOFT_CTS_OFLOW
1351			/* handle CTS change immediately for crisp flow ctl */
1352			if (com->state & CS_CTS_OFLOW) {
1353				if (modem_status & MSR_CTS) {
1354					com->state |= CS_ODEVREADY;
1355					if (com->state >= (CS_BUSY | CS_TTGO
1356							   | CS_ODEVREADY)
1357					    && !(com->intr_enable
1358						 & CD1400_SRER_TXRDY))
1359						cd_outb(iobase, CD1400_SRER,
1360							cy_align,
1361							com->intr_enable
1362							= com->intr_enable
1363							  & ~CD1400_SRER_TXMPTY
1364							  | CD1400_SRER_TXRDY);
1365				} else {
1366					com->state &= ~CS_ODEVREADY;
1367					if (com->intr_enable
1368					    & CD1400_SRER_TXRDY)
1369						cd_outb(iobase, CD1400_SRER,
1370							cy_align,
1371							com->intr_enable
1372							= com->intr_enable
1373							  & ~CD1400_SRER_TXRDY
1374							  | CD1400_SRER_TXMPTY);
1375				}
1376			}
1377#endif
1378		}
1379
1380			/* terminate service context */
1381#ifdef PollMode
1382			cd_outb(iobase, CD1400_MIR, cy_align,
1383				save_mir
1384				& ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
1385#else
1386			cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
1387#endif
1388		}
1389		if (status & CD1400_SVRR_TXRDY) {
1390			struct com_s	*com;
1391#ifdef PollMode
1392			u_char	save_tir;
1393#else
1394			u_char	vector;
1395#endif
1396
1397#ifdef PollMode
1398			save_tir = cd_inb(iobase, CD1400_TIR, cy_align);
1399
1400			/* enter tx service */
1401			cd_outb(iobase, CD1400_CAR, cy_align, save_tir);
1402			com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
1403			= save_tir & CD1400_CAR_CHAN;
1404
1405			com = com_addr(baseu
1406				       + cyu * CD1400_NO_OF_CHANNELS
1407				       + (save_tir & CD1400_TIR_CHAN));
1408#else
1409			/* ack transmit service */
1410			vector = cy_inb(iobase, CY8_SVCACKT, cy_align);
1411
1412			com = com_addr(baseu
1413				       + ((vector >> CD1400_xIVR_CHAN_SHIFT)
1414					  & CD1400_xIVR_CHAN));
1415#endif
1416
1417			if (com->etc != ETC_NONE) {
1418				if (com->intr_enable & CD1400_SRER_TXRDY) {
1419					/*
1420					 * Here due to sloppy SRER_TXRDY
1421					 * enabling.  Ignore.  Come back when
1422					 * tx is empty.
1423					 */
1424					cd_outb(iobase, CD1400_SRER, cy_align,
1425						com->intr_enable
1426						= (com->intr_enable
1427						  & ~CD1400_SRER_TXRDY)
1428						  | CD1400_SRER_TXMPTY);
1429					goto terminate_tx_service;
1430				}
1431				switch (com->etc) {
1432				case CD1400_ETC_SENDBREAK:
1433				case CD1400_ETC_STOPBREAK:
1434					/*
1435					 * Start the command.  Come back on
1436					 * next tx empty interrupt, hopefully
1437					 * after command has been executed.
1438					 */
1439					cd_outb(iobase, CD1400_COR2, cy_align,
1440						com->cor[1] |= CD1400_COR2_ETC);
1441					cd_outb(iobase, CD1400_TDR, cy_align,
1442						CD1400_ETC_CMD);
1443					cd_outb(iobase, CD1400_TDR, cy_align,
1444						com->etc);
1445					if (com->etc == CD1400_ETC_SENDBREAK)
1446						com->etc = ETC_BREAK_STARTING;
1447					else
1448						com->etc = ETC_BREAK_ENDING;
1449					goto terminate_tx_service;
1450				case ETC_BREAK_STARTING:
1451					/*
1452					 * BREAK is now on.  Continue with
1453					 * SRER_TXMPTY processing, hopefully
1454					 * don't come back.
1455					 */
1456					com->etc = ETC_BREAK_STARTED;
1457					break;
1458				case ETC_BREAK_STARTED:
1459					/*
1460					 * Came back due to sloppy SRER_TXMPTY
1461					 * enabling.  Hope again.
1462					 */
1463					break;
1464				case ETC_BREAK_ENDING:
1465					/*
1466					 * BREAK is now off.  Continue with
1467					 * SRER_TXMPTY processing and don't
1468					 * come back.  The SWI handler will
1469					 * restart tx interrupts if necessary.
1470					 */
1471					cd_outb(iobase, CD1400_COR2, cy_align,
1472						com->cor[1]
1473						&= ~CD1400_COR2_ETC);
1474					com->etc = ETC_BREAK_ENDED;
1475					if (!(com->state & CS_ODONE)) {
1476						com_events += LOTS_OF_EVENTS;
1477						com->state |= CS_ODONE;
1478						swi_sched(sio_ih, SWI_NOSWITCH);
1479					}
1480					break;
1481				case ETC_BREAK_ENDED:
1482					/*
1483					 * Shouldn't get here.  Hope again.
1484					 */
1485					break;
1486				}
1487			}
1488			if (com->intr_enable & CD1400_SRER_TXMPTY) {
1489				if (!(com->extra_state & CSE_ODONE)) {
1490					com_events += LOTS_OF_EVENTS;
1491					com->extra_state |= CSE_ODONE;
1492					swi_sched(sio_ih, SWI_NOSWITCH);
1493				}
1494				cd_outb(iobase, CD1400_SRER, cy_align,
1495					com->intr_enable
1496					&= ~CD1400_SRER_TXMPTY);
1497				goto terminate_tx_service;
1498			}
1499		if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1500			u_char	*ioptr;
1501			u_int	ocount;
1502
1503			ioptr = com->obufq.l_head;
1504				ocount = com->obufq.l_tail - ioptr;
1505				if (ocount > CD1400_TX_FIFO_SIZE)
1506					ocount = CD1400_TX_FIFO_SIZE;
1507				com->bytes_out += ocount;
1508				do
1509					cd_outb(iobase, CD1400_TDR, cy_align,
1510						*ioptr++);
1511				while (--ocount != 0);
1512			com->obufq.l_head = ioptr;
1513			if (ioptr >= com->obufq.l_tail) {
1514				struct lbq	*qp;
1515
1516				qp = com->obufq.l_next;
1517				qp->l_queued = FALSE;
1518				qp = qp->l_next;
1519				if (qp != NULL) {
1520					com->obufq.l_head = qp->l_head;
1521					com->obufq.l_tail = qp->l_tail;
1522					com->obufq.l_next = qp;
1523				} else {
1524					/* output just completed */
1525					com->state &= ~CS_BUSY;
1526
1527					/*
1528					 * The setting of CSE_ODONE may be
1529					 * stale here.  We currently only
1530					 * use it when CS_BUSY is set, and
1531					 * fixing it when we clear CS_BUSY
1532					 * is easiest.
1533					 */
1534					if (com->extra_state & CSE_ODONE) {
1535						com_events -= LOTS_OF_EVENTS;
1536						com->extra_state &= ~CSE_ODONE;
1537					}
1538
1539					cd_outb(iobase, CD1400_SRER, cy_align,
1540						com->intr_enable
1541						= (com->intr_enable
1542						  & ~CD1400_SRER_TXRDY)
1543						  | CD1400_SRER_TXMPTY);
1544				}
1545				if (!(com->state & CS_ODONE)) {
1546					com_events += LOTS_OF_EVENTS;
1547					com->state |= CS_ODONE;
1548
1549					/* handle at high level ASAP */
1550					swi_sched(sio_ih, SWI_NOSWITCH);
1551				}
1552			}
1553		}
1554
1555			/* terminate service context */
1556terminate_tx_service:
1557#ifdef PollMode
1558			cd_outb(iobase, CD1400_TIR, cy_align,
1559				save_tir
1560				& ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
1561#else
1562			cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
1563#endif
1564		}
1565	}
1566
1567	/* ensure an edge for the next interrupt */
1568	cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
1569
1570	swi_sched(sio_ih, SWI_NOSWITCH);
1571
1572	mtx_unlock_spin(&sio_lock);
1573}
1574
1575#if 0
1576static void
1577siointr1(com)
1578	struct com_s	*com;
1579{
1580}
1581#endif
1582
1583static int
1584sioioctl(dev, cmd, data, flag, p)
1585	dev_t		dev;
1586	u_long		cmd;
1587	caddr_t		data;
1588	int		flag;
1589	struct proc	*p;
1590{
1591	struct com_s	*com;
1592	int		error;
1593	int		mynor;
1594	int		s;
1595	struct tty	*tp;
1596#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1597	int		oldcmd;
1598	struct termios	term;
1599#endif
1600
1601	mynor = minor(dev);
1602	com = com_addr(MINOR_TO_UNIT(mynor));
1603	if (mynor & CONTROL_MASK) {
1604		struct termios	*ct;
1605
1606		switch (mynor & CONTROL_MASK) {
1607		case CONTROL_INIT_STATE:
1608			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
1609			break;
1610		case CONTROL_LOCK_STATE:
1611			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
1612			break;
1613		default:
1614			return (ENODEV);	/* /dev/nodev */
1615		}
1616		switch (cmd) {
1617		case TIOCSETA:
1618			error = suser(p);
1619			if (error != 0)
1620				return (error);
1621			*ct = *(struct termios *)data;
1622			return (0);
1623		case TIOCGETA:
1624			*(struct termios *)data = *ct;
1625			return (0);
1626		case TIOCGETD:
1627			*(int *)data = TTYDISC;
1628			return (0);
1629		case TIOCGWINSZ:
1630			bzero(data, sizeof(struct winsize));
1631			return (0);
1632		default:
1633			return (ENOTTY);
1634		}
1635	}
1636	tp = com->tp;
1637#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1638	term = tp->t_termios;
1639	oldcmd = cmd;
1640	error = ttsetcompat(tp, &cmd, data, &term);
1641	if (error != 0)
1642		return (error);
1643	if (cmd != oldcmd)
1644		data = (caddr_t)&term;
1645#endif
1646	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1647		int	cc;
1648		struct termios *dt = (struct termios *)data;
1649		struct termios *lt = mynor & CALLOUT_MASK
1650				     ? &com->lt_out : &com->lt_in;
1651
1652		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1653			      | (dt->c_iflag & ~lt->c_iflag);
1654		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1655			      | (dt->c_oflag & ~lt->c_oflag);
1656		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1657			      | (dt->c_cflag & ~lt->c_cflag);
1658		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1659			      | (dt->c_lflag & ~lt->c_lflag);
1660		for (cc = 0; cc < NCCS; ++cc)
1661			if (lt->c_cc[cc] != 0)
1662				dt->c_cc[cc] = tp->t_cc[cc];
1663		if (lt->c_ispeed != 0)
1664			dt->c_ispeed = tp->t_ispeed;
1665		if (lt->c_ospeed != 0)
1666			dt->c_ospeed = tp->t_ospeed;
1667	}
1668	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1669	if (error != ENOIOCTL)
1670		return (error);
1671	s = spltty();
1672	error = ttioctl(tp, cmd, data, flag);
1673	disc_optim(tp, &tp->t_termios, com);
1674	if (error != ENOIOCTL) {
1675		splx(s);
1676		return (error);
1677	}
1678	switch (cmd) {
1679	case TIOCSBRK:
1680#if 0
1681		outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
1682#else
1683		cd_etc(com, CD1400_ETC_SENDBREAK);
1684#endif
1685		break;
1686	case TIOCCBRK:
1687#if 0
1688		outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1689#else
1690		cd_etc(com, CD1400_ETC_STOPBREAK);
1691#endif
1692		break;
1693	case TIOCSDTR:
1694		(void)commctl(com, TIOCM_DTR, DMBIS);
1695		break;
1696	case TIOCCDTR:
1697		(void)commctl(com, TIOCM_DTR, DMBIC);
1698		break;
1699	/*
1700	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
1701	 * changes get undone on the next call to comparam().
1702	 */
1703	case TIOCMSET:
1704		(void)commctl(com, *(int *)data, DMSET);
1705		break;
1706	case TIOCMBIS:
1707		(void)commctl(com, *(int *)data, DMBIS);
1708		break;
1709	case TIOCMBIC:
1710		(void)commctl(com, *(int *)data, DMBIC);
1711		break;
1712	case TIOCMGET:
1713		*(int *)data = commctl(com, 0, DMGET);
1714		break;
1715	case TIOCMSDTRWAIT:
1716		/* must be root since the wait applies to following logins */
1717		error = suser(p);
1718		if (error != 0) {
1719			splx(s);
1720			return (error);
1721		}
1722		com->dtr_wait = *(int *)data * hz / 100;
1723		break;
1724	case TIOCMGDTRWAIT:
1725		*(int *)data = com->dtr_wait * 100 / hz;
1726		break;
1727	case TIOCTIMESTAMP:
1728		com->do_timestamp = TRUE;
1729		*(struct timeval *)data = com->timestamp;
1730		break;
1731	case TIOCDCDTIMESTAMP:
1732		com->do_dcd_timestamp = TRUE;
1733		*(struct timeval *)data = com->dcd_timestamp;
1734		break;
1735	default:
1736		splx(s);
1737		return (ENOTTY);
1738	}
1739	splx(s);
1740	return (0);
1741}
1742
1743static void
1744siopoll(void *arg)
1745{
1746	int		unit;
1747
1748#ifdef CyDebug
1749	++cy_timeouts;
1750#endif
1751	if (com_events == 0)
1752		return;
1753repeat:
1754	for (unit = 0; unit < NSIO; ++unit) {
1755		struct com_s	*com;
1756		int		incc;
1757		struct tty	*tp;
1758
1759		com = com_addr(unit);
1760		if (com == NULL)
1761			continue;
1762		tp = com->tp;
1763		if (tp == NULL) {
1764			/*
1765			 * XXX forget any events related to closed devices
1766			 * (actually never opened devices) so that we don't
1767			 * loop.
1768			 */
1769			mtx_lock_spin(&sio_lock);
1770			incc = com->iptr - com->ibuf;
1771			com->iptr = com->ibuf;
1772			if (com->state & CS_CHECKMSR) {
1773				incc += LOTS_OF_EVENTS;
1774				com->state &= ~CS_CHECKMSR;
1775			}
1776			com_events -= incc;
1777			mtx_unlock_spin(&sio_lock);
1778			if (incc != 0)
1779				log(LOG_DEBUG,
1780				    "sio%d: %d events for device with no tp\n",
1781				    unit, incc);
1782			continue;
1783		}
1784		if (com->iptr != com->ibuf) {
1785			mtx_lock_spin(&sio_lock);
1786			sioinput(com);
1787			mtx_unlock_spin(&sio_lock);
1788		}
1789		if (com->state & CS_CHECKMSR) {
1790			u_char	delta_modem_status;
1791
1792			mtx_lock_spin(&sio_lock);
1793			sioinput(com);
1794			delta_modem_status = com->last_modem_status
1795					     ^ com->prev_modem_status;
1796			com->prev_modem_status = com->last_modem_status;
1797			com_events -= LOTS_OF_EVENTS;
1798			com->state &= ~CS_CHECKMSR;
1799			mtx_unlock_spin(&sio_lock);
1800			if (delta_modem_status & MSR_DCD)
1801				(*linesw[tp->t_line].l_modem)
1802					(tp, com->prev_modem_status & MSR_DCD);
1803		}
1804		if (com->extra_state & CSE_ODONE) {
1805			mtx_lock_spin(&sio_lock);
1806			com_events -= LOTS_OF_EVENTS;
1807			com->extra_state &= ~CSE_ODONE;
1808			mtx_unlock_spin(&sio_lock);
1809			if (!(com->state & CS_BUSY)) {
1810				tp->t_state &= ~TS_BUSY;
1811				ttwwakeup(com->tp);
1812			}
1813			if (com->etc != ETC_NONE) {
1814				if (com->etc == ETC_BREAK_ENDED)
1815					com->etc = ETC_NONE;
1816				wakeup(&com->etc);
1817			}
1818		}
1819		if (com->state & CS_ODONE) {
1820			mtx_lock_spin(&sio_lock);
1821			com_events -= LOTS_OF_EVENTS;
1822			com->state &= ~CS_ODONE;
1823			mtx_unlock_spin(&sio_lock);
1824			(*linesw[tp->t_line].l_start)(tp);
1825		}
1826		if (com_events == 0)
1827			break;
1828	}
1829	if (com_events >= LOTS_OF_EVENTS)
1830		goto repeat;
1831}
1832
1833static int
1834comparam(tp, t)
1835	struct tty	*tp;
1836	struct termios	*t;
1837{
1838	int		bits;
1839	int		cflag;
1840	struct com_s	*com;
1841	u_char		cor_change;
1842	u_long		cy_clock;
1843	int		idivisor;
1844	int		iflag;
1845	int		iprescaler;
1846	int		itimeout;
1847	int		odivisor;
1848	int		oprescaler;
1849	u_char		opt;
1850	int		s;
1851	int		unit;
1852
1853	/* do historical conversions */
1854	if (t->c_ispeed == 0)
1855		t->c_ispeed = t->c_ospeed;
1856
1857	unit = DEV_TO_UNIT(tp->t_dev);
1858	com = com_addr(unit);
1859
1860	/* check requested parameters */
1861	cy_clock = CY_CLOCK(com->gfrcr_image);
1862	idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler);
1863	if (idivisor < 0)
1864		return (EINVAL);
1865	odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler);
1866	if (odivisor < 0)
1867		return (EINVAL);
1868
1869	/* parameters are OK, convert them to the com struct and the device */
1870	s = spltty();
1871	if (odivisor == 0)
1872		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
1873	else
1874		(void)commctl(com, TIOCM_DTR, DMBIS);
1875
1876	(void) siosetwater(com, t->c_ispeed);
1877
1878	/* XXX we don't actually change the speed atomically. */
1879
1880	if (idivisor != 0) {
1881		cd_setreg(com, CD1400_RBPR, idivisor);
1882		cd_setreg(com, CD1400_RCOR, iprescaler);
1883	}
1884	if (odivisor != 0) {
1885		cd_setreg(com, CD1400_TBPR, odivisor);
1886		cd_setreg(com, CD1400_TCOR, oprescaler);
1887	}
1888
1889	/*
1890	 * channel control
1891	 *	receiver enable
1892	 *	transmitter enable (always set)
1893	 */
1894	cflag = t->c_cflag;
1895	opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
1896	      | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
1897	if (opt != com->channel_control) {
1898		com->channel_control = opt;
1899		cd1400_channel_cmd(com, opt);
1900	}
1901
1902#ifdef Smarts
1903	/* set special chars */
1904	/* XXX if one is _POSIX_VDISABLE, can't use some others */
1905	if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
1906		cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]);
1907	if (t->c_cc[VSTART] != _POSIX_VDISABLE)
1908		cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]);
1909	if (t->c_cc[VINTR] != _POSIX_VDISABLE)
1910		cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]);
1911	if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
1912		cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]);
1913#endif
1914
1915	/*
1916	 * set channel option register 1 -
1917	 *	parity mode
1918	 *	stop bits
1919	 *	char length
1920	 */
1921	opt = 0;
1922	/* parity */
1923	if (cflag & PARENB) {
1924		if (cflag & PARODD)
1925			opt |= CD1400_COR1_PARODD;
1926		opt |= CD1400_COR1_PARNORMAL;
1927	}
1928	iflag = t->c_iflag;
1929	if (!(iflag & INPCK))
1930		opt |= CD1400_COR1_NOINPCK;
1931	bits = 1 + 1;
1932	/* stop bits */
1933	if (cflag & CSTOPB) {
1934		++bits;
1935		opt |= CD1400_COR1_STOP2;
1936	}
1937	/* char length */
1938	switch (cflag & CSIZE) {
1939	case CS5:
1940		bits += 5;
1941		opt |= CD1400_COR1_CS5;
1942		break;
1943	case CS6:
1944		bits += 6;
1945		opt |= CD1400_COR1_CS6;
1946		break;
1947	case CS7:
1948		bits += 7;
1949		opt |= CD1400_COR1_CS7;
1950		break;
1951	default:
1952		bits += 8;
1953		opt |= CD1400_COR1_CS8;
1954		break;
1955	}
1956	cor_change = 0;
1957	if (opt != com->cor[0]) {
1958		cor_change |= CD1400_CCR_COR1;
1959		cd_setreg(com, CD1400_COR1, com->cor[0] = opt);
1960	}
1961
1962	/*
1963	 * Set receive time-out period, normally to max(one char time, 5 ms).
1964	 */
1965	if (t->c_ispeed == 0)
1966		itimeout = cd_getreg(com, CD1400_RTPR);
1967	else {
1968		itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
1969#ifdef SOFT_HOTCHAR
1970#define	MIN_RTP		1
1971#else
1972#define	MIN_RTP		5
1973#endif
1974		if (itimeout < MIN_RTP)
1975			itimeout = MIN_RTP;
1976	}
1977	if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0
1978	    && t->c_cc[VTIME] * 10 > itimeout)
1979		itimeout = t->c_cc[VTIME] * 10;
1980	if (itimeout > 255)
1981		itimeout = 255;
1982	cd_setreg(com, CD1400_RTPR, itimeout);
1983
1984	/*
1985	 * set channel option register 2 -
1986	 *	flow control
1987	 */
1988	opt = 0;
1989#ifdef Smarts
1990	if (iflag & IXANY)
1991		opt |= CD1400_COR2_IXANY;
1992	if (iflag & IXOFF)
1993		opt |= CD1400_COR2_IXOFF;
1994#endif
1995#ifndef SOFT_CTS_OFLOW
1996	if (cflag & CCTS_OFLOW)
1997		opt |= CD1400_COR2_CCTS_OFLOW;
1998#endif
1999	if (opt != com->cor[1]) {
2000		cor_change |= CD1400_CCR_COR2;
2001		cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
2002	}
2003	mtx_unlock_spin(&sio_lock);
2004
2005	/*
2006	 * set channel option register 3 -
2007	 *	receiver FIFO interrupt threshold
2008	 *	flow control
2009	 */
2010	opt = RxFifoThreshold;
2011#ifdef Smarts
2012	if (t->c_lflag & ICANON)
2013		opt |= CD1400_COR3_SCD34;	/* detect INTR & SUSP chars */
2014	if (iflag & IXOFF)
2015		/* detect and transparently handle START and STOP chars */
2016		opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12;
2017#endif
2018	if (opt != com->cor[2]) {
2019		cor_change |= CD1400_CCR_COR3;
2020		cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
2021	}
2022
2023	/* notify the CD1400 if COR1-3 have changed */
2024	if (cor_change)
2025		cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change);
2026
2027	/*
2028	 * set channel option register 4 -
2029	 *	CR/NL processing
2030	 *	break processing
2031	 *	received exception processing
2032	 */
2033	opt = 0;
2034	if (iflag & IGNCR)
2035		opt |= CD1400_COR4_IGNCR;
2036#ifdef Smarts
2037	/*
2038	 * we need a new ttyinput() for this, as we don't want to
2039	 * have ICRNL && INLCR being done in both layers, or to have
2040	 * synchronisation problems
2041	 */
2042	if (iflag & ICRNL)
2043		opt |= CD1400_COR4_ICRNL;
2044	if (iflag & INLCR)
2045		opt |= CD1400_COR4_INLCR;
2046#endif
2047	if (iflag & IGNBRK)
2048		opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT;
2049	/*
2050	 * The `-ignbrk -brkint parmrk' case is not handled by the hardware,
2051	 * so only tell the hardware about -brkint if -parmrk.
2052	 */
2053	if (!(iflag & (BRKINT | PARMRK)))
2054		opt |= CD1400_COR4_NOBRKINT;
2055#if 0
2056	/* XXX using this "intelligence" breaks reporting of overruns. */
2057	if (iflag & IGNPAR)
2058		opt |= CD1400_COR4_PFO_DISCARD;
2059	else {
2060		if (iflag & PARMRK)
2061			opt |= CD1400_COR4_PFO_ESC;
2062		else
2063			opt |= CD1400_COR4_PFO_NUL;
2064	}
2065#else
2066	opt |= CD1400_COR4_PFO_EXCEPTION;
2067#endif
2068	cd_setreg(com, CD1400_COR4, opt);
2069
2070	/*
2071	 * set channel option register 5 -
2072	 */
2073	opt = 0;
2074	if (iflag & ISTRIP)
2075		opt |= CD1400_COR5_ISTRIP;
2076	if (t->c_iflag & IEXTEN)
2077		/* enable LNEXT (e.g. ctrl-v quoting) handling */
2078		opt |= CD1400_COR5_LNEXT;
2079#ifdef Smarts
2080	if (t->c_oflag & ONLCR)
2081		opt |= CD1400_COR5_ONLCR;
2082	if (t->c_oflag & OCRNL)
2083		opt |= CD1400_COR5_OCRNL;
2084#endif
2085	cd_setreg(com, CD1400_COR5, opt);
2086
2087	/*
2088	 * We always generate modem status change interrupts for CD changes.
2089	 * Among other things, this is necessary to track TS_CARR_ON for
2090	 * pstat to print even when the driver doesn't care.  CD changes
2091	 * should be rare so interrupts for them are not worth extra code to
2092	 * avoid.  We avoid interrupts for other modem status changes (except
2093	 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is
2094	 * simplest and best.
2095	 */
2096
2097	/*
2098	 * set modem change option register 1
2099	 *	generate modem interrupts on which 1 -> 0 input transitions
2100	 *	also controls auto-DTR output flow-control, which we don't use
2101	 */
2102	opt = CD1400_MCOR1_CDzd;
2103#ifdef SOFT_CTS_OFLOW
2104	if (cflag & CCTS_OFLOW)
2105		opt |= CD1400_MCOR1_CTSzd;
2106#endif
2107	cd_setreg(com, CD1400_MCOR1, opt);
2108
2109	/*
2110	 * set modem change option register 2
2111	 *	generate modem interrupts on specific 0 -> 1 input transitions
2112	 */
2113	opt = CD1400_MCOR2_CDod;
2114#ifdef SOFT_CTS_OFLOW
2115	if (cflag & CCTS_OFLOW)
2116		opt |= CD1400_MCOR2_CTSod;
2117#endif
2118	cd_setreg(com, CD1400_MCOR2, opt);
2119
2120	/*
2121	 * XXX should have done this long ago, but there is too much state
2122	 * to change all atomically.
2123	 */
2124	mtx_lock_spin(&sio_lock);
2125
2126	com->state &= ~CS_TTGO;
2127	if (!(tp->t_state & TS_TTSTOP))
2128		com->state |= CS_TTGO;
2129	if (cflag & CRTS_IFLOW) {
2130		com->state |= CS_RTS_IFLOW;
2131		/*
2132		 * If CS_RTS_IFLOW just changed from off to on, the change
2133		 * needs to be propagated to MCR_RTS.  This isn't urgent,
2134		 * so do it later by calling comstart() instead of repeating
2135		 * a lot of code from comstart() here.
2136		 */
2137	} else if (com->state & CS_RTS_IFLOW) {
2138		com->state &= ~CS_RTS_IFLOW;
2139		/*
2140		 * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
2141		 * on here, since comstart() won't do it later.
2142		 */
2143#if 0
2144		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2145#else
2146		cd_setreg(com, com->mcr_rts_reg,
2147			  com->mcr_image |= com->mcr_rts);
2148#endif
2149	}
2150
2151	/*
2152	 * Set up state to handle output flow control.
2153	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2154	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2155	 */
2156	com->state |= CS_ODEVREADY;
2157#ifdef SOFT_CTS_OFLOW
2158	com->state &= ~CS_CTS_OFLOW;
2159	if (cflag & CCTS_OFLOW) {
2160		com->state |= CS_CTS_OFLOW;
2161		if (!(com->last_modem_status & MSR_CTS))
2162			com->state &= ~CS_ODEVREADY;
2163	}
2164#endif
2165	/* XXX shouldn't call functions while intrs are disabled. */
2166	disc_optim(tp, t, com);
2167#if 0
2168	/*
2169	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
2170	 * unconditionally, but that defeated the careful discarding of
2171	 * stale input in sioopen().
2172	 */
2173	if (com->state >= (CS_BUSY | CS_TTGO))
2174		siointr1(com);
2175#endif
2176	if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2177		if (!(com->intr_enable & CD1400_SRER_TXRDY))
2178			cd_setreg(com, CD1400_SRER,
2179				  com->intr_enable
2180				  = (com->intr_enable & ~CD1400_SRER_TXMPTY)
2181				    | CD1400_SRER_TXRDY);
2182	} else {
2183		if (com->intr_enable & CD1400_SRER_TXRDY)
2184			cd_setreg(com, CD1400_SRER,
2185				  com->intr_enable
2186				  = (com->intr_enable & ~CD1400_SRER_TXRDY)
2187				    | CD1400_SRER_TXMPTY);
2188	}
2189
2190	mtx_unlock_spin(&sio_lock);
2191	splx(s);
2192	comstart(tp);
2193	if (com->ibufold != NULL) {
2194		free(com->ibufold, M_DEVBUF);
2195		com->ibufold = NULL;
2196	}
2197	return (0);
2198}
2199
2200/*
2201 * This function must be called with the sio_lock mutex released and will
2202 * return with it obtained.
2203 */
2204static int
2205siosetwater(com, speed)
2206	struct com_s	*com;
2207	speed_t		speed;
2208{
2209	int		cp4ticks;
2210	u_char		*ibuf;
2211	int		ibufsize;
2212	struct tty	*tp;
2213
2214	/*
2215	 * Make the buffer size large enough to handle a softtty interrupt
2216	 * latency of about 2 ticks without loss of throughput or data
2217	 * (about 3 ticks if input flow control is not used or not honoured,
2218	 * but a bit less for CS5-CS7 modes).
2219	 */
2220	cp4ticks = speed / 10 / hz * 4;
2221	for (ibufsize = 128; ibufsize < cp4ticks;)
2222		ibufsize <<= 1;
2223	if (ibufsize == com->ibufsize) {
2224		mtx_lock_spin(&sio_lock);
2225		return (0);
2226	}
2227
2228	/*
2229	 * Allocate input buffer.  The extra factor of 2 in the size is
2230	 * to allow for an error byte for each input byte.
2231	 */
2232	ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
2233	if (ibuf == NULL) {
2234		mtx_lock_spin(&sio_lock);
2235		return (ENOMEM);
2236	}
2237
2238	/* Initialize non-critical variables. */
2239	com->ibufold = com->ibuf;
2240	com->ibufsize = ibufsize;
2241	tp = com->tp;
2242	if (tp != NULL) {
2243		tp->t_ififosize = 2 * ibufsize;
2244		tp->t_ispeedwat = (speed_t)-1;
2245		tp->t_ospeedwat = (speed_t)-1;
2246	}
2247
2248	/*
2249	 * Read current input buffer, if any.  Continue with interrupts
2250	 * disabled.
2251	 */
2252	mtx_lock_spin(&sio_lock);
2253	if (com->iptr != com->ibuf)
2254		sioinput(com);
2255
2256	/*-
2257	 * Initialize critical variables, including input buffer watermarks.
2258	 * The external device is asked to stop sending when the buffer
2259	 * exactly reaches high water, or when the high level requests it.
2260	 * The high level is notified immediately (rather than at a later
2261	 * clock tick) when this watermark is reached.
2262	 * The buffer size is chosen so the watermark should almost never
2263	 * be reached.
2264	 * The low watermark is invisibly 0 since the buffer is always
2265	 * emptied all at once.
2266	 */
2267	com->iptr = com->ibuf = ibuf;
2268	com->ibufend = ibuf + ibufsize;
2269	com->ierroff = ibufsize;
2270	com->ihighwater = ibuf + 3 * ibufsize / 4;
2271
2272	return (0);
2273}
2274
2275static void
2276comstart(tp)
2277	struct tty	*tp;
2278{
2279	struct com_s	*com;
2280	int		s;
2281#ifdef CyDebug
2282	bool_t		started;
2283#endif
2284	int		unit;
2285
2286	unit = DEV_TO_UNIT(tp->t_dev);
2287	com = com_addr(unit);
2288	s = spltty();
2289
2290#ifdef CyDebug
2291	++com->start_count;
2292	started = FALSE;
2293#endif
2294
2295	mtx_lock_spin(&sio_lock);
2296	if (tp->t_state & TS_TTSTOP) {
2297		com->state &= ~CS_TTGO;
2298		if (com->intr_enable & CD1400_SRER_TXRDY)
2299			cd_setreg(com, CD1400_SRER,
2300				  com->intr_enable
2301				  = (com->intr_enable & ~CD1400_SRER_TXRDY)
2302				    | CD1400_SRER_TXMPTY);
2303	} else {
2304		com->state |= CS_TTGO;
2305		if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
2306		    && !(com->intr_enable & CD1400_SRER_TXRDY))
2307			cd_setreg(com, CD1400_SRER,
2308				  com->intr_enable
2309				  = (com->intr_enable & ~CD1400_SRER_TXMPTY)
2310				    | CD1400_SRER_TXRDY);
2311	}
2312	if (tp->t_state & TS_TBLOCK) {
2313		if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW)
2314#if 0
2315			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2316#else
2317			cd_setreg(com, com->mcr_rts_reg,
2318				  com->mcr_image &= ~com->mcr_rts);
2319#endif
2320	} else {
2321		if (!(com->mcr_image & com->mcr_rts)
2322		    && com->iptr < com->ihighwater
2323		    && com->state & CS_RTS_IFLOW)
2324#if 0
2325			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2326#else
2327			cd_setreg(com, com->mcr_rts_reg,
2328				  com->mcr_image |= com->mcr_rts);
2329#endif
2330	}
2331	mtx_unlock_spin(&sio_lock);
2332	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2333		ttwwakeup(tp);
2334		splx(s);
2335		return;
2336	}
2337	if (tp->t_outq.c_cc != 0) {
2338		struct lbq	*qp;
2339		struct lbq	*next;
2340
2341		if (!com->obufs[0].l_queued) {
2342#ifdef CyDebug
2343			started = TRUE;
2344#endif
2345			com->obufs[0].l_tail
2346			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2347						  sizeof com->obuf1);
2348			com->obufs[0].l_next = NULL;
2349			com->obufs[0].l_queued = TRUE;
2350			mtx_lock_spin(&sio_lock);
2351			if (com->state & CS_BUSY) {
2352				qp = com->obufq.l_next;
2353				while ((next = qp->l_next) != NULL)
2354					qp = next;
2355				qp->l_next = &com->obufs[0];
2356			} else {
2357				com->obufq.l_head = com->obufs[0].l_head;
2358				com->obufq.l_tail = com->obufs[0].l_tail;
2359				com->obufq.l_next = &com->obufs[0];
2360				com->state |= CS_BUSY;
2361				if (com->state >= (CS_BUSY | CS_TTGO
2362						   | CS_ODEVREADY))
2363					cd_setreg(com, CD1400_SRER,
2364						  com->intr_enable
2365						  = (com->intr_enable
2366						    & ~CD1400_SRER_TXMPTY)
2367						    | CD1400_SRER_TXRDY);
2368			}
2369			mtx_unlock_spin(&sio_lock);
2370		}
2371		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2372#ifdef CyDebug
2373			started = TRUE;
2374#endif
2375			com->obufs[1].l_tail
2376			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2377						  sizeof com->obuf2);
2378			com->obufs[1].l_next = NULL;
2379			com->obufs[1].l_queued = TRUE;
2380			mtx_lock_spin(&sio_lock);
2381			if (com->state & CS_BUSY) {
2382				qp = com->obufq.l_next;
2383				while ((next = qp->l_next) != NULL)
2384					qp = next;
2385				qp->l_next = &com->obufs[1];
2386			} else {
2387				com->obufq.l_head = com->obufs[1].l_head;
2388				com->obufq.l_tail = com->obufs[1].l_tail;
2389				com->obufq.l_next = &com->obufs[1];
2390				com->state |= CS_BUSY;
2391				if (com->state >= (CS_BUSY | CS_TTGO
2392						   | CS_ODEVREADY))
2393					cd_setreg(com, CD1400_SRER,
2394						  com->intr_enable
2395						  = (com->intr_enable
2396						    & ~CD1400_SRER_TXMPTY)
2397						    | CD1400_SRER_TXRDY);
2398			}
2399			mtx_unlock_spin(&sio_lock);
2400		}
2401		tp->t_state |= TS_BUSY;
2402	}
2403#ifdef CyDebug
2404	if (started)
2405		++com->start_real;
2406#endif
2407#if 0
2408	mtx_lock_spin(&sio_lock);
2409	if (com->state >= (CS_BUSY | CS_TTGO))
2410		siointr1(com);	/* fake interrupt to start output */
2411	mtx_unlock_spin(&sio_lock);
2412#endif
2413	ttwwakeup(tp);
2414	splx(s);
2415}
2416
2417static void
2418comstop(tp, rw)
2419	struct tty	*tp;
2420	int		rw;
2421{
2422	struct com_s	*com;
2423	bool_t		wakeup_etc;
2424
2425	com = com_addr(DEV_TO_UNIT(tp->t_dev));
2426	wakeup_etc = FALSE;
2427	mtx_lock_spin(&sio_lock);
2428	if (rw & FWRITE) {
2429		com->obufs[0].l_queued = FALSE;
2430		com->obufs[1].l_queued = FALSE;
2431		if (com->extra_state & CSE_ODONE) {
2432			com_events -= LOTS_OF_EVENTS;
2433			com->extra_state &= ~CSE_ODONE;
2434			if (com->etc != ETC_NONE) {
2435				if (com->etc == ETC_BREAK_ENDED)
2436					com->etc = ETC_NONE;
2437				wakeup_etc = TRUE;
2438			}
2439		}
2440		com->tp->t_state &= ~TS_BUSY;
2441		if (com->state & CS_ODONE)
2442			com_events -= LOTS_OF_EVENTS;
2443		com->state &= ~(CS_ODONE | CS_BUSY);
2444	}
2445	if (rw & FREAD) {
2446		/* XXX no way to reset only input fifo. */
2447		com_events -= (com->iptr - com->ibuf);
2448		com->iptr = com->ibuf;
2449	}
2450	mtx_unlock_spin(&sio_lock);
2451	if (wakeup_etc)
2452		wakeup(&com->etc);
2453	if (rw & FWRITE && com->etc == ETC_NONE)
2454		cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
2455	comstart(tp);
2456}
2457
2458static int
2459commctl(com, bits, how)
2460	struct com_s	*com;
2461	int		bits;
2462	int		how;
2463{
2464	int	mcr;
2465	int	msr;
2466
2467	if (how == DMGET) {
2468		if (com->channel_control & CD1400_CCR_RCVEN)
2469			bits |= TIOCM_LE;
2470		mcr = com->mcr_image;
2471		if (mcr & com->mcr_dtr)
2472			bits |= TIOCM_DTR;
2473		if (mcr & com->mcr_rts)
2474			/* XXX wired on for Cyclom-8Ys */
2475			bits |= TIOCM_RTS;
2476
2477		/*
2478		 * We must read the modem status from the hardware because
2479		 * we don't generate modem status change interrupts for all
2480		 * changes, so com->prev_modem_status is not guaranteed to
2481		 * be up to date.  This is safe, unlike for sio, because
2482		 * reading the status register doesn't clear pending modem
2483		 * status change interrupts.
2484		 */
2485		msr = cd_getreg(com, CD1400_MSVR2);
2486
2487		if (msr & MSR_CTS)
2488			bits |= TIOCM_CTS;
2489		if (msr & MSR_DCD)
2490			bits |= TIOCM_CD;
2491		if (msr & MSR_DSR)
2492			bits |= TIOCM_DSR;
2493		if (msr & MSR_RI)
2494			/* XXX not connected except for Cyclom-16Y? */
2495			bits |= TIOCM_RI;
2496		return (bits);
2497	}
2498	mcr = 0;
2499	if (bits & TIOCM_DTR)
2500		mcr |= com->mcr_dtr;
2501	if (bits & TIOCM_RTS)
2502		mcr |= com->mcr_rts;
2503	mtx_lock_spin(&sio_lock);
2504	switch (how) {
2505	case DMSET:
2506		com->mcr_image = mcr;
2507		cd_setreg(com, CD1400_MSVR1, mcr);
2508		cd_setreg(com, CD1400_MSVR2, mcr);
2509		break;
2510	case DMBIS:
2511		com->mcr_image = mcr = com->mcr_image | mcr;
2512		cd_setreg(com, CD1400_MSVR1, mcr);
2513		cd_setreg(com, CD1400_MSVR2, mcr);
2514		break;
2515	case DMBIC:
2516		com->mcr_image = mcr = com->mcr_image & ~mcr;
2517		cd_setreg(com, CD1400_MSVR1, mcr);
2518		cd_setreg(com, CD1400_MSVR2, mcr);
2519		break;
2520	}
2521	mtx_unlock_spin(&sio_lock);
2522	return (0);
2523}
2524
2525static void
2526siosettimeout()
2527{
2528	struct com_s	*com;
2529	bool_t		someopen;
2530	int		unit;
2531
2532	/*
2533	 * Set our timeout period to 1 second if no polled devices are open.
2534	 * Otherwise set it to max(1/200, 1/hz).
2535	 * Enable timeouts iff some device is open.
2536	 */
2537	untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2538	sio_timeout = hz;
2539	someopen = FALSE;
2540	for (unit = 0; unit < NSIO; ++unit) {
2541		com = com_addr(unit);
2542		if (com != NULL && com->tp != NULL
2543		    && com->tp->t_state & TS_ISOPEN) {
2544			someopen = TRUE;
2545#if 0
2546			if (com->poll || com->poll_output) {
2547				sio_timeout = hz > 200 ? hz / 200 : 1;
2548				break;
2549			}
2550#endif
2551		}
2552	}
2553	if (someopen) {
2554		sio_timeouts_until_log = hz / sio_timeout;
2555		sio_timeout_handle = timeout(comwakeup, (void *)NULL,
2556					     sio_timeout);
2557	} else {
2558		/* Flush error messages, if any. */
2559		sio_timeouts_until_log = 1;
2560		comwakeup((void *)NULL);
2561		untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2562	}
2563}
2564
2565static void
2566comwakeup(chan)
2567	void	*chan;
2568{
2569	struct com_s	*com;
2570	int		unit;
2571
2572	sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
2573
2574#if 0
2575	/*
2576	 * Recover from lost output interrupts.
2577	 * Poll any lines that don't use interrupts.
2578	 */
2579	for (unit = 0; unit < NSIO; ++unit) {
2580		com = com_addr(unit);
2581		if (com != NULL
2582		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2583			mtx_lock_spin(&sio_lock);
2584			siointr1(com);
2585			mtx_unlock_spin(&sio_lock);
2586		}
2587	}
2588#endif
2589
2590	/*
2591	 * Check for and log errors, but not too often.
2592	 */
2593	if (--sio_timeouts_until_log > 0)
2594		return;
2595	sio_timeouts_until_log = hz / sio_timeout;
2596	for (unit = 0; unit < NSIO; ++unit) {
2597		int	errnum;
2598
2599		com = com_addr(unit);
2600		if (com == NULL)
2601			continue;
2602		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2603			u_int	delta;
2604			u_long	total;
2605
2606			mtx_lock_spin(&sio_lock);
2607			delta = com->delta_error_counts[errnum];
2608			com->delta_error_counts[errnum] = 0;
2609			mtx_unlock_spin(&sio_lock);
2610			if (delta == 0)
2611				continue;
2612			total = com->error_counts[errnum] += delta;
2613			log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
2614			    unit, delta, error_desc[errnum],
2615			    delta == 1 ? "" : "s", total);
2616		}
2617	}
2618}
2619
2620static void
2621disc_optim(tp, t, com)
2622	struct tty	*tp;
2623	struct termios	*t;
2624	struct com_s	*com;
2625{
2626#ifndef SOFT_HOTCHAR
2627	u_char	opt;
2628#endif
2629
2630	/*
2631	 * XXX can skip a lot more cases if Smarts.  Maybe
2632	 * (IGNCR | ISTRIP | IXON) in c_iflag.  But perhaps we
2633	 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.
2634	 */
2635	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2636	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2637	    && (!(t->c_iflag & PARMRK)
2638		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2639	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2640	    && linesw[tp->t_line].l_rint == ttyinput)
2641		tp->t_state |= TS_CAN_BYPASS_L_RINT;
2642	else
2643		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2644	com->hotchar = linesw[tp->t_line].l_hotchar;
2645#ifndef SOFT_HOTCHAR
2646	opt = com->cor[2] & ~CD1400_COR3_SCD34;
2647	if (com->hotchar != 0) {
2648		cd_setreg(com, CD1400_SCHR3, com->hotchar);
2649		cd_setreg(com, CD1400_SCHR4, com->hotchar);
2650		opt |= CD1400_COR3_SCD34;
2651	}
2652	if (opt != com->cor[2]) {
2653		cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
2654		cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
2655	}
2656#endif
2657}
2658
2659#ifdef Smarts
2660/* standard line discipline input routine */
2661int
2662cyinput(c, tp)
2663	int		c;
2664	struct tty	*tp;
2665{
2666	/* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
2667	 * bits, as they are done by the CD1400.  Hardly worth the effort,
2668	 * given that high-throughput sessions are raw anyhow.
2669	 */
2670}
2671#endif /* Smarts */
2672
2673static int
2674comspeed(speed, cy_clock, prescaler_io)
2675	speed_t	speed;
2676	u_long	cy_clock;
2677	int	*prescaler_io;
2678{
2679	int	actual;
2680	int	error;
2681	int	divider;
2682	int	prescaler;
2683	int	prescaler_unit;
2684
2685	if (speed == 0)
2686		return (0);
2687	if (speed < 0 || speed > 150000)
2688		return (-1);
2689
2690	/* determine which prescaler to use */
2691	for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
2692		prescaler_unit--, prescaler >>= 2) {
2693		if (cy_clock / prescaler / speed > 63)
2694			break;
2695	}
2696
2697	divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */
2698	if (divider > 255)
2699		divider = 255;
2700	actual = cy_clock/prescaler/divider;
2701
2702	/* 10 times error in percent: */
2703	error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2;
2704
2705	/* 3.0% max error tolerance */
2706	if (error < -30 || error > 30)
2707		return (-1);
2708
2709#if 0
2710	printf("prescaler = %d (%d)\n", prescaler, prescaler_unit);
2711	printf("divider = %d (%x)\n", divider, divider);
2712	printf("actual = %d\n", actual);
2713	printf("error = %d\n", error);
2714#endif
2715
2716	*prescaler_io = prescaler_unit;
2717	return (divider);
2718}
2719
2720static void
2721cd1400_channel_cmd(com, cmd)
2722	struct com_s	*com;
2723	int		cmd;
2724{
2725	cd1400_channel_cmd_wait(com);
2726	cd_setreg(com, CD1400_CCR, cmd);
2727	cd1400_channel_cmd_wait(com);
2728}
2729
2730static void
2731cd1400_channel_cmd_wait(com)
2732	struct com_s	*com;
2733{
2734	struct timeval	start;
2735	struct timeval	tv;
2736	long		usec;
2737
2738	if (cd_getreg(com, CD1400_CCR) == 0)
2739		return;
2740	microtime(&start);
2741	for (;;) {
2742		if (cd_getreg(com, CD1400_CCR) == 0)
2743			return;
2744		microtime(&tv);
2745		usec = 1000000 * (tv.tv_sec - start.tv_sec) +
2746		    tv.tv_usec - start.tv_usec;
2747		if (usec >= 5000) {
2748			log(LOG_ERR,
2749			    "cy%d: channel command timeout (%ld usec)\n",
2750			    com->unit, usec);
2751			return;
2752		}
2753	}
2754}
2755
2756static void
2757cd_etc(com, etc)
2758	struct com_s	*com;
2759	int		etc;
2760{
2761
2762	/*
2763	 * We can't change the hardware's ETC state while there are any
2764	 * characters in the tx fifo, since those characters would be
2765	 * interpreted as commands!  Unputting characters from the fifo
2766	 * is difficult, so we wait up to 12 character times for the fifo
2767	 * to drain.  The command will be delayed for up to 2 character
2768	 * times for the tx to become empty.  Unputting characters from
2769	 * the tx holding and shift registers is impossible, so we wait
2770	 * for the tx to become empty so that the command is sure to be
2771	 * executed soon after we issue it.
2772	 */
2773	mtx_lock_spin(&sio_lock);
2774	if (com->etc == etc)
2775		goto wait;
2776	if ((etc == CD1400_ETC_SENDBREAK
2777	    && (com->etc == ETC_BREAK_STARTING
2778		|| com->etc == ETC_BREAK_STARTED))
2779	    || (etc == CD1400_ETC_STOPBREAK
2780	       && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED
2781		   || com->etc == ETC_NONE))) {
2782		mtx_unlock_spin(&sio_lock);
2783		return;
2784	}
2785	com->etc = etc;
2786	cd_setreg(com, CD1400_SRER,
2787		  com->intr_enable
2788		  = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY);
2789wait:
2790	mtx_unlock_spin(&sio_lock);
2791	while (com->etc == etc
2792	       && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0)
2793		continue;
2794}
2795
2796static int
2797cd_getreg(com, reg)
2798	struct com_s	*com;
2799	int		reg;
2800{
2801	struct com_s	*basecom;
2802	u_char	car;
2803	int	cy_align;
2804	cy_addr	iobase;
2805	int	val;
2806
2807	basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2808	car = com->unit & CD1400_CAR_CHAN;
2809	cy_align = com->cy_align;
2810	iobase = com->iobase;
2811	mtx_lock_spin(&sio_lock);
2812	if (basecom->car != car)
2813		cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2814	val = cd_inb(iobase, reg, cy_align);
2815	mtx_unlock_spin(&sio_lock);
2816	return (val);
2817}
2818
2819static void
2820cd_setreg(com, reg, val)
2821	struct com_s	*com;
2822	int		reg;
2823	int		val;
2824{
2825	struct com_s	*basecom;
2826	u_char	car;
2827	int	cy_align;
2828	cy_addr	iobase;
2829
2830	basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2831	car = com->unit & CD1400_CAR_CHAN;
2832	cy_align = com->cy_align;
2833	iobase = com->iobase;
2834	mtx_lock_spin(&sio_lock);
2835	if (basecom->car != car)
2836		cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2837	cd_outb(iobase, reg, cy_align, val);
2838	mtx_unlock_spin(&sio_lock);
2839}
2840
2841#ifdef CyDebug
2842/* useful in ddb */
2843void
2844cystatus(unit)
2845	int	unit;
2846{
2847	struct com_s	*com;
2848	cy_addr		iobase;
2849	u_int		ocount;
2850	struct tty	*tp;
2851
2852	com = com_addr(unit);
2853	printf("info for channel %d\n", unit);
2854	printf("------------------\n");
2855	printf("total cyclom service probes:\t%d\n", cy_svrr_probes);
2856	printf("calls to upper layer:\t\t%d\n", cy_timeouts);
2857	if (com == NULL)
2858		return;
2859	iobase = com->iobase;
2860	printf("\n");
2861	printf("cd1400 base address:\\tt%p\n", iobase);
2862	printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
2863	printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
2864	       com->cor[0], com->cor[1], com->cor[2]);
2865	printf("service request enable reg:\t0x%02x (0x%02x cached)\n",
2866	       cd_getreg(com, CD1400_SRER), com->intr_enable);
2867	printf("service request register:\t0x%02x\n",
2868	       cd_inb(iobase, CD1400_SVRR, com->cy_align));
2869	printf("modem status:\t\t\t0x%02x (0x%02x cached)\n",
2870	       cd_getreg(com, CD1400_MSVR2), com->prev_modem_status);
2871	printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n",
2872	       cd_inb(iobase, CD1400_RIR, com->cy_align),
2873	       cd_inb(iobase, CD1400_TIR, com->cy_align),
2874	       cd_inb(iobase, CD1400_MIR, com->cy_align));
2875	printf("\n");
2876	printf("com state:\t\t\t0x%02x\n", com->state);
2877	printf("calls to comstart():\t\t%d (%d useful)\n",
2878	       com->start_count, com->start_real);
2879	printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf);
2880	ocount = 0;
2881	if (com->obufs[0].l_queued)
2882		ocount += com->obufs[0].l_tail - com->obufs[0].l_head;
2883	if (com->obufs[1].l_queued)
2884		ocount += com->obufs[1].l_tail - com->obufs[1].l_head;
2885	printf("tx buffer chars:\t\t%u\n", ocount);
2886	printf("received chars:\t\t\t%d\n", com->bytes_in);
2887	printf("received exceptions:\t\t%d\n", com->recv_exception);
2888	printf("modem signal deltas:\t\t%d\n", com->mdm);
2889	printf("transmitted chars:\t\t%d\n", com->bytes_out);
2890	printf("\n");
2891	tp = com->tp;
2892	if (tp != NULL) {
2893		printf("tty state:\t\t\t0x%08x\n", tp->t_state);
2894		printf(
2895		"upper layer queue lengths:\t%d raw, %d canon, %d output\n",
2896		       tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
2897	} else
2898		printf("tty state:\t\t\tclosed\n");
2899}
2900#endif /* CyDebug */
2901