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