cy.c revision 12080
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 *	$Id: cy.c,v 1.17 1995/11/04 13:23:31 bde Exp $
31 */
32
33#include "cy.h"
34#if NCY > 0
35/*
36 * TODO:
37 * Check that cy16's work.
38 * Implement BREAK.
39 * Fix overflows when closing line.
40 * Atomic COR change.
41 * Don't report individual ports in devconf; busy flag for board should be
42 * union of the current individual busy flags.
43 * Consoles.
44 */
45
46/*
47 * Temporary compile-time configuration options.
48 */
49#define	RxFifoThreshold	(CD1400_RX_FIFO_SIZE / 2)
50			/* Number of chars in the receiver FIFO before an
51			 * an interrupt is generated.  Should depend on
52			 * line speed.  Needs to be about 6 on a 486DX33
53			 * for 4 active ports at 115200 bps.  Why doesn't
54			 * 10 work?
55			 */
56#define	PollMode	/* Use polling-based irq service routine, not the
57			 * hardware svcack lines.  Must be defined for
58			 * Cyclom-16Y boards.  Less efficient for Cyclom-8Ys,
59			 * and stops 4 * 115200 bps from working.
60			 */
61#undef	Smarts		/* Enable slightly more CD1400 intelligence.  Mainly
62			 * the output CR/LF processing, plus we can avoid a
63			 * few checks usually done in ttyinput().
64			 *
65			 * XXX not fully implemented, and not particularly
66			 * worthwhile.
67			 */
68#undef	CyDebug		/* Include debugging code (not very expensive). */
69
70/* These will go away. */
71#undef	SOFT_CTS_OFLOW
72#define	SOFT_HOTCHAR
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/reboot.h>
77#include <sys/ioctl.h>
78#include <sys/tty.h>
79#include <sys/proc.h>
80#include <sys/user.h>
81#include <sys/conf.h>
82#include <sys/dkstat.h>
83#include <sys/file.h>
84#include <sys/uio.h>
85#include <sys/kernel.h>
86#include <sys/malloc.h>
87#include <sys/syslog.h>
88#include <sys/devconf.h>
89
90#include <machine/clock.h>
91
92#include <i386/isa/icu.h>	/* XXX just to get at `imen' */
93#include <i386/isa/isa.h>
94#include <i386/isa/isa_device.h>
95#include <i386/isa/cyreg.h>
96#include <i386/isa/ic/cd1400.h>
97
98/*
99 * Dictionary so that I can name everything *sio* or *com* to compare with
100 * sio.c.  There is also lots of ugly formatting and unnecessary ifdefs to
101 * simplify the comparision.  These will go away.
102 */
103#define	LSR_BI		CD1400_RDSR_BREAK
104#define	LSR_FE		CD1400_RDSR_FE
105#define	LSR_OE		CD1400_RDSR_OE
106#define	LSR_PE		CD1400_RDSR_PE
107#define	MCR_DTR		CD1400_MSVR2_DTR
108#define	MCR_RTS		CD1400_MSVR1_RTS
109#define	MSR_CTS		CD1400_MSVR2_CTS
110#define	MSR_DCD		CD1400_MSVR2_CD
111#define	MSR_DSR		CD1400_MSVR2_DSR
112#define	MSR_RI		CD1400_MSVR2_RI
113#define	NSIO		(NCY * CY_MAX_PORTS)
114#define	comconsole	cyconsole
115#define	comdefaultrate	cydefaultrate
116#define	com_events	cy_events
117#define	comhardclose	cyhardclose
118#define	commajor	cymajor
119#define	commctl		cymctl
120#define	comparam	cyparam
121#define	comspeed	cyspeed
122#define	comstart	cystart
123#define	comwakeup	cywakeup
124#define	kdc_sio		kdc_cy
125#define	nsio_tty	ncy_tty
126#define	p_com_addr	p_cy_addr
127#define	sioattach	cyattach
128#define	sioclose	cyclose
129#define	siodevtotty	cydevtotty
130#define	siodriver	cydriver
131#define	siodtrwakeup	cydtrwakeup
132#define	sioioctl	cyioctl
133#define	siointr		cyintr
134#define	siointr1	cyintr1
135#define	siointrts	cyintrts
136#define	sioopen		cyopen
137#define	siopoll		cypoll
138#define	sioprobe	cyprobe
139#define	sioread		cyread
140#define	sioregisterdev	cyregisterdev
141#define	siosettimeout	cysettimeout
142#define	siostop		cystop
143#define	siowrite	cywrite
144#define	sio_timeout	cy_timeout
145#define	sio_timeouts_until_log	cy_timeouts_until_log
146#define	sio_tty		cy_tty
147
148#define	CY_MAX_PORTS		(CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s)
149
150/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
151#define	CD1400_xIVR_CHAN_SHIFT	3
152#define	CD1400_xIVR_CHAN	0x0F	/* XXX reduce to pack Cyclom-8Ys */
153
154#define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
155#define	RB_I_HIGH_WATER	(TTYHOG - 2 * RS_IBUFSIZE)
156#define	RS_IBUFSIZE	256
157
158#define	CALLOUT_MASK		0x80
159#define	CONTROL_MASK		0x60
160#define	CONTROL_INIT_STATE	0x20
161#define	CONTROL_LOCK_STATE	0x40
162#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
163#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
164#define	MINOR_TO_UNIT(mynor)	((mynor) & ~MINOR_MAGIC_MASK)
165
166/*
167 * Input buffer watermarks.
168 * The external device is asked to stop sending when the buffer exactly reaches
169 * high water, or when the high level requests it.
170 * The high level is notified immediately (rather than at a later clock tick)
171 * when this watermark is reached.
172 * The buffer size is chosen so the watermark should almost never be reached.
173 * The low watermark is invisibly 0 since the buffer is always emptied all at
174 * once.
175 */
176#define	RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
177
178/*
179 * com state bits.
180 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
181 * than the other bits so that they can be tested as a group without masking
182 * off the low bits.
183 *
184 * The following com and tty flags correspond closely:
185 *	CS_BUSY		= TS_BUSY (maintained by comstart(), siopoll() and
186 *				   siostop())
187 *	CS_TTGO		= ~TS_TTSTOP (maintained by comparam() and comstart())
188 *	CS_CTS_OFLOW	= CCTS_OFLOW (maintained by comparam())
189 *	CS_RTS_IFLOW	= CRTS_IFLOW (maintained by comparam())
190 * TS_FLUSH is not used.
191 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
192 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
193 */
194#define	CS_BUSY		0x80	/* output in progress */
195#define	CS_TTGO		0x40	/* output not stopped by XOFF */
196#define	CS_ODEVREADY	0x20	/* external device h/w ready (CTS) */
197#define	CS_CHECKMSR	1	/* check of MSR scheduled */
198#define	CS_CTS_OFLOW	2	/* use CTS output flow control */
199#define	CS_DTR_OFF	0x10	/* DTR held off */
200#define	CS_ODONE	4	/* output completed */
201#define	CS_RTS_IFLOW	8	/* use RTS input flow control */
202
203static	char const * const	error_desc[] = {
204#define	CE_OVERRUN			0
205	"silo overflow",
206#define	CE_INTERRUPT_BUF_OVERFLOW	1
207	"interrupt-level buffer overflow",
208#define	CE_TTY_BUF_OVERFLOW		2
209	"tty-level buffer overflow",
210};
211
212#define	CE_NTYPES			3
213#define	CE_RECORD(com, errnum)		(++(com)->delta_error_counts[errnum])
214
215/* types.  XXX - should be elsewhere */
216typedef u_char	bool_t;		/* boolean */
217typedef u_char volatile *cy_addr;
218
219/* queue of linear buffers */
220struct lbq {
221	u_char	*l_head;	/* next char to process */
222	u_char	*l_tail;	/* one past the last char to process */
223	struct lbq *l_next;	/* next in queue */
224	bool_t	l_queued;	/* nonzero if queued */
225};
226
227/* com device structure */
228struct com_s {
229	u_char	state;		/* miscellaneous flag bits */
230	bool_t  active_out;	/* nonzero if the callout device is open */
231#if 0
232	u_char	cfcr_image;	/* copy of value written to CFCR */
233	u_char	ftl;		/* current rx fifo trigger level */
234	u_char	ftl_init;	/* ftl_max for next open() */
235	u_char	ftl_max;	/* maximum ftl for curent open() */
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_image;	/* copy of value written to MCR */
240#if 0
241#ifdef COM_MULTIPORT
242	bool_t	multiport;	/* is this unit part of a multiport device? */
243#endif /* COM_MULTIPORT */
244	bool_t	no_irq;		/* nonzero if irq is not attached */
245	bool_t	poll;		/* nonzero if polling is required */
246	bool_t	poll_output;	/* nonzero if polling for output is required */
247#endif
248	int	unit;		/* unit	number */
249	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
250#if 0
251	u_int	tx_fifo_size;
252#endif
253	u_int	wopeners;	/* # processes waiting for DCD in open() */
254
255	/*
256	 * The high level of the driver never reads status registers directly
257	 * because there would be too many side effects to handle conveniently.
258	 * Instead, it reads copies of the registers stored here by the
259	 * interrupt handler.
260	 */
261	u_char	last_modem_status;	/* last MSR read by intr handler */
262	u_char	prev_modem_status;	/* last MSR handled by high level */
263
264	u_char	hotchar;	/* ldisc-specific char to be handled ASAP */
265	u_char	*ibuf;		/* start of input buffer */
266	u_char	*ibufend;	/* end of input buffer */
267	u_char	*ihighwater;	/* threshold in input buffer */
268	u_char	*iptr;		/* next free spot in input buffer */
269
270	struct lbq	obufq;	/* head of queue of output buffers */
271	struct lbq	obufs[2];	/* output buffers */
272
273	cy_addr	cy_iobase;	/* base address of this port's cyclom */
274	cy_addr	iobase;		/* base address of this port's cd1400 */
275
276	struct tty	*tp;	/* cross reference */
277
278	/* Initial state. */
279	struct termios	it_in;	/* should be in struct tty */
280	struct termios	it_out;
281
282	/* Lock state. */
283	struct termios	lt_in;	/* should be in struct tty */
284	struct termios	lt_out;
285
286	bool_t	do_timestamp;
287	struct timeval	timestamp;
288
289	u_long	bytes_in;	/* statistics */
290	u_long	bytes_out;
291	u_int	delta_error_counts[CE_NTYPES];
292	u_long	error_counts[CE_NTYPES];
293
294	u_int	recv_exception;	/* exception chars received */
295	u_int	mdm;		/* modem signal changes */
296#ifdef CyDebug
297	u_int	start_count;	/* no. of calls to comstart() */
298	u_int	start_real;	/* no. of calls that did something */
299#endif
300	u_char	channel_control;/* CD1400 CCR control command shadow */
301	u_char	cor[3];		/* CD1400 COR1-3 shadows */
302	u_char	intr_enable;	/* CD1400 SRER shadow */
303
304	/*
305	 * Ping-pong input buffers.  The extra factor of 2 in the sizes is
306	 * to allow for an error byte for each input byte.
307	 */
308#define	CE_INPUT_OFFSET		RS_IBUFSIZE
309	u_char	ibuf1[2 * RS_IBUFSIZE];
310	u_char	ibuf2[2 * RS_IBUFSIZE];
311
312	/*
313	 * Data area for output buffers.  Someday we should build the output
314	 * buffer queue without copying data.
315	 */
316	u_char	obuf1[256];
317	u_char	obuf2[256];
318
319	struct kern_devconf kdc;
320};
321
322/*
323 * XXX public functions in drivers should be declared in headers produced
324 * by `config', not here.
325 */
326
327/* Interrupt handling entry points. */
328inthand2_t	siointrts;
329void	siopoll		__P((void));
330
331/* Device switch entry points. */
332#define	sioreset	noreset
333#define	siommap		nommap
334#define	siostrategy	nostrategy
335
336static	int	sioattach	__P((struct isa_device *dev));
337static	void	cd1400_channel_cmd __P((cy_addr iobase, int cmd));
338static	timeout_t siodtrwakeup;
339static	void	comhardclose	__P((struct com_s *com));
340static	void	siointr1	__P((struct com_s *com));
341static	int	commctl		__P((struct com_s *com, int bits, int how));
342static	int	comparam	__P((struct tty *tp, struct termios *t));
343static	int	sioprobe	__P((struct isa_device *dev));
344static	void	sioregisterdev	__P((struct isa_device *id));
345static	void	siosettimeout	__P((void));
346static	int	comspeed	__P((speed_t speed, int *prescaler_io));
347static	void	comstart	__P((struct tty *tp));
348static	timeout_t comwakeup;
349static	void	disc_optim	__P((struct tty	*tp, struct termios *t,
350				     struct com_s *com));
351
352#ifdef CyDebug
353void	cystatus	__P((int unit));
354#endif
355
356/* table and macro for fast conversion from a unit number to its com struct */
357static	struct com_s	*p_com_addr[NSIO];
358#define	com_addr(unit)	(p_com_addr[unit])
359
360static  struct timeval	intr_timestamp;
361
362struct isa_driver	siodriver = {
363	sioprobe, sioattach, "cy"
364};
365
366static	int	comconsole = -1;
367static	speed_t	comdefaultrate = TTYDEF_SPEED;
368static	u_int	com_events;	/* input chars + weighted output completions */
369static	int	commajor;
370static	int	sio_timeout;
371static	int	sio_timeouts_until_log;
372#if 0 /* XXX */
373static struct tty	*sio_tty[NSIO];
374#else
375static struct tty	sio_tty[NSIO];
376static	int	nsio_tty = NSIO;
377#endif
378
379#ifdef KGDB
380#include <machine/remote-sl.h>
381
382extern	int	kgdb_dev;
383extern	int	kgdb_rate;
384extern	int	kgdb_debug_init;
385#endif
386
387#ifdef CyDebug
388static	u_int	cd_inbs;
389static	u_int	cy_inbs;
390static	u_int	cd_outbs;
391static	u_int	cy_outbs;
392static	u_int	cy_svrr_probes;
393static	u_int	cy_timeouts;
394#endif
395
396static	int	cy_nr_cd1400s[NCY];
397#undef	RxFifoThreshold
398static	int	volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
399
400static struct kern_devconf kdc_sio[NCY] = { {
401	0, 0, 0,		/* filled in by dev_attach */
402	"cyc", 0, { MDDT_ISA, 0, "tty" },
403	isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
404	&kdc_isa0,		/* parent */
405	0,			/* parentdata */
406	DC_UNCONFIGURED,	/* state */
407	"Cyclades multiport board",
408	DC_CLS_MISC		/* just an ordinary device */
409} };
410
411static void
412sioregisterdev(id)
413	struct isa_device *id;
414{
415	int	unit;
416
417	unit = id->id_unit;
418	if (unit != 0)
419		kdc_sio[unit] = kdc_sio[0];
420	kdc_sio[unit].kdc_unit = unit;
421	kdc_sio[unit].kdc_isa = id;
422	dev_attach(&kdc_sio[unit]);
423}
424
425static int
426sioprobe(dev)
427	struct isa_device	*dev;
428{
429	int	cyu;
430	u_char	firmware_version;
431	cy_addr	iobase;
432	int	unit;
433
434	iobase = (cy_addr)dev->id_maddr;
435	unit = dev->id_unit;
436	if ((u_int)unit >= NCY)
437		return (0);
438	cy_nr_cd1400s[unit] = 0;
439	sioregisterdev(dev);
440
441	/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
442	cy_inb(iobase, CY16_RESET);	/* XXX? */
443	DELAY(500);	/* wait for the board to get its act together */
444
445	/* this is needed to get the board out of reset */
446	cy_outb(iobase, CY_CLEAR_INTR, 0);
447	DELAY(500);
448
449	for (cyu = 0; cyu < CY_MAX_CD1400s;
450	    ++cyu, iobase += CY_CD1400_MEMSIZE) {
451		int	i;
452
453		/* wait for chip to become ready for new command */
454		for (i = 0; i < 10; i++) {
455			DELAY(50);
456			if (!cd_inb(iobase, CD1400_CCR))
457				break;
458		}
459
460		/* clear the GFRCR register */
461		cd_outb(iobase, CD1400_GFRCR, 0);
462
463		/* issue a reset command */
464		cd_outb(iobase, CD1400_CCR,
465			CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
466
467		/* wait for the CD1400 to initialize itself */
468		for (i = 0; i < 200; i++) {
469			DELAY(50);
470
471			/* retrieve firmware version */
472			firmware_version = cd_inb(iobase, CD1400_GFRCR);
473			if ((firmware_version & 0xf0) == 0x40)
474				break;
475		}
476
477		/*
478		 * Anything in the 0x40-0x4F range is fine.
479		 * If one CD1400 is bad then we don't support higher
480		 * numbered good ones on this board.
481		 */
482		if ((firmware_version & 0xf0) != 0x40)
483			break;
484		++cy_nr_cd1400s[unit];
485	}
486	return (cy_nr_cd1400s[unit] == 0 ? 0 : -1);
487}
488
489static int
490sioattach(isdp)
491	struct isa_device	*isdp;
492{
493	int	cyu;
494	cy_addr	cy_iobase;
495	cy_addr	iobase;
496	int	ncyu;
497	int	unit;
498
499	unit = isdp->id_unit;
500	if ((u_int)unit >= NCY)
501		return (0);
502	ncyu = cy_nr_cd1400s[unit];
503	if (ncyu == 0)
504		return (0);
505	isdp->id_ri_flags |= RI_FAST;
506
507	cy_iobase = (cy_addr)isdp->id_maddr;
508	unit *= CY_MAX_PORTS;
509	for (cyu = 0, iobase = cy_iobase; cyu < ncyu;
510	     ++cyu, iobase += CY_CD1400_MEMSIZE) {
511		int	cdu;
512
513		/* Set up a receive timeout period of than 1+ ms. */
514		cd_outb(iobase, CD1400_PPR,
515			howmany(CY_CLOCK / CD1400_PPR_PRESCALER, 1000));
516
517		for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
518			struct com_s	*com;
519			int		s;
520
521	com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT);
522	if (com == NULL)
523		break;
524	bzero(com, sizeof *com);
525	com->unit = unit;
526	com->dtr_wait = 3 * hz;
527	com->iptr = com->ibuf = com->ibuf1;
528	com->ibufend = com->ibuf1 + RS_IBUFSIZE;
529	com->ihighwater = com->ibuf1 + RS_IHIGHWATER;
530	com->obufs[0].l_head = com->obuf1;
531	com->obufs[1].l_head = com->obuf2;
532
533			com->cy_iobase = cy_iobase;
534	com->iobase = iobase;
535
536	/*
537	 * We don't use all the flags from <sys/ttydefaults.h> since they
538	 * are only relevant for logins.  It's important to have echo off
539	 * initially so that the line doesn't start blathering before the
540	 * echo flag can be turned off.
541	 */
542	com->it_in.c_iflag = 0;
543	com->it_in.c_oflag = 0;
544	com->it_in.c_cflag = TTYDEF_CFLAG;
545	com->it_in.c_lflag = 0;
546	if (unit == comconsole) {
547		com->it_in.c_iflag = TTYDEF_IFLAG;
548		com->it_in.c_oflag = TTYDEF_OFLAG;
549		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
550		com->it_in.c_lflag = TTYDEF_LFLAG;
551		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
552	}
553	termioschars(&com->it_in);
554	com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
555	com->it_out = com->it_in;
556
557			com->kdc = kdc_sio[0];
558			com->kdc.kdc_name = "cy";
559			com->kdc.kdc_unit = unit;
560			com->kdc.kdc_isa = isdp;
561			com->kdc.kdc_parent = &kdc_sio[isdp->id_unit];
562			com->kdc.kdc_state = DC_IDLE;
563			com->kdc.kdc_description =
564			  "Serial port: Cirrus Logic CD1400";
565			com->kdc.kdc_class = DC_CLS_SERIAL;
566			dev_attach(&com->kdc);
567
568	s = spltty();
569	com_addr(unit) = com;
570	splx(s);
571		}
572	}
573	kdc_sio[isdp->id_unit].kdc_state = DC_BUSY;	/* XXX */
574
575	/* ensure an edge for the next interrupt */
576	cy_outb(cy_iobase, CY_CLEAR_INTR, 0);
577
578	return (1);
579}
580
581int
582sioopen(dev, flag, mode, p)
583	dev_t		dev;
584	int		flag;
585	int		mode;
586	struct proc	*p;
587{
588	struct com_s	*com;
589	int		error;
590	cy_addr		iobase;
591	int		mynor;
592	int		s;
593	struct tty	*tp;
594	int		unit;
595
596	mynor = minor(dev);
597	unit = MINOR_TO_UNIT(mynor);
598	if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
599		return (ENXIO);
600	if (mynor & CONTROL_MASK)
601		return (0);
602#if 0 /* XXX */
603	tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]);
604#else
605	tp = com->tp = &sio_tty[unit];
606#endif
607	s = spltty();
608	/*
609	 * We jump to this label after all non-interrupted sleeps to pick
610	 * up any changes of the device state.
611	 */
612open_top:
613	while (com->state & CS_DTR_OFF) {
614		error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0);
615		if (error != 0)
616			goto out;
617	}
618	com->kdc.kdc_state = DC_BUSY;
619	if (tp->t_state & TS_ISOPEN) {
620		/*
621		 * The device is open, so everything has been initialized.
622		 * Handle conflicts.
623		 */
624		if (mynor & CALLOUT_MASK) {
625			if (!com->active_out) {
626				error = EBUSY;
627				goto out;
628			}
629		} else {
630			if (com->active_out) {
631				if (flag & O_NONBLOCK) {
632					error = EBUSY;
633					goto out;
634				}
635				error =	tsleep(&com->active_out,
636					       TTIPRI | PCATCH, "cybi", 0);
637				if (error != 0)
638					goto out;
639				goto open_top;
640			}
641		}
642		if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
643			error = EBUSY;
644			goto out;
645		}
646	} else {
647		/*
648		 * The device isn't open, so there are no conflicts.
649		 * Initialize it.  Initialization is done twice in many
650		 * cases: to preempt sleeping callin opens if we are
651		 * callout, and to complete a callin open after DCD rises.
652		 */
653		tp->t_oproc = comstart;
654		tp->t_param = comparam;
655		tp->t_dev = dev;
656		tp->t_termios = mynor & CALLOUT_MASK
657				? com->it_out : com->it_in;
658#if 0
659		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
660		com->ftl_max = com->ftl_init;
661		com->poll = com->no_irq;
662		com->poll_output = com->loses_outints;
663#endif
664		++com->wopeners;
665		iobase = com->iobase;
666
667		/* reset this channel */
668		cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN);
669		cd1400_channel_cmd(iobase, CD1400_CCR_CMDRESET);
670
671		/*
672		 * Resetting disables the transmitter and receiver as well as
673		 * flushing the fifos so some of our cached state becomes
674		 * invalid.  The documentation suggests that all registers
675		 * for the current channel are reset to defaults, but
676		 * apparently none are.  We wouldn't want DTR cleared.
677		 */
678		com->channel_control = 0;
679
680		/* Encode per-board unit in LIVR for access in intr routines. */
681		cd_outb(iobase, CD1400_LIVR,
682			(unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
683
684		/*
685		 * raise dtr and generally set things up correctly.  this
686		 * has the side-effect of selecting the appropriate cd1400
687		 * channel, to help us with subsequent channel control stuff
688		 */
689		error = comparam(tp, &tp->t_termios);
690		--com->wopeners;
691		if (error != 0)
692			goto out;
693		/*
694		 * XXX we should goto open_top if comparam() slept.
695		 */
696		ttsetwater(tp);
697#if 0
698		if (com->hasfifo) {
699			/*
700			 * (Re)enable and drain fifos.
701			 *
702			 * Certain SMC chips cause problems if the fifos
703			 * are enabled while input is ready.  Turn off the
704			 * fifo if necessary to clear the input.  We test
705			 * the input ready bit after enabling the fifos
706			 * since we've already enabled them in comparam()
707			 * and to handle races between enabling and fresh
708			 * input.
709			 */
710			while (TRUE) {
711				outb(iobase + com_fifo,
712				     FIFO_RCV_RST | FIFO_XMT_RST
713				     | FIFO_ENABLE | com->ftl);
714				DELAY(100);
715				if (!(inb(com->line_status_port) & LSR_RXRDY))
716					break;
717				outb(iobase + com_fifo, 0);
718				DELAY(100);
719				(void) inb(com->data_port);
720			}
721		}
722
723		disable_intr();
724		(void) inb(com->line_status_port);
725		(void) inb(com->data_port);
726		com->prev_modem_status = com->last_modem_status
727		    = inb(com->modem_status_port);
728		outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
729				       | IER_EMSC);
730		enable_intr();
731#else /* !0 */
732		/* XXX raise RTS too */
733		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
734		disable_intr();
735		com->prev_modem_status = com->last_modem_status
736		    = cd_inb(iobase, CD1400_MSVR2);
737		cd_outb(iobase, CD1400_SRER,
738			com->intr_enable
739			    = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
740		enable_intr();
741#endif /* 0 */
742		/*
743		 * Handle initial DCD.  Callout devices get a fake initial
744		 * DCD (trapdoor DCD).  If we are callout, then any sleeping
745		 * callin opens get woken up and resume sleeping on "cybi"
746		 * instead of "cydcd".
747		 */
748		/*
749		 * XXX `mynor & CALLOUT_MASK' should be
750		 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
751		 * TRAPDOOR_CARRIER is the default initial state for callout
752		 * devices and SOFT_CARRIER is like CLOCAL except it hides
753		 * the true carrier.
754		 */
755		if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
756			(*linesw[tp->t_line].l_modem)(tp, 1);
757	}
758	/*
759	 * Wait for DCD if necessary.
760	 */
761	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
762	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
763		++com->wopeners;
764		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0);
765		--com->wopeners;
766		if (error != 0)
767			goto out;
768		goto open_top;
769	}
770	error =	(*linesw[tp->t_line].l_open)(dev, tp);
771	disc_optim(tp, &tp->t_termios, com);
772	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
773		com->active_out = TRUE;
774	siosettimeout();
775out:
776	splx(s);
777	if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
778		comhardclose(com);
779	return (error);
780}
781
782int
783sioclose(dev, flag, mode, p)
784	dev_t		dev;
785	int		flag;
786	int		mode;
787	struct proc	*p;
788{
789	struct com_s	*com;
790	int		mynor;
791	int		s;
792	struct tty	*tp;
793
794	mynor = minor(dev);
795	if (mynor & CONTROL_MASK)
796		return (0);
797	com = com_addr(MINOR_TO_UNIT(mynor));
798	tp = com->tp;
799	s = spltty();
800	(*linesw[tp->t_line].l_close)(tp, flag);
801	disc_optim(tp, &tp->t_termios, com);
802	siostop(tp, FREAD | FWRITE);
803	comhardclose(com);
804	ttyclose(tp);
805	siosettimeout();
806	splx(s);
807#ifdef broken /* session holds a ref to the tty; can't deallocate */
808	ttyfree(tp);
809	com->tp = sio_tty[unit] = NULL;
810#endif
811	return (0);
812}
813
814static void
815comhardclose(com)
816	struct com_s	*com;
817{
818	cy_addr		iobase;
819	int		s;
820	struct tty	*tp;
821	int		unit;
822
823	unit = com->unit;
824	iobase = com->iobase;
825	s = spltty();
826#if 0
827	com->poll = FALSE;
828	com->poll_output = FALSE;
829#endif
830	com->do_timestamp = 0;
831	cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN);
832#if 0
833	outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
834#endif
835
836#ifdef KGDB
837	/* do not disable interrupts or hang up if debugging */
838	if (kgdb_dev != makedev(commajor, unit))
839#endif
840	{
841#if 0
842		outb(iobase + com_ier, 0);
843#else
844		disable_intr();
845		cd_outb(iobase, CD1400_SRER, com->intr_enable = 0);
846		enable_intr();
847#endif
848		tp = com->tp;
849		if (tp->t_cflag & HUPCL
850		    /*
851		     * XXX we will miss any carrier drop between here and the
852		     * next open.  Perhaps we should watch DCD even when the
853		     * port is closed; it is not sufficient to check it at
854		     * the next open because it might go up and down while
855		     * we're not watching.
856		     */
857		    || !com->active_out
858		       && !(com->prev_modem_status & MSR_DCD)
859		       && !(com->it_in.c_cflag & CLOCAL)
860		    || !(tp->t_state & TS_ISOPEN)) {
861			(void)commctl(com, TIOCM_DTR, DMBIC);
862
863			/* Disable receiver (leave transmitter enabled). */
864			com->channel_control = CD1400_CCR_CMDCHANCTL
865					       | CD1400_CCR_XMTEN
866					       | CD1400_CCR_RCVDIS;
867			cd1400_channel_cmd(iobase, com->channel_control);
868
869			if (com->dtr_wait != 0) {
870				timeout(siodtrwakeup, com, com->dtr_wait);
871				com->state |= CS_DTR_OFF;
872			}
873		}
874	}
875	com->active_out = FALSE;
876	wakeup(&com->active_out);
877	wakeup(TSA_CARR_ON(tp));	/* restart any wopeners */
878	if (!(com->state & CS_DTR_OFF) && unit != comconsole)
879		com->kdc.kdc_state = DC_IDLE;
880	splx(s);
881}
882
883int
884sioread(dev, uio, flag)
885	dev_t		dev;
886	struct uio	*uio;
887	int		flag;
888{
889	int		mynor;
890	struct tty	*tp;
891
892	mynor = minor(dev);
893	if (mynor & CONTROL_MASK)
894		return (ENODEV);
895	tp = com_addr(MINOR_TO_UNIT(mynor))->tp;
896	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
897}
898
899int
900siowrite(dev, uio, flag)
901	dev_t		dev;
902	struct uio	*uio;
903	int		flag;
904{
905	int		mynor;
906	struct tty	*tp;
907	int		unit;
908
909	mynor = minor(dev);
910	if (mynor & CONTROL_MASK)
911		return (ENODEV);
912
913	unit = MINOR_TO_UNIT(mynor);
914	tp = com_addr(unit)->tp;
915	/*
916	 * (XXX) We disallow virtual consoles if the physical console is
917	 * a serial port.  This is in case there is a display attached that
918	 * is not the console.  In that situation we don't need/want the X
919	 * server taking over the console.
920	 */
921	if (constty != NULL && unit == comconsole)
922		constty = NULL;
923#ifdef Smarts
924	/* XXX duplicate ttwrite(), but without so much output processing on
925	 * CR & LF chars.  Hardly worth the effort, given that high-throughput
926	 * sessions are raw anyhow.
927	 */
928#else
929	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
930#endif
931}
932
933static void
934siodtrwakeup(chan)
935	void	*chan;
936{
937	struct com_s	*com;
938
939	com = (struct com_s *)chan;
940	com->state &= ~CS_DTR_OFF;
941	if (com->unit != comconsole)
942		com->kdc.kdc_state = DC_IDLE;
943	wakeup(&com->dtr_wait);
944}
945
946/* Interrupt routine for timekeeping purposes */
947void
948siointrts(unit)
949	int	unit;
950{
951	/*
952	 * XXX microtime() reenables CPU interrupts.  We can't afford to
953	 * be interrupted and don't want to slow down microtime(), so lock
954	 * out interrupts in another way.
955	 */
956	outb(IO_ICU1 + 1, 0xff);
957	microtime(&intr_timestamp);
958	disable_intr();
959	outb(IO_ICU1 + 1, imen);
960
961	siointr(unit);
962}
963
964void
965siointr(unit)
966	int	unit;
967{
968	int	baseu;
969	cy_addr	cy_iobase;
970	int	cyu;
971	cy_addr	iobase;
972	u_char	status;
973
974	baseu = unit * CY_MAX_PORTS;
975	cy_iobase = com_addr(baseu)->cy_iobase;
976
977	/* check each CD1400 in turn */
978	for (cyu = 0, iobase = cy_iobase; cyu < cy_nr_cd1400s[unit];
979	     ++cyu, iobase += CY_CD1400_MEMSIZE) {
980		/* poll to see if it has any work */
981		status = cd_inb(iobase, CD1400_SVRR);
982		if (status == 0)
983			continue;
984#ifdef CyDebug
985		++cy_svrr_probes;
986#endif
987		/* service requests as appropriate, giving priority to RX */
988		if (status & CD1400_SVRR_RXRDY) {
989			struct com_s	*com;
990			u_int		count;
991			u_char		*ioptr;
992			u_char		line_status;
993			u_char		recv_data;
994			u_char		serv_type;
995#ifdef PollMode
996			u_char		save_car;
997			u_char		save_rir;
998#endif
999
1000#ifdef PollMode
1001			save_rir = cd_inb(iobase, CD1400_RIR);
1002			save_car = cd_inb(iobase, CD1400_CAR);
1003
1004			/* enter rx service */
1005			cd_outb(iobase, CD1400_CAR, save_rir);
1006
1007			serv_type = cd_inb(iobase, CD1400_RIVR);
1008			com = com_addr(baseu
1009				       + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
1010					  & CD1400_xIVR_CHAN));
1011#else
1012			/* ack receive service */
1013			serv_type = cy_inb(iobase, CY8_SVCACKR);
1014
1015			com = com_addr(baseu +
1016				       + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
1017					  & CD1400_xIVR_CHAN));
1018#endif
1019
1020	if (com->do_timestamp)
1021		/* XXX a little bloat here... */
1022		com->timestamp = intr_timestamp;
1023
1024		if (serv_type & CD1400_RIVR_EXCEPTION) {
1025			++com->recv_exception;
1026			line_status = cd_inb(iobase, CD1400_RDSR);
1027			/* break/unnattached error bits or real input? */
1028			recv_data = cd_inb(iobase, CD1400_RDSR);
1029#ifndef SOFT_HOTCHAR
1030			if (line_status & CD1400_RDSR_SPECIAL
1031			    && com->hotchar != 0)
1032				setsofttty();
1033#endif
1034#if 1 /* XXX "intelligent" PFO error handling would break O error handling */
1035			if (line_status & (LSR_PE|LSR_FE|LSR_BI)) {
1036				/*
1037				  Don't store PE if IGNPAR and BI if IGNBRK,
1038				  this hack allows "raw" tty optimization
1039				  works even if IGN* is set.
1040				*/
1041				if (   com->tp == NULL
1042				    || !(com->tp->t_state & TS_ISOPEN)
1043				    || (line_status & (LSR_PE|LSR_FE))
1044				    &&  (com->tp->t_iflag & IGNPAR)
1045				    || (line_status & LSR_BI)
1046				    &&  (com->tp->t_iflag & IGNBRK))
1047					goto cont;
1048				if (   (line_status & (LSR_PE|LSR_FE))
1049				    && (com->tp->t_state & TS_CAN_BYPASS_L_RINT)
1050				    && ((line_status & LSR_FE)
1051				    ||  (line_status & LSR_PE)
1052				    &&  (com->tp->t_iflag & INPCK)))
1053					recv_data = 0;
1054			}
1055#endif /* 1 */
1056			++com->bytes_in;
1057#ifdef SOFT_HOTCHAR
1058			if (com->hotchar != 0 && recv_data == com->hotchar)
1059				setsofttty();
1060#endif
1061			ioptr = com->iptr;
1062			if (ioptr >= com->ibufend)
1063				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1064			else {
1065				++com_events;
1066				ioptr[0] = recv_data;
1067				ioptr[CE_INPUT_OFFSET] = line_status;
1068				com->iptr = ++ioptr;
1069				if (ioptr == com->ihighwater
1070				    && com->state & CS_RTS_IFLOW)
1071#if 0
1072					outb(com->modem_ctl_port,
1073					     com->mcr_image &= ~MCR_RTS);
1074#else
1075					cd_outb(iobase, CD1400_MSVR1,
1076						com->mcr_image &= ~MCR_RTS);
1077#endif
1078				if (line_status & LSR_OE)
1079					CE_RECORD(com, CE_OVERRUN);
1080			}
1081			goto cont;
1082		} else {
1083			int	ifree;
1084
1085			count = cd_inb(iobase, CD1400_RDCR);
1086			com->bytes_in += count;
1087			ioptr = com->iptr;
1088			ifree = com->ibufend - ioptr;
1089			if (count > ifree) {
1090				count -= ifree;
1091				com_events += ifree;
1092				while (ifree-- != 0) {
1093					recv_data = cd_inb(iobase, CD1400_RDSR);
1094#ifdef SOFT_HOTCHAR
1095					if (com->hotchar != 0
1096					    && recv_data == com->hotchar)
1097						setsofttty();
1098#endif
1099					ioptr[0] = recv_data;
1100					ioptr[CE_INPUT_OFFSET] = 0;
1101					++ioptr;
1102				}
1103				com->delta_error_counts
1104				    [CE_INTERRUPT_BUF_OVERFLOW] += count;
1105				do {
1106					recv_data = cd_inb(iobase, CD1400_RDSR);
1107#ifdef SOFT_HOTCHAR
1108					if (com->hotchar != 0
1109					    && recv_data == com->hotchar)
1110						setsofttty();
1111#endif
1112				} while (--count != 0);
1113			} else {
1114				if (ioptr <= com->ihighwater
1115				    && ioptr + count > com->ihighwater
1116				    && com->state & CS_RTS_IFLOW)
1117#if 0
1118					outb(com->modem_ctl_port,
1119					     com->mcr_image &= ~MCR_RTS);
1120#else
1121					cd_outb(iobase, CD1400_MSVR1,
1122						com->mcr_image &= ~MCR_RTS);
1123#endif
1124				com_events += count;
1125				do {
1126					recv_data = cd_inb(iobase, CD1400_RDSR);
1127#ifdef SOFT_HOTCHAR
1128					if (com->hotchar != 0
1129					    && recv_data == com->hotchar)
1130						setsofttty();
1131#endif
1132					ioptr[0] = recv_data;
1133					ioptr[CE_INPUT_OFFSET] = 0;
1134					++ioptr;
1135				} while (--count != 0);
1136			}
1137			com->iptr = ioptr;
1138		}
1139cont:
1140
1141			/* terminate service context */
1142#ifdef PollMode
1143			cd_outb(iobase, CD1400_RIR,
1144				save_rir
1145				& ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
1146			cd_outb(iobase, CD1400_CAR, save_car);
1147#else
1148			cd_outb(iobase, CD1400_EOSRR, 0);
1149#endif
1150		}
1151		if (status & CD1400_SVRR_MDMCH) {
1152			struct com_s	*com;
1153			u_char	modem_status;
1154#ifdef PollMode
1155			u_char	save_car;
1156			u_char	save_mir;
1157#else
1158			u_char	vector;
1159#endif
1160
1161#ifdef PollMode
1162			save_mir = cd_inb(iobase, CD1400_MIR);
1163			save_car = cd_inb(iobase, CD1400_CAR);
1164
1165			/* enter modem service */
1166			cd_outb(iobase, CD1400_CAR, save_mir);
1167
1168			com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
1169				       + (save_mir & CD1400_MIR_CHAN));
1170#else
1171			/* ack modem service */
1172			vector = cy_inb(iobase, CY8_SVCACKM);
1173
1174			com = com_addr(baseu
1175				       + ((vector >> CD1400_xIVR_CHAN_SHIFT)
1176					  & CD1400_xIVR_CHAN));
1177#endif
1178			++com->mdm;
1179			modem_status = cd_inb(iobase, CD1400_MSVR2);
1180		if (modem_status != com->last_modem_status) {
1181			/*
1182			 * Schedule high level to handle DCD changes.  Note
1183			 * that we don't use the delta bits anywhere.  Some
1184			 * UARTs mess them up, and it's easy to remember the
1185			 * previous bits and calculate the delta.
1186			 */
1187			com->last_modem_status = modem_status;
1188			if (!(com->state & CS_CHECKMSR)) {
1189				com_events += LOTS_OF_EVENTS;
1190				com->state |= CS_CHECKMSR;
1191				setsofttty();
1192			}
1193
1194#ifdef SOFT_CTS_OFLOW
1195			/* handle CTS change immediately for crisp flow ctl */
1196			if (com->state & CS_CTS_OFLOW) {
1197				if (modem_status & MSR_CTS) {
1198					com->state |= CS_ODEVREADY;
1199					if (com->state >= (CS_BUSY | CS_TTGO
1200							   | CS_ODEVREADY)
1201					    && !(com->intr_enable
1202						 & CD1400_SRER_TXRDY))
1203						cd_outb(iobase, CD1400_SRER,
1204							com->intr_enable
1205							|= CD1400_SRER_TXRDY);
1206				} else {
1207					com->state &= ~CS_ODEVREADY;
1208					if (com->intr_enable & CD1400_SRER_TXRDY)
1209						cd_outb(iobase, CD1400_SRER,
1210							com->intr_enable
1211							&= ~CD1400_SRER_TXRDY);
1212				}
1213			}
1214#endif
1215		}
1216
1217			/* terminate service context */
1218#ifdef PollMode
1219			cd_outb(iobase, CD1400_MIR,
1220				save_mir
1221				& ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
1222			cd_outb(iobase, CD1400_CAR, save_car);
1223#else
1224			cd_outb(iobase, CD1400_EOSRR, 0);
1225#endif
1226		}
1227		if (status & CD1400_SVRR_TXRDY) {
1228			struct com_s	*com;
1229#ifdef PollMode
1230			u_char	save_car;
1231			u_char	save_tir;
1232#else
1233			u_char	vector;
1234#endif
1235
1236#ifdef PollMode
1237			save_tir = cd_inb(iobase, CD1400_TIR);
1238			save_car = cd_inb(iobase, CD1400_CAR);
1239
1240			/* enter tx service */
1241			cd_outb(iobase, CD1400_CAR, save_tir);
1242			com = com_addr(baseu
1243				       + cyu * CD1400_NO_OF_CHANNELS
1244				       + (save_tir & CD1400_TIR_CHAN));
1245#else
1246			/* ack transmit service */
1247			vector = cy_inb(iobase, CY8_SVCACKT);
1248
1249			com = com_addr(baseu
1250				       + ((vector >> CD1400_xIVR_CHAN_SHIFT)
1251					  & CD1400_xIVR_CHAN));
1252#endif
1253
1254		if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1255			u_char	*ioptr;
1256			u_int	ocount;
1257
1258			ioptr = com->obufq.l_head;
1259				ocount = com->obufq.l_tail - ioptr;
1260				if (ocount > CD1400_TX_FIFO_SIZE)
1261					ocount = CD1400_TX_FIFO_SIZE;
1262				com->bytes_out += ocount;
1263				do
1264					cd_outb(iobase, CD1400_TDR, *ioptr++);
1265				while (--ocount != 0);
1266			com->obufq.l_head = ioptr;
1267			if (ioptr >= com->obufq.l_tail) {
1268				struct lbq	*qp;
1269
1270				qp = com->obufq.l_next;
1271				qp->l_queued = FALSE;
1272				qp = qp->l_next;
1273				if (qp != NULL) {
1274					com->obufq.l_head = qp->l_head;
1275					com->obufq.l_tail = qp->l_tail;
1276					com->obufq.l_next = qp;
1277				} else {
1278					/* output just completed */
1279					com->state &= ~CS_BUSY;
1280					cd_outb(iobase, CD1400_SRER,
1281						com->intr_enable
1282						&= ~CD1400_SRER_TXRDY);
1283				}
1284				if (!(com->state & CS_ODONE)) {
1285					com_events += LOTS_OF_EVENTS;
1286					com->state |= CS_ODONE;
1287					setsofttty();	/* handle at high level ASAP */
1288				}
1289			}
1290		}
1291
1292			/* terminate service context */
1293#ifdef PollMode
1294			cd_outb(iobase, CD1400_TIR,
1295				save_tir
1296				& ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
1297			cd_outb(iobase, CD1400_CAR, save_car);
1298#else
1299			cd_outb(iobase, CD1400_EOSRR, 0);
1300#endif
1301		}
1302	}
1303
1304	/* ensure an edge for the next interrupt */
1305	cy_outb(cy_iobase, CY_CLEAR_INTR, 0);
1306
1307	schedsofttty();
1308}
1309
1310static void
1311siointr1(com)
1312	struct com_s	*com;
1313{
1314}
1315
1316int
1317sioioctl(dev, cmd, data, flag, p)
1318	dev_t		dev;
1319	int		cmd;
1320	caddr_t		data;
1321	int		flag;
1322	struct proc	*p;
1323{
1324	struct com_s	*com;
1325	int		error;
1326	cy_addr		iobase;
1327	int		mynor;
1328	int		s;
1329	struct tty	*tp;
1330#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1331	int		oldcmd;
1332	struct termios	term;
1333#endif
1334
1335	mynor = minor(dev);
1336	com = com_addr(MINOR_TO_UNIT(mynor));
1337	iobase = com->iobase;
1338	if (mynor & CONTROL_MASK) {
1339		struct termios	*ct;
1340
1341		switch (mynor & CONTROL_MASK) {
1342		case CONTROL_INIT_STATE:
1343			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
1344			break;
1345		case CONTROL_LOCK_STATE:
1346			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
1347			break;
1348		default:
1349			return (ENODEV);	/* /dev/nodev */
1350		}
1351		switch (cmd) {
1352		case TIOCSETA:
1353			error = suser(p->p_ucred, &p->p_acflag);
1354			if (error != 0)
1355				return (error);
1356			*ct = *(struct termios *)data;
1357			return (0);
1358		case TIOCGETA:
1359			*(struct termios *)data = *ct;
1360			return (0);
1361		case TIOCGETD:
1362			*(int *)data = TTYDISC;
1363			return (0);
1364		case TIOCGWINSZ:
1365			bzero(data, sizeof(struct winsize));
1366			return (0);
1367		default:
1368			return (ENOTTY);
1369		}
1370	}
1371	tp = com->tp;
1372#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1373	term = tp->t_termios;
1374	oldcmd = cmd;
1375	error = ttsetcompat(tp, &cmd, data, &term);
1376	if (error != 0)
1377		return (error);
1378	if (cmd != oldcmd)
1379		data = (caddr_t)&term;
1380#endif
1381	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1382		int	cc;
1383		struct termios *dt = (struct termios *)data;
1384		struct termios *lt = mynor & CALLOUT_MASK
1385				     ? &com->lt_out : &com->lt_in;
1386
1387		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1388			      | (dt->c_iflag & ~lt->c_iflag);
1389		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1390			      | (dt->c_oflag & ~lt->c_oflag);
1391		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1392			      | (dt->c_cflag & ~lt->c_cflag);
1393		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1394			      | (dt->c_lflag & ~lt->c_lflag);
1395		for (cc = 0; cc < NCCS; ++cc)
1396			if (lt->c_cc[cc] != 0)
1397				dt->c_cc[cc] = tp->t_cc[cc];
1398		if (lt->c_ispeed != 0)
1399			dt->c_ispeed = tp->t_ispeed;
1400		if (lt->c_ospeed != 0)
1401			dt->c_ospeed = tp->t_ospeed;
1402	}
1403	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1404	if (error >= 0)
1405		return (error);
1406	s = spltty();
1407	error = ttioctl(tp, cmd, data, flag);
1408	disc_optim(tp, &tp->t_termios, com);
1409	if (error >= 0) {
1410		splx(s);
1411		return (error);
1412	}
1413	cd_outb(iobase, CD1400_CAR, MINOR_TO_UNIT(mynor) & CD1400_CAR_CHAN);
1414	switch (cmd) {
1415#if 0
1416	case TIOCSBRK:
1417		outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
1418		break;
1419	case TIOCCBRK:
1420		outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1421		break;
1422#endif /* 0 */
1423	case TIOCSDTR:
1424		(void)commctl(com, TIOCM_DTR, DMBIS);
1425		break;
1426	case TIOCCDTR:
1427		(void)commctl(com, TIOCM_DTR, DMBIC);
1428		break;
1429	case TIOCMSET:
1430		(void)commctl(com, *(int *)data, DMSET);
1431		break;
1432	case TIOCMBIS:
1433		(void)commctl(com, *(int *)data, DMBIS);
1434		break;
1435	case TIOCMBIC:
1436		(void)commctl(com, *(int *)data, DMBIC);
1437		break;
1438	case TIOCMGET:
1439		*(int *)data = commctl(com, 0, DMGET);
1440		break;
1441	case TIOCMSDTRWAIT:
1442		/* must be root since the wait applies to following logins */
1443		error = suser(p->p_ucred, &p->p_acflag);
1444		if (error != 0) {
1445			splx(s);
1446			return (error);
1447		}
1448		com->dtr_wait = *(int *)data * hz / 100;
1449		break;
1450	case TIOCMGDTRWAIT:
1451		*(int *)data = com->dtr_wait * 100 / hz;
1452		break;
1453	case TIOCTIMESTAMP:
1454		com->do_timestamp = TRUE;
1455		*(struct timeval *)data = com->timestamp;
1456		break;
1457	default:
1458		splx(s);
1459		return (ENOTTY);
1460	}
1461	splx(s);
1462	return (0);
1463}
1464
1465void
1466siopoll()
1467{
1468	int		unit;
1469
1470#ifdef CyDebug
1471	++cy_timeouts;
1472#endif
1473	if (com_events == 0)
1474		return;
1475repeat:
1476	for (unit = 0; unit < NSIO; ++unit) {
1477		u_char		*buf;
1478		struct com_s	*com;
1479		u_char		*ibuf;
1480		cy_addr		iobase;
1481		int		incc;
1482		struct tty	*tp;
1483
1484		com = com_addr(unit);
1485		if (com == NULL)
1486			continue;
1487		tp = com->tp;
1488		if (tp == NULL) {
1489			/*
1490			 * XXX forget any events related to closed devices
1491			 * (actually never opened devices) so that we don't
1492			 * loop.
1493			 */
1494			disable_intr();
1495			incc = com->iptr - com->ibuf;
1496			com->iptr = com->ibuf;
1497			if (com->state & CS_CHECKMSR) {
1498				incc += LOTS_OF_EVENTS;
1499				com->state &= ~CS_CHECKMSR;
1500			}
1501			com_events -= incc;
1502			enable_intr();
1503			if (incc != 0)
1504				log(LOG_DEBUG,
1505				    "sio%d: %d events for device with no tp\n",
1506				    unit, incc);
1507			continue;
1508		}
1509
1510		/* switch the role of the low-level input buffers */
1511		if (com->iptr == (ibuf = com->ibuf)) {
1512			buf = NULL;     /* not used, but compiler can't tell */
1513			incc = 0;
1514		} else {
1515			buf = ibuf;
1516			disable_intr();
1517			incc = com->iptr - buf;
1518			com_events -= incc;
1519			if (ibuf == com->ibuf1)
1520				ibuf = com->ibuf2;
1521			else
1522				ibuf = com->ibuf1;
1523			com->ibufend = ibuf + RS_IBUFSIZE;
1524			com->ihighwater = ibuf + RS_IHIGHWATER;
1525			com->iptr = ibuf;
1526
1527			/*
1528			 * There is now room for another low-level buffer full
1529			 * of input, so enable RTS if it is now disabled and
1530			 * there is room in the high-level buffer.
1531			 */
1532			/*
1533			 * XXX this used not to look at CS_RTS_IFLOW.  The
1534			 * change is to allow full control of MCR_RTS via
1535			 * ioctls after turning CS_RTS_IFLOW off.  Check
1536			 * for races.  We shouldn't allow the ioctls while
1537			 * CS_RTS_IFLOW is on.
1538			 */
1539			if ((com->state & CS_RTS_IFLOW)
1540			    && !(com->mcr_image & MCR_RTS)
1541			    && !(tp->t_state & TS_TBLOCK))
1542#if 0
1543				outb(com->modem_ctl_port,
1544				     com->mcr_image |= MCR_RTS);
1545#else
1546				iobase = com->iobase,
1547				cd_outb(iobase, CD1400_CAR,
1548					unit & CD1400_CAR_CHAN),
1549				cd_outb(iobase, CD1400_MSVR1,
1550					com->mcr_image |= MCR_RTS);
1551#endif
1552			enable_intr();
1553			com->ibuf = ibuf;
1554		}
1555
1556		if (com->state & CS_CHECKMSR) {
1557			u_char	delta_modem_status;
1558
1559			disable_intr();
1560			delta_modem_status = com->last_modem_status
1561					     ^ com->prev_modem_status;
1562			com->prev_modem_status = com->last_modem_status;
1563			com_events -= LOTS_OF_EVENTS;
1564			com->state &= ~CS_CHECKMSR;
1565			enable_intr();
1566			if (delta_modem_status & MSR_DCD)
1567				(*linesw[tp->t_line].l_modem)
1568					(tp, com->prev_modem_status & MSR_DCD);
1569		}
1570		if (com->state & CS_ODONE) {
1571			disable_intr();
1572			com_events -= LOTS_OF_EVENTS;
1573			com->state &= ~CS_ODONE;
1574			if (!(com->state & CS_BUSY))
1575				com->tp->t_state &= ~TS_BUSY;
1576			enable_intr();
1577			(*linesw[tp->t_line].l_start)(tp);
1578		}
1579		if (incc <= 0 || !(tp->t_state & TS_ISOPEN))
1580			continue;
1581		/*
1582		 * Avoid the grotesquely inefficient lineswitch routine
1583		 * (ttyinput) in "raw" mode.  It usually takes about 450
1584		 * instructions (that's without canonical processing or echo!).
1585		 * slinput is reasonably fast (usually 40 instructions plus
1586		 * call overhead).
1587		 */
1588		if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1589			if (tp->t_rawq.c_cc + incc >= RB_I_HIGH_WATER
1590			    && (com->state & CS_RTS_IFLOW
1591				|| tp->t_iflag & IXOFF)
1592			    && !(tp->t_state & TS_TBLOCK))
1593				ttyblock(tp);
1594			tk_nin += incc;
1595			tk_rawcc += incc;
1596			tp->t_rawcc += incc;
1597			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1598				+= b_to_q((char *)buf, incc, &tp->t_rawq);
1599			ttwakeup(tp);
1600			if (tp->t_state & TS_TTSTOP
1601			    && (tp->t_iflag & IXANY
1602				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1603				tp->t_state &= ~TS_TTSTOP;
1604				tp->t_lflag &= ~FLUSHO;
1605				comstart(tp);
1606			}
1607		} else {
1608			do {
1609				u_char	line_status;
1610				int	recv_data;
1611
1612				line_status = (u_char) buf[CE_INPUT_OFFSET];
1613				recv_data = (u_char) *buf++;
1614				if (line_status
1615				    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1616					if (line_status & LSR_BI)
1617						recv_data |= TTY_BI;
1618					if (line_status & LSR_FE)
1619						recv_data |= TTY_FE;
1620					if (line_status & LSR_OE)
1621						recv_data |= TTY_OE;
1622					if (line_status & LSR_PE)
1623						recv_data |= TTY_PE;
1624				}
1625				(*linesw[tp->t_line].l_rint)(recv_data, tp);
1626			} while (--incc > 0);
1627		}
1628		if (com_events == 0)
1629			break;
1630	}
1631	if (com_events >= LOTS_OF_EVENTS)
1632		goto repeat;
1633}
1634
1635static int
1636comparam(tp, t)
1637	struct tty	*tp;
1638	struct termios	*t;
1639{
1640	int		bits;
1641	int		cflag;
1642	struct com_s	*com;
1643	u_char		cor_change;
1644	int		idivisor;
1645	int		iflag;
1646	cy_addr		iobase;
1647	int		iprescaler;
1648	int		itimeout;
1649	int		odivisor;
1650	int		oprescaler;
1651	u_char		opt;
1652	int		s;
1653	int		unit;
1654
1655	/* do historical conversions */
1656	if (t->c_ispeed == 0)
1657		t->c_ispeed = t->c_ospeed;
1658
1659	/* check requested parameters */
1660	idivisor = comspeed(t->c_ispeed, &iprescaler);
1661	if (idivisor < 0)
1662		return (EINVAL);
1663	odivisor = comspeed(t->c_ospeed, &oprescaler);
1664	if (odivisor < 0)
1665		return (EINVAL);
1666
1667	/* parameters are OK, convert them to the com struct and the device */
1668	unit = DEV_TO_UNIT(tp->t_dev);
1669	com = com_addr(unit);
1670	iobase = com->iobase;
1671	s = spltty();
1672	cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN);
1673	if (odivisor == 0)
1674		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
1675	else
1676		(void)commctl(com, TIOCM_DTR, DMBIS);
1677
1678	cd_outb(iobase, CD1400_RBPR, idivisor);
1679	cd_outb(iobase, CD1400_RCOR, iprescaler);
1680	cd_outb(iobase, CD1400_TBPR, odivisor);
1681	cd_outb(iobase, CD1400_TCOR, oprescaler);
1682
1683	/*
1684	 * channel control
1685	 *	receiver enable
1686	 *	transmitter enable (always set)
1687	 */
1688	cflag = t->c_cflag;
1689	opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
1690	      | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
1691	if (opt != com->channel_control) {
1692		com->channel_control = opt;
1693		cd1400_channel_cmd(iobase, opt);
1694	}
1695
1696#ifdef Smarts
1697	/* set special chars */
1698	/* XXX if one is _POSIX_VDISABLE, can't use some others */
1699	if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
1700		cd_outb(iobase, CD1400_SCHR1, t->c_cc[VSTOP]);
1701	if (t->c_cc[VSTART] != _POSIX_VDISABLE)
1702		cd_outb(iobase, CD1400_SCHR2, t->c_cc[VSTART]);
1703	if (t->c_cc[VINTR] != _POSIX_VDISABLE)
1704		cd_outb(iobase, CD1400_SCHR3, t->c_cc[VINTR]);
1705	if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
1706		cd_outb(iobase, CD1400_SCHR4, t->c_cc[VSUSP]);
1707#endif
1708
1709	/*
1710	 * set channel option register 1 -
1711	 *	parity mode
1712	 *	stop bits
1713	 *	char length
1714	 */
1715	opt = 0;
1716	/* parity */
1717	if (cflag & PARENB) {
1718		if (cflag & PARODD)
1719			opt |= CD1400_COR1_PARODD;
1720		opt |= CD1400_COR1_PARNORMAL;
1721	}
1722	iflag = t->c_iflag;
1723	if (!(iflag & INPCK))
1724		opt |= CD1400_COR1_NOINPCK;
1725	bits = 1 + 1;
1726	/* stop bits */
1727	if (cflag & CSTOPB) {
1728		++bits;
1729		opt |= CD1400_COR1_STOP2;
1730	}
1731	/* char length */
1732	switch (cflag & CSIZE) {
1733	case CS5:
1734		bits += 5;
1735		opt |= CD1400_COR1_CS5;
1736		break;
1737	case CS6:
1738		bits += 6;
1739		opt |= CD1400_COR1_CS6;
1740		break;
1741	case CS7:
1742		bits += 7;
1743		opt |= CD1400_COR1_CS7;
1744		break;
1745	default:
1746		bits += 8;
1747		opt |= CD1400_COR1_CS8;
1748		break;
1749	}
1750	cor_change = 0;
1751	if (opt != com->cor[0]) {
1752		cor_change |= CD1400_CCR_COR1;
1753		cd_outb(iobase, CD1400_COR1, com->cor[0] = opt);
1754	}
1755
1756	/*
1757	 * Set receive time-out period, normally to max(one char time, 5 ms).
1758	 */
1759	if (t->c_ispeed == 0)
1760		itimeout = cd_inb(iobase, CD1400_RTPR);
1761	else {
1762		itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
1763#ifdef SOFT_HOTCHAR
1764#define	MIN_RTP		1
1765#else
1766#define	MIN_RTP		5
1767#endif
1768		if (itimeout < MIN_RTP)
1769			itimeout = MIN_RTP;
1770	}
1771	if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0
1772	    && t->c_cc[VTIME] * 10 > itimeout)
1773		itimeout = t->c_cc[VTIME] * 10;
1774	if (itimeout > 255)
1775		itimeout = 255;
1776	cd_outb(iobase, CD1400_RTPR, itimeout);
1777
1778	/*
1779	 * set channel option register 2 -
1780	 *	flow control
1781	 */
1782	opt = 0;
1783#ifdef Smarts
1784	if (iflag & IXANY)
1785		opt |= CD1400_COR2_IXANY;
1786	if (iflag & IXOFF)
1787		opt |= CD1400_COR2_IXOFF;
1788#endif
1789#ifndef SOFT_CTS_OFLOW
1790	if (cflag & CCTS_OFLOW)
1791		opt |= CD1400_COR2_CCTS_OFLOW;
1792#endif
1793	if (opt != com->cor[1]) {
1794		cor_change |= CD1400_CCR_COR2;
1795		cd_outb(iobase, CD1400_COR2, com->cor[1] = opt);
1796	}
1797
1798	/*
1799	 * set channel option register 3 -
1800	 *	receiver FIFO interrupt threshold
1801	 *	flow control
1802	 */
1803	opt = RxFifoThreshold;
1804#ifdef Smarts
1805	if (t->c_lflag & ICANON)
1806		opt |= CD1400_COR3_SCD34;	/* detect INTR & SUSP chars */
1807	if (iflag & IXOFF)
1808		/* detect and transparently handle START and STOP chars */
1809		opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12;
1810#endif
1811	if (opt != com->cor[2]) {
1812		cor_change |= CD1400_CCR_COR3;
1813		cd_outb(iobase, CD1400_COR3, com->cor[2] = opt);
1814	}
1815
1816	/* notify the CD1400 if COR1-3 have changed */
1817	if (cor_change)
1818		cd1400_channel_cmd(iobase, CD1400_CCR_CMDCORCHG | cor_change);
1819
1820	/*
1821	 * set channel option register 4 -
1822	 *	CR/NL processing
1823	 *	break processing
1824	 *	received exception processing
1825	 */
1826	opt = 0;
1827	if (iflag & IGNCR)
1828		opt |= CD1400_COR4_IGNCR;
1829#ifdef Smarts
1830	/*
1831	 * we need a new ttyinput() for this, as we don't want to
1832	 * have ICRNL && INLCR being done in both layers, or to have
1833	 * synchronisation problems
1834	 */
1835	if (iflag & ICRNL)
1836		opt |= CD1400_COR4_ICRNL;
1837	if (iflag & INLCR)
1838		opt |= CD1400_COR4_INLCR;
1839#endif
1840	if (iflag & IGNBRK)
1841		opt |= CD1400_COR4_IGNBRK;
1842	if (!(iflag & BRKINT))
1843		opt |= CD1400_COR4_NOBRKINT;
1844#if 0
1845	/* XXX using this "intelligence" breaks reporting of overruns. */
1846	if (iflag & IGNPAR)
1847		opt |= CD1400_COR4_PFO_DISCARD;
1848	else {
1849		if (iflag & PARMRK)
1850			opt |= CD1400_COR4_PFO_ESC;
1851		else
1852			opt |= CD1400_COR4_PFO_NUL;
1853	}
1854#else
1855	opt |= CD1400_COR4_PFO_EXCEPTION;
1856#endif
1857	cd_outb(iobase, CD1400_COR4, opt);
1858
1859	/*
1860	 * set channel option register 5 -
1861	 */
1862	opt = 0;
1863	if (iflag & ISTRIP)
1864		opt |= CD1400_COR5_ISTRIP;
1865	if (t->c_iflag & IEXTEN)
1866		/* enable LNEXT (e.g. ctrl-v quoting) handling */
1867		opt |= CD1400_COR5_LNEXT;
1868#ifdef Smarts
1869	if (t->c_oflag & ONLCR)
1870		opt |= CD1400_COR5_ONLCR;
1871	if (t->c_oflag & OCRNL)
1872		opt |= CD1400_COR5_OCRNL;
1873#endif
1874	cd_outb(iobase, CD1400_COR5, opt);
1875
1876	/*
1877	 * XXX we probably alway want to track carrier changes, so that
1878	 * TS_CARR_ON gives the true carrier.  If we don't track them,
1879	 * then we should set TS_CARR_ON when CLOCAL drops.
1880	 */
1881	/*
1882	 * set modem change option register 1
1883	 *	generate modem interrupts on which 1 -> 0 input transitions
1884	 *	also controls auto-DTR output flow-control, which we don't use
1885	 */
1886	opt = cflag & CLOCAL ? 0 : CD1400_MCOR1_CDzd;
1887#ifdef SOFT_CTS_OFLOW
1888	if (cflag & CCTS_OFLOW)
1889		opt |= CD1400_MCOR1_CTSzd;
1890#endif
1891	cd_outb(iobase, CD1400_MCOR1, opt);
1892
1893	/*
1894	 * set modem change option register 2
1895	 *	generate modem interrupts on specific 0 -> 1 input transitions
1896	 */
1897	opt = cflag & CLOCAL ? 0 : CD1400_MCOR2_CDod;
1898#ifdef SOFT_CTS_OFLOW
1899	if (cflag & CCTS_OFLOW)
1900		opt |= CD1400_MCOR2_CTSod;
1901#endif
1902	cd_outb(iobase, CD1400_MCOR2, opt);
1903
1904	/*
1905	 * XXX should have done this long ago, but there is too much state
1906	 * to change all atomically.
1907	 */
1908	disable_intr();
1909
1910	com->state &= ~CS_TTGO;
1911	if (!(tp->t_state & TS_TTSTOP))
1912		com->state |= CS_TTGO;
1913	if (cflag & CRTS_IFLOW)
1914		com->state |= CS_RTS_IFLOW;	/* XXX - secondary changes? */
1915	else
1916		com->state &= ~CS_RTS_IFLOW;
1917
1918	/*
1919	 * Set up state to handle output flow control.
1920	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
1921	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
1922	 */
1923	com->state |= CS_ODEVREADY;
1924#ifdef SOFT_CTS_OFLOW
1925	com->state &= ~CS_CTS_OFLOW;
1926	if (cflag & CCTS_OFLOW) {
1927		com->state |= CS_CTS_OFLOW;
1928		if (!(com->last_modem_status & MSR_CTS))
1929			com->state &= ~CS_ODEVREADY;
1930	}
1931#endif
1932	/* XXX shouldn't call functions while intrs are disabled. */
1933	disc_optim(tp, t, com);
1934#if 0
1935	/*
1936	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
1937	 * unconditionally, but that defeated the careful discarding of
1938	 * stale input in sioopen().
1939	 */
1940	if (com->state >= (CS_BUSY | CS_TTGO))
1941		siointr1(com);
1942#endif
1943	if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1944		if (!(com->intr_enable & CD1400_SRER_TXRDY))
1945			cd_outb(iobase, CD1400_SRER,
1946				com->intr_enable |= CD1400_SRER_TXRDY);
1947	} else {
1948		if (com->intr_enable & CD1400_SRER_TXRDY)
1949			cd_outb(iobase, CD1400_SRER,
1950				com->intr_enable &= ~CD1400_SRER_TXRDY);
1951	}
1952
1953	enable_intr();
1954	splx(s);
1955	return (0);
1956}
1957
1958static void
1959comstart(tp)
1960	struct tty	*tp;
1961{
1962	struct com_s	*com;
1963	cy_addr		iobase;
1964	int		s;
1965#ifdef CyDebug
1966	bool_t		started;
1967#endif
1968	int		unit;
1969
1970	unit = DEV_TO_UNIT(tp->t_dev);
1971	com = com_addr(unit);
1972	iobase = com->iobase;
1973	s = spltty();
1974
1975#ifdef CyDebug
1976	++com->start_count;
1977	started = FALSE;
1978#endif
1979
1980	disable_intr();
1981	cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN);
1982	if (tp->t_state & TS_TTSTOP) {
1983		com->state &= ~CS_TTGO;
1984		if (com->intr_enable & CD1400_SRER_TXRDY)
1985			cd_outb(iobase, CD1400_SRER,
1986				com->intr_enable &= ~CD1400_SRER_TXRDY);
1987	} else {
1988		com->state |= CS_TTGO;
1989		if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
1990		    && !(com->intr_enable & CD1400_SRER_TXRDY))
1991			cd_outb(iobase, CD1400_SRER,
1992				com->intr_enable |= CD1400_SRER_TXRDY);
1993	}
1994	if (tp->t_state & TS_TBLOCK) {
1995		if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
1996#if 0
1997			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
1998#else
1999			cd_outb(iobase, CD1400_MSVR1,
2000				com->mcr_image &= ~MCR_RTS);
2001#endif
2002	} else {
2003		/*
2004		 * XXX don't raise MCR_RTS if CTS_RTS_IFLOW is off.  Set it
2005		 * appropriately in comparam() if RTS-flow is being changed.
2006		 * Check for races.
2007		 */
2008		if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater)
2009#if 0
2010			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2011#else
2012			cd_outb(iobase, CD1400_MSVR1,
2013				com->mcr_image |= MCR_RTS);
2014#endif
2015	}
2016	enable_intr();
2017	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2018		splx(s);
2019		return;
2020	}
2021	if (tp->t_outq.c_cc != 0) {
2022		struct lbq	*qp;
2023		struct lbq	*next;
2024
2025		if (!com->obufs[0].l_queued) {
2026#ifdef CyDebug
2027			started = TRUE;
2028#endif
2029			com->obufs[0].l_tail
2030			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2031						  sizeof com->obuf1);
2032			com->obufs[0].l_next = NULL;
2033			com->obufs[0].l_queued = TRUE;
2034			disable_intr();
2035			if (com->state & CS_BUSY) {
2036				qp = com->obufq.l_next;
2037				while ((next = qp->l_next) != NULL)
2038					qp = next;
2039				qp->l_next = &com->obufs[0];
2040			} else {
2041				com->obufq.l_head = com->obufs[0].l_head;
2042				com->obufq.l_tail = com->obufs[0].l_tail;
2043				com->obufq.l_next = &com->obufs[0];
2044				com->state |= CS_BUSY;
2045				if (com->state >= (CS_BUSY | CS_TTGO
2046						   | CS_ODEVREADY))
2047					cd_outb(iobase, CD1400_SRER,
2048						com->intr_enable
2049						|= CD1400_SRER_TXRDY);
2050			}
2051			enable_intr();
2052		}
2053		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2054#ifdef CyDebug
2055			started = TRUE;
2056#endif
2057			com->obufs[1].l_tail
2058			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2059						  sizeof com->obuf2);
2060			com->obufs[1].l_next = NULL;
2061			com->obufs[1].l_queued = TRUE;
2062			disable_intr();
2063			if (com->state & CS_BUSY) {
2064				qp = com->obufq.l_next;
2065				while ((next = qp->l_next) != NULL)
2066					qp = next;
2067				qp->l_next = &com->obufs[1];
2068			} else {
2069				com->obufq.l_head = com->obufs[1].l_head;
2070				com->obufq.l_tail = com->obufs[1].l_tail;
2071				com->obufq.l_next = &com->obufs[1];
2072				com->state |= CS_BUSY;
2073				if (com->state >= (CS_BUSY | CS_TTGO
2074						   | CS_ODEVREADY))
2075					cd_outb(iobase, CD1400_SRER,
2076						com->intr_enable
2077						|= CD1400_SRER_TXRDY);
2078			}
2079			enable_intr();
2080		}
2081		tp->t_state |= TS_BUSY;
2082	}
2083#ifdef CyDebug
2084	if (started)
2085		++com->start_real;
2086#endif
2087#if 0
2088	disable_intr();
2089	if (com->state >= (CS_BUSY | CS_TTGO)) {
2090		siointr1(com);	/* fake interrupt to start output */
2091	enable_intr();
2092#endif
2093	ttwwakeup(tp);
2094	splx(s);
2095}
2096
2097void
2098siostop(tp, rw)
2099	struct tty	*tp;
2100	int		rw;
2101{
2102	struct com_s	*com;
2103
2104	com = com_addr(DEV_TO_UNIT(tp->t_dev));
2105	disable_intr();
2106	if (rw & FWRITE) {
2107		com->obufs[0].l_queued = FALSE;
2108		com->obufs[1].l_queued = FALSE;
2109		if (com->state & CS_ODONE)
2110			com_events -= LOTS_OF_EVENTS;
2111		com->state &= ~(CS_ODONE | CS_BUSY);
2112		com->tp->t_state &= ~TS_BUSY;
2113	}
2114	if (rw & FREAD) {
2115		com_events -= (com->iptr - com->ibuf);
2116		com->iptr = com->ibuf;
2117	}
2118	enable_intr();
2119	comstart(tp);
2120
2121	/* XXX should clear h/w fifos too. */
2122}
2123
2124struct tty *
2125siodevtotty(dev)
2126	dev_t	dev;
2127{
2128	int	mynor;
2129	int	unit;
2130
2131	mynor = minor(dev);
2132	if (mynor & CONTROL_MASK)
2133		return (NULL);
2134	unit = MINOR_TO_UNIT(mynor);
2135	if ((u_int) unit >= NSIO)
2136		return (NULL);
2137	return (&sio_tty[unit]);
2138}
2139
2140static int
2141commctl(com, bits, how)
2142	struct com_s	*com;
2143	int		bits;
2144	int		how;
2145{
2146	cy_addr	iobase;
2147	int	mcr;
2148	int	msr;
2149
2150	if (how == DMGET) {
2151		if (com->channel_control & CD1400_CCR_RCVEN)
2152			bits |= TIOCM_LE;
2153		mcr = com->mcr_image;
2154		if (mcr & MCR_DTR)
2155			bits |= TIOCM_DTR;
2156		if (mcr & MCR_RTS)
2157			/* XXX wired on for Cyclom-8Ys */
2158			bits |= TIOCM_RTS;
2159		msr = com->prev_modem_status;
2160		if (msr & MSR_CTS)
2161			bits |= TIOCM_CTS;
2162		if (msr & MSR_DCD)
2163			bits |= TIOCM_CD;
2164		if (msr & MSR_DSR)
2165			bits |= TIOCM_DSR;
2166		if (msr & MSR_RI)
2167			/* XXX not connected except for Cyclom-16Y? */
2168			bits |= TIOCM_RI;
2169		return (bits);
2170	}
2171	iobase = com->iobase;
2172	mcr = 0;
2173	if (bits & TIOCM_DTR)
2174		mcr |= MCR_DTR;
2175	if (bits & TIOCM_RTS)
2176		mcr |= MCR_RTS;
2177	disable_intr();
2178	switch (how) {
2179	case DMSET:
2180		com->mcr_image = mcr;
2181		cd_outb(iobase, CD1400_MSVR1, mcr);
2182		cd_outb(iobase, CD1400_MSVR2, mcr);
2183		break;
2184	case DMBIS:
2185		com->mcr_image = mcr = com->mcr_image | mcr;
2186		cd_outb(iobase, CD1400_MSVR1, mcr);
2187		cd_outb(iobase, CD1400_MSVR2, mcr);
2188		break;
2189	case DMBIC:
2190		com->mcr_image = mcr = com->mcr_image & ~mcr;
2191		cd_outb(iobase, CD1400_MSVR1, mcr);
2192		cd_outb(iobase, CD1400_MSVR2, mcr);
2193		break;
2194	}
2195	enable_intr();
2196	return (0);
2197}
2198
2199static void
2200siosettimeout()
2201{
2202	struct com_s	*com;
2203	bool_t		someopen;
2204	int		unit;
2205
2206	/*
2207	 * Set our timeout period to 1 second if no polled devices are open.
2208	 * Otherwise set it to max(1/200, 1/hz).
2209	 * Enable timeouts iff some device is open.
2210	 */
2211	untimeout(comwakeup, (void *)NULL);
2212	sio_timeout = hz;
2213	someopen = FALSE;
2214	for (unit = 0; unit < NSIO; ++unit) {
2215		com = com_addr(unit);
2216		if (com != NULL && com->tp != NULL
2217		    && com->tp->t_state & TS_ISOPEN) {
2218			someopen = TRUE;
2219#if 0
2220			if (com->poll || com->poll_output) {
2221				sio_timeout = hz > 200 ? hz / 200 : 1;
2222				break;
2223			}
2224#endif
2225		}
2226	}
2227	if (someopen) {
2228		sio_timeouts_until_log = hz / sio_timeout;
2229		timeout(comwakeup, (void *)NULL, sio_timeout);
2230	} else {
2231		/* Flush error messages, if any. */
2232		sio_timeouts_until_log = 1;
2233		comwakeup((void *)NULL);
2234		untimeout(comwakeup, (void *)NULL);
2235	}
2236}
2237
2238static void
2239comwakeup(chan)
2240	void	*chan;
2241{
2242	struct com_s	*com;
2243	int		unit;
2244
2245	timeout(comwakeup, (void *)NULL, sio_timeout);
2246
2247#if 0
2248	/*
2249	 * Recover from lost output interrupts.
2250	 * Poll any lines that don't use interrupts.
2251	 */
2252	for (unit = 0; unit < NSIO; ++unit) {
2253		com = com_addr(unit);
2254		if (com != NULL
2255		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2256			disable_intr();
2257			siointr1(com);
2258			enable_intr();
2259		}
2260	}
2261#endif
2262
2263	/*
2264	 * Check for and log errors, but not too often.
2265	 */
2266	if (--sio_timeouts_until_log > 0)
2267		return;
2268	sio_timeouts_until_log = hz / sio_timeout;
2269	for (unit = 0; unit < NSIO; ++unit) {
2270		int	errnum;
2271
2272		com = com_addr(unit);
2273		if (com == NULL)
2274			continue;
2275		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2276			u_int	delta;
2277			u_long	total;
2278
2279			disable_intr();
2280			delta = com->delta_error_counts[errnum];
2281			com->delta_error_counts[errnum] = 0;
2282			enable_intr();
2283			if (delta == 0)
2284				continue;
2285			total = com->error_counts[errnum] += delta;
2286			log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
2287			    unit, delta, error_desc[errnum],
2288			    delta == 1 ? "" : "s", total);
2289#if 0
2290			/*
2291			 * XXX if we resurrect this then we should move
2292			 * the dropping of the ftl to somewhere with less
2293			 * latency.
2294			 */
2295			if (errnum == CE_OVERRUN && com->hasfifo
2296			    && com->ftl > FIFO_TRIGGER_1) {
2297				static	u_char	ftl_in_bytes[] =
2298					{ 1, 4, 8, 14, };
2299
2300				com->ftl_init = FIFO_TRIGGER_8;
2301#define	FIFO_TRIGGER_DELTA	FIFO_TRIGGER_4
2302				com->ftl_max =
2303				com->ftl -= FIFO_TRIGGER_DELTA;
2304				outb(com->iobase + com_fifo,
2305				     FIFO_ENABLE | com->ftl);
2306				log(LOG_DEBUG,
2307				    "sio%d: reduced fifo trigger level to %d\n",
2308				    unit,
2309				    ftl_in_bytes[com->ftl
2310						 / FIFO_TRIGGER_DELTA]);
2311			}
2312#endif
2313		}
2314	}
2315}
2316
2317static void
2318disc_optim(tp, t, com)
2319	struct tty	*tp;
2320	struct termios	*t;
2321	struct com_s	*com;
2322{
2323#ifndef SOFT_HOTCHAR
2324	cy_addr	iobase;
2325	u_char	opt;
2326#endif
2327
2328	/*
2329	 * XXX can skip a lot more cases if Smarts.  Maybe
2330	 * (IGNCR | ISTRIP | IXON) in c_iflag.  But perhaps we
2331	 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.
2332	 */
2333	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2334	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2335	    && (!(t->c_iflag & PARMRK)
2336		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2337	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2338	    && linesw[tp->t_line].l_rint == ttyinput)
2339		tp->t_state |= TS_CAN_BYPASS_L_RINT;
2340	else
2341		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2342	/*
2343	 * Prepare to reduce input latency for packet
2344	 * discplines with a end of packet character.
2345	 */
2346	if (tp->t_line == SLIPDISC)
2347		com->hotchar = 0xc0;
2348	else if (tp->t_line == PPPDISC)
2349		com->hotchar = 0x7e;
2350	else
2351		com->hotchar = 0;
2352#ifndef SOFT_HOTCHAR
2353	iobase = com->iobase;
2354	cd_outb(iobase, CD1400_CAR, com->unit & CD1400_CAR_CHAN);
2355	opt = com->cor[2] & ~CD1400_COR3_SCD34;
2356	if (com->hotchar != 0) {
2357		cd_outb(iobase, CD1400_SCHR3, com->hotchar);
2358		cd_outb(iobase, CD1400_SCHR4, com->hotchar);
2359		opt |= CD1400_COR3_SCD34;
2360	}
2361	if (opt != com->cor[2]) {
2362		cd_outb(iobase, CD1400_COR3, com->cor[2] = opt);
2363		cd1400_channel_cmd(com->iobase,
2364				   CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
2365	}
2366#endif
2367}
2368
2369#ifdef Smarts
2370/* standard line discipline input routine */
2371int
2372cyinput(c, tp)
2373	int		c;
2374	struct tty	*tp;
2375{
2376	/* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
2377	 * bits, as they are done by the CD1400.  Hardly worth the effort,
2378	 * given that high-throughput sessions are raw anyhow.
2379	 */
2380}
2381#endif /* Smarts */
2382
2383static int
2384comspeed(speed, prescaler_io)
2385	speed_t	speed;
2386	int	*prescaler_io;
2387{
2388	int	actual;
2389	int	error;
2390	int	divider;
2391	int	prescaler;
2392	int	prescaler_unit;
2393
2394	if (speed == 0)
2395		return (0);
2396	if (speed < 0 || speed > 150000)
2397		return (-1);
2398
2399	/* determine which prescaler to use */
2400	for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
2401		prescaler_unit--, prescaler >>= 2) {
2402		if (CY_CLOCK / prescaler / speed > 63)
2403			break;
2404	}
2405
2406	divider = (CY_CLOCK / prescaler * 2 / speed + 1) / 2; /* round off */
2407	if (divider > 255)
2408		divider = 255;
2409	actual = CY_CLOCK/prescaler/divider;
2410	error = ((actual - speed) * 2000 / speed + 1) / 2;	/* percentage */
2411
2412	/* 3.0% max error tolerance */
2413	if (error < -30 || error > 30)
2414		return (-1);
2415
2416#if 0
2417	printf("prescaler = %d (%d)\n", prescaler, prescaler_unit);
2418	printf("divider = %d (%x)\n", divider, divider);
2419	printf("actual = %d\n", actual);
2420	printf("error = %d\n", error);
2421#endif
2422
2423	*prescaler_io = prescaler_unit;
2424	return (divider);
2425}
2426
2427static void
2428cd1400_channel_cmd(iobase, cmd)
2429	cy_addr	iobase;
2430	int	cmd;
2431{
2432	/* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed,
2433	   as the card is probed every round?  Replaced delaycount with 8k.
2434	   Either delaycount has to be implemented in FreeBSD or more sensible
2435	   way of doing these should be implemented.  DELAY isn't enough here.
2436	   */
2437	u_int	maxwait = 5 * 8 * 1024;	/* approx. 5 ms */
2438
2439	/* wait for processing of previous command to complete */
2440	while (cd_inb(iobase, CD1400_CCR) && maxwait--)
2441		;
2442
2443	if (!maxwait)
2444		log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n",
2445		    5 * 8 * 1024);
2446
2447	cd_outb(iobase, CD1400_CCR, cmd);
2448}
2449
2450#ifdef CyDebug
2451/* useful in ddb */
2452void
2453cystatus(unit)
2454	int	unit;
2455{
2456	struct com_s	*com;
2457	cy_addr		iobase;
2458	u_int		ocount;
2459	struct tty	*tp;
2460
2461	com = com_addr(unit);
2462	printf("info for channel %d\n", unit);
2463	printf("------------------\n");
2464	printf("total cyclom service probes:\t%d\n", cy_svrr_probes);
2465	printf("calls to upper layer:\t\t%d\n", cy_timeouts);
2466	if (com == NULL)
2467		return;
2468	iobase = com->iobase;
2469	printf("\n");
2470	printf("cd1400 base address:\\tt%p\n", iobase);
2471	cd_outb(iobase, CD1400_CAR, unit & CD1400_CAR_CHAN);
2472	printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
2473	printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
2474	       com->cor[0], com->cor[1], com->cor[2]);
2475	printf("service request enable reg:\t0x%02x (0x%02x cached)\n",
2476	       cd_inb(iobase, CD1400_SRER), com->intr_enable);
2477	printf("service request register:\t0x%02x\n",
2478	       cd_inb(iobase, CD1400_SVRR));
2479	printf("modem status:\t\t\t0x%02x (0x%02x cached)\n",
2480	       cd_inb(iobase, CD1400_MSVR2), com->prev_modem_status);
2481	printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n",
2482	       cd_inb(iobase, CD1400_RIR), cd_inb(iobase, CD1400_TIR),
2483	       cd_inb(iobase, CD1400_MIR));
2484	printf("\n");
2485	printf("com state:\t\t\t0x%02x\n", com->state);
2486	printf("calls to comstart():\t\t%d (%d useful)\n",
2487	       com->start_count, com->start_real);
2488	printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf);
2489	ocount = 0;
2490	if (com->obufs[0].l_queued)
2491		ocount += com->obufs[0].l_tail - com->obufs[0].l_head;
2492	if (com->obufs[1].l_queued)
2493		ocount += com->obufs[1].l_tail - com->obufs[1].l_head;
2494	printf("tx buffer chars:\t\t%u\n", ocount);
2495	printf("received chars:\t\t\t%d\n", com->bytes_in);
2496	printf("received exceptions:\t\t%d\n", com->recv_exception);
2497	printf("modem signal deltas:\t\t%d\n", com->mdm);
2498	printf("transmitted chars:\t\t%d\n", com->bytes_out);
2499	printf("\n");
2500	tp = com->tp;
2501	if (tp != NULL) {
2502		printf("tty state:\t\t\t0x%08x\n", tp->t_state);
2503		printf("upper layer queue lengths:\t%d raw, %d canon, %d output\n",
2504		       tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
2505	} else
2506		printf("tty state:\t\t\tclosed\n");
2507}
2508#endif /* CyDebug */
2509
2510#endif /* NCY > 0 */
2511