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