rc.c revision 131981
1/*
2 * Copyright (C) 1995 by Pavel Antonov, Moscow, Russia.
3 * Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia.
4 * Copyright (C) 2002 by John Baldwin <jhb@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/rc/rc.c 131981 2004-07-11 15:18:39Z phk $
29 */
30
31/*
32 * SDL Communications Riscom/8 (based on Cirrus Logic CL-CD180) driver
33 *
34 */
35
36/*#define RCDEBUG*/
37
38#include "opt_tty.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/bus.h>
43#include <sys/conf.h>
44#include <sys/fcntl.h>
45#include <sys/interrupt.h>
46#include <sys/kernel.h>
47#include <sys/malloc.h>
48#include <sys/module.h>
49#include <sys/serial.h>
50#include <sys/tty.h>
51#include <machine/bus.h>
52#include <machine/resource.h>
53#include <sys/rman.h>
54
55#include <dev/ic/cd180.h>
56#include <dev/rc/rcreg.h>
57#include <isa/isavar.h>
58
59#define	IOBASE_ADDRS	14
60
61#define	DEV_TO_RC(dev)		(struct rc_chans *)((dev)->si_drv1)
62#define	TTY_TO_RC(tty)		DEV_TO_RC((tty)->t_dev)
63
64#define rcin(sc, port)		RC_IN(sc, port)
65#define rcout(sc, port, v)	RC_OUT(sc, port, v)
66
67#define WAITFORCCR(sc, chan)	rc_wait0((sc), (chan), __LINE__)
68
69#define CCRCMD(sc, chan, cmd) do {					\
70	WAITFORCCR((sc), (chan));					\
71	rcout((sc), CD180_CCR, (cmd));					\
72} while (0)
73
74#define RC_IBUFSIZE     256
75#define RB_I_HIGH_WATER (TTYHOG - 2 * RC_IBUFSIZE)
76#define RC_OBUFSIZE     512
77#define RC_IHIGHWATER   (3 * RC_IBUFSIZE / 4)
78#define INPUT_FLAGS_SHIFT (2 * RC_IBUFSIZE)
79#define LOTS_OF_EVENTS  64
80
81#define RC_FAKEID       0x10
82
83#define CALLOUT(dev)    (((intptr_t)(dev)->si_drv2) != 0)
84
85/* Per-channel structure */
86struct rc_chans  {
87	struct rc_softc *rc_rcb;                /* back ptr             */
88	struct cdev *rc_dev;		/* non-callout device	*/
89	struct cdev *rc_cdev;		/* callout device	*/
90	u_short          rc_flags;              /* Misc. flags          */
91	int              rc_chan;               /* Channel #            */
92	u_char           rc_ier;                /* intr. enable reg     */
93	u_char           rc_msvr;               /* modem sig. status    */
94	u_char           rc_cor2;               /* options reg          */
95	u_char           rc_pendcmd;            /* special cmd pending  */
96	u_int            rc_dcdwaits;           /* how many waits DCD in open */
97	struct tty       rc_tp;                 /* tty struct           */
98	u_char          *rc_iptr;               /* Chars input buffer         */
99	u_char          *rc_hiwat;              /* hi-water mark        */
100	u_char          *rc_bufend;             /* end of buffer        */
101	u_char          *rc_optr;               /* ptr in output buf    */
102	u_char          *rc_obufend;            /* end of output buf    */
103	u_char           rc_ibuf[4 * RC_IBUFSIZE];  /* input buffer         */
104	u_char           rc_obuf[RC_OBUFSIZE];  /* output buffer        */
105	struct callout	 rc_dtrcallout;
106};
107
108/* Per-board structure */
109struct rc_softc {
110	device_t	 sc_dev;
111	struct resource *sc_irq;
112	struct resource *sc_port[IOBASE_ADDRS];
113	int		 sc_irqrid;
114	void		*sc_hwicookie;
115	bus_space_tag_t  sc_bt;
116	bus_space_handle_t sc_bh;
117	u_int            sc_unit;       /* unit #               */
118	u_char           sc_dtr;        /* DTR status           */
119	int		 sc_opencount;
120	int		 sc_scheduled_event;
121	void		*sc_swicookie;
122	struct rc_chans  sc_channels[CD180_NCHAN]; /* channels */
123};
124
125/* Static prototypes */
126static void rc_break(struct tty *, int);
127static void rc_release_resources(device_t dev);
128static void rc_intr(void *);
129static void rc_hwreset(struct rc_softc *, unsigned int);
130static int  rc_test(struct rc_softc *);
131static void rc_discard_output(struct rc_chans *);
132static void rc_hardclose(struct rc_chans *);
133static int  rc_modem(struct tty *, int, int);
134static void rc_start(struct tty *);
135static void rc_stop(struct tty *, int rw);
136static int  rc_param(struct tty *, struct termios *);
137static void rc_pollcard(void *);
138static void rc_reinit(struct rc_softc *);
139#ifdef RCDEBUG
140static void printrcflags();
141#endif
142static void rc_wait0(struct rc_softc *sc, int chan, int line);
143
144static	d_open_t	rcopen;
145static	d_close_t	rcclose;
146
147static struct cdevsw rc_cdevsw = {
148	.d_version =	D_VERSION,
149	.d_open =	rcopen,
150	.d_close =	rcclose,
151	.d_name =	"rc",
152	.d_flags =	D_TTY | D_NEEDGIANT,
153};
154
155static devclass_t rc_devclass;
156
157/* Flags */
158#define RC_DTR_OFF      0x0001          /* DTR wait, for close/open     */
159#define RC_ACTOUT       0x0002          /* Dial-out port active         */
160#define RC_RTSFLOW      0x0004          /* RTS flow ctl enabled         */
161#define RC_CTSFLOW      0x0008          /* CTS flow ctl enabled         */
162#define RC_DORXFER      0x0010          /* RXFER event planned          */
163#define RC_DOXXFER      0x0020          /* XXFER event planned          */
164#define RC_MODCHG       0x0040          /* Modem status changed         */
165#define RC_OSUSP        0x0080          /* Output suspended             */
166#define RC_OSBUSY       0x0100          /* start() routine in progress  */
167#define RC_WAS_BUFOVFL  0x0200          /* low-level buffer ovferflow   */
168#define RC_WAS_SILOVFL  0x0400          /* silo buffer overflow         */
169#define RC_SEND_RDY     0x0800          /* ready to send */
170
171/* Table for translation of RCSR status bits to internal form */
172static int rc_rcsrt[16] = {
173	0,             TTY_OE,               TTY_FE,
174	TTY_FE|TTY_OE, TTY_PE,               TTY_PE|TTY_OE,
175	TTY_PE|TTY_FE, TTY_PE|TTY_FE|TTY_OE, TTY_BI,
176	TTY_BI|TTY_OE, TTY_BI|TTY_FE,        TTY_BI|TTY_FE|TTY_OE,
177	TTY_BI|TTY_PE, TTY_BI|TTY_PE|TTY_OE, TTY_BI|TTY_PE|TTY_FE,
178	TTY_BI|TTY_PE|TTY_FE|TTY_OE
179};
180
181static int rc_ports[] =
182    { 0x220, 0x240, 0x250, 0x260, 0x2a0, 0x2b0, 0x300, 0x320 };
183static int iobase_addrs[IOBASE_ADDRS] =
184    { 0, 0x400, 0x800, 0xc00, 0x1400, 0x1800, 0x1c00, 0x2000,
185      0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x8000 };
186
187/**********************************************/
188
189static int
190rc_probe(device_t dev)
191{
192	u_int port;
193	int i, found;
194
195	/*
196	 * We don't know of any PnP ID's for these cards.
197	 */
198	if (isa_get_logicalid(dev) != 0)
199		return (ENXIO);
200
201	/*
202	 * We have to have an IO port hint that is valid.
203	 */
204	port = isa_get_port(dev);
205	if (port == -1)
206		return (ENXIO);
207	found = 0;
208	for (i = 0; i < sizeof(rc_ports) / sizeof(int); i++)
209		if (rc_ports[i] == port) {
210			found = 1;
211			break;
212		}
213	if (!found)
214		return (ENXIO);
215
216	/*
217	 * We have to have an IRQ hint.
218	 */
219	if (isa_get_irq(dev) == -1)
220		return (ENXIO);
221
222	device_set_desc(dev, "SDL Riscom/8");
223	return (0);
224}
225
226static int
227rc_attach(device_t dev)
228{
229 	struct rc_chans *rc;
230	struct tty *tp;
231	struct rc_softc *sc;
232	u_int port;
233	int base, chan, error, i, x;
234	struct cdev *cdev;
235
236	sc = device_get_softc(dev);
237	sc->sc_dev = dev;
238
239	/*
240	 * We need to have IO ports.  Lots of them.  We need
241	 * the following ranges relative to the base port:
242	 * 0x0    -   0x10
243	 * 0x400  -  0x410
244	 * 0x800  -  0x810
245	 * 0xc00  -  0xc10
246	 * 0x1400 - 0x1410
247	 * 0x1800 - 0x1810
248	 * 0x1c00 - 0x1c10
249	 * 0x2000 - 0x2010
250	 * 0x3000 - 0x3010
251	 * 0x3400 - 0x3410
252	 * 0x3800 - 0x3810
253	 * 0x3c00 - 0x3c10
254	 * 0x4000 - 0x4010
255	 * 0x8000 - 0x8010
256	 */
257	port = isa_get_port(dev);
258	for (i = 0; i < IOBASE_ADDRS; i++)
259		if (bus_set_resource(dev, SYS_RES_IOPORT, i,
260		    port + iobase_addrs[i], 0x10) != 0)
261			return (ENXIO);
262	error = ENOMEM;
263	for (i = 0; i < IOBASE_ADDRS; i++) {
264		x = i;
265		sc->sc_port[i] = bus_alloc_resource(dev, SYS_RES_IOPORT, &x,
266		    0ul, ~0ul, 0x10, RF_ACTIVE);
267		if (x != i) {
268			device_printf(dev, "ioport %d was rid %d\n", i, x);
269			goto fail;
270		}
271		if (sc->sc_port[i] == NULL) {
272			device_printf(dev, "failed to alloc ioports %x-%x\n",
273			    port + iobase_addrs[i],
274			    port + iobase_addrs[i] + 0x10);
275			goto fail;
276		}
277	}
278	sc->sc_bt = rman_get_bustag(sc->sc_port[0]);
279	sc->sc_bh = rman_get_bushandle(sc->sc_port[0]);
280
281	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid,
282	    RF_ACTIVE);
283	if (sc->sc_irq == NULL) {
284		device_printf(dev, "failed to alloc IRQ\n");
285		goto fail;
286	}
287
288	/*
289	 * Now do some actual tests to make sure it works.
290	 */
291	error = ENXIO;
292	rcout(sc, CD180_PPRL, 0x22); /* Random values to Prescale reg. */
293	rcout(sc, CD180_PPRH, 0x11);
294	if (rcin(sc, CD180_PPRL) != 0x22 || rcin(sc, CD180_PPRH) != 0x11)
295		goto fail;
296	if (rc_test(sc))
297		goto fail;
298
299	/*
300	 * Ok, start actually hooking things up.
301	 */
302	sc->sc_unit = device_get_unit(dev);
303	/*sc->sc_chipid = 0x10 + device_get_unit(dev);*/
304	device_printf(dev, "%d chans, firmware rev. %c\n",
305		CD180_NCHAN, (rcin(sc, CD180_GFRCR) & 0xF) + 'A');
306	rc = sc->sc_channels;
307	base = CD180_NCHAN * sc->sc_unit;
308	for (chan = 0; chan < CD180_NCHAN; chan++, rc++) {
309		rc->rc_rcb     = sc;
310		rc->rc_chan    = chan;
311		rc->rc_iptr    = rc->rc_ibuf;
312		rc->rc_bufend  = &rc->rc_ibuf[RC_IBUFSIZE];
313		rc->rc_hiwat   = &rc->rc_ibuf[RC_IHIGHWATER];
314		rc->rc_optr    = rc->rc_obufend  = rc->rc_obuf;
315		callout_init(&rc->rc_dtrcallout, 0);
316		tp = &rc->rc_tp;
317		ttychars(tp);
318		tp->t_lflag = tp->t_iflag = tp->t_oflag = 0;
319		tp->t_cflag = TTYDEF_CFLAG;
320		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
321		cdev = make_dev(&rc_cdevsw, chan + base,
322		    UID_ROOT, GID_WHEEL, 0600, "ttym%d", chan + base);
323		cdev->si_drv1 = rc;
324		cdev->si_drv2 = 0;
325		cdev->si_tty = tp;
326		rc->rc_dev = cdev;
327		cdev = make_dev(&rc_cdevsw, chan + base + 128,
328		    UID_UUCP, GID_DIALER, 0660, "cuam%d", chan + base);
329		cdev->si_drv1 = rc;
330		cdev->si_drv2 = (void *)1;
331		cdev->si_tty = tp;
332		rc->rc_cdev = cdev;
333	}
334
335	error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_TTY, rc_intr, sc,
336	    &sc->sc_hwicookie);
337	if (error) {
338		device_printf(dev, "failed to register interrupt handler\n");
339		goto fail;
340	}
341
342	swi_add(&tty_ithd, "tty:rc", rc_pollcard, sc, SWI_TTY, 0,
343	    &sc->sc_swicookie);
344	return (0);
345
346fail:
347	rc_release_resources(dev);
348	return (error);
349}
350
351static int
352rc_detach(device_t dev)
353{
354	struct rc_softc *sc;
355	struct rc_chans *rc;
356	int error, i;
357
358	sc = device_get_softc(dev);
359	if (sc->sc_opencount > 0)
360		return (EBUSY);
361	sc->sc_opencount = -1;
362
363	rc = sc->sc_channels;
364	for (i = 0; i < CD180_NCHAN; i++, rc++) {
365		ttygone(&rc->rc_tp);
366		destroy_dev(rc->rc_dev);
367		destroy_dev(rc->rc_cdev);
368	}
369
370	error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie);
371	if (error)
372		device_printf(dev, "failed to deregister interrupt handler\n");
373	ithread_remove_handler(sc->sc_swicookie);
374	rc_release_resources(dev);
375
376	return (0);
377}
378
379static void
380rc_release_resources(device_t dev)
381{
382	struct rc_softc *sc;
383	int i;
384
385	sc = device_get_softc(dev);
386	if (sc->sc_irq != NULL) {
387		bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
388		    sc->sc_irq);
389		sc->sc_irq = NULL;
390	}
391	for (i = 0; i < IOBASE_ADDRS; i++) {
392		if (sc->sc_port[i] == NULL)
393			break;
394		bus_release_resource(dev, SYS_RES_IOPORT, i, sc->sc_port[i]);
395		sc->sc_port[i] = NULL;
396	}
397}
398
399/* RC interrupt handling */
400static void
401rc_intr(void *arg)
402{
403	struct rc_softc        *sc;
404	struct rc_chans        *rc;
405	int                    resid, chan;
406	u_char                 val, iack, bsr, ucnt, *optr;
407	int                    good_data, t_state;
408
409	sc = (struct rc_softc *)arg;
410	bsr = ~(rcin(sc, RC_BSR));
411	if (!(bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT))) {
412		device_printf(sc->sc_dev, "extra interrupt\n");
413		rcout(sc, CD180_EOIR, 0);
414		return;
415	}
416
417	while (bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT)) {
418#ifdef RCDEBUG_DETAILED
419		device_printf(sc->sc_dev, "intr (%p) %s%s%s%s\n", arg, bsr,
420			(bsr & RC_BSR_TOUT)?"TOUT ":"",
421			(bsr & RC_BSR_RXINT)?"RXINT ":"",
422			(bsr & RC_BSR_TXINT)?"TXINT ":"",
423			(bsr & RC_BSR_MOINT)?"MOINT":"");
424#endif
425		if (bsr & RC_BSR_TOUT) {
426			device_printf(sc->sc_dev,
427			    "hardware failure, reset board\n");
428			rcout(sc, RC_CTOUT, 0);
429			rc_reinit(sc);
430			return;
431		}
432		if (bsr & RC_BSR_RXINT) {
433			iack = rcin(sc, RC_PILR_RX);
434			good_data = (iack == (GIVR_IT_RGDI | RC_FAKEID));
435			if (!good_data && iack != (GIVR_IT_REI | RC_FAKEID)) {
436				device_printf(sc->sc_dev,
437				    "fake rxint: %02x\n", iack);
438				goto more_intrs;
439			}
440			chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH);
441			rc = &sc->sc_channels[chan];
442			t_state = rc->rc_tp.t_state;
443			/* Do RTS flow control stuff */
444			if (  (rc->rc_flags & RC_RTSFLOW)
445			    || !(t_state & TS_ISOPEN)
446			   ) {
447				if (  (   !(t_state & TS_ISOPEN)
448				       || (t_state & TS_TBLOCK)
449				      )
450				    && (rc->rc_msvr & MSVR_RTS)
451				   )
452					rcout(sc, CD180_MSVR,
453						rc->rc_msvr &= ~MSVR_RTS);
454				else if (!(rc->rc_msvr & MSVR_RTS))
455					rcout(sc, CD180_MSVR,
456						rc->rc_msvr |= MSVR_RTS);
457			}
458			ucnt  = rcin(sc, CD180_RDCR) & 0xF;
459			resid = 0;
460
461			if (t_state & TS_ISOPEN) {
462				/* check for input buffer overflow */
463				if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) {
464					resid  = ucnt;
465					ucnt   = rc->rc_bufend - rc->rc_iptr;
466					resid -= ucnt;
467					if (!(rc->rc_flags & RC_WAS_BUFOVFL)) {
468						rc->rc_flags |= RC_WAS_BUFOVFL;
469						sc->sc_scheduled_event++;
470					}
471				}
472				optr = rc->rc_iptr;
473				/* check foor good data */
474				if (good_data) {
475					while (ucnt-- > 0) {
476						val = rcin(sc, CD180_RDR);
477						optr[0] = val;
478						optr[INPUT_FLAGS_SHIFT] = 0;
479						optr++;
480						sc->sc_scheduled_event++;
481						if (val != 0 && val == rc->rc_tp.t_hotchar)
482							swi_sched(sc->sc_swicookie, 0);
483					}
484				} else {
485					/* Store also status data */
486					while (ucnt-- > 0) {
487						iack = rcin(sc, CD180_RCSR);
488						if (iack & RCSR_Timeout)
489							break;
490						if (   (iack & RCSR_OE)
491						    && !(rc->rc_flags & RC_WAS_SILOVFL)) {
492							rc->rc_flags |= RC_WAS_SILOVFL;
493							sc->sc_scheduled_event++;
494						}
495						val = rcin(sc, CD180_RDR);
496						/*
497						  Don't store PE if IGNPAR and BREAK if IGNBRK,
498						  this hack allows "raw" tty optimization
499						  works even if IGN* is set.
500						*/
501						if (   !(iack & (RCSR_PE|RCSR_FE|RCSR_Break))
502						    || ((!(iack & (RCSR_PE|RCSR_FE))
503						    ||  !(rc->rc_tp.t_iflag & IGNPAR))
504						    && (!(iack & RCSR_Break)
505						    ||  !(rc->rc_tp.t_iflag & IGNBRK)))) {
506							if (   (iack & (RCSR_PE|RCSR_FE))
507							    && (t_state & TS_CAN_BYPASS_L_RINT)
508							    && ((iack & RCSR_FE)
509							    ||  ((iack & RCSR_PE)
510							    &&  (rc->rc_tp.t_iflag & INPCK))))
511								val = 0;
512							else if (val != 0 && val == rc->rc_tp.t_hotchar)
513								swi_sched(sc->sc_swicookie, 0);
514							optr[0] = val;
515							optr[INPUT_FLAGS_SHIFT] = iack;
516							optr++;
517							sc->sc_scheduled_event++;
518						}
519					}
520				}
521				rc->rc_iptr = optr;
522				rc->rc_flags |= RC_DORXFER;
523			} else
524				resid = ucnt;
525			/* Clear FIFO if necessary */
526			while (resid-- > 0) {
527				if (!good_data)
528					iack = rcin(sc, CD180_RCSR);
529				else
530					iack = 0;
531				if (iack & RCSR_Timeout)
532					break;
533				(void) rcin(sc, CD180_RDR);
534			}
535			goto more_intrs;
536		}
537		if (bsr & RC_BSR_MOINT) {
538			iack = rcin(sc, RC_PILR_MODEM);
539			if (iack != (GIVR_IT_MSCI | RC_FAKEID)) {
540				device_printf(sc->sc_dev, "fake moint: %02x\n",
541				    iack);
542				goto more_intrs;
543			}
544			chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH);
545			rc = &sc->sc_channels[chan];
546			iack = rcin(sc, CD180_MCR);
547			rc->rc_msvr = rcin(sc, CD180_MSVR);
548			rcout(sc, CD180_MCR, 0);
549#ifdef RCDEBUG
550			printrcflags(rc, "moint");
551#endif
552			if (rc->rc_flags & RC_CTSFLOW) {
553				if (rc->rc_msvr & MSVR_CTS)
554					rc->rc_flags |= RC_SEND_RDY;
555				else
556					rc->rc_flags &= ~RC_SEND_RDY;
557			} else
558				rc->rc_flags |= RC_SEND_RDY;
559			if ((iack & MCR_CDchg) && !(rc->rc_flags & RC_MODCHG)) {
560				sc->sc_scheduled_event += LOTS_OF_EVENTS;
561				rc->rc_flags |= RC_MODCHG;
562				swi_sched(sc->sc_swicookie, 0);
563			}
564			goto more_intrs;
565		}
566		if (bsr & RC_BSR_TXINT) {
567			iack = rcin(sc, RC_PILR_TX);
568			if (iack != (GIVR_IT_TDI | RC_FAKEID)) {
569				device_printf(sc->sc_dev, "fake txint: %02x\n",
570				    iack);
571				goto more_intrs;
572			}
573			chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH);
574			rc = &sc->sc_channels[chan];
575			if (    (rc->rc_flags & RC_OSUSP)
576			    || !(rc->rc_flags & RC_SEND_RDY)
577			   )
578				goto more_intrs;
579			/* Handle breaks and other stuff */
580			if (rc->rc_pendcmd) {
581				rcout(sc, CD180_COR2, rc->rc_cor2 |= COR2_ETC);
582				rcout(sc, CD180_TDR,  CD180_C_ESC);
583				rcout(sc, CD180_TDR,  rc->rc_pendcmd);
584				rcout(sc, CD180_COR2, rc->rc_cor2 &= ~COR2_ETC);
585				rc->rc_pendcmd = 0;
586				goto more_intrs;
587			}
588			optr = rc->rc_optr;
589			resid = rc->rc_obufend - optr;
590			if (resid > CD180_NFIFO)
591				resid = CD180_NFIFO;
592			while (resid-- > 0)
593				rcout(sc, CD180_TDR, *optr++);
594			rc->rc_optr = optr;
595
596			/* output completed? */
597			if (optr >= rc->rc_obufend) {
598				rcout(sc, CD180_IER, rc->rc_ier &= ~IER_TxRdy);
599#ifdef RCDEBUG
600				device_printf(sc->sc_dev,
601				    "channel %d: output completed\n",
602				    rc->rc_chan);
603#endif
604				if (!(rc->rc_flags & RC_DOXXFER)) {
605					sc->sc_scheduled_event += LOTS_OF_EVENTS;
606					rc->rc_flags |= RC_DOXXFER;
607					swi_sched(sc->sc_swicookie, 0);
608				}
609			}
610		}
611	more_intrs:
612		rcout(sc, CD180_EOIR, 0);   /* end of interrupt */
613		rcout(sc, RC_CTOUT, 0);
614		bsr = ~(rcin(sc, RC_BSR));
615	}
616}
617
618/* Feed characters to output buffer */
619static void
620rc_start(struct tty *tp)
621{
622	struct rc_softc *sc;
623	struct rc_chans *rc;
624	int s;
625
626	rc = TTY_TO_RC(tp);
627	if (rc->rc_flags & RC_OSBUSY)
628		return;
629	sc = rc->rc_rcb;
630	s = spltty();
631	rc->rc_flags |= RC_OSBUSY;
632	critical_enter();
633	if (tp->t_state & TS_TTSTOP)
634		rc->rc_flags |= RC_OSUSP;
635	else
636		rc->rc_flags &= ~RC_OSUSP;
637	/* Do RTS flow control stuff */
638	if (   (rc->rc_flags & RC_RTSFLOW)
639	    && (tp->t_state & TS_TBLOCK)
640	    && (rc->rc_msvr & MSVR_RTS)
641	   ) {
642		rcout(sc, CD180_CAR, rc->rc_chan);
643		rcout(sc, CD180_MSVR, rc->rc_msvr &= ~MSVR_RTS);
644	} else if (!(rc->rc_msvr & MSVR_RTS)) {
645		rcout(sc, CD180_CAR, rc->rc_chan);
646		rcout(sc, CD180_MSVR, rc->rc_msvr |= MSVR_RTS);
647	}
648	critical_exit();
649	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
650		goto out;
651#ifdef RCDEBUG
652	printrcflags(rc, "rcstart");
653#endif
654	ttwwakeup(tp);
655#ifdef RCDEBUG
656	printf("rcstart: outq = %d obuf = %d\n",
657		tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr);
658#endif
659	if (tp->t_state & TS_BUSY)
660		goto out;    /* output still in progress ... */
661
662	if (tp->t_outq.c_cc > 0) {
663		u_int   ocnt;
664
665		tp->t_state |= TS_BUSY;
666		ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf);
667		critical_enter();
668		rc->rc_optr = rc->rc_obuf;
669		rc->rc_obufend = rc->rc_optr + ocnt;
670		critical_exit();
671		if (!(rc->rc_ier & IER_TxRdy)) {
672#ifdef RCDEBUG
673			device_printf(sc->sc_dev,
674			    "channel %d: rcstart enable txint\n", rc->rc_chan);
675#endif
676			rcout(sc, CD180_CAR, rc->rc_chan);
677			rcout(sc, CD180_IER, rc->rc_ier |= IER_TxRdy);
678		}
679	}
680out:
681	rc->rc_flags &= ~RC_OSBUSY;
682	(void) splx(s);
683}
684
685/* Handle delayed events. */
686void
687rc_pollcard(void *arg)
688{
689	struct rc_softc *sc;
690	struct rc_chans *rc;
691	struct tty *tp;
692	u_char *tptr, *eptr;
693	int chan, icnt;
694
695	sc = (struct rc_softc *)arg;
696	if (sc->sc_scheduled_event == 0)
697		return;
698	do {
699		rc = sc->sc_channels;
700		for (chan = 0; chan < CD180_NCHAN; rc++, chan++) {
701			tp = &rc->rc_tp;
702#ifdef RCDEBUG
703			if (rc->rc_flags & (RC_DORXFER|RC_DOXXFER|RC_MODCHG|
704			    RC_WAS_BUFOVFL|RC_WAS_SILOVFL))
705				printrcflags(rc, "rcevent");
706#endif
707			if (rc->rc_flags & RC_WAS_BUFOVFL) {
708				critical_enter();
709				rc->rc_flags &= ~RC_WAS_BUFOVFL;
710				sc->sc_scheduled_event--;
711				critical_exit();
712				device_printf(sc->sc_dev,
713			    "channel %d: interrupt-level buffer overflow\n",
714				     chan);
715			}
716			if (rc->rc_flags & RC_WAS_SILOVFL) {
717				critical_enter();
718				rc->rc_flags &= ~RC_WAS_SILOVFL;
719				sc->sc_scheduled_event--;
720				critical_exit();
721				device_printf(sc->sc_dev,
722				    "channel %d: silo overflow\n", chan);
723			}
724			if (rc->rc_flags & RC_MODCHG) {
725				critical_enter();
726				rc->rc_flags &= ~RC_MODCHG;
727				sc->sc_scheduled_event -= LOTS_OF_EVENTS;
728				critical_exit();
729				ttyld_modem(tp, !!(rc->rc_msvr & MSVR_CD));
730			}
731			if (rc->rc_flags & RC_DORXFER) {
732				critical_enter();
733				rc->rc_flags &= ~RC_DORXFER;
734				eptr = rc->rc_iptr;
735				if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE])
736					tptr = &rc->rc_ibuf[RC_IBUFSIZE];
737				else
738					tptr = rc->rc_ibuf;
739				icnt = eptr - tptr;
740				if (icnt > 0) {
741					if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) {
742						rc->rc_iptr   = rc->rc_ibuf;
743						rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE];
744						rc->rc_hiwat  = &rc->rc_ibuf[RC_IHIGHWATER];
745					} else {
746						rc->rc_iptr   = &rc->rc_ibuf[RC_IBUFSIZE];
747						rc->rc_bufend = &rc->rc_ibuf[2 * RC_IBUFSIZE];
748						rc->rc_hiwat  =
749							&rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER];
750					}
751					if (   (rc->rc_flags & RC_RTSFLOW)
752					    && (tp->t_state & TS_ISOPEN)
753					    && !(tp->t_state & TS_TBLOCK)
754					    && !(rc->rc_msvr & MSVR_RTS)
755					    ) {
756						rcout(sc, CD180_CAR, chan);
757						rcout(sc, CD180_MSVR,
758							rc->rc_msvr |= MSVR_RTS);
759					}
760					sc->sc_scheduled_event -= icnt;
761				}
762				critical_exit();
763
764				if (icnt <= 0 || !(tp->t_state & TS_ISOPEN))
765					goto done1;
766
767				if (   (tp->t_state & TS_CAN_BYPASS_L_RINT)
768				    && !(tp->t_state & TS_LOCAL)) {
769					if ((tp->t_rawq.c_cc + icnt) >= RB_I_HIGH_WATER
770					    && ((rc->rc_flags & RC_RTSFLOW) || (tp->t_iflag & IXOFF))
771					    && !(tp->t_state & TS_TBLOCK))
772						ttyblock(tp);
773					tk_nin += icnt;
774					tk_rawcc += icnt;
775					tp->t_rawcc += icnt;
776					if (b_to_q(tptr, icnt, &tp->t_rawq))
777						device_printf(sc->sc_dev,
778				    "channel %d: tty-level buffer overflow\n",
779						    chan);
780					ttwakeup(tp);
781					if ((tp->t_state & TS_TTSTOP) && ((tp->t_iflag & IXANY)
782					    || (tp->t_cc[VSTART] == tp->t_cc[VSTOP]))) {
783						tp->t_state &= ~TS_TTSTOP;
784						tp->t_lflag &= ~FLUSHO;
785						rc_start(tp);
786					}
787				} else {
788					for (; tptr < eptr; tptr++)
789						ttyld_rint(tp,
790						    (tptr[0] |
791						    rc_rcsrt[tptr[INPUT_FLAGS_SHIFT] & 0xF]));
792				}
793done1: ;
794			}
795			if (rc->rc_flags & RC_DOXXFER) {
796				critical_enter();
797				sc->sc_scheduled_event -= LOTS_OF_EVENTS;
798				rc->rc_flags &= ~RC_DOXXFER;
799				rc->rc_tp.t_state &= ~TS_BUSY;
800				critical_exit();
801				ttyld_start(tp);
802			}
803			if (sc->sc_scheduled_event == 0)
804				break;
805		}
806	} while (sc->sc_scheduled_event >= LOTS_OF_EVENTS);
807}
808
809static void
810rc_stop(struct tty *tp, int rw)
811{
812	struct rc_softc *sc;
813	struct rc_chans *rc;
814	u_char *tptr, *eptr;
815
816	rc = TTY_TO_RC(tp);
817	sc = rc->rc_rcb;
818#ifdef RCDEBUG
819	device_printf(sc->sc_dev, "channel %d: rc_stop %s%s\n",
820	    rc->rc_chan, (rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":"");
821#endif
822	if (rw & FWRITE)
823		rc_discard_output(rc);
824	critical_enter();
825	if (rw & FREAD) {
826		rc->rc_flags &= ~RC_DORXFER;
827		eptr = rc->rc_iptr;
828		if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) {
829			tptr = &rc->rc_ibuf[RC_IBUFSIZE];
830			rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE];
831		} else {
832			tptr = rc->rc_ibuf;
833			rc->rc_iptr = rc->rc_ibuf;
834		}
835		sc->sc_scheduled_event -= eptr - tptr;
836	}
837	if (tp->t_state & TS_TTSTOP)
838		rc->rc_flags |= RC_OSUSP;
839	else
840		rc->rc_flags &= ~RC_OSUSP;
841	critical_exit();
842}
843
844static int
845rcopen(struct cdev *dev, int flag, int mode, d_thread_t *td)
846{
847	struct rc_softc *sc;
848	struct rc_chans *rc;
849	struct tty *tp;
850	int s, error = 0;
851
852	rc = DEV_TO_RC(dev);
853	sc = rc->rc_rcb;
854	tp = &rc->rc_tp;
855	if (sc->sc_opencount < 0)
856		return (ENXIO);
857	sc->sc_opencount++;
858#ifdef RCDEBUG
859	device_printf(sc->sc_dev, "channel %d: rcopen: dev %p\n",
860	    rc->rc_chan, dev);
861#endif
862	s = spltty();
863
864again:
865	error = ttydtrwaitsleep(tp);
866	if (error != 0)
867		goto out;
868	if (tp->t_state & TS_ISOPEN) {
869		if (CALLOUT(dev)) {
870			if (!(rc->rc_flags & RC_ACTOUT)) {
871				error = EBUSY;
872				goto out;
873			}
874		} else {
875			if (rc->rc_flags & RC_ACTOUT) {
876				if (flag & O_NONBLOCK) {
877					error = EBUSY;
878					goto out;
879				}
880				error = tsleep(&rc->rc_rcb,
881				     TTIPRI|PCATCH, "rcbi", 0);
882				if (error)
883					goto out;
884				goto again;
885			}
886		}
887		if (tp->t_state & TS_XCLUDE &&
888		    suser(td)) {
889			error = EBUSY;
890			goto out;
891		}
892	} else {
893		tp->t_oproc   = rc_start;
894		tp->t_param   = rc_param;
895		tp->t_modem   = rc_modem;
896		tp->t_break   = rc_break;
897		tp->t_stop    = rc_stop;
898		tp->t_dev     = dev;
899
900		if (CALLOUT(dev))
901			tp->t_cflag |= CLOCAL;
902		else
903			tp->t_cflag &= ~CLOCAL;
904
905		error = rc_param(tp, &tp->t_termios);
906		if (error)
907			goto out;
908		(void) rc_modem(tp, SER_DTR | SER_RTS, 0);
909
910		if ((rc->rc_msvr & MSVR_CD) || CALLOUT(dev))
911			ttyld_modem(tp, 1);
912	}
913	if (!(tp->t_state & TS_CARR_ON) && !CALLOUT(dev)
914	    && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
915		rc->rc_dcdwaits++;
916		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "rcdcd", 0);
917		rc->rc_dcdwaits--;
918		if (error != 0)
919			goto out;
920		goto again;
921	}
922	error = ttyld_open(tp, dev);
923	ttyldoptim(tp);
924	if ((tp->t_state & TS_ISOPEN) && CALLOUT(dev))
925		rc->rc_flags |= RC_ACTOUT;
926out:
927	(void) splx(s);
928
929	if(rc->rc_dcdwaits == 0 && !(tp->t_state & TS_ISOPEN))
930		rc_hardclose(rc);
931
932	return error;
933}
934
935static int
936rcclose(struct cdev *dev, int flag, int mode, d_thread_t *td)
937{
938	struct rc_softc *sc;
939	struct rc_chans *rc;
940	struct tty *tp;
941	int  s;
942
943	rc = DEV_TO_RC(dev);
944	sc = rc->rc_rcb;
945	tp = &rc->rc_tp;
946#ifdef RCDEBUG
947	device_printf(sc->sc_dev, "channel %d: rcclose dev %p\n",
948	    rc->rc_chan, dev);
949#endif
950	s = spltty();
951	ttyld_close(tp, flag);
952	ttyldoptim(tp);
953	rc_hardclose(rc);
954	ttyclose(tp);
955	splx(s);
956	KASSERT(sc->sc_opencount > 0, ("rcclose: non-positive open count"));
957	sc->sc_opencount--;
958	return 0;
959}
960
961static void
962rc_hardclose(struct rc_chans *rc)
963{
964	struct rc_softc *sc;
965	struct tty *tp;
966	int s;
967
968	tp = &rc->rc_tp;
969	sc = rc->rc_rcb;
970	s = spltty();
971	rcout(sc, CD180_CAR, rc->rc_chan);
972
973	/* Disable rx/tx intrs */
974	rcout(sc, CD180_IER, rc->rc_ier = 0);
975	if (   (tp->t_cflag & HUPCL)
976	    || (!(rc->rc_flags & RC_ACTOUT)
977	       && !(rc->rc_msvr & MSVR_CD)
978	       && !(tp->t_cflag & CLOCAL))
979	    || !(tp->t_state & TS_ISOPEN)
980	   ) {
981		CCRCMD(sc, rc->rc_chan, CCR_ResetChan);
982		WAITFORCCR(sc, rc->rc_chan);
983		(void) rc_modem(tp, SER_RTS, 0);
984		ttydtrwaitstart(tp);
985	}
986	rc->rc_flags &= ~RC_ACTOUT;
987	wakeup( &rc->rc_rcb);  /* wake bi */
988	wakeup(TSA_CARR_ON(tp));
989	(void) splx(s);
990}
991
992/* Reset the bastard */
993static void
994rc_hwreset(struct rc_softc *sc, u_int chipid)
995{
996	CCRCMD(sc, -1, CCR_HWRESET);            /* Hardware reset */
997	DELAY(20000);
998	WAITFORCCR(sc, -1);
999
1000	rcout(sc, RC_CTOUT, 0);             /* Clear timeout  */
1001	rcout(sc, CD180_GIVR,  chipid);
1002	rcout(sc, CD180_GICR,  0);
1003
1004	/* Set Prescaler Registers (1 msec) */
1005	rcout(sc, CD180_PPRL, ((RC_OSCFREQ + 999) / 1000) & 0xFF);
1006	rcout(sc, CD180_PPRH, ((RC_OSCFREQ + 999) / 1000) >> 8);
1007
1008	/* Initialize Priority Interrupt Level Registers */
1009	rcout(sc, CD180_PILR1, RC_PILR_MODEM);
1010	rcout(sc, CD180_PILR2, RC_PILR_TX);
1011	rcout(sc, CD180_PILR3, RC_PILR_RX);
1012
1013	/* Reset DTR */
1014	rcout(sc, RC_DTREG, ~0);
1015}
1016
1017/* Set channel parameters */
1018static int
1019rc_param(struct tty *tp, struct termios *ts)
1020{
1021	struct rc_softc *sc;
1022	struct rc_chans *rc;
1023	int idivs, odivs, s, val, cflag, iflag, lflag, inpflow;
1024
1025	if (   ts->c_ospeed < 0 || ts->c_ospeed > 76800
1026	    || ts->c_ispeed < 0 || ts->c_ispeed > 76800
1027	   )
1028		return (EINVAL);
1029	if (ts->c_ispeed == 0)
1030		ts->c_ispeed = ts->c_ospeed;
1031	odivs = RC_BRD(ts->c_ospeed);
1032	idivs = RC_BRD(ts->c_ispeed);
1033
1034	rc = TTY_TO_RC(tp);
1035	sc = rc->rc_rcb;
1036	s = spltty();
1037
1038	/* Select channel */
1039	rcout(sc, CD180_CAR, rc->rc_chan);
1040
1041	/* If speed == 0, hangup line */
1042	if (ts->c_ospeed == 0) {
1043		CCRCMD(sc, rc->rc_chan, CCR_ResetChan);
1044		WAITFORCCR(sc, rc->rc_chan);
1045		(void) rc_modem(tp, 0, SER_DTR);
1046	}
1047
1048	tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1049	cflag = ts->c_cflag;
1050	iflag = ts->c_iflag;
1051	lflag = ts->c_lflag;
1052
1053	if (idivs > 0) {
1054		rcout(sc, CD180_RBPRL, idivs & 0xFF);
1055		rcout(sc, CD180_RBPRH, idivs >> 8);
1056	}
1057	if (odivs > 0) {
1058		rcout(sc, CD180_TBPRL, odivs & 0xFF);
1059		rcout(sc, CD180_TBPRH, odivs >> 8);
1060	}
1061
1062	/* set timeout value */
1063	if (ts->c_ispeed > 0) {
1064		int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1;
1065
1066		if (   !(lflag & ICANON)
1067		    && ts->c_cc[VMIN] != 0 && ts->c_cc[VTIME] != 0
1068		    && ts->c_cc[VTIME] * 10 > itm)
1069			itm = ts->c_cc[VTIME] * 10;
1070
1071		rcout(sc, CD180_RTPR, itm <= 255 ? itm : 255);
1072	}
1073
1074	switch (cflag & CSIZE) {
1075		case CS5:       val = COR1_5BITS;      break;
1076		case CS6:       val = COR1_6BITS;      break;
1077		case CS7:       val = COR1_7BITS;      break;
1078		default:
1079		case CS8:       val = COR1_8BITS;      break;
1080	}
1081	if (cflag & PARENB) {
1082		val |= COR1_NORMPAR;
1083		if (cflag & PARODD)
1084			val |= COR1_ODDP;
1085		if (!(cflag & INPCK))
1086			val |= COR1_Ignore;
1087	} else
1088		val |= COR1_Ignore;
1089	if (cflag & CSTOPB)
1090		val |= COR1_2SB;
1091	rcout(sc, CD180_COR1, val);
1092
1093	/* Set FIFO threshold */
1094	val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2;
1095	inpflow = 0;
1096	if (   (iflag & IXOFF)
1097	    && (   ts->c_cc[VSTOP] != _POSIX_VDISABLE
1098		&& (   ts->c_cc[VSTART] != _POSIX_VDISABLE
1099		    || (iflag & IXANY)
1100		   )
1101	       )
1102	   ) {
1103		inpflow = 1;
1104		val |= COR3_SCDE|COR3_FCT;
1105	}
1106	rcout(sc, CD180_COR3, val);
1107
1108	/* Initialize on-chip automatic flow control */
1109	val = 0;
1110	rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY);
1111	if (cflag & CCTS_OFLOW) {
1112		rc->rc_flags |= RC_CTSFLOW;
1113		val |= COR2_CtsAE;
1114	} else
1115		rc->rc_flags |= RC_SEND_RDY;
1116	if (tp->t_state & TS_TTSTOP)
1117		rc->rc_flags |= RC_OSUSP;
1118	else
1119		rc->rc_flags &= ~RC_OSUSP;
1120	if (cflag & CRTS_IFLOW)
1121		rc->rc_flags |= RC_RTSFLOW;
1122	else
1123		rc->rc_flags &= ~RC_RTSFLOW;
1124
1125	if (inpflow) {
1126		if (ts->c_cc[VSTART] != _POSIX_VDISABLE)
1127			rcout(sc, CD180_SCHR1, ts->c_cc[VSTART]);
1128		rcout(sc, CD180_SCHR2, ts->c_cc[VSTOP]);
1129		val |= COR2_TxIBE;
1130		if (iflag & IXANY)
1131			val |= COR2_IXM;
1132	}
1133
1134	rcout(sc, CD180_COR2, rc->rc_cor2 = val);
1135
1136	CCRCMD(sc, rc->rc_chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1137
1138	ttyldoptim(tp);
1139
1140	/* modem ctl */
1141	val = cflag & CLOCAL ? 0 : MCOR1_CDzd;
1142	if (cflag & CCTS_OFLOW)
1143		val |= MCOR1_CTSzd;
1144	rcout(sc, CD180_MCOR1, val);
1145
1146	val = cflag & CLOCAL ? 0 : MCOR2_CDod;
1147	if (cflag & CCTS_OFLOW)
1148		val |= MCOR2_CTSod;
1149	rcout(sc, CD180_MCOR2, val);
1150
1151	/* enable i/o and interrupts */
1152	CCRCMD(sc, rc->rc_chan,
1153		CCR_XMTREN | ((cflag & CREAD) ? CCR_RCVREN : CCR_RCVRDIS));
1154	WAITFORCCR(sc, rc->rc_chan);
1155
1156	rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD;
1157	if (cflag & CCTS_OFLOW)
1158		rc->rc_ier |= IER_CTS;
1159	if (cflag & CREAD)
1160		rc->rc_ier |= IER_RxData;
1161	if (tp->t_state & TS_BUSY)
1162		rc->rc_ier |= IER_TxRdy;
1163	if (ts->c_ospeed != 0)
1164		rc_modem(tp, SER_DTR, 0);
1165	if ((cflag & CCTS_OFLOW) && (rc->rc_msvr & MSVR_CTS))
1166		rc->rc_flags |= RC_SEND_RDY;
1167	rcout(sc, CD180_IER, rc->rc_ier);
1168	(void) splx(s);
1169	return 0;
1170}
1171
1172/* Re-initialize board after bogus interrupts */
1173static void
1174rc_reinit(struct rc_softc *sc)
1175{
1176	struct rc_chans *rc;
1177	int i;
1178
1179	rc_hwreset(sc, RC_FAKEID);
1180	rc = sc->sc_channels;
1181	for (i = 0; i < CD180_NCHAN; i++, rc++)
1182		(void) rc_param(&rc->rc_tp, &rc->rc_tp.t_termios);
1183}
1184
1185/* Modem control routines */
1186
1187static int
1188rc_modem(struct tty *tp, int biton, int bitoff)
1189{
1190	struct rc_chans *rc;
1191	struct rc_softc *sc;
1192	u_char *dtr;
1193	u_char msvr;
1194
1195	rc = DEV_TO_RC(tp->t_dev);
1196	sc = rc->rc_rcb;
1197	dtr = &sc->sc_dtr;
1198	rcout(sc, CD180_CAR, rc->rc_chan);
1199
1200	if (biton == 0 && bitoff == 0) {
1201		msvr = rc->rc_msvr = rcin(sc, CD180_MSVR);
1202
1203		if (msvr & MSVR_RTS)
1204			biton |= SER_RTS;
1205		if (msvr & MSVR_CTS)
1206			biton |= SER_CTS;
1207		if (msvr & MSVR_DSR)
1208			biton |= SER_DSR;
1209		if (msvr & MSVR_DTR)
1210			biton |= SER_DTR;
1211		if (msvr & MSVR_CD)
1212			biton |= SER_DCD;
1213		if (~rcin(sc, RC_RIREG) & (1 << rc->rc_chan))
1214			biton |= SER_RI;
1215		return biton;
1216	}
1217	if (biton & SER_DTR)
1218		rcout(sc, RC_DTREG, ~(*dtr |= 1 << rc->rc_chan));
1219	if (bitoff & SER_DTR)
1220		rcout(sc, RC_DTREG, ~(*dtr &= ~(1 << rc->rc_chan)));
1221	msvr = rcin(sc, CD180_MSVR);
1222	if (biton & SER_DTR)
1223		msvr |= MSVR_DTR;
1224	if (bitoff & SER_DTR)
1225		msvr &= ~MSVR_DTR;
1226	if (biton & SER_RTS)
1227		msvr |= MSVR_RTS;
1228	if (bitoff & SER_RTS)
1229		msvr &= ~MSVR_RTS;
1230	rcout(sc, CD180_MSVR, msvr);
1231	return 0;
1232}
1233
1234static void
1235rc_break(struct tty *tp, int brk)
1236{
1237	struct rc_chans *rc;
1238
1239	rc = DEV_TO_RC(tp->t_dev);
1240
1241	if (brk)
1242		rc->rc_pendcmd = CD180_C_SBRK;
1243	else
1244		rc->rc_pendcmd = CD180_C_EBRK;
1245}
1246
1247#define ERR(s) do {							\
1248	device_printf(sc->sc_dev, "%s", "");				\
1249	printf s ;							\
1250	printf("\n");							\
1251	(void) splx(old_level);						\
1252	return 1;							\
1253} while (0)
1254
1255/* Test the board. */
1256int
1257rc_test(struct rc_softc *sc)
1258{
1259	int     chan = 0;
1260	int     i = 0, rcnt, old_level;
1261	unsigned int    iack, chipid;
1262	unsigned short  divs;
1263	static  u_char  ctest[] = "\377\125\252\045\244\0\377";
1264#define CTLEN   8
1265
1266	struct rtest {
1267		u_char  txbuf[CD180_NFIFO];     /* TX buffer  */
1268		u_char  rxbuf[CD180_NFIFO];     /* RX buffer  */
1269		int     rxptr;                  /* RX pointer */
1270		int     txptr;                  /* TX pointer */
1271	} tchans[CD180_NCHAN];
1272
1273	old_level = spltty();
1274
1275	chipid = RC_FAKEID;
1276
1277	/* First, reset board to inital state */
1278	rc_hwreset(sc, chipid);
1279
1280	divs = RC_BRD(19200);
1281
1282	/* Initialize channels */
1283	for (chan = 0; chan < CD180_NCHAN; chan++) {
1284
1285		/* Select and reset channel */
1286		rcout(sc, CD180_CAR, chan);
1287		CCRCMD(sc, chan, CCR_ResetChan);
1288		WAITFORCCR(sc, chan);
1289
1290		/* Set speed */
1291		rcout(sc, CD180_RBPRL, divs & 0xFF);
1292		rcout(sc, CD180_RBPRH, divs >> 8);
1293		rcout(sc, CD180_TBPRL, divs & 0xFF);
1294		rcout(sc, CD180_TBPRH, divs >> 8);
1295
1296		/* set timeout value */
1297		rcout(sc, CD180_RTPR,  0);
1298
1299		/* Establish local loopback */
1300		rcout(sc, CD180_COR1, COR1_NOPAR | COR1_8BITS | COR1_1SB);
1301		rcout(sc, CD180_COR2, COR2_LLM);
1302		rcout(sc, CD180_COR3, CD180_NFIFO);
1303		CCRCMD(sc, chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1304		CCRCMD(sc, chan, CCR_RCVREN | CCR_XMTREN);
1305		WAITFORCCR(sc, chan);
1306		rcout(sc, CD180_MSVR, MSVR_RTS);
1307
1308		/* Fill TXBUF with test data */
1309		for (i = 0; i < CD180_NFIFO; i++) {
1310			tchans[chan].txbuf[i] = ctest[i];
1311			tchans[chan].rxbuf[i] = 0;
1312		}
1313		tchans[chan].txptr = tchans[chan].rxptr = 0;
1314
1315		/* Now, start transmit */
1316		rcout(sc, CD180_IER, IER_TxMpty|IER_RxData);
1317	}
1318	/* Pseudo-interrupt poll stuff */
1319	for (rcnt = 10000; rcnt-- > 0; rcnt--) {
1320		i = ~(rcin(sc, RC_BSR));
1321		if (i & RC_BSR_TOUT)
1322			ERR(("BSR timeout bit set\n"));
1323		else if (i & RC_BSR_TXINT) {
1324			iack = rcin(sc, RC_PILR_TX);
1325			if (iack != (GIVR_IT_TDI | chipid))
1326				ERR(("Bad TX intr ack (%02x != %02x)\n",
1327					iack, GIVR_IT_TDI | chipid));
1328			chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH;
1329			/* If no more data to transmit, disable TX intr */
1330			if (tchans[chan].txptr >= CD180_NFIFO) {
1331				iack = rcin(sc, CD180_IER);
1332				rcout(sc, CD180_IER, iack & ~IER_TxMpty);
1333			} else {
1334				for (iack = tchans[chan].txptr;
1335				    iack < CD180_NFIFO; iack++)
1336					rcout(sc, CD180_TDR,
1337					    tchans[chan].txbuf[iack]);
1338				tchans[chan].txptr = iack;
1339			}
1340			rcout(sc, CD180_EOIR, 0);
1341		} else if (i & RC_BSR_RXINT) {
1342			u_char ucnt;
1343
1344			iack = rcin(sc, RC_PILR_RX);
1345			if (iack != (GIVR_IT_RGDI | chipid) &&
1346			    iack != (GIVR_IT_REI  | chipid))
1347				ERR(("Bad RX intr ack (%02x != %02x)\n",
1348					iack, GIVR_IT_RGDI | chipid));
1349			chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH;
1350			ucnt = rcin(sc, CD180_RDCR) & 0xF;
1351			while (ucnt-- > 0) {
1352				iack = rcin(sc, CD180_RCSR);
1353				if (iack & RCSR_Timeout)
1354					break;
1355				if (iack & 0xF)
1356					ERR(("Bad char chan %d (RCSR = %02X)\n",
1357					    chan, iack));
1358				if (tchans[chan].rxptr > CD180_NFIFO)
1359					ERR(("Got extra chars chan %d\n",
1360					    chan));
1361				tchans[chan].rxbuf[tchans[chan].rxptr++] =
1362					rcin(sc, CD180_RDR);
1363			}
1364			rcout(sc, CD180_EOIR, 0);
1365		}
1366		rcout(sc, RC_CTOUT, 0);
1367		for (iack = chan = 0; chan < CD180_NCHAN; chan++)
1368			if (tchans[chan].rxptr >= CD180_NFIFO)
1369				iack++;
1370		if (iack == CD180_NCHAN)
1371			break;
1372	}
1373	for (chan = 0; chan < CD180_NCHAN; chan++) {
1374		/* Select and reset channel */
1375		rcout(sc, CD180_CAR, chan);
1376		CCRCMD(sc, chan, CCR_ResetChan);
1377	}
1378
1379	if (!rcnt)
1380		ERR(("looses characters during local loopback\n"));
1381	/* Now, check data */
1382	for (chan = 0; chan < CD180_NCHAN; chan++)
1383		for (i = 0; i < CD180_NFIFO; i++)
1384			if (ctest[i] != tchans[chan].rxbuf[i])
1385				ERR(("data mismatch chan %d ptr %d (%d != %d)\n",
1386				    chan, i, ctest[i], tchans[chan].rxbuf[i]));
1387	(void) splx(old_level);
1388	return 0;
1389}
1390
1391#ifdef RCDEBUG
1392static void
1393printrcflags(struct rc_chans *rc, char *comment)
1394{
1395	struct rc_softc *sc;
1396	u_short f = rc->rc_flags;
1397
1398	sc = rc->rc_rcb;
1399	printf("rc%d/%d: %s flags: %s%s%s%s%s%s%s%s%s%s%s%s\n",
1400		rc->rc_rcb->rcb_unit, rc->rc_chan, comment,
1401		(f & RC_DTR_OFF)?"DTR_OFF " :"",
1402		(f & RC_ACTOUT) ?"ACTOUT " :"",
1403		(f & RC_RTSFLOW)?"RTSFLOW " :"",
1404		(f & RC_CTSFLOW)?"CTSFLOW " :"",
1405		(f & RC_DORXFER)?"DORXFER " :"",
1406		(f & RC_DOXXFER)?"DOXXFER " :"",
1407		(f & RC_MODCHG) ?"MODCHG "  :"",
1408		(f & RC_OSUSP)  ?"OSUSP " :"",
1409		(f & RC_OSBUSY) ?"OSBUSY " :"",
1410		(f & RC_WAS_BUFOVFL) ?"BUFOVFL " :"",
1411		(f & RC_WAS_SILOVFL) ?"SILOVFL " :"",
1412		(f & RC_SEND_RDY) ?"SEND_RDY":"");
1413
1414	rcout(sc, CD180_CAR, rc->rc_chan);
1415
1416	printf("rc%d/%d: msvr %02x ier %02x ccsr %02x\n",
1417		rc->rc_rcb->rcb_unit, rc->rc_chan,
1418		rcin(sc, CD180_MSVR),
1419		rcin(sc, CD180_IER),
1420		rcin(sc, CD180_CCSR));
1421}
1422#endif /* RCDEBUG */
1423
1424static void
1425rc_discard_output(struct rc_chans *rc)
1426{
1427	critical_enter();
1428	if (rc->rc_flags & RC_DOXXFER) {
1429		rc->rc_rcb->sc_scheduled_event -= LOTS_OF_EVENTS;
1430		rc->rc_flags &= ~RC_DOXXFER;
1431	}
1432	rc->rc_optr = rc->rc_obufend;
1433	rc->rc_tp.t_state &= ~TS_BUSY;
1434	critical_exit();
1435	ttwwakeup(&rc->rc_tp);
1436}
1437
1438static void
1439rc_wait0(struct rc_softc *sc, int chan, int line)
1440{
1441	int rcnt;
1442
1443	for (rcnt = 50; rcnt && rcin(sc, CD180_CCR); rcnt--)
1444		DELAY(30);
1445	if (rcnt == 0)
1446		device_printf(sc->sc_dev,
1447		    "channel %d command timeout, rc.c line: %d\n", chan, line);
1448}
1449
1450static device_method_t rc_methods[] = {
1451	/* Device interface */
1452	DEVMETHOD(device_probe,		rc_probe),
1453	DEVMETHOD(device_attach,	rc_attach),
1454	DEVMETHOD(device_detach,	rc_detach),
1455	{ 0, 0 }
1456};
1457
1458static driver_t rc_driver = {
1459	"rc",
1460	rc_methods, sizeof(struct rc_softc),
1461};
1462
1463DRIVER_MODULE(rc, isa, rc_driver, rc_devclass, 0, 0);
1464