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