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