cy.c revision 42045
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.81 1998/12/19 16:28:57 bde Exp $
31 */
32
33#include "opt_compat.h"
34#include "opt_devfs.h"
35
36#include "cy.h"
37
38/*
39 * TODO:
40 * Atomic COR change.
41 * Consoles.
42 */
43
44/*
45 * Temporary compile-time configuration options.
46 */
47#define	RxFifoThreshold	(CD1400_RX_FIFO_SIZE / 2)
48			/* Number of chars in the receiver FIFO before an
49			 * an interrupt is generated.  Should depend on
50			 * line speed.  Needs to be about 6 on a 486DX33
51			 * for 4 active ports at 115200 bps.  Why doesn't
52			 * 10 work?
53			 */
54#define	PollMode	/* Use polling-based irq service routine, not the
55			 * hardware svcack lines.  Must be defined for
56			 * Cyclom-16Y boards.  Less efficient for Cyclom-8Ys,
57			 * and stops 4 * 115200 bps from working.
58			 */
59#undef	Smarts		/* Enable slightly more CD1400 intelligence.  Mainly
60			 * the output CR/LF processing, plus we can avoid a
61			 * few checks usually done in ttyinput().
62			 *
63			 * XXX not fully implemented, and not particularly
64			 * worthwhile.
65			 */
66#undef	CyDebug		/* Include debugging code (not very expensive). */
67
68/* These will go away. */
69#undef	SOFT_CTS_OFLOW
70#define	SOFT_HOTCHAR
71
72#include <sys/param.h>
73#include <sys/systm.h>
74#include <sys/tty.h>
75#include <sys/proc.h>
76#include <sys/conf.h>
77#include <sys/dkstat.h>
78#include <sys/fcntl.h>
79#include <sys/interrupt.h>
80#include <sys/kernel.h>
81#include <sys/malloc.h>
82#include <sys/syslog.h>
83#ifdef DEVFS
84#include <sys/devfsext.h>
85#endif
86
87#include <machine/clock.h>
88#include <machine/ipl.h>
89
90#include <i386/isa/isa_device.h>
91#include <i386/isa/cyreg.h>
92#include <i386/isa/ic/cd1400.h>
93
94#ifdef SMP
95#define disable_intr()	COM_DISABLE_INTR()
96#define enable_intr()	COM_ENABLE_INTR()
97#endif /* SMP */
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	nsio_tty	ncy_tty
125#define	p_com_addr	p_cy_addr
126#define	sioattach	cyattach
127#define	sioclose	cyclose
128#define	siodevtotty	cydevtotty
129#define	siodriver	cydriver
130#define	siodtrwakeup	cydtrwakeup
131#define	siointr		cyintr
132#define	siointr1	cyintr1
133#define	sioioctl	cyioctl
134#define	sioopen		cyopen
135#define	siopoll		cypoll
136#define	sioprobe	cyprobe
137#define	sioread		cyread
138#define	siosettimeout	cysettimeout
139#define	siostop		cystop
140#define	siowrite	cywrite
141#define	sio_registered	cy_registered
142#define	sio_timeout	cy_timeout
143#define	sio_timeout_handle cy_timeout_handle
144#define	sio_timeouts_until_log	cy_timeouts_until_log
145#define	sio_tty		cy_tty
146
147#define	CY_MAX_PORTS		(CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s)
148
149/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
150#define	CD1400_xIVR_CHAN_SHIFT	3
151#define	CD1400_xIVR_CHAN	0x1F
152
153/*
154 * ETC states.  com->etc may also contain a hardware ETC command value,
155 * meaning that execution of that command is pending.
156 */
157#define	ETC_NONE		0	/* we depend on bzero() setting this */
158#define	ETC_BREAK_STARTING	1
159#define	ETC_BREAK_STARTED	2
160#define	ETC_BREAK_ENDING	3
161#define	ETC_BREAK_ENDED		4
162
163#define	LOTS_OF_EVENTS	64	/* helps separate urgent events from input */
164#define	RS_IBUFSIZE	256
165
166#define	CALLOUT_MASK		0x80
167#define	CONTROL_MASK		0x60
168#define	CONTROL_INIT_STATE	0x20
169#define	CONTROL_LOCK_STATE	0x40
170#define	DEV_TO_UNIT(dev)	(MINOR_TO_UNIT(minor(dev)))
171#define	MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
172#define	MINOR_TO_UNIT(mynor)	(((mynor) >> 16) * CY_MAX_PORTS \
173				 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK))
174
175/*
176 * Input buffer watermarks.
177 * The external device is asked to stop sending when the buffer exactly reaches
178 * high water, or when the high level requests it.
179 * The high level is notified immediately (rather than at a later clock tick)
180 * when this watermark is reached.
181 * The buffer size is chosen so the watermark should almost never be reached.
182 * The low watermark is invisibly 0 since the buffer is always emptied all at
183 * once.
184 */
185#define	RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
186
187/*
188 * com state bits.
189 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
190 * than the other bits so that they can be tested as a group without masking
191 * off the low bits.
192 *
193 * The following com and tty flags correspond closely:
194 *	CS_BUSY		= TS_BUSY (maintained by comstart(), siopoll() and
195 *				   siostop())
196 *	CS_TTGO		= ~TS_TTSTOP (maintained by comparam() and comstart())
197 *	CS_CTS_OFLOW	= CCTS_OFLOW (maintained by comparam())
198 *	CS_RTS_IFLOW	= CRTS_IFLOW (maintained by comparam())
199 * TS_FLUSH is not used.
200 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
201 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
202 */
203#define	CS_BUSY		0x80	/* output in progress */
204#define	CS_TTGO		0x40	/* output not stopped by XOFF */
205#define	CS_ODEVREADY	0x20	/* external device h/w ready (CTS) */
206#define	CS_CHECKMSR	1	/* check of MSR scheduled */
207#define	CS_CTS_OFLOW	2	/* use CTS output flow control */
208#define	CS_DTR_OFF	0x10	/* DTR held off */
209#define	CS_ODONE	4	/* output completed */
210#define	CS_RTS_IFLOW	8	/* use RTS input flow control */
211#define	CSE_ODONE	1	/* output transmitted */
212
213static	char const * const	error_desc[] = {
214#define	CE_OVERRUN			0
215	"silo overflow",
216#define	CE_INTERRUPT_BUF_OVERFLOW	1
217	"interrupt-level buffer overflow",
218#define	CE_TTY_BUF_OVERFLOW		2
219	"tty-level buffer overflow",
220};
221
222#define	CE_NTYPES			3
223#define	CE_RECORD(com, errnum)		(++(com)->delta_error_counts[errnum])
224
225/* types.  XXX - should be elsewhere */
226typedef u_char	bool_t;		/* boolean */
227typedef u_char volatile *cy_addr;
228
229/* queue of linear buffers */
230struct lbq {
231	u_char	*l_head;	/* next char to process */
232	u_char	*l_tail;	/* one past the last char to process */
233	struct lbq *l_next;	/* next in queue */
234	bool_t	l_queued;	/* nonzero if queued */
235};
236
237/* com device structure */
238struct com_s {
239	u_char	state;		/* miscellaneous flag bits */
240	bool_t  active_out;	/* nonzero if the callout device is open */
241#if 0
242	u_char	cfcr_image;	/* copy of value written to CFCR */
243#endif
244	u_char	etc;		/* pending Embedded Transmit Command */
245	u_char	extra_state;	/* more flag bits, separate for order trick */
246#if 0
247	u_char	fifo_image;	/* copy of value written to FIFO */
248#endif
249	u_char	gfrcr_image;	/* copy of value read from GFRCR */
250#if 0
251	bool_t	hasfifo;	/* nonzero for 16550 UARTs */
252	bool_t	loses_outints;	/* nonzero if device loses output interrupts */
253#endif
254	u_char	mcr_dtr;	/* MCR bit that is wired to DTR */
255	u_char	mcr_image;	/* copy of value written to MCR */
256	u_char	mcr_rts;	/* MCR bit that is wired to RTS */
257#if 0
258#ifdef COM_MULTIPORT
259	bool_t	multiport;	/* is this unit part of a multiport device? */
260#endif /* COM_MULTIPORT */
261	bool_t	no_irq;		/* nonzero if irq is not attached */
262	bool_t	poll;		/* nonzero if polling is required */
263	bool_t	poll_output;	/* nonzero if polling for output is required */
264#endif
265	int	unit;		/* unit	number */
266	int	dtr_wait;	/* time to hold DTR down on close (* 1/hz) */
267#if 0
268	u_int	tx_fifo_size;
269#endif
270	u_int	wopeners;	/* # processes waiting for DCD in open() */
271
272	/*
273	 * The high level of the driver never reads status registers directly
274	 * because there would be too many side effects to handle conveniently.
275	 * Instead, it reads copies of the registers stored here by the
276	 * interrupt handler.
277	 */
278	u_char	last_modem_status;	/* last MSR read by intr handler */
279	u_char	prev_modem_status;	/* last MSR handled by high level */
280
281	u_char	hotchar;	/* ldisc-specific char to be handled ASAP */
282	u_char	*ibuf;		/* start of input buffer */
283	u_char	*ibufend;	/* end of input buffer */
284	u_char	*ihighwater;	/* threshold in input buffer */
285	u_char	*iptr;		/* next free spot in input buffer */
286
287	struct lbq	obufq;	/* head of queue of output buffers */
288	struct lbq	obufs[2];	/* output buffers */
289
290	int	cy_align;	/* index for register alignment */
291	cy_addr	cy_iobase;	/* base address of this port's cyclom */
292	cy_addr	iobase;		/* base address of this port's cd1400 */
293	int	mcr_rts_reg;	/* cd1400 reg number of reg holding mcr_rts */
294
295	struct tty	*tp;	/* cross reference */
296
297	/* Initial state. */
298	struct termios	it_in;	/* should be in struct tty */
299	struct termios	it_out;
300
301	/* Lock state. */
302	struct termios	lt_in;	/* should be in struct tty */
303	struct termios	lt_out;
304
305	bool_t	do_timestamp;
306	bool_t	do_dcd_timestamp;
307	struct timeval	timestamp;
308	struct timeval	dcd_timestamp;
309
310	u_long	bytes_in;	/* statistics */
311	u_long	bytes_out;
312	u_int	delta_error_counts[CE_NTYPES];
313	u_long	error_counts[CE_NTYPES];
314
315	u_int	recv_exception;	/* exception chars received */
316	u_int	mdm;		/* modem signal changes */
317#ifdef CyDebug
318	u_int	start_count;	/* no. of calls to comstart() */
319	u_int	start_real;	/* no. of calls that did something */
320#endif
321	u_char	car;		/* CD1400 CAR shadow (if first unit in cd) */
322	u_char	channel_control;/* CD1400 CCR control command shadow */
323	u_char	cor[3];		/* CD1400 COR1-3 shadows */
324	u_char	intr_enable;	/* CD1400 SRER shadow */
325
326	/*
327	 * Ping-pong input buffers.  The extra factor of 2 in the sizes is
328	 * to allow for an error byte for each input byte.
329	 */
330#define	CE_INPUT_OFFSET		RS_IBUFSIZE
331	u_char	ibuf1[2 * RS_IBUFSIZE];
332	u_char	ibuf2[2 * RS_IBUFSIZE];
333
334	/*
335	 * Data area for output buffers.  Someday we should build the output
336	 * buffer queue without copying data.
337	 */
338	u_char	obuf1[256];
339	u_char	obuf2[256];
340#ifdef DEVFS
341	void	*devfs_token_ttyd;
342	void	*devfs_token_ttyl;
343	void	*devfs_token_ttyi;
344	void	*devfs_token_cuaa;
345	void	*devfs_token_cual;
346	void	*devfs_token_cuai;
347#endif
348};
349
350/* PCI driver entry point. */
351int	cyattach_common		__P((cy_addr cy_iobase, int cy_align));
352ointhand2_t	siointr;
353
354static	int	cy_units	__P((cy_addr cy_iobase, int cy_align));
355static	int	sioattach	__P((struct isa_device *dev));
356static	void	cd1400_channel_cmd __P((struct com_s *com, int cmd));
357static	void	cd1400_channel_cmd_wait __P((struct com_s *com));
358static	void	cd_etc		__P((struct com_s *com, int etc));
359static	int	cd_getreg	__P((struct com_s *com, int reg));
360static	void	cd_setreg	__P((struct com_s *com, int reg, int val));
361static	timeout_t siodtrwakeup;
362static	void	comhardclose	__P((struct com_s *com));
363#if 0
364static	void	siointr1	__P((struct com_s *com));
365#endif
366static	int	commctl		__P((struct com_s *com, int bits, int how));
367static	int	comparam	__P((struct tty *tp, struct termios *t));
368static	swihand_t siopoll;
369static	int	sioprobe	__P((struct isa_device *dev));
370static	void	siosettimeout	__P((void));
371static	int	comspeed	__P((speed_t speed, u_long cy_clock,
372				     int *prescaler_io));
373static	void	comstart	__P((struct tty *tp));
374static	timeout_t comwakeup;
375static	void	disc_optim	__P((struct tty	*tp, struct termios *t,
376				     struct com_s *com));
377
378#ifdef CyDebug
379void	cystatus	__P((int unit));
380#endif
381
382static char driver_name[] = "cy";
383
384/* table and macro for fast conversion from a unit number to its com struct */
385static	struct com_s	*p_com_addr[NSIO];
386#define	com_addr(unit)	(p_com_addr[unit])
387
388struct isa_driver	siodriver = {
389	sioprobe, sioattach, driver_name
390};
391
392static	d_open_t	sioopen;
393static	d_close_t	sioclose;
394static	d_read_t	sioread;
395static	d_write_t	siowrite;
396static	d_ioctl_t	sioioctl;
397static	d_stop_t	siostop;
398static	d_devtotty_t	siodevtotty;
399
400#define	CDEV_MAJOR	48
401static	struct cdevsw	sio_cdevsw = {
402	sioopen,	sioclose,	sioread,	siowrite,
403	sioioctl,	siostop,	noreset,	siodevtotty,
404	ttpoll,		nommap,		NULL,		driver_name,
405	NULL,		-1,		nodump,		nopsize,
406	D_TTY,
407};
408
409static	int	comconsole = -1;
410static	speed_t	comdefaultrate = TTYDEF_SPEED;
411static	u_int	com_events;	/* input chars + weighted output completions */
412static	bool_t	sio_registered;
413static	int	sio_timeout;
414static	int	sio_timeouts_until_log;
415static	struct	callout_handle sio_timeout_handle
416    = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
417#if 0 /* XXX */
418static struct tty	*sio_tty[NSIO];
419#else
420static struct tty	sio_tty[NSIO];
421#endif
422static	const int	nsio_tty = NSIO;
423
424#ifdef CyDebug
425static	u_int	cd_inbs;
426static	u_int	cy_inbs;
427static	u_int	cd_outbs;
428static	u_int	cy_outbs;
429static	u_int	cy_svrr_probes;
430static	u_int	cy_timeouts;
431#endif
432
433static	int	cy_chip_offset[] = {
434	0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00,
435};
436static	int	cy_nr_cd1400s[NCY];
437static	int	cy_total_devices;
438#undef	RxFifoThreshold
439static	int	volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
440
441static int
442sioprobe(dev)
443	struct isa_device	*dev;
444{
445	cy_addr	iobase;
446
447	iobase = (cy_addr)dev->id_maddr;
448
449	/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
450	cy_inb(iobase, CY16_RESET, 0);	/* XXX? */
451	DELAY(500);	/* wait for the board to get its act together */
452
453	/* this is needed to get the board out of reset */
454	cy_outb(iobase, CY_CLEAR_INTR, 0, 0);
455	DELAY(500);
456
457	return (cy_units(iobase, 0) == 0 ? 0 : -1);
458}
459
460static int
461cy_units(cy_iobase, cy_align)
462	cy_addr	cy_iobase;
463	int	cy_align;
464{
465	int	cyu;
466	u_char	firmware_version;
467	int	i;
468	cy_addr	iobase;
469
470	for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) {
471		iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align);
472
473		/* wait for chip to become ready for new command */
474		for (i = 0; i < 10; i++) {
475			DELAY(50);
476			if (!cd_inb(iobase, CD1400_CCR, cy_align))
477				break;
478		}
479
480		/* clear the GFRCR register */
481		cd_outb(iobase, CD1400_GFRCR, cy_align, 0);
482
483		/* issue a reset command */
484		cd_outb(iobase, CD1400_CCR, cy_align,
485			CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
486
487		/* wait for the CD1400 to initialize itself */
488		for (i = 0; i < 200; i++) {
489			DELAY(50);
490
491			/* retrieve firmware version */
492			firmware_version = cd_inb(iobase, CD1400_GFRCR,
493						  cy_align);
494			if ((firmware_version & 0xf0) == 0x40)
495				break;
496		}
497
498		/*
499		 * Anything in the 0x40-0x4F range is fine.
500		 * If one CD1400 is bad then we don't support higher
501		 * numbered good ones on this board.
502		 */
503		if ((firmware_version & 0xf0) != 0x40)
504			break;
505	}
506	return (cyu);
507}
508
509static int
510sioattach(isdp)
511	struct isa_device	*isdp;
512{
513	int	adapter;
514
515	adapter = cyattach_common((cy_addr) isdp->id_maddr, 0);
516	if (adapter < 0)
517		return (0);
518
519	/*
520	 * XXX
521	 * This kludge is to allow ISA/PCI device specifications in the
522	 * kernel config file to be in any order.
523	 */
524	if (isdp->id_unit != adapter) {
525		printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter);
526		isdp->id_unit = adapter;	/* XXX */
527	}
528	isdp->id_ointr = siointr;
529	isdp->id_ri_flags |= RI_FAST;
530	return (1);
531}
532
533int
534cyattach_common(cy_iobase, cy_align)
535	cy_addr	cy_iobase;
536	int	cy_align;
537{
538	int	adapter;
539	int	cyu;
540	dev_t	dev;
541	u_char	firmware_version;
542	cy_addr	iobase;
543	int	ncyu;
544	int	unit;
545
546	adapter = cy_total_devices;
547	if ((u_int)adapter >= NCY) {
548		printf(
549	"cy%d: can't attach adapter: insufficient cy devices configured\n",
550		       adapter);
551		return (-1);
552	}
553	ncyu = cy_units(cy_iobase, cy_align);
554	if (ncyu == 0)
555		return (-1);
556	cy_nr_cd1400s[adapter] = ncyu;
557	cy_total_devices++;
558
559	unit = adapter * CY_MAX_PORTS;
560	for (cyu = 0; cyu < ncyu; ++cyu) {
561		int	cdu;
562
563		iobase = (cy_addr) (cy_iobase
564				    + (cy_chip_offset[cyu] << cy_align));
565		firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align);
566
567		/* Set up a receive timeout period of than 1+ ms. */
568		cd_outb(iobase, CD1400_PPR, cy_align,
569			howmany(CY_CLOCK(firmware_version)
570				/ CD1400_PPR_PRESCALER, 1000));
571
572		for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
573			struct com_s	*com;
574			int		s;
575
576	com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT);
577	if (com == NULL)
578		break;
579	bzero(com, sizeof *com);
580	com->unit = unit;
581			com->gfrcr_image = firmware_version;
582			if (CY_RTS_DTR_SWAPPED(firmware_version)) {
583				com->mcr_dtr = MCR_RTS;
584				com->mcr_rts = MCR_DTR;
585				com->mcr_rts_reg = CD1400_MSVR2;
586			} else {
587				com->mcr_dtr = MCR_DTR;
588				com->mcr_rts = MCR_RTS;
589				com->mcr_rts_reg = CD1400_MSVR1;
590			}
591	com->dtr_wait = 3 * hz;
592	com->iptr = com->ibuf = com->ibuf1;
593	com->ibufend = com->ibuf1 + RS_IBUFSIZE;
594	com->ihighwater = com->ibuf1 + RS_IHIGHWATER;
595	com->obufs[0].l_head = com->obuf1;
596	com->obufs[1].l_head = com->obuf2;
597
598			com->cy_align = cy_align;
599			com->cy_iobase = cy_iobase;
600	com->iobase = iobase;
601			com->car = ~CD1400_CAR_CHAN;
602
603	/*
604	 * We don't use all the flags from <sys/ttydefaults.h> since they
605	 * are only relevant for logins.  It's important to have echo off
606	 * initially so that the line doesn't start blathering before the
607	 * echo flag can be turned off.
608	 */
609	com->it_in.c_iflag = 0;
610	com->it_in.c_oflag = 0;
611	com->it_in.c_cflag = TTYDEF_CFLAG;
612	com->it_in.c_lflag = 0;
613	if (unit == comconsole) {
614		com->it_in.c_iflag = TTYDEF_IFLAG;
615		com->it_in.c_oflag = TTYDEF_OFLAG;
616		com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
617		com->it_in.c_lflag = TTYDEF_LFLAG;
618		com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
619	}
620	termioschars(&com->it_in);
621	com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
622	com->it_out = com->it_in;
623
624	s = spltty();
625	com_addr(unit) = com;
626	splx(s);
627
628	if (!sio_registered) {
629		dev = makedev(CDEV_MAJOR, 0);
630		cdevsw_add(&dev, &sio_cdevsw, NULL);
631		register_swi(SWI_TTY, siopoll);
632		sio_registered = TRUE;
633	}
634#ifdef DEVFS
635	com->devfs_token_ttyd = devfs_add_devswf(&sio_cdevsw,
636		unit, DV_CHR,
637		UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter,
638		unit % CY_MAX_PORTS);
639	com->devfs_token_ttyi = devfs_add_devswf(&sio_cdevsw,
640		unit | CONTROL_INIT_STATE, DV_CHR,
641		UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter,
642		unit % CY_MAX_PORTS);
643	com->devfs_token_ttyl = devfs_add_devswf(&sio_cdevsw,
644		unit | CONTROL_LOCK_STATE, DV_CHR,
645		UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter,
646		unit % CY_MAX_PORTS);
647	com->devfs_token_cuaa = devfs_add_devswf(&sio_cdevsw,
648		unit | CALLOUT_MASK, DV_CHR,
649		UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter,
650		unit % CY_MAX_PORTS);
651	com->devfs_token_cuai = devfs_add_devswf(&sio_cdevsw,
652		unit | CALLOUT_MASK | CONTROL_INIT_STATE, DV_CHR,
653		UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter,
654		unit % CY_MAX_PORTS);
655	com->devfs_token_cual = devfs_add_devswf(&sio_cdevsw,
656		unit | CALLOUT_MASK | CONTROL_LOCK_STATE, DV_CHR,
657		UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter,
658		unit % CY_MAX_PORTS);
659#endif
660		}
661	}
662
663	/* ensure an edge for the next interrupt */
664	cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
665
666	return (adapter);
667}
668
669static int
670sioopen(dev, flag, mode, p)
671	dev_t		dev;
672	int		flag;
673	int		mode;
674	struct proc	*p;
675{
676	struct com_s	*com;
677	int		error;
678	int		mynor;
679	int		s;
680	struct tty	*tp;
681	int		unit;
682
683	mynor = minor(dev);
684	unit = MINOR_TO_UNIT(mynor);
685	if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
686		return (ENXIO);
687	if (mynor & CONTROL_MASK)
688		return (0);
689#if 0 /* XXX */
690	tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]);
691#else
692	tp = com->tp = &sio_tty[unit];
693#endif
694	s = spltty();
695	/*
696	 * We jump to this label after all non-interrupted sleeps to pick
697	 * up any changes of the device state.
698	 */
699open_top:
700	while (com->state & CS_DTR_OFF) {
701		error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0);
702		if (error != 0)
703			goto out;
704	}
705	if (tp->t_state & TS_ISOPEN) {
706		/*
707		 * The device is open, so everything has been initialized.
708		 * Handle conflicts.
709		 */
710		if (mynor & CALLOUT_MASK) {
711			if (!com->active_out) {
712				error = EBUSY;
713				goto out;
714			}
715		} else {
716			if (com->active_out) {
717				if (flag & O_NONBLOCK) {
718					error = EBUSY;
719					goto out;
720				}
721				error =	tsleep(&com->active_out,
722					       TTIPRI | PCATCH, "cybi", 0);
723				if (error != 0)
724					goto out;
725				goto open_top;
726			}
727		}
728		if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
729			error = EBUSY;
730			goto out;
731		}
732	} else {
733		/*
734		 * The device isn't open, so there are no conflicts.
735		 * Initialize it.  Initialization is done twice in many
736		 * cases: to preempt sleeping callin opens if we are
737		 * callout, and to complete a callin open after DCD rises.
738		 */
739		tp->t_oproc = comstart;
740		tp->t_param = comparam;
741		tp->t_dev = dev;
742		tp->t_termios = mynor & CALLOUT_MASK
743				? com->it_out : com->it_in;
744		tp->t_ififosize = 2 * RS_IBUFSIZE;
745		tp->t_ispeedwat = (speed_t)-1;
746		tp->t_ospeedwat = (speed_t)-1;
747
748		/* Encode per-board unit in LIVR for access in intr routines. */
749		cd_setreg(com, CD1400_LIVR,
750			  (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
751
752		(void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
753#if 0
754		com->poll = com->no_irq;
755		com->poll_output = com->loses_outints;
756#endif
757		++com->wopeners;
758		error = comparam(tp, &tp->t_termios);
759		--com->wopeners;
760		if (error != 0)
761			goto out;
762#if 0
763		if (com->hasfifo) {
764			/*
765			 * (Re)enable and flush fifos.
766			 *
767			 * Certain SMC chips cause problems if the fifos
768			 * are enabled while input is ready.  Turn off the
769			 * fifo if necessary to clear the input.  We test
770			 * the input ready bit after enabling the fifos
771			 * since we've already enabled them in comparam()
772			 * and to handle races between enabling and fresh
773			 * input.
774			 */
775			while (TRUE) {
776				outb(iobase + com_fifo,
777				     FIFO_RCV_RST | FIFO_XMT_RST
778				     | com->fifo_image);
779				DELAY(100);
780				if (!(inb(com->line_status_port) & LSR_RXRDY))
781					break;
782				outb(iobase + com_fifo, 0);
783				DELAY(100);
784				(void) inb(com->data_port);
785			}
786		}
787
788		disable_intr();
789		(void) inb(com->line_status_port);
790		(void) inb(com->data_port);
791		com->prev_modem_status = com->last_modem_status
792		    = inb(com->modem_status_port);
793		outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS
794				       | IER_EMSC);
795		enable_intr();
796#else /* !0 */
797		/*
798		 * Flush fifos.  This requires a full channel reset which
799		 * also disables the transmitter and receiver.  Recover
800		 * from this.
801		 */
802		cd1400_channel_cmd(com,
803				   CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET);
804		cd1400_channel_cmd(com, com->channel_control);
805
806		disable_intr();
807		com->prev_modem_status = com->last_modem_status
808		    = cd_getreg(com, CD1400_MSVR2);
809		cd_setreg(com, CD1400_SRER,
810			  com->intr_enable
811			  = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
812		enable_intr();
813#endif /* 0 */
814		/*
815		 * Handle initial DCD.  Callout devices get a fake initial
816		 * DCD (trapdoor DCD).  If we are callout, then any sleeping
817		 * callin opens get woken up and resume sleeping on "cybi"
818		 * instead of "cydcd".
819		 */
820		/*
821		 * XXX `mynor & CALLOUT_MASK' should be
822		 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
823		 * TRAPDOOR_CARRIER is the default initial state for callout
824		 * devices and SOFT_CARRIER is like CLOCAL except it hides
825		 * the true carrier.
826		 */
827		if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
828			(*linesw[tp->t_line].l_modem)(tp, 1);
829	}
830	/*
831	 * Wait for DCD if necessary.
832	 */
833	if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
834	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
835		++com->wopeners;
836		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0);
837		--com->wopeners;
838		if (error != 0)
839			goto out;
840		goto open_top;
841	}
842	error =	(*linesw[tp->t_line].l_open)(dev, tp);
843	disc_optim(tp, &tp->t_termios, com);
844	if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
845		com->active_out = TRUE;
846	siosettimeout();
847out:
848	splx(s);
849	if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
850		comhardclose(com);
851	return (error);
852}
853
854static int
855sioclose(dev, flag, mode, p)
856	dev_t		dev;
857	int		flag;
858	int		mode;
859	struct proc	*p;
860{
861	struct com_s	*com;
862	int		mynor;
863	int		s;
864	struct tty	*tp;
865
866	mynor = minor(dev);
867	if (mynor & CONTROL_MASK)
868		return (0);
869	com = com_addr(MINOR_TO_UNIT(mynor));
870	tp = com->tp;
871	s = spltty();
872	cd_etc(com, CD1400_ETC_STOPBREAK);
873	(*linesw[tp->t_line].l_close)(tp, flag);
874	disc_optim(tp, &tp->t_termios, com);
875	siostop(tp, FREAD | FWRITE);
876	comhardclose(com);
877	ttyclose(tp);
878	siosettimeout();
879	splx(s);
880#ifdef broken /* session holds a ref to the tty; can't deallocate */
881	ttyfree(tp);
882	com->tp = sio_tty[unit] = NULL;
883#endif
884	return (0);
885}
886
887static void
888comhardclose(com)
889	struct com_s	*com;
890{
891	cy_addr		iobase;
892	int		s;
893	struct tty	*tp;
894	int		unit;
895
896	unit = com->unit;
897	iobase = com->iobase;
898	s = spltty();
899#if 0
900	com->poll = FALSE;
901	com->poll_output = FALSE;
902#endif
903	com->do_timestamp = 0;
904#if 0
905	outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
906#else
907	/* XXX */
908	disable_intr();
909	com->etc = ETC_NONE;
910	cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC);
911	enable_intr();
912	cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
913#endif
914
915	{
916#if 0
917		outb(iobase + com_ier, 0);
918#else
919		disable_intr();
920		cd_setreg(com, CD1400_SRER, com->intr_enable = 0);
921		enable_intr();
922#endif
923		tp = com->tp;
924		if (tp->t_cflag & HUPCL
925		    /*
926		     * XXX we will miss any carrier drop between here and the
927		     * next open.  Perhaps we should watch DCD even when the
928		     * port is closed; it is not sufficient to check it at
929		     * the next open because it might go up and down while
930		     * we're not watching.
931		     */
932		    || !com->active_out
933		       && !(com->prev_modem_status & MSR_DCD)
934		       && !(com->it_in.c_cflag & CLOCAL)
935		    || !(tp->t_state & TS_ISOPEN)) {
936			(void)commctl(com, TIOCM_DTR, DMBIC);
937
938			/* Disable receiver (leave transmitter enabled). */
939			com->channel_control = CD1400_CCR_CMDCHANCTL
940					       | CD1400_CCR_XMTEN
941					       | CD1400_CCR_RCVDIS;
942			cd1400_channel_cmd(com, com->channel_control);
943
944			if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
945				timeout(siodtrwakeup, com, com->dtr_wait);
946				com->state |= CS_DTR_OFF;
947			}
948		}
949	}
950#if 0
951	if (com->hasfifo) {
952		/*
953		 * Disable fifos so that they are off after controlled
954		 * reboots.  Some BIOSes fail to detect 16550s when the
955		 * fifos are enabled.
956		 */
957		outb(iobase + com_fifo, 0);
958	}
959#endif
960	com->active_out = FALSE;
961	wakeup(&com->active_out);
962	wakeup(TSA_CARR_ON(tp));	/* restart any wopeners */
963	splx(s);
964}
965
966static int
967sioread(dev, uio, flag)
968	dev_t		dev;
969	struct uio	*uio;
970	int		flag;
971{
972	int		mynor;
973	struct tty	*tp;
974
975	mynor = minor(dev);
976	if (mynor & CONTROL_MASK)
977		return (ENODEV);
978	tp = com_addr(MINOR_TO_UNIT(mynor))->tp;
979	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
980}
981
982static int
983siowrite(dev, uio, flag)
984	dev_t		dev;
985	struct uio	*uio;
986	int		flag;
987{
988	int		mynor;
989	struct tty	*tp;
990	int		unit;
991
992	mynor = minor(dev);
993	if (mynor & CONTROL_MASK)
994		return (ENODEV);
995
996	unit = MINOR_TO_UNIT(mynor);
997	tp = com_addr(unit)->tp;
998	/*
999	 * (XXX) We disallow virtual consoles if the physical console is
1000	 * a serial port.  This is in case there is a display attached that
1001	 * is not the console.  In that situation we don't need/want the X
1002	 * server taking over the console.
1003	 */
1004	if (constty != NULL && unit == comconsole)
1005		constty = NULL;
1006#ifdef Smarts
1007	/* XXX duplicate ttwrite(), but without so much output processing on
1008	 * CR & LF chars.  Hardly worth the effort, given that high-throughput
1009	 * sessions are raw anyhow.
1010	 */
1011#else
1012	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
1013#endif
1014}
1015
1016static void
1017siodtrwakeup(chan)
1018	void	*chan;
1019{
1020	struct com_s	*com;
1021
1022	com = (struct com_s *)chan;
1023	com->state &= ~CS_DTR_OFF;
1024	wakeup(&com->dtr_wait);
1025}
1026
1027void
1028siointr(unit)
1029	int	unit;
1030{
1031	int	baseu;
1032	int	cy_align;
1033	cy_addr	cy_iobase;
1034	int	cyu;
1035	cy_addr	iobase;
1036	u_char	status;
1037
1038	COM_LOCK();	/* XXX could this be placed down lower in the loop? */
1039
1040	baseu = unit * CY_MAX_PORTS;
1041	cy_align = com_addr(baseu)->cy_align;
1042	cy_iobase = com_addr(baseu)->cy_iobase;
1043
1044	/* check each CD1400 in turn */
1045	for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) {
1046		iobase = (cy_addr) (cy_iobase
1047				    + (cy_chip_offset[cyu] << cy_align));
1048		/* poll to see if it has any work */
1049		status = cd_inb(iobase, CD1400_SVRR, cy_align);
1050		if (status == 0)
1051			continue;
1052#ifdef CyDebug
1053		++cy_svrr_probes;
1054#endif
1055		/* service requests as appropriate, giving priority to RX */
1056		if (status & CD1400_SVRR_RXRDY) {
1057			struct com_s	*com;
1058			u_int		count;
1059			u_char		*ioptr;
1060			u_char		line_status;
1061			u_char		recv_data;
1062			u_char		serv_type;
1063#ifdef PollMode
1064			u_char		save_rir;
1065#endif
1066
1067#ifdef PollMode
1068			save_rir = cd_inb(iobase, CD1400_RIR, cy_align);
1069
1070			/* enter rx service */
1071			cd_outb(iobase, CD1400_CAR, cy_align, save_rir);
1072			com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
1073			= save_rir & CD1400_CAR_CHAN;
1074
1075			serv_type = cd_inb(iobase, CD1400_RIVR, cy_align);
1076			com = com_addr(baseu
1077				       + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
1078					  & CD1400_xIVR_CHAN));
1079#else
1080			/* ack receive service */
1081			serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align);
1082
1083			com = com_addr(baseu +
1084				       + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
1085					  & CD1400_xIVR_CHAN));
1086#endif
1087
1088		if (serv_type & CD1400_RIVR_EXCEPTION) {
1089			++com->recv_exception;
1090			line_status = cd_inb(iobase, CD1400_RDSR, cy_align);
1091			/* break/unnattached error bits or real input? */
1092			recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
1093#ifndef SOFT_HOTCHAR
1094			if (line_status & CD1400_RDSR_SPECIAL
1095			    && com->hotchar != 0)
1096				setsofttty();
1097#endif
1098#if 1 /* XXX "intelligent" PFO error handling would break O error handling */
1099			if (line_status & (LSR_PE|LSR_FE|LSR_BI)) {
1100				/*
1101				  Don't store PE if IGNPAR and BI if IGNBRK,
1102				  this hack allows "raw" tty optimization
1103				  works even if IGN* is set.
1104				*/
1105				if (   com->tp == NULL
1106				    || !(com->tp->t_state & TS_ISOPEN)
1107				    || (line_status & (LSR_PE|LSR_FE))
1108				    &&  (com->tp->t_iflag & IGNPAR)
1109				    || (line_status & LSR_BI)
1110				    &&  (com->tp->t_iflag & IGNBRK))
1111					goto cont;
1112				if (   (line_status & (LSR_PE|LSR_FE))
1113				    && (com->tp->t_state & TS_CAN_BYPASS_L_RINT)
1114				    && ((line_status & LSR_FE)
1115				    ||  (line_status & LSR_PE)
1116				    &&  (com->tp->t_iflag & INPCK)))
1117					recv_data = 0;
1118			}
1119#endif /* 1 */
1120			++com->bytes_in;
1121#ifdef SOFT_HOTCHAR
1122			if (com->hotchar != 0 && recv_data == com->hotchar)
1123				setsofttty();
1124#endif
1125			ioptr = com->iptr;
1126			if (ioptr >= com->ibufend)
1127				CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1128			else {
1129				if (com->do_timestamp)
1130					microtime(&com->timestamp);
1131				++com_events;
1132				ioptr[0] = recv_data;
1133				ioptr[CE_INPUT_OFFSET] = line_status;
1134				com->iptr = ++ioptr;
1135				if (ioptr == com->ihighwater
1136				    && com->state & CS_RTS_IFLOW)
1137#if 0
1138					outb(com->modem_ctl_port,
1139					     com->mcr_image &= ~MCR_RTS);
1140#else
1141					cd_outb(iobase, com->mcr_rts_reg,
1142						cy_align,
1143						com->mcr_image &=
1144						~com->mcr_rts);
1145#endif
1146				if (line_status & LSR_OE)
1147					CE_RECORD(com, CE_OVERRUN);
1148			}
1149			goto cont;
1150		} else {
1151			int	ifree;
1152
1153			count = cd_inb(iobase, CD1400_RDCR, cy_align);
1154			if (!count)
1155				goto cont;
1156			com->bytes_in += count;
1157			ioptr = com->iptr;
1158			ifree = com->ibufend - ioptr;
1159			if (count > ifree) {
1160				count -= ifree;
1161				com_events += ifree;
1162				if (ifree != 0) {
1163					if (com->do_timestamp)
1164						microtime(&com->timestamp);
1165					do {
1166						recv_data = cd_inb(iobase,
1167								   CD1400_RDSR,
1168								   cy_align);
1169#ifdef SOFT_HOTCHAR
1170						if (com->hotchar != 0
1171						    && recv_data
1172						       == com->hotchar)
1173							setsofttty();
1174#endif
1175						ioptr[0] = recv_data;
1176						ioptr[CE_INPUT_OFFSET] = 0;
1177						++ioptr;
1178					} while (--ifree != 0);
1179				}
1180				com->delta_error_counts
1181				    [CE_INTERRUPT_BUF_OVERFLOW] += count;
1182				do {
1183					recv_data = cd_inb(iobase, CD1400_RDSR,
1184							   cy_align);
1185#ifdef SOFT_HOTCHAR
1186					if (com->hotchar != 0
1187					    && recv_data == com->hotchar)
1188						setsofttty();
1189#endif
1190				} while (--count != 0);
1191			} else {
1192				if (com->do_timestamp)
1193					microtime(&com->timestamp);
1194				if (ioptr <= com->ihighwater
1195				    && ioptr + count > com->ihighwater
1196				    && com->state & CS_RTS_IFLOW)
1197#if 0
1198					outb(com->modem_ctl_port,
1199					     com->mcr_image &= ~MCR_RTS);
1200#else
1201					cd_outb(iobase, com->mcr_rts_reg,
1202						cy_align,
1203						com->mcr_image
1204						&= ~com->mcr_rts);
1205#endif
1206				com_events += count;
1207				do {
1208					recv_data = cd_inb(iobase, CD1400_RDSR,
1209							   cy_align);
1210#ifdef SOFT_HOTCHAR
1211					if (com->hotchar != 0
1212					    && recv_data == com->hotchar)
1213						setsofttty();
1214#endif
1215					ioptr[0] = recv_data;
1216					ioptr[CE_INPUT_OFFSET] = 0;
1217					++ioptr;
1218				} while (--count != 0);
1219			}
1220			com->iptr = ioptr;
1221		}
1222cont:
1223
1224			/* terminate service context */
1225#ifdef PollMode
1226			cd_outb(iobase, CD1400_RIR, cy_align,
1227				save_rir
1228				& ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
1229#else
1230			cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
1231#endif
1232		}
1233		if (status & CD1400_SVRR_MDMCH) {
1234			struct com_s	*com;
1235			u_char	modem_status;
1236#ifdef PollMode
1237			u_char	save_mir;
1238#else
1239			u_char	vector;
1240#endif
1241
1242#ifdef PollMode
1243			save_mir = cd_inb(iobase, CD1400_MIR, cy_align);
1244
1245			/* enter modem service */
1246			cd_outb(iobase, CD1400_CAR, cy_align, save_mir);
1247			com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
1248			= save_mir & CD1400_CAR_CHAN;
1249
1250			com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
1251				       + (save_mir & CD1400_MIR_CHAN));
1252#else
1253			/* ack modem service */
1254			vector = cy_inb(iobase, CY8_SVCACKM, cy_align);
1255
1256			com = com_addr(baseu
1257				       + ((vector >> CD1400_xIVR_CHAN_SHIFT)
1258					  & CD1400_xIVR_CHAN));
1259#endif
1260			++com->mdm;
1261			modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align);
1262		if (modem_status != com->last_modem_status) {
1263			if (com->do_dcd_timestamp
1264			    && !(com->last_modem_status & MSR_DCD)
1265			    && modem_status & MSR_DCD)
1266				microtime(&com->dcd_timestamp);
1267
1268			/*
1269			 * Schedule high level to handle DCD changes.  Note
1270			 * that we don't use the delta bits anywhere.  Some
1271			 * UARTs mess them up, and it's easy to remember the
1272			 * previous bits and calculate the delta.
1273			 */
1274			com->last_modem_status = modem_status;
1275			if (!(com->state & CS_CHECKMSR)) {
1276				com_events += LOTS_OF_EVENTS;
1277				com->state |= CS_CHECKMSR;
1278				setsofttty();
1279			}
1280
1281#ifdef SOFT_CTS_OFLOW
1282			/* handle CTS change immediately for crisp flow ctl */
1283			if (com->state & CS_CTS_OFLOW) {
1284				if (modem_status & MSR_CTS) {
1285					com->state |= CS_ODEVREADY;
1286					if (com->state >= (CS_BUSY | CS_TTGO
1287							   | CS_ODEVREADY)
1288					    && !(com->intr_enable
1289						 & CD1400_SRER_TXRDY))
1290						cd_outb(iobase, CD1400_SRER,
1291							cy_align,
1292							com->intr_enable
1293							= com->intr_enable
1294							  & ~CD1400_SRER_TXMPTY
1295							  | CD1400_SRER_TXRDY);
1296				} else {
1297					com->state &= ~CS_ODEVREADY;
1298					if (com->intr_enable
1299					    & CD1400_SRER_TXRDY)
1300						cd_outb(iobase, CD1400_SRER,
1301							cy_align,
1302							com->intr_enable
1303							= com->intr_enable
1304							  & ~CD1400_SRER_TXRDY
1305							  | CD1400_SRER_TXMPTY);
1306				}
1307			}
1308#endif
1309		}
1310
1311			/* terminate service context */
1312#ifdef PollMode
1313			cd_outb(iobase, CD1400_MIR, cy_align,
1314				save_mir
1315				& ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
1316#else
1317			cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
1318#endif
1319		}
1320		if (status & CD1400_SVRR_TXRDY) {
1321			struct com_s	*com;
1322#ifdef PollMode
1323			u_char	save_tir;
1324#else
1325			u_char	vector;
1326#endif
1327
1328#ifdef PollMode
1329			save_tir = cd_inb(iobase, CD1400_TIR, cy_align);
1330
1331			/* enter tx service */
1332			cd_outb(iobase, CD1400_CAR, cy_align, save_tir);
1333			com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
1334			= save_tir & CD1400_CAR_CHAN;
1335
1336			com = com_addr(baseu
1337				       + cyu * CD1400_NO_OF_CHANNELS
1338				       + (save_tir & CD1400_TIR_CHAN));
1339#else
1340			/* ack transmit service */
1341			vector = cy_inb(iobase, CY8_SVCACKT, cy_align);
1342
1343			com = com_addr(baseu
1344				       + ((vector >> CD1400_xIVR_CHAN_SHIFT)
1345					  & CD1400_xIVR_CHAN));
1346#endif
1347
1348			if (com->etc != ETC_NONE) {
1349				if (com->intr_enable & CD1400_SRER_TXRDY) {
1350					/*
1351					 * Here due to sloppy SRER_TXRDY
1352					 * enabling.  Ignore.  Come back when
1353					 * tx is empty.
1354					 */
1355					cd_outb(iobase, CD1400_SRER, cy_align,
1356						com->intr_enable
1357						= com->intr_enable
1358						  & ~CD1400_SRER_TXRDY
1359						  | CD1400_SRER_TXMPTY);
1360					goto terminate_tx_service;
1361				}
1362				switch (com->etc) {
1363				case CD1400_ETC_SENDBREAK:
1364				case CD1400_ETC_STOPBREAK:
1365					/*
1366					 * Start the command.  Come back on
1367					 * next tx empty interrupt, hopefully
1368					 * after command has been executed.
1369					 */
1370					cd_outb(iobase, CD1400_COR2, cy_align,
1371						com->cor[1] |= CD1400_COR2_ETC);
1372					cd_outb(iobase, CD1400_TDR, cy_align,
1373						CD1400_ETC_CMD);
1374					cd_outb(iobase, CD1400_TDR, cy_align,
1375						com->etc);
1376					if (com->etc == CD1400_ETC_SENDBREAK)
1377						com->etc = ETC_BREAK_STARTING;
1378					else
1379						com->etc = ETC_BREAK_ENDING;
1380					goto terminate_tx_service;
1381				case ETC_BREAK_STARTING:
1382					/*
1383					 * BREAK is now on.  Continue with
1384					 * SRER_TXMPTY processing, hopefully
1385					 * don't come back.
1386					 */
1387					com->etc = ETC_BREAK_STARTED;
1388					break;
1389				case ETC_BREAK_STARTED:
1390					/*
1391					 * Came back due to sloppy SRER_TXMPTY
1392					 * enabling.  Hope again.
1393					 */
1394					break;
1395				case ETC_BREAK_ENDING:
1396					/*
1397					 * BREAK is now off.  Continue with
1398					 * SRER_TXMPTY processing and don't
1399					 * come back.  The SWI handler will
1400					 * restart tx interrupts if necessary.
1401					 */
1402					cd_outb(iobase, CD1400_COR2, cy_align,
1403						com->cor[1]
1404						&= ~CD1400_COR2_ETC);
1405					com->etc = ETC_BREAK_ENDED;
1406					if (!(com->state & CS_ODONE)) {
1407						com_events += LOTS_OF_EVENTS;
1408						com->state |= CS_ODONE;
1409						setsofttty();
1410					}
1411					break;
1412				case ETC_BREAK_ENDED:
1413					/*
1414					 * Shouldn't get here.  Hope again.
1415					 */
1416					break;
1417				}
1418			}
1419			if (com->intr_enable & CD1400_SRER_TXMPTY) {
1420				if (!(com->extra_state & CSE_ODONE)) {
1421					com_events += LOTS_OF_EVENTS;
1422					com->extra_state |= CSE_ODONE;
1423					setsofttty();
1424				}
1425				cd_outb(iobase, CD1400_SRER, cy_align,
1426					com->intr_enable
1427					&= ~CD1400_SRER_TXMPTY);
1428				goto terminate_tx_service;
1429			}
1430		if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1431			u_char	*ioptr;
1432			u_int	ocount;
1433
1434			ioptr = com->obufq.l_head;
1435				ocount = com->obufq.l_tail - ioptr;
1436				if (ocount > CD1400_TX_FIFO_SIZE)
1437					ocount = CD1400_TX_FIFO_SIZE;
1438				com->bytes_out += ocount;
1439				do
1440					cd_outb(iobase, CD1400_TDR, cy_align,
1441						*ioptr++);
1442				while (--ocount != 0);
1443			com->obufq.l_head = ioptr;
1444			if (ioptr >= com->obufq.l_tail) {
1445				struct lbq	*qp;
1446
1447				qp = com->obufq.l_next;
1448				qp->l_queued = FALSE;
1449				qp = qp->l_next;
1450				if (qp != NULL) {
1451					com->obufq.l_head = qp->l_head;
1452					com->obufq.l_tail = qp->l_tail;
1453					com->obufq.l_next = qp;
1454				} else {
1455					/* output just completed */
1456					com->state &= ~CS_BUSY;
1457
1458					/*
1459					 * The setting of CSE_ODONE may be
1460					 * stale here.  We currently only
1461					 * use it when CS_BUSY is set, and
1462					 * fixing it when we clear CS_BUSY
1463					 * is easiest.
1464					 */
1465					if (com->extra_state & CSE_ODONE) {
1466						com_events -= LOTS_OF_EVENTS;
1467						com->extra_state &= ~CSE_ODONE;
1468					}
1469
1470					cd_outb(iobase, CD1400_SRER, cy_align,
1471						com->intr_enable
1472						= com->intr_enable
1473						  & ~CD1400_SRER_TXRDY
1474						  | CD1400_SRER_TXMPTY);
1475				}
1476				if (!(com->state & CS_ODONE)) {
1477					com_events += LOTS_OF_EVENTS;
1478					com->state |= CS_ODONE;
1479
1480					/* handle at high level ASAP */
1481					setsofttty();
1482				}
1483			}
1484		}
1485
1486			/* terminate service context */
1487terminate_tx_service:
1488#ifdef PollMode
1489			cd_outb(iobase, CD1400_TIR, cy_align,
1490				save_tir
1491				& ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
1492#else
1493			cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
1494#endif
1495		}
1496	}
1497
1498	/* ensure an edge for the next interrupt */
1499	cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
1500
1501	schedsofttty();
1502
1503	COM_UNLOCK();
1504}
1505
1506#if 0
1507static void
1508siointr1(com)
1509	struct com_s	*com;
1510{
1511}
1512#endif
1513
1514static int
1515sioioctl(dev, cmd, data, flag, p)
1516	dev_t		dev;
1517	u_long		cmd;
1518	caddr_t		data;
1519	int		flag;
1520	struct proc	*p;
1521{
1522	struct com_s	*com;
1523	int		error;
1524	int		mynor;
1525	int		s;
1526	struct tty	*tp;
1527#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1528	int		oldcmd;
1529	struct termios	term;
1530#endif
1531
1532	mynor = minor(dev);
1533	com = com_addr(MINOR_TO_UNIT(mynor));
1534	if (mynor & CONTROL_MASK) {
1535		struct termios	*ct;
1536
1537		switch (mynor & CONTROL_MASK) {
1538		case CONTROL_INIT_STATE:
1539			ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
1540			break;
1541		case CONTROL_LOCK_STATE:
1542			ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
1543			break;
1544		default:
1545			return (ENODEV);	/* /dev/nodev */
1546		}
1547		switch (cmd) {
1548		case TIOCSETA:
1549			error = suser(p->p_ucred, &p->p_acflag);
1550			if (error != 0)
1551				return (error);
1552			*ct = *(struct termios *)data;
1553			return (0);
1554		case TIOCGETA:
1555			*(struct termios *)data = *ct;
1556			return (0);
1557		case TIOCGETD:
1558			*(int *)data = TTYDISC;
1559			return (0);
1560		case TIOCGWINSZ:
1561			bzero(data, sizeof(struct winsize));
1562			return (0);
1563		default:
1564			return (ENOTTY);
1565		}
1566	}
1567	tp = com->tp;
1568#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1569	term = tp->t_termios;
1570	oldcmd = cmd;
1571	error = ttsetcompat(tp, &cmd, data, &term);
1572	if (error != 0)
1573		return (error);
1574	if (cmd != oldcmd)
1575		data = (caddr_t)&term;
1576#endif
1577	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
1578		int	cc;
1579		struct termios *dt = (struct termios *)data;
1580		struct termios *lt = mynor & CALLOUT_MASK
1581				     ? &com->lt_out : &com->lt_in;
1582
1583		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1584			      | (dt->c_iflag & ~lt->c_iflag);
1585		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1586			      | (dt->c_oflag & ~lt->c_oflag);
1587		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1588			      | (dt->c_cflag & ~lt->c_cflag);
1589		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1590			      | (dt->c_lflag & ~lt->c_lflag);
1591		for (cc = 0; cc < NCCS; ++cc)
1592			if (lt->c_cc[cc] != 0)
1593				dt->c_cc[cc] = tp->t_cc[cc];
1594		if (lt->c_ispeed != 0)
1595			dt->c_ispeed = tp->t_ispeed;
1596		if (lt->c_ospeed != 0)
1597			dt->c_ospeed = tp->t_ospeed;
1598	}
1599	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1600	if (error != ENOIOCTL)
1601		return (error);
1602	s = spltty();
1603	error = ttioctl(tp, cmd, data, flag);
1604	disc_optim(tp, &tp->t_termios, com);
1605	if (error != ENOIOCTL) {
1606		splx(s);
1607		return (error);
1608	}
1609	switch (cmd) {
1610	case TIOCSBRK:
1611#if 0
1612		outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
1613#else
1614		cd_etc(com, CD1400_ETC_SENDBREAK);
1615#endif
1616		break;
1617	case TIOCCBRK:
1618#if 0
1619		outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1620#else
1621		cd_etc(com, CD1400_ETC_STOPBREAK);
1622#endif
1623		break;
1624	case TIOCSDTR:
1625		(void)commctl(com, TIOCM_DTR, DMBIS);
1626		break;
1627	case TIOCCDTR:
1628		(void)commctl(com, TIOCM_DTR, DMBIC);
1629		break;
1630	/*
1631	 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
1632	 * changes get undone on the next call to comparam().
1633	 */
1634	case TIOCMSET:
1635		(void)commctl(com, *(int *)data, DMSET);
1636		break;
1637	case TIOCMBIS:
1638		(void)commctl(com, *(int *)data, DMBIS);
1639		break;
1640	case TIOCMBIC:
1641		(void)commctl(com, *(int *)data, DMBIC);
1642		break;
1643	case TIOCMGET:
1644		*(int *)data = commctl(com, 0, DMGET);
1645		break;
1646	case TIOCMSDTRWAIT:
1647		/* must be root since the wait applies to following logins */
1648		error = suser(p->p_ucred, &p->p_acflag);
1649		if (error != 0) {
1650			splx(s);
1651			return (error);
1652		}
1653		com->dtr_wait = *(int *)data * hz / 100;
1654		break;
1655	case TIOCMGDTRWAIT:
1656		*(int *)data = com->dtr_wait * 100 / hz;
1657		break;
1658	case TIOCTIMESTAMP:
1659		com->do_timestamp = TRUE;
1660		*(struct timeval *)data = com->timestamp;
1661		break;
1662	case TIOCDCDTIMESTAMP:
1663		com->do_dcd_timestamp = TRUE;
1664		*(struct timeval *)data = com->dcd_timestamp;
1665		break;
1666	default:
1667		splx(s);
1668		return (ENOTTY);
1669	}
1670	splx(s);
1671	return (0);
1672}
1673
1674static void
1675siopoll()
1676{
1677	int		unit;
1678
1679#ifdef CyDebug
1680	++cy_timeouts;
1681#endif
1682	if (com_events == 0)
1683		return;
1684repeat:
1685	for (unit = 0; unit < NSIO; ++unit) {
1686		u_char		*buf;
1687		struct com_s	*com;
1688		u_char		*ibuf;
1689		int		incc;
1690		struct tty	*tp;
1691
1692		com = com_addr(unit);
1693		if (com == NULL)
1694			continue;
1695		tp = com->tp;
1696		if (tp == NULL) {
1697			/*
1698			 * XXX forget any events related to closed devices
1699			 * (actually never opened devices) so that we don't
1700			 * loop.
1701			 */
1702			disable_intr();
1703			incc = com->iptr - com->ibuf;
1704			com->iptr = com->ibuf;
1705			if (com->state & CS_CHECKMSR) {
1706				incc += LOTS_OF_EVENTS;
1707				com->state &= ~CS_CHECKMSR;
1708			}
1709			com_events -= incc;
1710			enable_intr();
1711			if (incc != 0)
1712				log(LOG_DEBUG,
1713				    "sio%d: %d events for device with no tp\n",
1714				    unit, incc);
1715			continue;
1716		}
1717
1718		/* switch the role of the low-level input buffers */
1719		if (com->iptr == (ibuf = com->ibuf)) {
1720			buf = NULL;     /* not used, but compiler can't tell */
1721			incc = 0;
1722		} else {
1723			buf = ibuf;
1724			disable_intr();
1725			incc = com->iptr - buf;
1726			com_events -= incc;
1727			if (ibuf == com->ibuf1)
1728				ibuf = com->ibuf2;
1729			else
1730				ibuf = com->ibuf1;
1731			com->ibufend = ibuf + RS_IBUFSIZE;
1732			com->ihighwater = ibuf + RS_IHIGHWATER;
1733			com->iptr = ibuf;
1734
1735			/*
1736			 * There is now room for another low-level buffer full
1737			 * of input, so enable RTS if it is now disabled and
1738			 * there is room in the high-level buffer.
1739			 */
1740			if ((com->state & CS_RTS_IFLOW)
1741			    && !(com->mcr_image & com->mcr_rts)
1742			    && !(tp->t_state & TS_TBLOCK))
1743#if 0
1744				outb(com->modem_ctl_port,
1745				     com->mcr_image |= MCR_RTS);
1746#else
1747				cd_setreg(com, com->mcr_rts_reg,
1748					  com->mcr_image |= com->mcr_rts);
1749#endif
1750			enable_intr();
1751			com->ibuf = ibuf;
1752		}
1753
1754		if (com->state & CS_CHECKMSR) {
1755			u_char	delta_modem_status;
1756
1757			disable_intr();
1758			delta_modem_status = com->last_modem_status
1759					     ^ com->prev_modem_status;
1760			com->prev_modem_status = com->last_modem_status;
1761			com_events -= LOTS_OF_EVENTS;
1762			com->state &= ~CS_CHECKMSR;
1763			enable_intr();
1764			if (delta_modem_status & MSR_DCD)
1765				(*linesw[tp->t_line].l_modem)
1766					(tp, com->prev_modem_status & MSR_DCD);
1767		}
1768		if (com->extra_state & CSE_ODONE) {
1769			disable_intr();
1770			com_events -= LOTS_OF_EVENTS;
1771			com->extra_state &= ~CSE_ODONE;
1772			enable_intr();
1773			if (!(com->state & CS_BUSY)) {
1774				tp->t_state &= ~TS_BUSY;
1775				ttwwakeup(com->tp);
1776			}
1777			if (com->etc != ETC_NONE) {
1778				if (com->etc == ETC_BREAK_ENDED)
1779					com->etc = ETC_NONE;
1780				wakeup(&com->etc);
1781			}
1782		}
1783		if (com->state & CS_ODONE) {
1784			disable_intr();
1785			com_events -= LOTS_OF_EVENTS;
1786			com->state &= ~CS_ODONE;
1787			enable_intr();
1788			(*linesw[tp->t_line].l_start)(tp);
1789		}
1790		if (incc <= 0 || !(tp->t_state & TS_ISOPEN))
1791			continue;
1792		/*
1793		 * Avoid the grotesquely inefficient lineswitch routine
1794		 * (ttyinput) in "raw" mode.  It usually takes about 450
1795		 * instructions (that's without canonical processing or echo!).
1796		 * slinput is reasonably fast (usually 40 instructions plus
1797		 * call overhead).
1798		 */
1799		if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1800			if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1801			    && (com->state & CS_RTS_IFLOW
1802				|| tp->t_iflag & IXOFF)
1803			    && !(tp->t_state & TS_TBLOCK))
1804				ttyblock(tp);
1805			tk_nin += incc;
1806			tk_rawcc += incc;
1807			tp->t_rawcc += incc;
1808			com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1809				+= b_to_q((char *)buf, incc, &tp->t_rawq);
1810			ttwakeup(tp);
1811			if (tp->t_state & TS_TTSTOP
1812			    && (tp->t_iflag & IXANY
1813				|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1814				tp->t_state &= ~TS_TTSTOP;
1815				tp->t_lflag &= ~FLUSHO;
1816				comstart(tp);
1817			}
1818		} else {
1819			do {
1820				u_char	line_status;
1821				int	recv_data;
1822
1823				line_status = (u_char) buf[CE_INPUT_OFFSET];
1824				recv_data = (u_char) *buf++;
1825				if (line_status
1826				    & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1827					if (line_status & LSR_BI)
1828						recv_data |= TTY_BI;
1829					if (line_status & LSR_FE)
1830						recv_data |= TTY_FE;
1831					if (line_status & LSR_OE)
1832						recv_data |= TTY_OE;
1833					if (line_status & LSR_PE)
1834						recv_data |= TTY_PE;
1835				}
1836				(*linesw[tp->t_line].l_rint)(recv_data, tp);
1837			} while (--incc > 0);
1838		}
1839		if (com_events == 0)
1840			break;
1841	}
1842	if (com_events >= LOTS_OF_EVENTS)
1843		goto repeat;
1844}
1845
1846static int
1847comparam(tp, t)
1848	struct tty	*tp;
1849	struct termios	*t;
1850{
1851	int		bits;
1852	int		cflag;
1853	struct com_s	*com;
1854	u_char		cor_change;
1855	u_long		cy_clock;
1856	int		idivisor;
1857	int		iflag;
1858	int		iprescaler;
1859	int		itimeout;
1860	int		odivisor;
1861	int		oprescaler;
1862	u_char		opt;
1863	int		s;
1864	int		unit;
1865
1866	/* do historical conversions */
1867	if (t->c_ispeed == 0)
1868		t->c_ispeed = t->c_ospeed;
1869
1870	unit = DEV_TO_UNIT(tp->t_dev);
1871	com = com_addr(unit);
1872
1873	/* check requested parameters */
1874	cy_clock = CY_CLOCK(com->gfrcr_image);
1875	idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler);
1876	if (idivisor < 0)
1877		return (EINVAL);
1878	odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler);
1879	if (odivisor < 0)
1880		return (EINVAL);
1881
1882	/* parameters are OK, convert them to the com struct and the device */
1883	s = spltty();
1884	if (odivisor == 0)
1885		(void)commctl(com, TIOCM_DTR, DMBIC);	/* hang up line */
1886	else
1887		(void)commctl(com, TIOCM_DTR, DMBIS);
1888
1889	if (idivisor != 0) {
1890		cd_setreg(com, CD1400_RBPR, idivisor);
1891		cd_setreg(com, CD1400_RCOR, iprescaler);
1892	}
1893	if (odivisor != 0) {
1894		cd_setreg(com, CD1400_TBPR, odivisor);
1895		cd_setreg(com, CD1400_TCOR, oprescaler);
1896	}
1897
1898	/*
1899	 * channel control
1900	 *	receiver enable
1901	 *	transmitter enable (always set)
1902	 */
1903	cflag = t->c_cflag;
1904	opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
1905	      | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
1906	if (opt != com->channel_control) {
1907		com->channel_control = opt;
1908		cd1400_channel_cmd(com, opt);
1909	}
1910
1911#ifdef Smarts
1912	/* set special chars */
1913	/* XXX if one is _POSIX_VDISABLE, can't use some others */
1914	if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
1915		cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]);
1916	if (t->c_cc[VSTART] != _POSIX_VDISABLE)
1917		cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]);
1918	if (t->c_cc[VINTR] != _POSIX_VDISABLE)
1919		cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]);
1920	if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
1921		cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]);
1922#endif
1923
1924	/*
1925	 * set channel option register 1 -
1926	 *	parity mode
1927	 *	stop bits
1928	 *	char length
1929	 */
1930	opt = 0;
1931	/* parity */
1932	if (cflag & PARENB) {
1933		if (cflag & PARODD)
1934			opt |= CD1400_COR1_PARODD;
1935		opt |= CD1400_COR1_PARNORMAL;
1936	}
1937	iflag = t->c_iflag;
1938	if (!(iflag & INPCK))
1939		opt |= CD1400_COR1_NOINPCK;
1940	bits = 1 + 1;
1941	/* stop bits */
1942	if (cflag & CSTOPB) {
1943		++bits;
1944		opt |= CD1400_COR1_STOP2;
1945	}
1946	/* char length */
1947	switch (cflag & CSIZE) {
1948	case CS5:
1949		bits += 5;
1950		opt |= CD1400_COR1_CS5;
1951		break;
1952	case CS6:
1953		bits += 6;
1954		opt |= CD1400_COR1_CS6;
1955		break;
1956	case CS7:
1957		bits += 7;
1958		opt |= CD1400_COR1_CS7;
1959		break;
1960	default:
1961		bits += 8;
1962		opt |= CD1400_COR1_CS8;
1963		break;
1964	}
1965	cor_change = 0;
1966	if (opt != com->cor[0]) {
1967		cor_change |= CD1400_CCR_COR1;
1968		cd_setreg(com, CD1400_COR1, com->cor[0] = opt);
1969	}
1970
1971	/*
1972	 * Set receive time-out period, normally to max(one char time, 5 ms).
1973	 */
1974	if (t->c_ispeed == 0)
1975		itimeout = cd_getreg(com, CD1400_RTPR);
1976	else {
1977		itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
1978#ifdef SOFT_HOTCHAR
1979#define	MIN_RTP		1
1980#else
1981#define	MIN_RTP		5
1982#endif
1983		if (itimeout < MIN_RTP)
1984			itimeout = MIN_RTP;
1985	}
1986	if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0
1987	    && t->c_cc[VTIME] * 10 > itimeout)
1988		itimeout = t->c_cc[VTIME] * 10;
1989	if (itimeout > 255)
1990		itimeout = 255;
1991	cd_setreg(com, CD1400_RTPR, itimeout);
1992
1993	/*
1994	 * set channel option register 2 -
1995	 *	flow control
1996	 */
1997	opt = 0;
1998#ifdef Smarts
1999	if (iflag & IXANY)
2000		opt |= CD1400_COR2_IXANY;
2001	if (iflag & IXOFF)
2002		opt |= CD1400_COR2_IXOFF;
2003#endif
2004#ifndef SOFT_CTS_OFLOW
2005	if (cflag & CCTS_OFLOW)
2006		opt |= CD1400_COR2_CCTS_OFLOW;
2007#endif
2008	disable_intr();
2009	if (opt != com->cor[1]) {
2010		cor_change |= CD1400_CCR_COR2;
2011		cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
2012	}
2013	enable_intr();
2014
2015	/*
2016	 * set channel option register 3 -
2017	 *	receiver FIFO interrupt threshold
2018	 *	flow control
2019	 */
2020	opt = RxFifoThreshold;
2021#ifdef Smarts
2022	if (t->c_lflag & ICANON)
2023		opt |= CD1400_COR3_SCD34;	/* detect INTR & SUSP chars */
2024	if (iflag & IXOFF)
2025		/* detect and transparently handle START and STOP chars */
2026		opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12;
2027#endif
2028	if (opt != com->cor[2]) {
2029		cor_change |= CD1400_CCR_COR3;
2030		cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
2031	}
2032
2033	/* notify the CD1400 if COR1-3 have changed */
2034	if (cor_change)
2035		cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change);
2036
2037	/*
2038	 * set channel option register 4 -
2039	 *	CR/NL processing
2040	 *	break processing
2041	 *	received exception processing
2042	 */
2043	opt = 0;
2044	if (iflag & IGNCR)
2045		opt |= CD1400_COR4_IGNCR;
2046#ifdef Smarts
2047	/*
2048	 * we need a new ttyinput() for this, as we don't want to
2049	 * have ICRNL && INLCR being done in both layers, or to have
2050	 * synchronisation problems
2051	 */
2052	if (iflag & ICRNL)
2053		opt |= CD1400_COR4_ICRNL;
2054	if (iflag & INLCR)
2055		opt |= CD1400_COR4_INLCR;
2056#endif
2057	if (iflag & IGNBRK)
2058		opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT;
2059	/*
2060	 * The `-ignbrk -brkint parmrk' case is not handled by the hardware,
2061	 * so only tell the hardware about -brkint if -parmrk.
2062	 */
2063	if (!(iflag & (BRKINT | PARMRK)))
2064		opt |= CD1400_COR4_NOBRKINT;
2065#if 0
2066	/* XXX using this "intelligence" breaks reporting of overruns. */
2067	if (iflag & IGNPAR)
2068		opt |= CD1400_COR4_PFO_DISCARD;
2069	else {
2070		if (iflag & PARMRK)
2071			opt |= CD1400_COR4_PFO_ESC;
2072		else
2073			opt |= CD1400_COR4_PFO_NUL;
2074	}
2075#else
2076	opt |= CD1400_COR4_PFO_EXCEPTION;
2077#endif
2078	cd_setreg(com, CD1400_COR4, opt);
2079
2080	/*
2081	 * set channel option register 5 -
2082	 */
2083	opt = 0;
2084	if (iflag & ISTRIP)
2085		opt |= CD1400_COR5_ISTRIP;
2086	if (t->c_iflag & IEXTEN)
2087		/* enable LNEXT (e.g. ctrl-v quoting) handling */
2088		opt |= CD1400_COR5_LNEXT;
2089#ifdef Smarts
2090	if (t->c_oflag & ONLCR)
2091		opt |= CD1400_COR5_ONLCR;
2092	if (t->c_oflag & OCRNL)
2093		opt |= CD1400_COR5_OCRNL;
2094#endif
2095	cd_setreg(com, CD1400_COR5, opt);
2096
2097	/*
2098	 * We always generate modem status change interrupts for CD changes.
2099	 * Among other things, this is necessary to track TS_CARR_ON for
2100	 * pstat to print even when the driver doesn't care.  CD changes
2101	 * should be rare so interrupts for them are not worth extra code to
2102	 * avoid.  We avoid interrupts for other modem status changes (except
2103	 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is
2104	 * simplest and best.
2105	 */
2106
2107	/*
2108	 * set modem change option register 1
2109	 *	generate modem interrupts on which 1 -> 0 input transitions
2110	 *	also controls auto-DTR output flow-control, which we don't use
2111	 */
2112	opt = CD1400_MCOR1_CDzd;
2113#ifdef SOFT_CTS_OFLOW
2114	if (cflag & CCTS_OFLOW)
2115		opt |= CD1400_MCOR1_CTSzd;
2116#endif
2117	cd_setreg(com, CD1400_MCOR1, opt);
2118
2119	/*
2120	 * set modem change option register 2
2121	 *	generate modem interrupts on specific 0 -> 1 input transitions
2122	 */
2123	opt = CD1400_MCOR2_CDod;
2124#ifdef SOFT_CTS_OFLOW
2125	if (cflag & CCTS_OFLOW)
2126		opt |= CD1400_MCOR2_CTSod;
2127#endif
2128	cd_setreg(com, CD1400_MCOR2, opt);
2129
2130	/*
2131	 * XXX should have done this long ago, but there is too much state
2132	 * to change all atomically.
2133	 */
2134	disable_intr();
2135
2136	com->state &= ~CS_TTGO;
2137	if (!(tp->t_state & TS_TTSTOP))
2138		com->state |= CS_TTGO;
2139	if (cflag & CRTS_IFLOW) {
2140		com->state |= CS_RTS_IFLOW;
2141		/*
2142		 * If CS_RTS_IFLOW just changed from off to on, the change
2143		 * needs to be propagated to MCR_RTS.  This isn't urgent,
2144		 * so do it later by calling comstart() instead of repeating
2145		 * a lot of code from comstart() here.
2146		 */
2147	} else if (com->state & CS_RTS_IFLOW) {
2148		com->state &= ~CS_RTS_IFLOW;
2149		/*
2150		 * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
2151		 * on here, since comstart() won't do it later.
2152		 */
2153#if 0
2154		outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2155#else
2156		cd_setreg(com, com->mcr_rts_reg,
2157			  com->mcr_image |= com->mcr_rts);
2158#endif
2159	}
2160
2161	/*
2162	 * Set up state to handle output flow control.
2163	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2164	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2165	 */
2166	com->state |= CS_ODEVREADY;
2167#ifdef SOFT_CTS_OFLOW
2168	com->state &= ~CS_CTS_OFLOW;
2169	if (cflag & CCTS_OFLOW) {
2170		com->state |= CS_CTS_OFLOW;
2171		if (!(com->last_modem_status & MSR_CTS))
2172			com->state &= ~CS_ODEVREADY;
2173	}
2174#endif
2175	/* XXX shouldn't call functions while intrs are disabled. */
2176	disc_optim(tp, t, com);
2177#if 0
2178	/*
2179	 * Recover from fiddling with CS_TTGO.  We used to call siointr1()
2180	 * unconditionally, but that defeated the careful discarding of
2181	 * stale input in sioopen().
2182	 */
2183	if (com->state >= (CS_BUSY | CS_TTGO))
2184		siointr1(com);
2185#endif
2186	if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2187		if (!(com->intr_enable & CD1400_SRER_TXRDY))
2188			cd_setreg(com, CD1400_SRER,
2189				  com->intr_enable
2190				  = com->intr_enable & ~CD1400_SRER_TXMPTY
2191				    | CD1400_SRER_TXRDY);
2192	} else {
2193		if (com->intr_enable & CD1400_SRER_TXRDY)
2194			cd_setreg(com, CD1400_SRER,
2195				  com->intr_enable
2196				  = com->intr_enable & ~CD1400_SRER_TXRDY
2197				    | CD1400_SRER_TXMPTY);
2198	}
2199
2200	enable_intr();
2201	splx(s);
2202	comstart(tp);
2203	return (0);
2204}
2205
2206static void
2207comstart(tp)
2208	struct tty	*tp;
2209{
2210	struct com_s	*com;
2211	int		s;
2212#ifdef CyDebug
2213	bool_t		started;
2214#endif
2215	int		unit;
2216
2217	unit = DEV_TO_UNIT(tp->t_dev);
2218	com = com_addr(unit);
2219	s = spltty();
2220
2221#ifdef CyDebug
2222	++com->start_count;
2223	started = FALSE;
2224#endif
2225
2226	disable_intr();
2227	if (tp->t_state & TS_TTSTOP) {
2228		com->state &= ~CS_TTGO;
2229		if (com->intr_enable & CD1400_SRER_TXRDY)
2230			cd_setreg(com, CD1400_SRER,
2231				  com->intr_enable
2232				  = com->intr_enable & ~CD1400_SRER_TXRDY
2233				    | CD1400_SRER_TXMPTY);
2234	} else {
2235		com->state |= CS_TTGO;
2236		if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
2237		    && !(com->intr_enable & CD1400_SRER_TXRDY))
2238			cd_setreg(com, CD1400_SRER,
2239				  com->intr_enable
2240				  = com->intr_enable & ~CD1400_SRER_TXMPTY
2241				    | CD1400_SRER_TXRDY);
2242	}
2243	if (tp->t_state & TS_TBLOCK) {
2244		if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW)
2245#if 0
2246			outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2247#else
2248			cd_setreg(com, com->mcr_rts_reg,
2249				  com->mcr_image &= ~com->mcr_rts);
2250#endif
2251	} else {
2252		if (!(com->mcr_image & com->mcr_rts)
2253		    && com->iptr < com->ihighwater
2254		    && com->state & CS_RTS_IFLOW)
2255#if 0
2256			outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2257#else
2258			cd_setreg(com, com->mcr_rts_reg,
2259				  com->mcr_image |= com->mcr_rts);
2260#endif
2261	}
2262	enable_intr();
2263	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2264		ttwwakeup(tp);
2265		splx(s);
2266		return;
2267	}
2268	if (tp->t_outq.c_cc != 0) {
2269		struct lbq	*qp;
2270		struct lbq	*next;
2271
2272		if (!com->obufs[0].l_queued) {
2273#ifdef CyDebug
2274			started = TRUE;
2275#endif
2276			com->obufs[0].l_tail
2277			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2278						  sizeof com->obuf1);
2279			com->obufs[0].l_next = NULL;
2280			com->obufs[0].l_queued = TRUE;
2281			disable_intr();
2282			if (com->state & CS_BUSY) {
2283				qp = com->obufq.l_next;
2284				while ((next = qp->l_next) != NULL)
2285					qp = next;
2286				qp->l_next = &com->obufs[0];
2287			} else {
2288				com->obufq.l_head = com->obufs[0].l_head;
2289				com->obufq.l_tail = com->obufs[0].l_tail;
2290				com->obufq.l_next = &com->obufs[0];
2291				com->state |= CS_BUSY;
2292				if (com->state >= (CS_BUSY | CS_TTGO
2293						   | CS_ODEVREADY))
2294					cd_setreg(com, CD1400_SRER,
2295						  com->intr_enable
2296						  = com->intr_enable
2297						    & ~CD1400_SRER_TXMPTY
2298						    | CD1400_SRER_TXRDY);
2299			}
2300			enable_intr();
2301		}
2302		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2303#ifdef CyDebug
2304			started = TRUE;
2305#endif
2306			com->obufs[1].l_tail
2307			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2308						  sizeof com->obuf2);
2309			com->obufs[1].l_next = NULL;
2310			com->obufs[1].l_queued = TRUE;
2311			disable_intr();
2312			if (com->state & CS_BUSY) {
2313				qp = com->obufq.l_next;
2314				while ((next = qp->l_next) != NULL)
2315					qp = next;
2316				qp->l_next = &com->obufs[1];
2317			} else {
2318				com->obufq.l_head = com->obufs[1].l_head;
2319				com->obufq.l_tail = com->obufs[1].l_tail;
2320				com->obufq.l_next = &com->obufs[1];
2321				com->state |= CS_BUSY;
2322				if (com->state >= (CS_BUSY | CS_TTGO
2323						   | CS_ODEVREADY))
2324					cd_setreg(com, CD1400_SRER,
2325						  com->intr_enable
2326						  = com->intr_enable
2327						    & ~CD1400_SRER_TXMPTY
2328						    | CD1400_SRER_TXRDY);
2329			}
2330			enable_intr();
2331		}
2332		tp->t_state |= TS_BUSY;
2333	}
2334#ifdef CyDebug
2335	if (started)
2336		++com->start_real;
2337#endif
2338#if 0
2339	disable_intr();
2340	if (com->state >= (CS_BUSY | CS_TTGO))
2341		siointr1(com);	/* fake interrupt to start output */
2342	enable_intr();
2343#endif
2344	ttwwakeup(tp);
2345	splx(s);
2346}
2347
2348static void
2349siostop(tp, rw)
2350	struct tty	*tp;
2351	int		rw;
2352{
2353	struct com_s	*com;
2354	bool_t		wakeup_etc;
2355
2356	com = com_addr(DEV_TO_UNIT(tp->t_dev));
2357	wakeup_etc = FALSE;
2358	disable_intr();
2359	if (rw & FWRITE) {
2360		com->obufs[0].l_queued = FALSE;
2361		com->obufs[1].l_queued = FALSE;
2362		if (com->extra_state & CSE_ODONE) {
2363			com_events -= LOTS_OF_EVENTS;
2364			com->extra_state &= ~CSE_ODONE;
2365			if (com->etc != ETC_NONE) {
2366				if (com->etc == ETC_BREAK_ENDED)
2367					com->etc = ETC_NONE;
2368				wakeup_etc = TRUE;
2369			}
2370		}
2371		com->tp->t_state &= ~TS_BUSY;
2372		if (com->state & CS_ODONE)
2373			com_events -= LOTS_OF_EVENTS;
2374		com->state &= ~(CS_ODONE | CS_BUSY);
2375	}
2376	if (rw & FREAD) {
2377		/* XXX no way to reset only input fifo. */
2378		com_events -= (com->iptr - com->ibuf);
2379		com->iptr = com->ibuf;
2380	}
2381	enable_intr();
2382	if (wakeup_etc)
2383		wakeup(&com->etc);
2384	if (rw & FWRITE && com->etc == ETC_NONE)
2385		cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
2386	comstart(tp);
2387}
2388
2389static struct tty *
2390siodevtotty(dev)
2391	dev_t	dev;
2392{
2393	int	mynor;
2394	int	unit;
2395
2396	mynor = minor(dev);
2397	if (mynor & CONTROL_MASK)
2398		return (NULL);
2399	unit = MINOR_TO_UNIT(mynor);
2400	if ((u_int) unit >= NSIO)
2401		return (NULL);
2402	return (&sio_tty[unit]);
2403}
2404
2405static int
2406commctl(com, bits, how)
2407	struct com_s	*com;
2408	int		bits;
2409	int		how;
2410{
2411	int	mcr;
2412	int	msr;
2413
2414	if (how == DMGET) {
2415		if (com->channel_control & CD1400_CCR_RCVEN)
2416			bits |= TIOCM_LE;
2417		mcr = com->mcr_image;
2418		if (mcr & com->mcr_dtr)
2419			bits |= TIOCM_DTR;
2420		if (mcr & com->mcr_rts)
2421			/* XXX wired on for Cyclom-8Ys */
2422			bits |= TIOCM_RTS;
2423
2424		/*
2425		 * We must read the modem status from the hardware because
2426		 * we don't generate modem status change interrupts for all
2427		 * changes, so com->prev_modem_status is not guaranteed to
2428		 * be up to date.  This is safe, unlike for sio, because
2429		 * reading the status register doesn't clear pending modem
2430		 * status change interrupts.
2431		 */
2432		msr = cd_getreg(com, CD1400_MSVR2);
2433
2434		if (msr & MSR_CTS)
2435			bits |= TIOCM_CTS;
2436		if (msr & MSR_DCD)
2437			bits |= TIOCM_CD;
2438		if (msr & MSR_DSR)
2439			bits |= TIOCM_DSR;
2440		if (msr & MSR_RI)
2441			/* XXX not connected except for Cyclom-16Y? */
2442			bits |= TIOCM_RI;
2443		return (bits);
2444	}
2445	mcr = 0;
2446	if (bits & TIOCM_DTR)
2447		mcr |= com->mcr_dtr;
2448	if (bits & TIOCM_RTS)
2449		mcr |= com->mcr_rts;
2450	disable_intr();
2451	switch (how) {
2452	case DMSET:
2453		com->mcr_image = mcr;
2454		cd_setreg(com, CD1400_MSVR1, mcr);
2455		cd_setreg(com, CD1400_MSVR2, mcr);
2456		break;
2457	case DMBIS:
2458		com->mcr_image = mcr = com->mcr_image | mcr;
2459		cd_setreg(com, CD1400_MSVR1, mcr);
2460		cd_setreg(com, CD1400_MSVR2, mcr);
2461		break;
2462	case DMBIC:
2463		com->mcr_image = mcr = com->mcr_image & ~mcr;
2464		cd_setreg(com, CD1400_MSVR1, mcr);
2465		cd_setreg(com, CD1400_MSVR2, mcr);
2466		break;
2467	}
2468	enable_intr();
2469	return (0);
2470}
2471
2472static void
2473siosettimeout()
2474{
2475	struct com_s	*com;
2476	bool_t		someopen;
2477	int		unit;
2478
2479	/*
2480	 * Set our timeout period to 1 second if no polled devices are open.
2481	 * Otherwise set it to max(1/200, 1/hz).
2482	 * Enable timeouts iff some device is open.
2483	 */
2484	untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2485	sio_timeout = hz;
2486	someopen = FALSE;
2487	for (unit = 0; unit < NSIO; ++unit) {
2488		com = com_addr(unit);
2489		if (com != NULL && com->tp != NULL
2490		    && com->tp->t_state & TS_ISOPEN) {
2491			someopen = TRUE;
2492#if 0
2493			if (com->poll || com->poll_output) {
2494				sio_timeout = hz > 200 ? hz / 200 : 1;
2495				break;
2496			}
2497#endif
2498		}
2499	}
2500	if (someopen) {
2501		sio_timeouts_until_log = hz / sio_timeout;
2502		sio_timeout_handle = timeout(comwakeup, (void *)NULL,
2503					     sio_timeout);
2504	} else {
2505		/* Flush error messages, if any. */
2506		sio_timeouts_until_log = 1;
2507		comwakeup((void *)NULL);
2508		untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2509	}
2510}
2511
2512static void
2513comwakeup(chan)
2514	void	*chan;
2515{
2516	struct com_s	*com;
2517	int		unit;
2518
2519	sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
2520
2521#if 0
2522	/*
2523	 * Recover from lost output interrupts.
2524	 * Poll any lines that don't use interrupts.
2525	 */
2526	for (unit = 0; unit < NSIO; ++unit) {
2527		com = com_addr(unit);
2528		if (com != NULL
2529		    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2530			disable_intr();
2531			siointr1(com);
2532			enable_intr();
2533		}
2534	}
2535#endif
2536
2537	/*
2538	 * Check for and log errors, but not too often.
2539	 */
2540	if (--sio_timeouts_until_log > 0)
2541		return;
2542	sio_timeouts_until_log = hz / sio_timeout;
2543	for (unit = 0; unit < NSIO; ++unit) {
2544		int	errnum;
2545
2546		com = com_addr(unit);
2547		if (com == NULL)
2548			continue;
2549		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2550			u_int	delta;
2551			u_long	total;
2552
2553			disable_intr();
2554			delta = com->delta_error_counts[errnum];
2555			com->delta_error_counts[errnum] = 0;
2556			enable_intr();
2557			if (delta == 0)
2558				continue;
2559			total = com->error_counts[errnum] += delta;
2560			log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
2561			    unit, delta, error_desc[errnum],
2562			    delta == 1 ? "" : "s", total);
2563		}
2564	}
2565}
2566
2567static void
2568disc_optim(tp, t, com)
2569	struct tty	*tp;
2570	struct termios	*t;
2571	struct com_s	*com;
2572{
2573#ifndef SOFT_HOTCHAR
2574	u_char	opt;
2575#endif
2576
2577	/*
2578	 * XXX can skip a lot more cases if Smarts.  Maybe
2579	 * (IGNCR | ISTRIP | IXON) in c_iflag.  But perhaps we
2580	 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.
2581	 */
2582	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2583	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2584	    && (!(t->c_iflag & PARMRK)
2585		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2586	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2587	    && linesw[tp->t_line].l_rint == ttyinput)
2588		tp->t_state |= TS_CAN_BYPASS_L_RINT;
2589	else
2590		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2591	com->hotchar = linesw[tp->t_line].l_hotchar;
2592#ifndef SOFT_HOTCHAR
2593	opt = com->cor[2] & ~CD1400_COR3_SCD34;
2594	if (com->hotchar != 0) {
2595		cd_setreg(com, CD1400_SCHR3, com->hotchar);
2596		cd_setreg(com, CD1400_SCHR4, com->hotchar);
2597		opt |= CD1400_COR3_SCD34;
2598	}
2599	if (opt != com->cor[2]) {
2600		cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
2601		cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
2602	}
2603#endif
2604}
2605
2606#ifdef Smarts
2607/* standard line discipline input routine */
2608int
2609cyinput(c, tp)
2610	int		c;
2611	struct tty	*tp;
2612{
2613	/* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
2614	 * bits, as they are done by the CD1400.  Hardly worth the effort,
2615	 * given that high-throughput sessions are raw anyhow.
2616	 */
2617}
2618#endif /* Smarts */
2619
2620static int
2621comspeed(speed, cy_clock, prescaler_io)
2622	speed_t	speed;
2623	u_long	cy_clock;
2624	int	*prescaler_io;
2625{
2626	int	actual;
2627	int	error;
2628	int	divider;
2629	int	prescaler;
2630	int	prescaler_unit;
2631
2632	if (speed == 0)
2633		return (0);
2634	if (speed < 0 || speed > 150000)
2635		return (-1);
2636
2637	/* determine which prescaler to use */
2638	for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
2639		prescaler_unit--, prescaler >>= 2) {
2640		if (cy_clock / prescaler / speed > 63)
2641			break;
2642	}
2643
2644	divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */
2645	if (divider > 255)
2646		divider = 255;
2647	actual = cy_clock/prescaler/divider;
2648
2649	/* 10 times error in percent: */
2650	error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2;
2651
2652	/* 3.0% max error tolerance */
2653	if (error < -30 || error > 30)
2654		return (-1);
2655
2656#if 0
2657	printf("prescaler = %d (%d)\n", prescaler, prescaler_unit);
2658	printf("divider = %d (%x)\n", divider, divider);
2659	printf("actual = %d\n", actual);
2660	printf("error = %d\n", error);
2661#endif
2662
2663	*prescaler_io = prescaler_unit;
2664	return (divider);
2665}
2666
2667static void
2668cd1400_channel_cmd(com, cmd)
2669	struct com_s	*com;
2670	int		cmd;
2671{
2672	cd1400_channel_cmd_wait(com);
2673	cd_setreg(com, CD1400_CCR, cmd);
2674	cd1400_channel_cmd_wait(com);
2675}
2676
2677static void
2678cd1400_channel_cmd_wait(com)
2679	struct com_s	*com;
2680{
2681	struct timeval	start;
2682	struct timeval	tv;
2683	long		usec;
2684
2685	if (cd_getreg(com, CD1400_CCR) == 0)
2686		return;
2687	microtime(&start);
2688	for (;;) {
2689		if (cd_getreg(com, CD1400_CCR) == 0)
2690			return;
2691		microtime(&tv);
2692		usec = 1000000 * (tv.tv_sec - start.tv_sec) +
2693		    tv.tv_usec - start.tv_usec;
2694		if (usec >= 5000) {
2695			log(LOG_ERR,
2696			    "cy%d: channel command timeout (%ld usec)\n",
2697			    com->unit, usec);
2698			return;
2699		}
2700	}
2701}
2702
2703static void
2704cd_etc(com, etc)
2705	struct com_s	*com;
2706	int		etc;
2707{
2708	/*
2709	 * We can't change the hardware's ETC state while there are any
2710	 * characters in the tx fifo, since those characters would be
2711	 * interpreted as commands!  Unputting characters from the fifo
2712	 * is difficult, so we wait up to 12 character times for the fifo
2713	 * to drain.  The command will be delayed for up to 2 character
2714	 * times for the tx to become empty.  Unputting characters from
2715	 * the tx holding and shift registers is impossible, so we wait
2716	 * for the tx to become empty so that the command is sure to be
2717	 * executed soon after we issue it.
2718	 */
2719	disable_intr();
2720	if (com->etc == etc) {
2721		enable_intr();
2722		goto wait;
2723	}
2724	if (etc == CD1400_ETC_SENDBREAK
2725	    && (com->etc == ETC_BREAK_STARTING
2726		|| com->etc == ETC_BREAK_STARTED)
2727	    || etc == CD1400_ETC_STOPBREAK
2728	       && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED
2729		   || com->etc == ETC_NONE)) {
2730		enable_intr();
2731		return;
2732	}
2733	com->etc = etc;
2734	cd_setreg(com, CD1400_SRER,
2735		  com->intr_enable
2736		  = com->intr_enable & ~CD1400_SRER_TXRDY | CD1400_SRER_TXMPTY);
2737	enable_intr();
2738wait:
2739	while (com->etc == etc
2740	       && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0)
2741		continue;
2742}
2743
2744static int
2745cd_getreg(com, reg)
2746	struct com_s	*com;
2747	int		reg;
2748{
2749	struct com_s	*basecom;
2750	u_char	car;
2751	int	cy_align;
2752	u_long	ef;
2753	cy_addr	iobase;
2754	int	val;
2755
2756	basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2757	car = com->unit & CD1400_CAR_CHAN;
2758	cy_align = com->cy_align;
2759	iobase = com->iobase;
2760	ef = read_eflags();
2761	disable_intr();
2762	if (basecom->car != car)
2763		cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2764	val = cd_inb(iobase, reg, cy_align);
2765	write_eflags(ef);
2766	return (val);
2767}
2768
2769static void
2770cd_setreg(com, reg, val)
2771	struct com_s	*com;
2772	int		reg;
2773	int		val;
2774{
2775	struct com_s	*basecom;
2776	u_char	car;
2777	int	cy_align;
2778	u_long	ef;
2779	cy_addr	iobase;
2780
2781	basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2782	car = com->unit & CD1400_CAR_CHAN;
2783	cy_align = com->cy_align;
2784	iobase = com->iobase;
2785	ef = read_eflags();
2786	disable_intr();
2787	if (basecom->car != car)
2788		cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2789	cd_outb(iobase, reg, cy_align, val);
2790	write_eflags(ef);
2791}
2792
2793#ifdef CyDebug
2794/* useful in ddb */
2795void
2796cystatus(unit)
2797	int	unit;
2798{
2799	struct com_s	*com;
2800	cy_addr		iobase;
2801	u_int		ocount;
2802	struct tty	*tp;
2803
2804	com = com_addr(unit);
2805	printf("info for channel %d\n", unit);
2806	printf("------------------\n");
2807	printf("total cyclom service probes:\t%d\n", cy_svrr_probes);
2808	printf("calls to upper layer:\t\t%d\n", cy_timeouts);
2809	if (com == NULL)
2810		return;
2811	iobase = com->iobase;
2812	printf("\n");
2813	printf("cd1400 base address:\\tt%p\n", iobase);
2814	printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
2815	printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
2816	       com->cor[0], com->cor[1], com->cor[2]);
2817	printf("service request enable reg:\t0x%02x (0x%02x cached)\n",
2818	       cd_getreg(com, CD1400_SRER), com->intr_enable);
2819	printf("service request register:\t0x%02x\n",
2820	       cd_inb(iobase, CD1400_SVRR, com->cy_align));
2821	printf("modem status:\t\t\t0x%02x (0x%02x cached)\n",
2822	       cd_getreg(com, CD1400_MSVR2), com->prev_modem_status);
2823	printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n",
2824	       cd_inb(iobase, CD1400_RIR, com->cy_align),
2825	       cd_inb(iobase, CD1400_TIR, com->cy_align),
2826	       cd_inb(iobase, CD1400_MIR, com->cy_align));
2827	printf("\n");
2828	printf("com state:\t\t\t0x%02x\n", com->state);
2829	printf("calls to comstart():\t\t%d (%d useful)\n",
2830	       com->start_count, com->start_real);
2831	printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf);
2832	ocount = 0;
2833	if (com->obufs[0].l_queued)
2834		ocount += com->obufs[0].l_tail - com->obufs[0].l_head;
2835	if (com->obufs[1].l_queued)
2836		ocount += com->obufs[1].l_tail - com->obufs[1].l_head;
2837	printf("tx buffer chars:\t\t%u\n", ocount);
2838	printf("received chars:\t\t\t%d\n", com->bytes_in);
2839	printf("received exceptions:\t\t%d\n", com->recv_exception);
2840	printf("modem signal deltas:\t\t%d\n", com->mdm);
2841	printf("transmitted chars:\t\t%d\n", com->bytes_out);
2842	printf("\n");
2843	tp = com->tp;
2844	if (tp != NULL) {
2845		printf("tty state:\t\t\t0x%08x\n", tp->t_state);
2846		printf(
2847		"upper layer queue lengths:\t%d raw, %d canon, %d output\n",
2848		       tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
2849	} else
2850		printf("tty state:\t\t\tclosed\n");
2851}
2852#endif /* CyDebug */
2853