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