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