cy_isa.c revision 6454
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.1 1995/02/09 09:47:27 jkh Exp $
31 */
32
33/*
34 * Device minor number encoding:
35 *
36 *	c c x x u u u u		- bits in the minor device number
37 *
38 *	bits	meaning
39 *	----	-------
40 *	uuuu	physical serial line (i.e. unit) to use
41 *			0-7 on a cyclom-8Y, 0-15 on a cyclom-16Y
42 *	xx	unused
43 *	cc	carrier control mode
44 *			00	complete hardware carrier control of the tty.
45 *				DCD must be high for the open(2) to complete.
46 *			01	dialin pseudo-device (not yet implemented)
47 *			10	carrier ignored until a high->low transition
48 *			11	carrier completed ignored
49 */
50
51/*
52 * Known deficiencies:
53 *
54 *	* no BREAK handling - breaks are ignored, and can't be sent either
55 *	* no support for bad-char reporting, except via PARMRK
56 *	* no support for dialin + dialout devices
57 */
58
59#include "cy.h"
60#if NCY > 0
61
62/* This disgusing hack because we actually have 16 units on one controller */
63#if NCY < 2
64#undef NCY
65#define NCY (16)
66#endif
67
68#include <sys/param.h>
69#include <sys/systm.h>
70#include <sys/kernel.h>
71#include <sys/malloc.h>
72#include <sys/ioctl.h>
73#include <sys/tty.h>
74#include <sys/proc.h>
75#include <sys/user.h>
76#include <sys/conf.h>
77#include <sys/file.h>
78#include <sys/uio.h>
79#include <sys/kernel.h>
80#include <sys/syslog.h>
81
82#include <machine/cpu.h>
83#ifdef NetBSD
84#include <machine/pio.h>
85#endif
86#include <machine/cpufunc.h>
87
88#include <i386/isa/isa_device.h>
89#include <i386/isa/ic/cd1400.h>
90
91#define RxFifoThreshold	3	/* 3 characters (out of 12) in the receive
92				 * FIFO before an interrupt is generated
93				 */
94#define	FastRawInput	/* bypass the regular char-by-char canonical input
95			 * processing whenever possible
96			 */
97#define	PollMode	/* use polling-based irq service routine, not the
98			 * hardware svcack lines.  Must be defined for
99			 * cyclom-16y boards.
100			 *
101			 * XXX cyclom-8y doesn't work without this defined
102			 * either (!)
103			 */
104#define	LogOverruns	/* log receive fifo overruns */
105#undef	TxBuffer	/* buffer driver output, to be slightly more
106			 * efficient
107			 *
108			 * XXX presently buggy
109			 */
110#undef	Smarts		/* enable slightly more CD1400 intelligence.  Mainly
111			 * the output CR/LF processing, plus we can avoid a
112			 * few checks usually done in ttyinput().
113			 *
114			 * XXX not yet implemented, and not particularly
115			 * worthwhile either.
116			 */
117#define CyDebug		/* include debugging code (minimal effect on
118			 * performance)
119			 */
120
121#define CY_RX_BUFS		2	/* two receive buffers per port */
122#define	CY_RX_BUF_SIZE		256	/* bytes per receive buffer */
123#define	CY_TX_BUF_SIZE		512	/* bytes per transmit buffer */
124
125/* #define CD1400s_PER_CYCLOM	1 */	/* cyclom-4y */
126/* #define CD1400s_PER_CYCLOM	2 */	/* cyclom-8y */
127#define CD1400s_PER_CYCLOM	4	/* cyclom-16y */
128
129/* FreeBSD's getty doesn't know option for setting RTS/CTS handshake.  Its
130   getty, like a lot of other old cruft, should be replaced with something
131   which used POSIX tty interfaces which at least allow enabling it.  In the
132   meantime, use the force. */
133#define ALWAYS_RTS_CTS	1
134
135#if CD1400s_PER_CYCLOM < 4
136#define CD1400_MEMSIZE		0x400	/* 4*256 bytes per chip: cyclom-[48]y */
137#else
138#define CD1400_MEMSIZE		0x100	/* 256 bytes per chip: cyclom-16y */
139					/* XXX or is it 0x400 like the rest? */
140#define CYCLOM_16	1		/* This is a cyclom-16Y */
141#endif
142
143#define PORTS_PER_CYCLOM	(CD1400_NO_OF_CHANNELS * CD1400s_PER_CYCLOM)
144#define CYCLOM_RESET_16		0x1400			/* cyclom-16y reset */
145#define CYCLOM_CLEAR_INTR	0x1800			/* intr ack address */
146#define CYCLOM_CLOCK		25000000		/* baud rate clock */
147
148#define	CY_UNITMASK		0x0f
149#define	CY_CARRIERMASK		0xC0
150#define CY_CARRIERSHIFT		6
151
152#define	UNIT(x)		(minor(x) & CY_UNITMASK)
153#define	CARRIER_MODE(x)	((minor(x) & CY_CARRIERMASK) >> CY_CARRIERSHIFT)
154
155typedef u_char * volatile cy_addr;
156
157int		cyprobe(struct isa_device *dev);
158int		cyattach(struct isa_device *isdp);
159void		cystart(struct tty *tp);
160int		cyparam(struct tty *tp, struct termios *t);
161int		cyspeed(int speed, int *prescaler_io);
162static void	cy_channel_init(dev_t dev, int reset);
163static void	cd1400_channel_cmd(cy_addr base, u_char cmd);
164
165/* hsu@clinet.fi: sigh */
166#ifdef __NetBSD__
167#define DELAY(foo) delay(foo)
168void		delay(int delay);
169#endif
170
171/* Better get rid of this until the core people agree on kernel interfaces.
172   At least it will then compile on both WhichBSDs.
173 */
174#if 0
175extern unsigned int	delaycount;	/* calibrated 1 ms cpu-spin delay */
176#endif
177
178struct	isa_driver cydriver = {
179	cyprobe, cyattach, "cy"
180};
181
182/* low-level ping-pong buffer structure */
183
184struct cy_buf {
185	u_char		*next_char;	/* location of next char to write */
186	u_int		free;		/* free chars remaining in buffer */
187	struct cy_buf	*next_buf;	/* circular, you know */
188	u_char		buf[CY_RX_BUF_SIZE];	/* start of the buffer */
189};
190
191/* low-level ring buffer */
192
193#ifdef TxBuffer
194struct cy_ring {
195	u_char		buf[CY_TX_BUF_SIZE];
196	u_char		*head;
197	u_char		*tail;		/* next pos. to insert char */
198	u_char		*endish;	/* physical end of buf */
199	u_int		used;		/* no. of chars in queue */
200};
201#endif
202
203
204/*
205 * define a structure to keep track of each serial line
206 */
207
208struct cy {
209	cy_addr		base_addr;	/* base address of this port's cd1400 */
210	struct tty	*tty;
211	u_int		dtrwait;	/* time (in ticks) to hold dtr low after close */
212	u_int		recv_exception;	/* exception chars received */
213	u_int		recv_normal;	/* normal chars received */
214	u_int		xmit;		/* chars transmitted */
215	u_int		mdm;		/* modem signal changes */
216#ifdef CyDebug
217	u_int		start_count;	/* no. of calls to cystart() */
218	u_int		start_real;	/* no. of calls that did something */
219#endif
220	u_char		carrier_mode;	/* hardware carrier handling mode */
221					/*
222					 * 0 = always use
223					 * 1 = always use (dialin port)
224					 * 2 = ignore during open, then use it
225					 * 3 = ignore completely
226					 */
227	u_char		carrier_delta;	/* true if carrier has changed state */
228	u_char		fifo_overrun;	/* true if cd1400 receive fifo has... */
229	u_char		rx_buf_overrun;	/* true if low-level buf overflow */
230	u_char		intr_enable;	/* CD1400 SRER shadow */
231	u_char		modem_sig;	/* CD1400 modem signal shadow */
232	u_char		channel_control;/* CD1400 CCR control command shadow */
233	u_char		cor[3];		/* CD1400 COR1-3 shadows */
234#ifdef Smarts
235	u_char		spec_char[4];	/* CD1400 SCHR1-4 shadows */
236#endif
237	struct cy_buf	*rx_buf;		/* current receive buffer */
238	struct cy_buf	rx_buf_pool[CY_RX_BUFS];/* receive ping-pong buffers */
239#ifdef TxBuffer
240	struct cy_ring	tx_buf;		/* transmit buffer */
241#endif
242};
243
244int	cydefaultrate = TTYDEF_SPEED;
245cy_addr	cyclom_base;			/* base address of the card */
246static	struct cy *info[NCY*PORTS_PER_CYCLOM];
247#ifdef __FreeBSD__ /* XXX actually only temporarily for 2.1-Development */
248struct	tty cy_tty[NCY*PORTS_PER_CYCLOM];
249#else
250struct	tty *cy_tty[NCY*PORTS_PER_CYCLOM];
251#endif
252static	volatile u_char timeout_scheduled = 0;	/* true if a timeout has been scheduled */
253
254#ifdef CyDebug
255u_int	cy_svrr_probes = 0;		/* debugging */
256u_int	cy_timeouts = 0;
257u_int	cy_timeout_req = 0;
258#endif
259
260/**********************************************************************/
261
262int
263cyprobe(struct isa_device *dev)
264{
265    int		i, j;
266    u_char	version = 0;	/* firmware version */
267
268    /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
269    i = *(cy_addr)(dev->id_maddr + CYCLOM_RESET_16);
270
271    DELAY(500);	/* wait for the board to get its act together (500 us) */
272
273    for (i = 0; i < CD1400s_PER_CYCLOM; i++) {
274	cy_addr	base = dev->id_maddr + i * CD1400_MEMSIZE;
275
276	/* wait for chip to become ready for new command */
277	for (j = 0; j < 100; j += 50) {
278	    DELAY(50);	/* wait 50 us */
279
280	    if (!*(base + CD1400_CCR))
281	    	break;
282	}
283
284	/* clear the GFRCR register */
285	*(base + CD1400_GFRCR) = 0;
286
287	/* issue a reset command */
288	*(base + CD1400_CCR) = CD1400_CMD_RESET;
289
290	/* wait for the CD1400 to initialise itself */
291	for (j = 0; j < 1000; j += 50) {
292	    DELAY(50);	/* wait 50 us */
293
294	    /* retrieve firmware version */
295	    version = *(base + CD1400_GFRCR);
296	    if (version)
297		break;
298	}
299
300	/* anything in the 40-4f range is fine */
301	if ((version & 0xf0) != 0x40) {
302	    return 0;
303	}
304    }
305
306    return 1;	/* found */
307}
308
309
310int
311cyattach(struct isa_device *isdp)
312{
313/*    u_char	unit = UNIT(isdp->id_unit); */
314    int		i, j, k;
315
316    /* global variable used various routines */
317    cyclom_base = (cy_addr)isdp->id_maddr;
318
319    for (i = 0, k = 0; i < CD1400s_PER_CYCLOM; i++) {
320	cy_addr	base = cyclom_base + i * CD1400_MEMSIZE;
321
322	/* setup a 1ms clock tick */
323	*(base + CD1400_PPR) = CD1400_CLOCK_25_1MS;
324
325	for (j = 0; j < CD1400_NO_OF_CHANNELS; j++, k++) {
326	    struct cy	*ip;
327
328	    /*
329	     * grab some space.  it'd be more polite to do this in cyopen(),
330	     * but hey.
331	     */
332	    info[k] = ip = malloc(sizeof(struct cy), M_DEVBUF, M_WAITOK);
333
334	    /* clear all sorts of junk */
335	    bzero(ip, sizeof(struct cy));
336
337	    ip->base_addr = base;
338
339	    /* initialise the channel, without resetting it first */
340	    cy_channel_init(k, 0);
341	}
342    }
343
344    /* clear interrupts */
345    *(cyclom_base + CYCLOM_CLEAR_INTR) = (u_char)0;
346
347    return 1;
348}
349
350
351int
352cyopen(dev_t dev, int flag, int mode, struct proc *p)
353{
354	u_int		unit = UNIT(dev);
355	struct cy	*infop;
356	cy_addr		base;
357	struct tty	*tp;
358	int		error = 0;
359	u_char		carrier;
360
361	if (unit >= /* NCY * ? */ PORTS_PER_CYCLOM)
362		return (ENXIO);
363
364	infop = info[unit];
365	base = infop->base_addr;
366#ifdef __FreeBSD__
367	infop->tty = &cy_tty[unit];
368#else
369	if (!cy_tty[unit])
370	    infop->tty = cy_tty[unit] = ttymalloc();
371#endif
372	tp = infop->tty;
373
374	tp->t_oproc = cystart;
375	tp->t_param = cyparam;
376	tp->t_dev = dev;
377	if (!(tp->t_state & TS_ISOPEN)) {
378		tp->t_state |= TS_WOPEN;
379		ttychars(tp);
380		if (tp->t_ispeed == 0) {
381			tp->t_iflag = TTYDEF_IFLAG;
382			tp->t_oflag = TTYDEF_OFLAG;
383			tp->t_cflag = TTYDEF_CFLAG;
384			tp->t_lflag = TTYDEF_LFLAG;
385			tp->t_ispeed = tp->t_ospeed = cydefaultrate;
386		}
387
388		(void) spltty();
389		cy_channel_init(unit, 1);	/* reset the hardware */
390
391		/*
392		 * raise dtr and generally set things up correctly.  this
393		 * has the side-effect of selecting the appropriate cd1400
394		 * channel, to help us with subsequent channel control stuff
395		 */
396		cyparam(tp, &tp->t_termios);
397
398		/* check carrier, and set t_state's TS_CARR_ON flag accordingly */
399		infop->modem_sig = *(base + CD1400_MSVR);
400		carrier = infop->modem_sig & CD1400_MSVR_CD;
401
402		if (carrier || (infop->carrier_mode >= 2))
403			tp->t_state |= TS_CARR_ON;
404		else
405			tp->t_state &=~ TS_CARR_ON;
406
407		/*
408		 * enable modem & rx interrupts - relies on cyparam()
409		 * having selected the appropriate cd1400 channel
410		 */
411		infop->intr_enable = (1 << 7) | (1 << 4);
412		*(base + CD1400_SRER) = infop->intr_enable;
413
414		ttsetwater(tp);
415	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
416		return (EBUSY);
417
418	if (!(flag & O_NONBLOCK))
419		while (!(tp->t_cflag & CLOCAL) &&
420		       !(tp->t_state & TS_CARR_ON) && !error)
421			error = ttysleep(tp, (caddr_t)&tp->t_rawq,
422		       			TTIPRI|PCATCH, ttopen, 0);
423	(void) spl0();
424
425	if (!error)
426		error = (*linesw[(u_char)tp->t_line].l_open)(dev, tp);
427	return (error);
428} /* end of cyopen() */
429
430
431void
432cyclose_wakeup(void *arg)
433{
434	wakeup(arg);
435} /* end of cyclose_wakeup() */
436
437
438int
439cyclose(dev_t dev, int flag, int mode, struct proc *p)
440{
441	u_int		unit = UNIT(dev);
442	struct cy	*infop = info[unit];
443	struct tty	*tp = infop->tty;
444	cy_addr		base = infop->base_addr;
445	int		s;
446
447	(*linesw[(u_char)tp->t_line].l_close)(tp, flag);
448
449	s = spltty();
450	/* select the appropriate channel on the CD1400 */
451	*(base + CD1400_CAR) = (u_char)(unit & 0x03);
452
453	/* disable this channel and lower DTR */
454	infop->intr_enable = 0;
455	*(base + CD1400_SRER) = (u_char)0;			/* no intrs */
456	*(base + CD1400_DTR) = (u_char)CD1400_DTR_CLEAR;	/* no DTR */
457	infop->modem_sig &= ~CD1400_MSVR_DTR;
458
459	/* disable receiver (leave transmitter enabled) */
460	infop->channel_control = (1 << 4) | (1 << 3) | 1;
461	cd1400_channel_cmd(base, infop->channel_control);
462	splx(s);
463
464	ttyclose(tp);
465#ifdef broken /* session holds a ref to the tty; can't deallocate */
466	ttyfree(tp);
467	infop->tty = cy_tty[unit] = (struct tty *)NULL;
468#endif
469
470	if (infop->dtrwait) {
471		int error;
472
473		timeout(cyclose_wakeup, (caddr_t)&infop->dtrwait, infop->dtrwait);
474		do {
475			error = tsleep((caddr_t)&infop->dtrwait,
476					TTIPRI|PCATCH, "cyclose", 0);
477		} while (error == ERESTART);
478	}
479
480	return 0;
481} /* end of cyclose() */
482
483
484int
485cyread(dev_t dev, struct uio *uio, int flag)
486{
487	u_int		unit = UNIT(dev);
488	struct tty	*tp = info[unit]->tty;
489
490	return (*linesw[(u_char)tp->t_line].l_read)(tp, uio, flag);
491} /* end of cyread() */
492
493
494int
495cywrite(dev_t dev, struct uio *uio, int flag)
496{
497	u_int		unit = UNIT(dev);
498	struct tty	*tp = info[unit]->tty;
499
500#ifdef Smarts
501	/* XXX duplicate ttwrite(), but without so much output processing on
502	 * CR & LF chars.  Hardly worth the effort, given that high-throughput
503	 * sessions are raw anyhow.
504	 */
505#else
506	return (*linesw[(u_char)tp->t_line].l_write)(tp, uio, flag);
507#endif
508} /* end of cywrite() */
509
510
511#ifdef Smarts
512/* standard line discipline input routine */
513int
514cyinput(int c, struct tty *tp)
515{
516	/* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
517	 * bits, as they are done by the CD1400.  Hardly worth the effort,
518	 * given that high-throughput sessions are raw anyhow.
519	 */
520} /* end of cyinput() */
521#endif /* Smarts */
522
523
524inline static void
525service_upper_rx(int unit)
526{
527	struct	cy *ip = info[unit];
528	struct	tty *tp = ip->tty;
529	struct	cy_buf *buf;
530	int		i;
531	u_char	*ch;
532
533	buf = ip->rx_buf;
534
535	/* give service_rx() a new one */
536	disable_intr();		/* faster than spltty() */
537	ip->rx_buf = buf->next_buf;
538	enable_intr();
539
540	if (tp->t_state & TS_ISOPEN) {
541	    ch = buf->buf;
542	    i = buf->next_char - buf->buf;
543
544#ifdef FastRawInput
545	    /* try to avoid calling the line discipline stuff if we can */
546	    if ((tp->t_line == 0) &&
547		    !(tp->t_iflag & (ICRNL | IMAXBEL | INLCR)) &&
548		    !(tp->t_lflag & (ECHO | ECHONL | ICANON | IEXTEN |
549			ISIG | PENDIN)) &&
550		    !(tp->t_state & (TS_CNTTB | TS_LNCH))) {
551
552		i = b_to_q(ch, i, &tp->t_rawq);
553		if (i) {
554			/*
555			 * we have no RTS flow control support on cy-8
556			 * boards, so this is really just tough luck
557			 */
558
559			log(LOG_WARNING, "cy%d: tty input queue overflow\n",
560			    unit);
561		}
562
563		ttwakeup(tp);	/* notify any readers */
564	    }
565	    else
566#endif /* FastRawInput */
567	    {
568		while (i--)
569		    (*linesw[(u_char)tp->t_line].l_rint)((int)*ch++, tp);
570	    }
571	}
572
573	/* clear the buffer we've just processed */
574	buf->next_char = buf->buf;
575	buf->free = CY_RX_BUF_SIZE;
576} /* end of service_upper_rx() */
577
578
579#ifdef TxBuffer
580static void
581service_upper_tx(int unit)
582{
583	struct	cy *ip = info[unit];
584	struct	tty *tp = ip->tty;
585
586	tp->t_state &=~ (TS_BUSY|TS_FLUSH);
587
588	if (tp->t_outq.c_cc <= tp->t_lowat) {
589		if (tp->t_state&TS_ASLEEP) {
590			tp->t_state &= ~TS_ASLEEP;
591			wakeup((caddr_t)&tp->t_outq);
592		}
593		selwakeup(&tp->t_wsel);
594	}
595
596	if (tp->t_outq.c_cc > 0) {
597		struct	cy_ring *txq = &ip->tx_buf;
598		int	free_count = CY_TX_BUF_SIZE - ip->tx_buf.used;
599		u_char	*cp = txq->tail;
600		int	count;
601		int	chars_done;
602
603		tp->t_state |= TS_BUSY;
604
605		/* find the largest contig. copy we can do */
606		count = ((txq->endish - cp) > free_count) ?
607			    free_count : txq->endish - cp;
608
609		count = ((cp + free_count) > txq->endish) ?
610			    txq->endish - cp : free_count;
611
612		/* copy the first slab */
613		chars_done = q_to_b(&tp->t_outq, cp, count);
614
615		/* check for wrap-around time */
616		cp += chars_done;
617		if (cp == txq->endish)
618			cp = txq->buf;		/* back to the start */
619
620		/* copy anything else, after we've wrapped around */
621		if ((chars_done == count) && (count != free_count)) {
622			/* copy the second slab */
623			count = q_to_b(&tp->t_outq, cp, free_count - count);
624			cp += count;
625			chars_done += count;
626		}
627
628		/*
629		 * update queue, protecting ourselves from any rampant
630		 * lower-layers
631		 */
632		disable_intr();
633		txq->tail = cp;
634		txq->used += chars_done;
635		enable_intr();
636	}
637
638	if (!tp->t_outq.c_cc)
639		tp->t_state &=~ TS_BUSY;
640} /* end of service_upper_tx() */
641#endif /* TxBuffer */
642
643
644inline static void
645service_upper_mdm(int unit)
646{
647	struct	cy *ip = info[unit];
648
649	if (ip->carrier_delta) {
650		int	carrier = ip->modem_sig & CD1400_MSVR_CD;
651		struct	tty *tp = ip->tty;
652
653		if (!(*linesw[(u_char)tp->t_line].l_modem)(tp, carrier)) {
654			cy_addr	base = ip->base_addr;
655
656			/* clear DTR */
657			disable_intr();
658			*(base + CD1400_CAR) = (u_char)(unit & 0x03);
659			*(base + CD1400_DTR) = (u_char)CD1400_DTR_CLEAR;
660			ip->modem_sig &= ~CD1400_MSVR_DTR;
661			ip->carrier_delta = 0;
662			enable_intr();
663		}
664		else {
665			disable_intr();
666			ip->carrier_delta = 0;
667			enable_intr();
668		}
669	}
670} /* end of service_upper_mdm() */
671
672
673/* upper level character processing routine */
674void
675cytimeout(void *ptr)
676{
677	int	unit;
678
679	timeout_scheduled = 0;
680
681#ifdef CyDebug
682	cy_timeouts++;
683#endif
684
685	/* check each port in turn */
686	for (unit = 0; unit < NCY*PORTS_PER_CYCLOM; unit++) {
687		struct	cy *ip = info[unit];
688#ifndef TxBuffer
689		struct	tty *tp = ip->tty;
690#endif
691
692		/* ignore anything that is not open */
693		if (!ip->tty)
694			continue;
695
696		/*
697		 * any received chars to handle? (doesn't matter if intr routine
698		 * kicks in while we're testing this)
699		 */
700		if (ip->rx_buf->free != CY_RX_BUF_SIZE)
701			service_upper_rx(unit);
702
703#ifdef TxBuffer
704		/* anything to add to the transmit buffer (low-water mark)? */
705		if (ip->tx_buf.used < CY_TX_BUF_SIZE/2)
706			service_upper_tx(unit);
707#else
708		if (tp->t_outq.c_cc <= tp->t_lowat) {
709			if (tp->t_state&TS_ASLEEP) {
710				tp->t_state &= ~TS_ASLEEP;
711				wakeup((caddr_t)&tp->t_outq);
712			}
713			selwakeup(&tp->t_wsel);
714		}
715#endif
716
717		/* anything modem signals altered? */
718		service_upper_mdm(unit);
719
720		/* any overruns to log? */
721#ifdef LogOverruns
722		if (ip->fifo_overrun) {
723			/*
724			 * turn off the alarm - not important enough to bother
725			 * with interrupt protection.
726			 */
727			ip->fifo_overrun = 0;
728
729			log(LOG_WARNING, "cy%d: receive fifo overrun\n", unit);
730		}
731#endif
732		if (ip->rx_buf_overrun) {
733			/*
734			 * turn off the alarm - not important enough to bother
735			 * with interrupt protection.
736			 */
737			ip->rx_buf_overrun = 0;
738
739			log(LOG_WARNING, "cy%d: receive buffer full\n", unit);
740		}
741	}
742} /* cytimeout() */
743
744
745inline static void
746schedule_upper_service(void)
747{
748#ifdef CyDebug
749    cy_timeout_req++;
750#endif
751
752    if (!timeout_scheduled) {
753	timeout(cytimeout, (caddr_t)0, 1);	/* call next tick */
754	timeout_scheduled = 1;
755    }
756} /* end of schedule_upper_service() */
757
758
759/* initialise a channel on the cyclom board */
760
761static void
762cy_channel_init(dev_t dev, int reset)
763{
764	u_int	unit = UNIT(dev);
765	int	carrier_mode = CARRIER_MODE(dev);
766	struct	cy *ip = info[unit];
767	cy_addr	base = ip->base_addr;
768	struct	tty *tp = ip->tty;
769	struct	cy_buf *buf, *next_buf;
770	int	i;
771#ifndef PollMode
772	u_char	cd1400_unit;
773#endif
774
775	/* clear the structure and refill it */
776	bzero(ip, sizeof(struct cy));
777	ip->base_addr = base;
778	ip->tty = tp;
779	ip->carrier_mode = carrier_mode;
780
781	/* select channel of the CD1400 */
782	*(base + CD1400_CAR) = (u_char)(unit & 0x03);
783
784	if (reset)
785		cd1400_channel_cmd(base, 0x80);	/* reset the channel */
786
787	/* set LIVR to 0 - intr routines depend on this */
788	*(base + CD1400_LIVR) = 0;
789
790#ifndef PollMode
791	/* set top four bits of {R,T,M}ICR to the cd1400
792	 * number, cd1400_unit
793	 */
794	cd1400_unit = unit / CD1400_NO_OF_CHANNELS;
795	*(base + CD1400_RICR) = (u_char)(cd1400_unit << 4);
796	*(base + CD1400_TICR) = (u_char)(cd1400_unit << 4);
797	*(base + CD1400_MICR) = (u_char)(cd1400_unit << 4);
798#endif
799
800	ip->dtrwait = hz/4;	/* quarter of a second */
801
802	/* setup low-level buffers */
803	i = CY_RX_BUFS;
804	ip->rx_buf = next_buf = &ip->rx_buf_pool[0];
805	while (i--) {
806		buf = &ip->rx_buf_pool[i];
807
808		buf->next_char = buf->buf;	/* first char to use */
809		buf->free = CY_RX_BUF_SIZE;	/* i.e. empty */
810		buf->next_buf = next_buf;	/* where to go next */
811		next_buf = buf;
812	}
813
814#ifdef TxBuffer
815	ip->tx_buf.endish = ip->tx_buf.buf + CY_TX_BUF_SIZE;
816
817	/* clear the low-level tx buffer */
818	ip->tx_buf.head = ip->tx_buf.tail = ip->tx_buf.buf;
819	ip->tx_buf.used = 0;
820#endif
821
822	/* clear the low-level rx buffer */
823	ip->rx_buf->next_char = ip->rx_buf->buf;	/* first char to use */
824	ip->rx_buf->free = CY_RX_BUF_SIZE;		/* completely empty */
825} /* end of cy_channel_init() */
826
827
828/* service a receive interrupt */
829inline static void
830service_rx(int cd, caddr_t base)
831{
832	struct cy	*infop;
833	unsigned	count;
834	int		ch;
835	u_char		serv_type, channel;
836#ifdef PollMode
837	u_char		save_rir, save_car;
838#endif
839
840	/* setup */
841#ifdef PollMode
842	save_rir = *(base + CD1400_RIR);
843	channel = cd * CD1400_NO_OF_CHANNELS + (save_rir & 0x3);
844	save_car = *(base + CD1400_CAR);
845	*(base + CD1400_CAR) = save_rir;	/* enter modem service */
846	serv_type = *(base + CD1400_RIVR);
847#else
848	serv_type = *(base + CD1400_SVCACKR);	/* ack receive service */
849	channel = ((u_char)*(base + CD1400_RICR)) >> 2;	/* get cyclom channel # */
850
851#ifdef CyDebug
852	if (channel >= PORTS_PER_CYCLOM) {
853	    printf("cy: service_rx - channel %02x\n", channel);
854	    panic("cy: service_rx - bad channel");
855	}
856#endif
857#endif
858
859	infop = info[channel];
860
861	/* read those chars */
862	if (serv_type & CD1400_RIVR_EXCEPTION) {
863		/* read the exception status */
864		u_char status = *(base + CD1400_RDSR);
865
866		/* XXX is it a break?  Do something if it is! */
867
868		/* XXX is IGNPAR not set?  Store a null in the buffer. */
869
870#ifdef LogOverruns
871		if (status & CD1400_RDSR_OVERRUN) {
872#if 0
873			ch |= TTY_PE;		/* for SLIP */
874#endif
875			infop->fifo_overrun++;
876		}
877#endif
878		infop->recv_exception++;
879	}
880	else {
881		struct	cy_buf *buf = infop->rx_buf;
882
883		count = (u_char)*(base + CD1400_RDCR);	/* how many to read? */
884		infop->recv_normal += count;
885		if (buf->free < count) {
886			infop->rx_buf_overrun += count;
887
888			/* read & discard everything */
889			while (count--)
890				ch = (u_char)*(base + CD1400_RDSR);
891		}
892		else {
893			/* slurp it into our low-level buffer */
894			buf->free -= count;
895			while (count--) {
896				ch = (u_char)*(base + CD1400_RDSR);	/* read the char */
897				*(buf->next_char++) = ch;
898			}
899		}
900	}
901
902#ifdef PollMode
903	*(base + CD1400_RIR) = (u_char)(save_rir & 0x3f);	/* terminate service context */
904#else
905	*(base + CD1400_EOSRR) = (u_char)0;	/* terminate service context */
906#endif
907} /* end of service_rx */
908
909
910/* service a transmit interrupt */
911inline static void
912service_tx(int cd, caddr_t base)
913{
914	struct cy	*ip;
915#ifdef TxBuffer
916	struct cy_ring	*txq;
917#else
918	struct tty	*tp;
919#endif
920	u_char		channel;
921#ifdef PollMode
922	u_char		save_tir, save_car;
923#else
924	u_char		vector;
925#endif
926
927	/* setup */
928#ifdef PollMode
929	save_tir = *(base + CD1400_TIR);
930	channel = cd * CD1400_NO_OF_CHANNELS + (save_tir & 0x3);
931	save_car = *(base + CD1400_CAR);
932	*(base + CD1400_CAR) = save_tir;	/* enter tx service */
933#else
934	vector = *(base + CD1400_SVCACKT);	/* ack transmit service */
935	channel = ((u_char)*(base + CD1400_TICR)) >> 2;	/* get cyclom channel # */
936
937#ifdef CyDebug
938	if (channel >= PORTS_PER_CYCLOM) {
939	    printf("cy: service_tx - channel %02x\n", channel);
940	    panic("cy: service_tx - bad channel");
941	}
942#endif
943#endif
944
945	ip = info[channel];
946#ifdef TxBuffer
947	txq = &ip->tx_buf;
948
949	if (txq->used > 0) {
950		cy_addr	base = ip->base_addr;
951		int	count = min(CD1400_FIFOSIZE, txq->used);
952		int	chars_done = count;
953		u_char	*cp = txq->head;
954		u_char	*buf_end = txq->endish;
955
956		/* ip->state |= CY_BUSY; */
957		while (count--) {
958			*(base + CD1400_TDR) = *cp++;
959			if (cp >= buf_end)
960				cp = txq->buf;
961		};
962		txq->head = cp;
963		txq->used -= chars_done; /* important that this is atomic */
964		ip->xmit += chars_done;
965	}
966
967	/*
968	 * disable tx intrs if no more chars to send.  we re-enable
969	 * them in cystart()
970	 */
971	if (!txq->used) {
972		ip->intr_enable &=~ (1 << 2);
973		*(base + CD1400_SRER) = ip->intr_enable;
974		/* ip->state &= ~CY_BUSY; */
975	}
976#else
977	tp = ip->tty;
978
979	if (!(tp->t_state & TS_TTSTOP) && (tp->t_outq.c_cc > 0)) {
980		cy_addr	base = ip->base_addr;
981		int	count = min(CD1400_FIFOSIZE, tp->t_outq.c_cc);
982
983		ip->xmit += count;
984		tp->t_state |= TS_BUSY;
985		while (count--)
986			*(base + CD1400_TDR) = getc(&tp->t_outq);
987	}
988
989	/*
990	 * disable tx intrs if no more chars to send.  we re-enable them
991	 * in cystart()
992	 */
993	if (!tp->t_outq.c_cc) {
994		ip->intr_enable &=~ (1 << 2);
995		*(base + CD1400_SRER) = ip->intr_enable;
996		tp->t_state &= ~TS_BUSY;
997	}
998#endif
999
1000#ifdef PollMode
1001	*(base + CD1400_TIR) = (u_char)(save_tir & 0x3f);	/* terminate service context */
1002#else
1003	*(base + CD1400_EOSRR) = (u_char)0;	/* terminate service context */
1004#endif
1005} /* end of service_tx */
1006
1007
1008/* service a modem status interrupt */
1009inline static void
1010service_mdm(int cd, caddr_t base)
1011{
1012	struct cy	*infop;
1013	u_char		channel, deltas;
1014#ifdef PollMode
1015	u_char		save_mir, save_car;
1016#else
1017	u_char		vector;
1018#endif
1019
1020	/* setup */
1021#ifdef PollMode
1022	save_mir = *(base + CD1400_MIR);
1023	channel = cd * CD1400_NO_OF_CHANNELS + (save_mir & 0x3);
1024	save_car = *(base + CD1400_CAR);
1025	*(base + CD1400_CAR) = save_mir;	/* enter modem service */
1026#else
1027	vector = *(base + CD1400_SVCACKM);	/* ack modem service */
1028	channel = ((u_char)*(base + CD1400_MICR)) >> 2;	/* get cyclom channel # */
1029
1030#ifdef CyDebug
1031	if (channel >= PORTS_PER_CYCLOM) {
1032	    printf("cy: service_mdm - channel %02x\n", channel);
1033	    panic("cy: service_mdm - bad channel");
1034	}
1035#endif
1036#endif
1037
1038	infop = info[channel];
1039
1040	/* read the siggies and see what's changed */
1041	infop->modem_sig = (u_char)*(base + CD1400_MSVR);
1042	deltas = (u_char)*(base + CD1400_MISR);
1043
1044	if ((infop->carrier_mode <= 2) && (deltas & CD1400_MISR_CDd))
1045		/* something for the upper layer to deal with */
1046		infop->carrier_delta = 1;
1047
1048	infop->mdm++;
1049
1050	/* terminate service context */
1051#ifdef PollMode
1052	*(base + CD1400_MIR) = (u_char)(save_mir & 0x3f);
1053#else
1054	*(base + CD1400_EOSRR) = (u_char)0;
1055#endif
1056} /* end of service_mdm */
1057
1058
1059int
1060cyintr(int unit)
1061{
1062    int		cd;
1063    u_char	status;
1064
1065    /* check each CD1400 in turn */
1066    for (cd = 0; cd < CD1400s_PER_CYCLOM; cd++) {
1067	cy_addr	base = cyclom_base + cd*CD1400_MEMSIZE;
1068
1069	/* poll to see if it has any work */
1070	while (status = (u_char)*(base + CD1400_SVRR)) {
1071#ifdef CyDebug
1072	    cy_svrr_probes++;
1073#endif
1074	    /* service requests as appropriate, giving priority to RX */
1075	    if (status & CD1400_SVRR_RX)
1076		    service_rx(cd, base);
1077	    if (status & CD1400_SVRR_TX)
1078		    service_tx(cd, base);
1079	    if (status & CD1400_SVRR_MDM)
1080		    service_mdm(cd, base);
1081	}
1082    }
1083
1084    /* request upper level service to deal with whatever happened */
1085    schedule_upper_service();
1086
1087    /* re-enable interrupts on the cyclom */
1088    *(cyclom_base + CYCLOM_CLEAR_INTR) = (u_char)0;
1089
1090    return 1;
1091}
1092
1093
1094int
1095cyioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
1096{
1097	int		unit = UNIT(dev);
1098	struct cy	*infop = info[unit];
1099	struct tty	*tp = infop->tty;
1100	int		error;
1101
1102	error = (*linesw[(u_char)tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1103	if (error >= 0)
1104		return (error);
1105	error = ttioctl(tp, cmd, data, flag
1106#ifdef NetBSD
1107			, p
1108#endif
1109			);
1110	if (error >= 0)
1111		return (error);
1112
1113	switch (cmd) {
1114#ifdef notyet	/* sigh - more junk to do XXX */
1115	case TIOCSBRK:
1116		break;
1117	case TIOCCBRK:
1118		break;
1119	case TIOCSDTR:
1120		break;
1121	case TIOCCDTR:
1122		break;
1123
1124	case TIOCMSET:
1125		break;
1126	case TIOCMBIS:
1127		break;
1128	case TIOCMBIC:
1129		break;
1130#endif /* notyet */
1131
1132	case TIOCMGET: {
1133		int	bits = 0;
1134		u_char	status = infop->modem_sig;
1135
1136		if (status & CD1400_MSVR_DTR) bits |= TIOCM_DTR | TIOCM_RTS;
1137		if (status & CD1400_MSVR_CD) bits |= TIOCM_CD;
1138		if (status & CD1400_MSVR_CTS) bits |= TIOCM_CTS;
1139		if (status & CD1400_MSVR_DSR) bits |= TIOCM_DSR;
1140#ifdef CYCLOM_16
1141		if (status & CD1400_MSVR_RI) bits |= TIOCM_RI;
1142#endif
1143		if (infop->channel_control & 0x02) bits |= TIOCM_LE;
1144		*(int *)data = bits;
1145		break;
1146	}
1147
1148#ifdef TIOCMSBIDIR
1149	case TIOCMSBIDIR:
1150		return (ENOTTY);
1151#endif /* TIOCMSBIDIR */
1152
1153#ifdef TIOCMGBIDIR
1154	case TIOCMGBIDIR:
1155		return (ENOTTY);
1156#endif /* TIOCMGBIDIR */
1157
1158#ifdef TIOCMSDTRWAIT
1159	case TIOCMSDTRWAIT:
1160		/* must be root to set dtr delay */
1161			if (p->p_ucred->cr_uid != 0)
1162				return(EPERM);
1163
1164			infop->dtrwait = *(u_int *)data;
1165			break;
1166#endif /* TIOCMSDTRWAIT */
1167
1168#ifdef TIOCMGDTRWAIT
1169	case TIOCMGDTRWAIT:
1170		*(u_int *)data = infop->dtrwait;
1171		break;
1172#endif /* TIOCMGDTRWAIT */
1173
1174	default:
1175		return (ENOTTY);
1176	}
1177
1178	return 0;
1179} /* end of cyioctl() */
1180
1181
1182int
1183cyparam(struct tty *tp, struct termios *t)
1184{
1185	u_char		unit = UNIT(tp->t_dev);
1186	struct cy	*infop = info[unit];
1187	cy_addr		base = infop->base_addr;
1188	int		cflag = t->c_cflag;
1189	int		iflag = t->c_iflag;
1190	int		ispeed, ospeed;
1191	int		itimeout;
1192	int		iprescaler, oprescaler;
1193	int		s;
1194	u_char		cor_change = 0;
1195	u_char		opt;
1196
1197	if (!t->c_ispeed)
1198	    t->c_ispeed = t->c_ospeed;
1199
1200	s = spltty();
1201
1202	/* select the appropriate channel on the CD1400 */
1203	*(base + CD1400_CAR) = unit & 0x03;
1204
1205	/* handle DTR drop on speed == 0 trick */
1206	if (t->c_ospeed == 0) {
1207	    *(base + CD1400_DTR) = CD1400_DTR_CLEAR;
1208	    infop->modem_sig &= ~CD1400_MSVR_DTR;
1209	}
1210	else {
1211	    *(base + CD1400_DTR) = CD1400_DTR_SET;
1212	    infop->modem_sig |= CD1400_MSVR_DTR;
1213	}
1214
1215	/* set baud rates if they've changed from last time */
1216
1217	if ((ospeed = cyspeed(t->c_ospeed, &oprescaler)) < 0)
1218	    return EINVAL;
1219	*(base + CD1400_TBPR) = (u_char)ospeed;
1220	*(base + CD1400_TCOR) = (u_char)oprescaler;
1221
1222	if ((ispeed = cyspeed(t->c_ispeed, &iprescaler)) < 0)
1223	    return EINVAL;
1224	*(base + CD1400_RBPR) = (u_char)ispeed;
1225	*(base + CD1400_RCOR) = (u_char)iprescaler;
1226
1227	/*
1228	 * set receive time-out period
1229	 *	generate a rx interrupt if no new chars are received in
1230	 *	this many ticks
1231	 * don't bother comparing old & new VMIN, VTIME and ispeed - it
1232	 * can't be much worse just to calculate and set it each time!
1233	 * certainly less hassle. :-)
1234	 */
1235
1236	/*
1237	 * calculate minimum timeout period:
1238	 *     5 ms or the time it takes to receive 1 char, rounded up to the
1239	 *     next ms, whichever is greater
1240	 */
1241	if (t->c_ispeed > 0) {
1242	    itimeout = (t->c_ispeed > 2200) ? 5 : (10000/t->c_ispeed + 1);
1243
1244	    /* if we're using VTIME as an inter-char timeout, and it is set to
1245	     * be longer than the minimum calculated above, go for it
1246	     */
1247	    if (t->c_cc[VMIN] && t->c_cc[VTIME] && t->c_cc[VTIME]*10 > itimeout)
1248		itimeout = t->c_cc[VTIME]*10;
1249
1250	    /* store it, taking care not to overflow the byte-sized register */
1251	    *(base + CD1400_RTPR) = (u_char)((itimeout <= 255) ? itimeout : 255);
1252	}
1253
1254
1255	/*
1256	 * channel control
1257	 *	receiver enable
1258	 *	transmitter enable (always set)
1259	 */
1260	opt = (1 << 4) | (1 << 3) | ((cflag & CREAD) ? (1 << 1) : 1);
1261	if (opt != infop->channel_control) {
1262	    infop->channel_control = opt;
1263	    cd1400_channel_cmd(base, opt);
1264	}
1265
1266#ifdef Smarts
1267	/* set special chars */
1268	if (t->c_cc[VSTOP] != _POSIX_VDISABLE &&
1269		(t->c_cc[VSTOP] != infop->spec_char[0])) {
1270	    *(base + CD1400_SCHR1) = infop->spec_char[0] = t->c_cc[VSTOP];
1271	}
1272	if (t->c_cc[VSTART] != _POSIX_VDISABLE &&
1273		(t->c_cc[VSTART] != infop->spec_char[1])) {
1274	    *(base + CD1400_SCHR2) = infop->spec_char[0] = t->c_cc[VSTART];
1275	}
1276	if (t->c_cc[VINTR] != _POSIX_VDISABLE &&
1277		(t->c_cc[VINTR] != infop->spec_char[2])) {
1278	    *(base + CD1400_SCHR3) = infop->spec_char[0] = t->c_cc[VINTR];
1279	}
1280	if (t->c_cc[VSUSP] != _POSIX_VDISABLE &&
1281		(t->c_cc[VSUSP] != infop->spec_char[3])) {
1282	    *(base + CD1400_SCHR4) = infop->spec_char[0] = t->c_cc[VSUSP];
1283	}
1284#endif
1285
1286	/*
1287	 * set channel option register 1 -
1288	 *	parity mode
1289	 *	stop bits
1290	 *	char length
1291	 */
1292	opt = 0;
1293	/* parity */
1294	if (cflag & PARENB) {
1295	    if (cflag & PARODD)
1296		opt |= 1 << 7;
1297	    opt |= 2 << 5;		/* normal parity mode */
1298	}
1299	if (!(iflag & INPCK))
1300	    opt |= 1 << 4;		/* ignore parity */
1301	/* stop bits */
1302	if (cflag & CSTOPB)
1303	    opt |= 2 << 2;
1304	/* char length */
1305	opt |= (cflag & CSIZE) >> 8;	/* nasty, but fast */
1306	if (opt != infop->cor[0]) {
1307	    cor_change |= 1 << 1;
1308	    *(base + CD1400_COR1) = opt;
1309	}
1310
1311	/*
1312	 * set channel option register 2 -
1313	 *	flow control
1314	 */
1315	opt = 0;
1316#ifdef Smarts
1317	if (iflag & IXANY)
1318	    opt |= 1 << 7;		/* auto output restart on any char after XOFF */
1319	if (iflag & IXOFF)
1320	    opt |= 1 << 6;		/* auto XOFF output flow-control */
1321#endif
1322#ifndef ALWAYS_RTS_CTS
1323	if (cflag & CCTS_OFLOW)
1324#endif
1325	    opt |= 1 << 1;		/* auto CTS flow-control */
1326
1327	if (opt != infop->cor[1]) {
1328	    cor_change |= 1 << 2;
1329	    *(base + CD1400_COR2) = opt;
1330	}
1331
1332	/*
1333	 * set channel option register 3 -
1334	 *	receiver FIFO interrupt threshold
1335	 *	flow control
1336	 */
1337	opt = RxFifoThreshold;	/* rx fifo threshold */
1338#ifdef Smarts
1339	if (t->c_lflag & ICANON)
1340	    opt |= 1 << 6;		/* detect INTR & SUSP chars */
1341	if (iflag & IXOFF)
1342	    opt |= (1 << 5) | (1 << 4);	/* transparent in-band flow control */
1343#endif
1344	if (opt != infop->cor[2]) {
1345	    cor_change |= 1 << 3;
1346	    *(base + CD1400_COR3) = opt;
1347	}
1348
1349
1350	/* notify the CD1400 if COR1-3 have changed */
1351	if (cor_change) {
1352	    cor_change |= 1 << 6;	/* COR change flag */
1353	    cd1400_channel_cmd(base, cor_change);
1354	}
1355
1356	/*
1357	 * set channel option register 4 -
1358	 *	CR/NL processing
1359	 *	break processing
1360	 *	received exception processing
1361	 */
1362	opt = 0;
1363	if (iflag & IGNCR)
1364	    opt |= 1 << 7;
1365#ifdef Smarts
1366	/*
1367	 * we need a new ttyinput() for this, as we don't want to
1368	 * have ICRNL && INLCR being done in both layers, or to have
1369	 * synchronisation problems
1370	 */
1371	if (iflag & ICRNL)
1372	    opt |= 1 << 6;
1373	if (iflag & INLCR)
1374	    opt |= 1 << 5;
1375#endif
1376	if (iflag & IGNBRK)
1377	    opt |= 1 << 4;
1378	if (!(iflag & BRKINT))
1379	    opt |= 1 << 3;
1380	if (iflag & IGNPAR)
1381#ifdef LogOverruns
1382	    opt |= 0;		/* broken chars cause receive exceptions */
1383#else
1384	    opt |= 2;		/* discard broken chars */
1385#endif
1386	else {
1387	    if (iflag & PARMRK)
1388		opt |= 4;	/* precede broken chars with 0xff 0x0 */
1389	    else
1390#ifdef LogOverruns
1391		opt |= 0;	/* broken chars cause receive exceptions */
1392#else
1393		opt |= 3;	/* convert framing/parity errs to nulls */
1394#endif
1395	}
1396	*(base + CD1400_COR4) = opt;
1397
1398	/*
1399	 * set channel option register 5 -
1400	 */
1401	opt = 0;
1402	if (iflag & ISTRIP)
1403	    opt |= 1 << 7;
1404	if (t->c_iflag & IEXTEN) {
1405	    opt |= 1 << 6;	/* enable LNEXT (e.g. ctrl-v quoting) handling */
1406	}
1407#ifdef Smarts
1408	if (t->c_oflag & ONLCR)
1409	    opt |= 1 << 1;
1410	if (t->c_oflag & OCRNL)
1411	    opt |= 1;
1412#endif
1413	*(base + CD1400_COR5) = opt;
1414
1415	/*
1416	 * set modem change option register 1
1417	 *	generate modem interrupts on which 1 -> 0 input transitions
1418	 *	also controls auto-DTR output flow-control, which we don't use
1419	 */
1420	opt = (cflag & CLOCAL) ? 0 : 1 << 4;	/* CD */
1421	*(base + CD1400_MCOR1) = opt;
1422
1423	/*
1424	 * set modem change option register 2
1425	 *	generate modem interrupts on specific 0 -> 1 input transitions
1426	 */
1427	opt = (cflag & CLOCAL) ? 0 : 1 << 4;	/* CD */
1428	*(base + CD1400_MCOR2) = opt;
1429
1430	splx(s);
1431
1432	return 0;
1433} /* end of cyparam */
1434
1435
1436void
1437cystart(struct tty *tp)
1438{
1439	u_char		unit = UNIT(tp->t_dev);
1440	struct cy	*infop = info[unit];
1441	cy_addr		base = infop->base_addr;
1442	int		s;
1443
1444#ifdef CyDebug
1445	infop->start_count++;
1446#endif
1447
1448	/* check the flow-control situation */
1449	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
1450		return;
1451
1452	if (tp->t_outq.c_cc <= tp->t_lowat) {
1453		if (tp->t_state&TS_ASLEEP) {
1454			tp->t_state &= ~TS_ASLEEP;
1455			wakeup((caddr_t)&tp->t_outq);
1456		}
1457		selwakeup(&tp->t_wsel);
1458	}
1459
1460#ifdef TxBuffer
1461	service_upper_tx(unit);		/* feed the monster */
1462#endif
1463
1464	s = spltty();
1465
1466	if (!(infop->intr_enable & (1 << 2))) {
1467	    /* select the channel */
1468	    *(base + CD1400_CAR) = unit & (u_char)3;
1469
1470	    /* (re)enable interrupts to set things in motion */
1471	    infop->intr_enable |= (1 << 2);
1472	    *(base + CD1400_SRER) = infop->intr_enable;
1473
1474	    infop->start_real++;
1475	}
1476
1477	splx(s);
1478} /* end of cystart() */
1479
1480
1481int
1482cystop(struct tty *tp, int flag)
1483{
1484	u_char		unit = UNIT(tp->t_dev);
1485	struct cy	*ip = info[unit];
1486	cy_addr		base = ip->base_addr;
1487	int		s;
1488
1489	s = spltty();
1490
1491	/* select the channel */
1492	*(base + CD1400_CAR) = unit & 3;
1493
1494	/* halt output by disabling transmit interrupts */
1495	ip->intr_enable &=~ (1 << 2);
1496	*(base + CD1400_SRER) = ip->intr_enable;
1497
1498	splx(s);
1499
1500	return 0;
1501}
1502
1503
1504int
1505cyselect(dev_t dev, int rw, struct proc *p)
1506{
1507	return (ttselect(UNIT(dev), rw, p));
1508} /* end of cyselect() */
1509
1510
1511int
1512cyspeed(int speed, int *prescaler_io)
1513{
1514    int		actual;
1515    int		error;
1516    int		divider;
1517    int		prescaler;
1518    int		prescaler_unit;
1519
1520    if (speed == 0)
1521	return 0;
1522
1523    if (speed < 0 || speed > 150000)
1524	return -1;
1525
1526    /* determine which prescaler to use */
1527    for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
1528	    prescaler_unit--, prescaler >>= 2) {
1529	if (CYCLOM_CLOCK/prescaler/speed > 63)
1530	    break;
1531    }
1532
1533    divider = (CYCLOM_CLOCK/prescaler*2/speed + 1)/2;	/* round off */
1534    if (divider > 255)
1535	divider = 255;
1536    actual = CYCLOM_CLOCK/prescaler/divider;
1537    error = ((actual-speed)*2000/speed +1)/2;	/* percentage */
1538
1539    /* 3.0% max error tolerance */
1540    if (error < -30 || error > 30)
1541	return -1;
1542
1543#if 0
1544    printf("prescaler = %d (%d)\n", prescaler, prescaler_unit);
1545    printf("divider = %d (%x)\n", divider, divider);
1546    printf("actual = %d\n", actual);
1547    printf("error = %d\n", error);
1548#endif
1549
1550    *prescaler_io = prescaler_unit;
1551    return divider;
1552} /* end of cyspeed() */
1553
1554
1555static void
1556cd1400_channel_cmd(cy_addr base, u_char cmd)
1557{
1558 	/* XXX hsu@clinet.fi: This is always more dependent on ISA bus speed,
1559	   as the card is probed every round?  Replaced delaycount with 8k.
1560	   Either delaycount has to be implemented in FreeBSD or more sensible
1561	   way of doing these should be implemented.  DELAY isn't enough here.
1562	   */
1563	unsigned maxwait = 5 * 8 * 1024;	/* approx. 5 ms */
1564
1565	/* wait for processing of previous command to complete */
1566	while (*(base + CD1400_CCR) && maxwait--)
1567	  	;
1568
1569	if (!maxwait)
1570		log(LOG_ERR, "cy: channel command timeout (%d loops) - arrgh\n",
1571		    5 * 8 * 1024);
1572
1573	*(base + CD1400_CCR) = cmd;
1574} /* end of cd1400_channel_cmd() */
1575
1576
1577#ifdef CyDebug
1578/* useful in ddb */
1579void
1580cyclear(void)
1581{
1582    /* clear the timeout request */
1583    disable_intr();
1584    timeout_scheduled = 0;
1585    enable_intr();
1586}
1587
1588void
1589cyclearintr(void)
1590{
1591    /* clear interrupts */
1592    *(cyclom_base + CYCLOM_CLEAR_INTR) = (u_char)0;
1593}
1594
1595int
1596cyparam_dummy(struct tty *tp, struct termios *t)
1597{
1598    return 0;
1599}
1600
1601void
1602cyset(int unit, int active)
1603{
1604    if (unit < 0 || unit >= /* NCY *? */ PORTS_PER_CYCLOM) {
1605	printf("bad unit number %d\n", unit);
1606	return;
1607    }
1608#ifdef __FreeBSD__
1609    cy_tty[unit].t_param = active ? cyparam : cyparam_dummy;
1610#else
1611    cy_tty[unit]->t_param = active ? cyparam : cyparam_dummy;
1612#endif
1613}
1614
1615
1616/* useful in ddb */
1617void
1618cystatus(int unit)
1619{
1620	struct cy	*infop = info[unit];
1621	struct tty	*tp = infop->tty;
1622	cy_addr		base = infop->base_addr;
1623
1624	printf("info for channel %d\n", unit);
1625	printf("------------------\n");
1626
1627	printf("cd1400 base address:\t0x%x\n", (int)infop->base_addr);
1628
1629	/* select the port */
1630	*(base + CD1400_CAR) = (u_char)unit;
1631
1632	printf("saved channel_control:\t%02x\n", infop->channel_control);
1633	printf("saved cor1:\t\t%02x\n", infop->cor[0]);
1634	printf("service request enable reg:\t%02x (%02x cached)\n",
1635		(u_char)*(base + CD1400_SRER), infop->intr_enable);
1636	printf("service request register:\t%02x\n",
1637		(u_char)*(base + CD1400_SVRR));
1638	printf("\n");
1639	printf("modem status:\t\t\t%02x (%02x cached)\n",
1640		(u_char)*(base + CD1400_MSVR), infop->modem_sig);
1641	printf("rx/tx/mdm interrupt registers:\t%02x %02x %02x\n",
1642		(u_char)*(base + CD1400_RIR), (u_char)*(base + CD1400_TIR),
1643		(u_char)*(base + CD1400_MIR));
1644	printf("\n");
1645	if (tp) {
1646		printf("tty state:\t\t\t%04x\n", tp->t_state);
1647		printf("upper layer queue lengths:\t%d raw, %d canon, %d output\n",
1648		    tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
1649	}
1650	else
1651		printf("tty state:\t\t\tclosed\n");
1652	printf("\n");
1653
1654	printf("calls to cystart():\t\t%d (%d useful)\n",
1655		infop->start_count, infop->start_real);
1656	printf("\n");
1657	printf("total cyclom service probes:\t%d\n", cy_svrr_probes);
1658	printf("calls to upper layer:\t\t%d\n", cy_timeouts);
1659	printf("rx buffer chars free:\t\t%d\n", infop->rx_buf->free);
1660#ifdef TxBuffer
1661	printf("tx buffer chars used:\t\t%d\n", infop->tx_buf.used);
1662#endif
1663	printf("received chars:\t\t\t%d good, %d exception\n",
1664		infop->recv_normal, infop->recv_exception);
1665	printf("transmitted chars:\t\t%d\n", infop->xmit);
1666	printf("modem signal deltas:\t\t%d\n", infop->mdm);
1667	printf("\n");
1668} /* end of cystatus() */
1669#endif
1670#endif /* NCY > 0 */
1671