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