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