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>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 * SDL Communications Riscom/8 (based on Cirrus Logic CL-CD180) driver
40 #include <sys/param.h>
41 #include <sys/systm.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>
51 #include <machine/bus.h>
52 #include <machine/resource.h>
55 #include <dev/ic/cd180.h>
56 #include <dev/rc/rcreg.h>
57 #include <isa/isavar.h>
59 #define IOBASE_ADDRS 14
61 #define rcin(sc, port) RC_IN(sc, port)
62 #define rcout(sc, port, v) RC_OUT(sc, port, v)
64 #define WAITFORCCR(sc, chan) rc_wait0((sc), (chan), __LINE__)
66 #define CCRCMD(sc, chan, cmd) do { \
67 WAITFORCCR((sc), (chan)); \
68 rcout((sc), CD180_CCR, (cmd)); \
71 #define RC_IBUFSIZE 256
72 #define RB_I_HIGH_WATER (TTYHOG - 2 * RC_IBUFSIZE)
73 #define RC_OBUFSIZE 512
74 #define RC_IHIGHWATER (3 * RC_IBUFSIZE / 4)
75 #define INPUT_FLAGS_SHIFT (2 * RC_IBUFSIZE)
76 #define LOTS_OF_EVENTS 64
78 #define RC_FAKEID 0x10
80 /* Per-channel structure */
82 struct rc_softc *rc_rcb; /* back ptr */
83 u_short rc_flags; /* Misc. flags */
84 int rc_chan; /* Channel # */
85 u_char rc_ier; /* intr. enable reg */
86 u_char rc_msvr; /* modem sig. status */
87 u_char rc_cor2; /* options reg */
88 u_char rc_pendcmd; /* special cmd pending */
89 u_int rc_dcdwaits; /* how many waits DCD in open */
90 struct tty *rc_tp; /* tty struct */
91 u_char *rc_iptr; /* Chars input buffer */
92 u_char *rc_hiwat; /* hi-water mark */
93 u_char *rc_bufend; /* end of buffer */
94 u_char *rc_optr; /* ptr in output buf */
95 u_char *rc_obufend; /* end of output buf */
96 u_char rc_ibuf[4 * RC_IBUFSIZE]; /* input buffer */
97 u_char rc_obuf[RC_OBUFSIZE]; /* output buffer */
98 struct callout rc_dtrcallout;
101 /* Per-board structure */
104 struct resource *sc_irq;
105 struct resource *sc_port[IOBASE_ADDRS];
108 bus_space_tag_t sc_bt;
109 bus_space_handle_t sc_bh;
110 u_int sc_unit; /* unit # */
111 u_char sc_dtr; /* DTR status */
112 int sc_scheduled_event;
114 struct rc_chans sc_channels[CD180_NCHAN]; /* channels */
117 /* Static prototypes */
118 static t_close_t rc_close;
119 static void rc_break(struct tty *, int);
120 static void rc_release_resources(device_t dev);
121 static void rc_intr(void *);
122 static void rc_hwreset(struct rc_softc *, unsigned int);
123 static int rc_test(struct rc_softc *);
124 static void rc_discard_output(struct rc_chans *);
125 static int rc_modem(struct tty *, int, int);
126 static void rc_start(struct tty *);
127 static void rc_stop(struct tty *, int rw);
128 static int rc_param(struct tty *, struct termios *);
129 static void rc_pollcard(void *);
130 static void rc_reinit(struct rc_softc *);
132 static void printrcflags();
134 static void rc_wait0(struct rc_softc *sc, int chan, int line);
136 static devclass_t rc_devclass;
139 #define RC_DTR_OFF 0x0001 /* DTR wait, for close/open */
140 #define RC_ACTOUT 0x0002 /* Dial-out port active */
141 #define RC_RTSFLOW 0x0004 /* RTS flow ctl enabled */
142 #define RC_CTSFLOW 0x0008 /* CTS flow ctl enabled */
143 #define RC_DORXFER 0x0010 /* RXFER event planned */
144 #define RC_DOXXFER 0x0020 /* XXFER event planned */
145 #define RC_MODCHG 0x0040 /* Modem status changed */
146 #define RC_OSUSP 0x0080 /* Output suspended */
147 #define RC_OSBUSY 0x0100 /* start() routine in progress */
148 #define RC_WAS_BUFOVFL 0x0200 /* low-level buffer ovferflow */
149 #define RC_WAS_SILOVFL 0x0400 /* silo buffer overflow */
150 #define RC_SEND_RDY 0x0800 /* ready to send */
152 /* Table for translation of RCSR status bits to internal form */
153 static int rc_rcsrt[16] = {
155 TTY_FE|TTY_OE, TTY_PE, TTY_PE|TTY_OE,
156 TTY_PE|TTY_FE, TTY_PE|TTY_FE|TTY_OE, TTY_BI,
157 TTY_BI|TTY_OE, TTY_BI|TTY_FE, TTY_BI|TTY_FE|TTY_OE,
158 TTY_BI|TTY_PE, TTY_BI|TTY_PE|TTY_OE, TTY_BI|TTY_PE|TTY_FE,
159 TTY_BI|TTY_PE|TTY_FE|TTY_OE
162 static int rc_ports[] =
163 { 0x220, 0x240, 0x250, 0x260, 0x2a0, 0x2b0, 0x300, 0x320 };
164 static int iobase_addrs[IOBASE_ADDRS] =
165 { 0, 0x400, 0x800, 0xc00, 0x1400, 0x1800, 0x1c00, 0x2000,
166 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x8000 };
168 /**********************************************/
171 rc_probe(device_t dev)
177 * We don't know of any PnP ID's for these cards.
179 if (isa_get_logicalid(dev) != 0)
183 * We have to have an IO port hint that is valid.
185 port = isa_get_port(dev);
189 for (i = 0; i < sizeof(rc_ports) / sizeof(int); i++)
190 if (rc_ports[i] == port) {
198 * We have to have an IRQ hint.
200 if (isa_get_irq(dev) == -1)
203 device_set_desc(dev, "SDL Riscom/8");
208 rc_attach(device_t dev)
214 int base, chan, error, i, x;
216 sc = device_get_softc(dev);
220 * We need to have IO ports. Lots of them. We need
221 * the following ranges relative to the base port:
237 port = isa_get_port(dev);
238 for (i = 0; i < IOBASE_ADDRS; i++)
239 if (bus_set_resource(dev, SYS_RES_IOPORT, i,
240 port + iobase_addrs[i], 0x10) != 0)
243 for (i = 0; i < IOBASE_ADDRS; i++) {
245 sc->sc_port[i] = bus_alloc_resource(dev, SYS_RES_IOPORT, &x,
246 0ul, ~0ul, 0x10, RF_ACTIVE);
248 device_printf(dev, "ioport %d was rid %d\n", i, x);
251 if (sc->sc_port[i] == NULL) {
252 device_printf(dev, "failed to alloc ioports %x-%x\n",
253 port + iobase_addrs[i],
254 port + iobase_addrs[i] + 0x10);
258 sc->sc_bt = rman_get_bustag(sc->sc_port[0]);
259 sc->sc_bh = rman_get_bushandle(sc->sc_port[0]);
261 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid,
263 if (sc->sc_irq == NULL) {
264 device_printf(dev, "failed to alloc IRQ\n");
269 * Now do some actual tests to make sure it works.
272 rcout(sc, CD180_PPRL, 0x22); /* Random values to Prescale reg. */
273 rcout(sc, CD180_PPRH, 0x11);
274 if (rcin(sc, CD180_PPRL) != 0x22 || rcin(sc, CD180_PPRH) != 0x11)
280 * Ok, start actually hooking things up.
282 sc->sc_unit = device_get_unit(dev);
283 /*sc->sc_chipid = 0x10 + device_get_unit(dev);*/
284 device_printf(dev, "%d chans, firmware rev. %c\n",
285 CD180_NCHAN, (rcin(sc, CD180_GFRCR) & 0xF) + 'A');
286 rc = sc->sc_channels;
287 base = CD180_NCHAN * sc->sc_unit;
288 for (chan = 0; chan < CD180_NCHAN; chan++, rc++) {
291 rc->rc_iptr = rc->rc_ibuf;
292 rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE];
293 rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER];
294 rc->rc_optr = rc->rc_obufend = rc->rc_obuf;
295 callout_init(&rc->rc_dtrcallout, 0);
296 tp = rc->rc_tp = ttyalloc();
298 tp->t_oproc = rc_start;
299 tp->t_param = rc_param;
300 tp->t_modem = rc_modem;
301 tp->t_break = rc_break;
302 tp->t_close = rc_close;
303 tp->t_stop = rc_stop;
304 ttycreate(tp, NULL, 0, MINOR_CALLOUT, "m%d", chan + base);
307 error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_TTY, rc_intr, sc,
310 device_printf(dev, "failed to register interrupt handler\n");
314 swi_add(&tty_ithd, "tty:rc", rc_pollcard, sc, SWI_TTY, 0,
319 rc_release_resources(dev);
324 rc_detach(device_t dev)
330 sc = device_get_softc(dev);
332 rc = sc->sc_channels;
333 for (i = 0; i < CD180_NCHAN; i++, rc++)
336 error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie);
338 device_printf(dev, "failed to deregister interrupt handler\n");
339 ithread_remove_handler(sc->sc_swicookie);
340 rc_release_resources(dev);
346 rc_release_resources(device_t dev)
351 sc = device_get_softc(dev);
352 if (sc->sc_irq != NULL) {
353 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
357 for (i = 0; i < IOBASE_ADDRS; i++) {
358 if (sc->sc_port[i] == NULL)
360 bus_release_resource(dev, SYS_RES_IOPORT, i, sc->sc_port[i]);
361 sc->sc_port[i] = NULL;
365 /* RC interrupt handling */
372 u_char val, iack, bsr, ucnt, *optr;
373 int good_data, t_state;
375 sc = (struct rc_softc *)arg;
376 bsr = ~(rcin(sc, RC_BSR));
377 if (!(bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT))) {
378 device_printf(sc->sc_dev, "extra interrupt\n");
379 rcout(sc, CD180_EOIR, 0);
383 while (bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT)) {
384 #ifdef RCDEBUG_DETAILED
385 device_printf(sc->sc_dev, "intr (%p) %s%s%s%s\n", arg, bsr,
386 (bsr & RC_BSR_TOUT)?"TOUT ":"",
387 (bsr & RC_BSR_RXINT)?"RXINT ":"",
388 (bsr & RC_BSR_TXINT)?"TXINT ":"",
389 (bsr & RC_BSR_MOINT)?"MOINT":"");
391 if (bsr & RC_BSR_TOUT) {
392 device_printf(sc->sc_dev,
393 "hardware failure, reset board\n");
394 rcout(sc, RC_CTOUT, 0);
398 if (bsr & RC_BSR_RXINT) {
399 iack = rcin(sc, RC_PILR_RX);
400 good_data = (iack == (GIVR_IT_RGDI | RC_FAKEID));
401 if (!good_data && iack != (GIVR_IT_REI | RC_FAKEID)) {
402 device_printf(sc->sc_dev,
403 "fake rxint: %02x\n", iack);
406 chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH);
407 rc = &sc->sc_channels[chan];
408 t_state = rc->rc_tp->t_state;
409 /* Do RTS flow control stuff */
410 if ( (rc->rc_flags & RC_RTSFLOW)
411 || !(t_state & TS_ISOPEN)
413 if ( ( !(t_state & TS_ISOPEN)
414 || (t_state & TS_TBLOCK)
416 && (rc->rc_msvr & MSVR_RTS)
418 rcout(sc, CD180_MSVR,
419 rc->rc_msvr &= ~MSVR_RTS);
420 else if (!(rc->rc_msvr & MSVR_RTS))
421 rcout(sc, CD180_MSVR,
422 rc->rc_msvr |= MSVR_RTS);
424 ucnt = rcin(sc, CD180_RDCR) & 0xF;
427 if (t_state & TS_ISOPEN) {
428 /* check for input buffer overflow */
429 if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) {
431 ucnt = rc->rc_bufend - rc->rc_iptr;
433 if (!(rc->rc_flags & RC_WAS_BUFOVFL)) {
434 rc->rc_flags |= RC_WAS_BUFOVFL;
435 sc->sc_scheduled_event++;
439 /* check foor good data */
442 val = rcin(sc, CD180_RDR);
444 optr[INPUT_FLAGS_SHIFT] = 0;
446 sc->sc_scheduled_event++;
447 if (val != 0 && val == rc->rc_tp->t_hotchar)
448 swi_sched(sc->sc_swicookie, 0);
451 /* Store also status data */
453 iack = rcin(sc, CD180_RCSR);
454 if (iack & RCSR_Timeout)
456 if ( (iack & RCSR_OE)
457 && !(rc->rc_flags & RC_WAS_SILOVFL)) {
458 rc->rc_flags |= RC_WAS_SILOVFL;
459 sc->sc_scheduled_event++;
461 val = rcin(sc, CD180_RDR);
463 Don't store PE if IGNPAR and BREAK if IGNBRK,
464 this hack allows "raw" tty optimization
465 works even if IGN* is set.
467 if ( !(iack & (RCSR_PE|RCSR_FE|RCSR_Break))
468 || ((!(iack & (RCSR_PE|RCSR_FE))
469 || !(rc->rc_tp->t_iflag & IGNPAR))
470 && (!(iack & RCSR_Break)
471 || !(rc->rc_tp->t_iflag & IGNBRK)))) {
472 if ( (iack & (RCSR_PE|RCSR_FE))
473 && (t_state & TS_CAN_BYPASS_L_RINT)
476 && (rc->rc_tp->t_iflag & INPCK))))
478 else if (val != 0 && val == rc->rc_tp->t_hotchar)
479 swi_sched(sc->sc_swicookie, 0);
481 optr[INPUT_FLAGS_SHIFT] = iack;
483 sc->sc_scheduled_event++;
488 rc->rc_flags |= RC_DORXFER;
491 /* Clear FIFO if necessary */
492 while (resid-- > 0) {
494 iack = rcin(sc, CD180_RCSR);
497 if (iack & RCSR_Timeout)
499 (void) rcin(sc, CD180_RDR);
503 if (bsr & RC_BSR_MOINT) {
504 iack = rcin(sc, RC_PILR_MODEM);
505 if (iack != (GIVR_IT_MSCI | RC_FAKEID)) {
506 device_printf(sc->sc_dev, "fake moint: %02x\n",
510 chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH);
511 rc = &sc->sc_channels[chan];
512 iack = rcin(sc, CD180_MCR);
513 rc->rc_msvr = rcin(sc, CD180_MSVR);
514 rcout(sc, CD180_MCR, 0);
516 printrcflags(rc, "moint");
518 if (rc->rc_flags & RC_CTSFLOW) {
519 if (rc->rc_msvr & MSVR_CTS)
520 rc->rc_flags |= RC_SEND_RDY;
522 rc->rc_flags &= ~RC_SEND_RDY;
524 rc->rc_flags |= RC_SEND_RDY;
525 if ((iack & MCR_CDchg) && !(rc->rc_flags & RC_MODCHG)) {
526 sc->sc_scheduled_event += LOTS_OF_EVENTS;
527 rc->rc_flags |= RC_MODCHG;
528 swi_sched(sc->sc_swicookie, 0);
532 if (bsr & RC_BSR_TXINT) {
533 iack = rcin(sc, RC_PILR_TX);
534 if (iack != (GIVR_IT_TDI | RC_FAKEID)) {
535 device_printf(sc->sc_dev, "fake txint: %02x\n",
539 chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH);
540 rc = &sc->sc_channels[chan];
541 if ( (rc->rc_flags & RC_OSUSP)
542 || !(rc->rc_flags & RC_SEND_RDY)
545 /* Handle breaks and other stuff */
546 if (rc->rc_pendcmd) {
547 rcout(sc, CD180_COR2, rc->rc_cor2 |= COR2_ETC);
548 rcout(sc, CD180_TDR, CD180_C_ESC);
549 rcout(sc, CD180_TDR, rc->rc_pendcmd);
550 rcout(sc, CD180_COR2, rc->rc_cor2 &= ~COR2_ETC);
555 resid = rc->rc_obufend - optr;
556 if (resid > CD180_NFIFO)
559 rcout(sc, CD180_TDR, *optr++);
562 /* output completed? */
563 if (optr >= rc->rc_obufend) {
564 rcout(sc, CD180_IER, rc->rc_ier &= ~IER_TxRdy);
566 device_printf(sc->sc_dev,
567 "channel %d: output completed\n",
570 if (!(rc->rc_flags & RC_DOXXFER)) {
571 sc->sc_scheduled_event += LOTS_OF_EVENTS;
572 rc->rc_flags |= RC_DOXXFER;
573 swi_sched(sc->sc_swicookie, 0);
578 rcout(sc, CD180_EOIR, 0); /* end of interrupt */
579 rcout(sc, RC_CTOUT, 0);
580 bsr = ~(rcin(sc, RC_BSR));
584 /* Feed characters to output buffer */
586 rc_start(struct tty *tp)
593 if (rc->rc_flags & RC_OSBUSY)
597 rc->rc_flags |= RC_OSBUSY;
599 if (tp->t_state & TS_TTSTOP)
600 rc->rc_flags |= RC_OSUSP;
602 rc->rc_flags &= ~RC_OSUSP;
603 /* Do RTS flow control stuff */
604 if ( (rc->rc_flags & RC_RTSFLOW)
605 && (tp->t_state & TS_TBLOCK)
606 && (rc->rc_msvr & MSVR_RTS)
608 rcout(sc, CD180_CAR, rc->rc_chan);
609 rcout(sc, CD180_MSVR, rc->rc_msvr &= ~MSVR_RTS);
610 } else if (!(rc->rc_msvr & MSVR_RTS)) {
611 rcout(sc, CD180_CAR, rc->rc_chan);
612 rcout(sc, CD180_MSVR, rc->rc_msvr |= MSVR_RTS);
615 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
618 printrcflags(rc, "rcstart");
622 printf("rcstart: outq = %d obuf = %d\n",
623 tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr);
625 if (tp->t_state & TS_BUSY)
626 goto out; /* output still in progress ... */
628 if (tp->t_outq.c_cc > 0) {
631 tp->t_state |= TS_BUSY;
632 ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf);
634 rc->rc_optr = rc->rc_obuf;
635 rc->rc_obufend = rc->rc_optr + ocnt;
637 if (!(rc->rc_ier & IER_TxRdy)) {
639 device_printf(sc->sc_dev,
640 "channel %d: rcstart enable txint\n", rc->rc_chan);
642 rcout(sc, CD180_CAR, rc->rc_chan);
643 rcout(sc, CD180_IER, rc->rc_ier |= IER_TxRdy);
647 rc->rc_flags &= ~RC_OSBUSY;
651 /* Handle delayed events. */
653 rc_pollcard(void *arg)
661 sc = (struct rc_softc *)arg;
662 if (sc->sc_scheduled_event == 0)
665 rc = sc->sc_channels;
666 for (chan = 0; chan < CD180_NCHAN; rc++, chan++) {
669 if (rc->rc_flags & (RC_DORXFER|RC_DOXXFER|RC_MODCHG|
670 RC_WAS_BUFOVFL|RC_WAS_SILOVFL))
671 printrcflags(rc, "rcevent");
673 if (rc->rc_flags & RC_WAS_BUFOVFL) {
675 rc->rc_flags &= ~RC_WAS_BUFOVFL;
676 sc->sc_scheduled_event--;
678 device_printf(sc->sc_dev,
679 "channel %d: interrupt-level buffer overflow\n",
682 if (rc->rc_flags & RC_WAS_SILOVFL) {
684 rc->rc_flags &= ~RC_WAS_SILOVFL;
685 sc->sc_scheduled_event--;
687 device_printf(sc->sc_dev,
688 "channel %d: silo overflow\n", chan);
690 if (rc->rc_flags & RC_MODCHG) {
692 rc->rc_flags &= ~RC_MODCHG;
693 sc->sc_scheduled_event -= LOTS_OF_EVENTS;
695 ttyld_modem(tp, !!(rc->rc_msvr & MSVR_CD));
697 if (rc->rc_flags & RC_DORXFER) {
699 rc->rc_flags &= ~RC_DORXFER;
701 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE])
702 tptr = &rc->rc_ibuf[RC_IBUFSIZE];
707 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) {
708 rc->rc_iptr = rc->rc_ibuf;
709 rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE];
710 rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER];
712 rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE];
713 rc->rc_bufend = &rc->rc_ibuf[2 * RC_IBUFSIZE];
715 &rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER];
717 if ( (rc->rc_flags & RC_RTSFLOW)
718 && (tp->t_state & TS_ISOPEN)
719 && !(tp->t_state & TS_TBLOCK)
720 && !(rc->rc_msvr & MSVR_RTS)
722 rcout(sc, CD180_CAR, chan);
723 rcout(sc, CD180_MSVR,
724 rc->rc_msvr |= MSVR_RTS);
726 sc->sc_scheduled_event -= icnt;
730 if (icnt <= 0 || !(tp->t_state & TS_ISOPEN))
733 if ( (tp->t_state & TS_CAN_BYPASS_L_RINT)
734 && !(tp->t_state & TS_LOCAL)) {
735 if ((tp->t_rawq.c_cc + icnt) >= RB_I_HIGH_WATER
736 && ((rc->rc_flags & RC_RTSFLOW) || (tp->t_iflag & IXOFF))
737 && !(tp->t_state & TS_TBLOCK))
742 if (b_to_q(tptr, icnt, &tp->t_rawq))
743 device_printf(sc->sc_dev,
744 "channel %d: tty-level buffer overflow\n",
747 if ((tp->t_state & TS_TTSTOP) && ((tp->t_iflag & IXANY)
748 || (tp->t_cc[VSTART] == tp->t_cc[VSTOP]))) {
749 tp->t_state &= ~TS_TTSTOP;
750 tp->t_lflag &= ~FLUSHO;
754 for (; tptr < eptr; tptr++)
757 rc_rcsrt[tptr[INPUT_FLAGS_SHIFT] & 0xF]));
761 if (rc->rc_flags & RC_DOXXFER) {
763 sc->sc_scheduled_event -= LOTS_OF_EVENTS;
764 rc->rc_flags &= ~RC_DOXXFER;
765 rc->rc_tp->t_state &= ~TS_BUSY;
769 if (sc->sc_scheduled_event == 0)
772 } while (sc->sc_scheduled_event >= LOTS_OF_EVENTS);
776 rc_stop(struct tty *tp, int rw)
785 device_printf(sc->sc_dev, "channel %d: rc_stop %s%s\n",
786 rc->rc_chan, (rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":"");
789 rc_discard_output(rc);
792 rc->rc_flags &= ~RC_DORXFER;
794 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) {
795 tptr = &rc->rc_ibuf[RC_IBUFSIZE];
796 rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE];
799 rc->rc_iptr = rc->rc_ibuf;
801 sc->sc_scheduled_event -= eptr - tptr;
803 if (tp->t_state & TS_TTSTOP)
804 rc->rc_flags |= RC_OSUSP;
806 rc->rc_flags &= ~RC_OSUSP;
811 rc_close(struct tty *tp)
820 rcout(sc, CD180_CAR, rc->rc_chan);
822 /* Disable rx/tx intrs */
823 rcout(sc, CD180_IER, rc->rc_ier = 0);
824 if ( (tp->t_cflag & HUPCL)
825 || (!(rc->rc_flags & RC_ACTOUT)
826 && !(rc->rc_msvr & MSVR_CD)
827 && !(tp->t_cflag & CLOCAL))
828 || !(tp->t_state & TS_ISOPEN)
830 CCRCMD(sc, rc->rc_chan, CCR_ResetChan);
831 WAITFORCCR(sc, rc->rc_chan);
832 (void) rc_modem(tp, SER_RTS, 0);
835 rc->rc_flags &= ~RC_ACTOUT;
836 wakeup( &rc->rc_rcb); /* wake bi */
837 wakeup(TSA_CARR_ON(tp));
841 /* Reset the bastard */
843 rc_hwreset(struct rc_softc *sc, u_int chipid)
845 CCRCMD(sc, -1, CCR_HWRESET); /* Hardware reset */
849 rcout(sc, RC_CTOUT, 0); /* Clear timeout */
850 rcout(sc, CD180_GIVR, chipid);
851 rcout(sc, CD180_GICR, 0);
853 /* Set Prescaler Registers (1 msec) */
854 rcout(sc, CD180_PPRL, ((RC_OSCFREQ + 999) / 1000) & 0xFF);
855 rcout(sc, CD180_PPRH, ((RC_OSCFREQ + 999) / 1000) >> 8);
857 /* Initialize Priority Interrupt Level Registers */
858 rcout(sc, CD180_PILR1, RC_PILR_MODEM);
859 rcout(sc, CD180_PILR2, RC_PILR_TX);
860 rcout(sc, CD180_PILR3, RC_PILR_RX);
863 rcout(sc, RC_DTREG, ~0);
866 /* Set channel parameters */
868 rc_param(struct tty *tp, struct termios *ts)
872 int idivs, odivs, s, val, cflag, iflag, lflag, inpflow;
874 if ( ts->c_ospeed < 0 || ts->c_ospeed > 76800
875 || ts->c_ispeed < 0 || ts->c_ispeed > 76800
878 if (ts->c_ispeed == 0)
879 ts->c_ispeed = ts->c_ospeed;
880 odivs = RC_BRD(ts->c_ospeed);
881 idivs = RC_BRD(ts->c_ispeed);
888 rcout(sc, CD180_CAR, rc->rc_chan);
890 /* If speed == 0, hangup line */
891 if (ts->c_ospeed == 0) {
892 CCRCMD(sc, rc->rc_chan, CCR_ResetChan);
893 WAITFORCCR(sc, rc->rc_chan);
894 (void) rc_modem(tp, 0, SER_DTR);
897 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
903 rcout(sc, CD180_RBPRL, idivs & 0xFF);
904 rcout(sc, CD180_RBPRH, idivs >> 8);
907 rcout(sc, CD180_TBPRL, odivs & 0xFF);
908 rcout(sc, CD180_TBPRH, odivs >> 8);
911 /* set timeout value */
912 if (ts->c_ispeed > 0) {
913 int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1;
915 if ( !(lflag & ICANON)
916 && ts->c_cc[VMIN] != 0 && ts->c_cc[VTIME] != 0
917 && ts->c_cc[VTIME] * 10 > itm)
918 itm = ts->c_cc[VTIME] * 10;
920 rcout(sc, CD180_RTPR, itm <= 255 ? itm : 255);
923 switch (cflag & CSIZE) {
924 case CS5: val = COR1_5BITS; break;
925 case CS6: val = COR1_6BITS; break;
926 case CS7: val = COR1_7BITS; break;
928 case CS8: val = COR1_8BITS; break;
930 if (cflag & PARENB) {
934 if (!(cflag & INPCK))
940 rcout(sc, CD180_COR1, val);
942 /* Set FIFO threshold */
943 val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2;
946 && ( ts->c_cc[VSTOP] != _POSIX_VDISABLE
947 && ( ts->c_cc[VSTART] != _POSIX_VDISABLE
953 val |= COR3_SCDE|COR3_FCT;
955 rcout(sc, CD180_COR3, val);
957 /* Initialize on-chip automatic flow control */
959 rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY);
960 if (cflag & CCTS_OFLOW) {
961 rc->rc_flags |= RC_CTSFLOW;
964 rc->rc_flags |= RC_SEND_RDY;
965 if (tp->t_state & TS_TTSTOP)
966 rc->rc_flags |= RC_OSUSP;
968 rc->rc_flags &= ~RC_OSUSP;
969 if (cflag & CRTS_IFLOW)
970 rc->rc_flags |= RC_RTSFLOW;
972 rc->rc_flags &= ~RC_RTSFLOW;
975 if (ts->c_cc[VSTART] != _POSIX_VDISABLE)
976 rcout(sc, CD180_SCHR1, ts->c_cc[VSTART]);
977 rcout(sc, CD180_SCHR2, ts->c_cc[VSTOP]);
983 rcout(sc, CD180_COR2, rc->rc_cor2 = val);
985 CCRCMD(sc, rc->rc_chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
990 val = cflag & CLOCAL ? 0 : MCOR1_CDzd;
991 if (cflag & CCTS_OFLOW)
993 rcout(sc, CD180_MCOR1, val);
995 val = cflag & CLOCAL ? 0 : MCOR2_CDod;
996 if (cflag & CCTS_OFLOW)
998 rcout(sc, CD180_MCOR2, val);
1000 /* enable i/o and interrupts */
1001 CCRCMD(sc, rc->rc_chan,
1002 CCR_XMTREN | ((cflag & CREAD) ? CCR_RCVREN : CCR_RCVRDIS));
1003 WAITFORCCR(sc, rc->rc_chan);
1005 rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD;
1006 if (cflag & CCTS_OFLOW)
1007 rc->rc_ier |= IER_CTS;
1009 rc->rc_ier |= IER_RxData;
1010 if (tp->t_state & TS_BUSY)
1011 rc->rc_ier |= IER_TxRdy;
1012 if (ts->c_ospeed != 0)
1013 rc_modem(tp, SER_DTR, 0);
1014 if ((cflag & CCTS_OFLOW) && (rc->rc_msvr & MSVR_CTS))
1015 rc->rc_flags |= RC_SEND_RDY;
1016 rcout(sc, CD180_IER, rc->rc_ier);
1021 /* Re-initialize board after bogus interrupts */
1023 rc_reinit(struct rc_softc *sc)
1025 struct rc_chans *rc;
1028 rc_hwreset(sc, RC_FAKEID);
1029 rc = sc->sc_channels;
1030 for (i = 0; i < CD180_NCHAN; i++, rc++)
1031 (void) rc_param(rc->rc_tp, &rc->rc_tp->t_termios);
1034 /* Modem control routines */
1037 rc_modem(struct tty *tp, int biton, int bitoff)
1039 struct rc_chans *rc;
1040 struct rc_softc *sc;
1047 rcout(sc, CD180_CAR, rc->rc_chan);
1049 if (biton == 0 && bitoff == 0) {
1050 msvr = rc->rc_msvr = rcin(sc, CD180_MSVR);
1052 if (msvr & MSVR_RTS)
1054 if (msvr & MSVR_CTS)
1056 if (msvr & MSVR_DSR)
1058 if (msvr & MSVR_DTR)
1062 if (~rcin(sc, RC_RIREG) & (1 << rc->rc_chan))
1066 if (biton & SER_DTR)
1067 rcout(sc, RC_DTREG, ~(*dtr |= 1 << rc->rc_chan));
1068 if (bitoff & SER_DTR)
1069 rcout(sc, RC_DTREG, ~(*dtr &= ~(1 << rc->rc_chan)));
1070 msvr = rcin(sc, CD180_MSVR);
1071 if (biton & SER_DTR)
1073 if (bitoff & SER_DTR)
1075 if (biton & SER_RTS)
1077 if (bitoff & SER_RTS)
1079 rcout(sc, CD180_MSVR, msvr);
1084 rc_break(struct tty *tp, int brk)
1086 struct rc_chans *rc;
1091 rc->rc_pendcmd = CD180_C_SBRK;
1093 rc->rc_pendcmd = CD180_C_EBRK;
1096 #define ERR(s) do { \
1097 device_printf(sc->sc_dev, "%s", ""); \
1100 (void) splx(old_level); \
1104 /* Test the board. */
1106 rc_test(struct rc_softc *sc)
1109 int i = 0, rcnt, old_level;
1110 unsigned int iack, chipid;
1111 unsigned short divs;
1112 static u_char ctest[] = "\377\125\252\045\244\0\377";
1116 u_char txbuf[CD180_NFIFO]; /* TX buffer */
1117 u_char rxbuf[CD180_NFIFO]; /* RX buffer */
1118 int rxptr; /* RX pointer */
1119 int txptr; /* TX pointer */
1120 } tchans[CD180_NCHAN];
1122 old_level = spltty();
1126 /* First, reset board to inital state */
1127 rc_hwreset(sc, chipid);
1129 divs = RC_BRD(19200);
1131 /* Initialize channels */
1132 for (chan = 0; chan < CD180_NCHAN; chan++) {
1134 /* Select and reset channel */
1135 rcout(sc, CD180_CAR, chan);
1136 CCRCMD(sc, chan, CCR_ResetChan);
1137 WAITFORCCR(sc, chan);
1140 rcout(sc, CD180_RBPRL, divs & 0xFF);
1141 rcout(sc, CD180_RBPRH, divs >> 8);
1142 rcout(sc, CD180_TBPRL, divs & 0xFF);
1143 rcout(sc, CD180_TBPRH, divs >> 8);
1145 /* set timeout value */
1146 rcout(sc, CD180_RTPR, 0);
1148 /* Establish local loopback */
1149 rcout(sc, CD180_COR1, COR1_NOPAR | COR1_8BITS | COR1_1SB);
1150 rcout(sc, CD180_COR2, COR2_LLM);
1151 rcout(sc, CD180_COR3, CD180_NFIFO);
1152 CCRCMD(sc, chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1153 CCRCMD(sc, chan, CCR_RCVREN | CCR_XMTREN);
1154 WAITFORCCR(sc, chan);
1155 rcout(sc, CD180_MSVR, MSVR_RTS);
1157 /* Fill TXBUF with test data */
1158 for (i = 0; i < CD180_NFIFO; i++) {
1159 tchans[chan].txbuf[i] = ctest[i];
1160 tchans[chan].rxbuf[i] = 0;
1162 tchans[chan].txptr = tchans[chan].rxptr = 0;
1164 /* Now, start transmit */
1165 rcout(sc, CD180_IER, IER_TxMpty|IER_RxData);
1167 /* Pseudo-interrupt poll stuff */
1168 for (rcnt = 10000; rcnt-- > 0; rcnt--) {
1169 i = ~(rcin(sc, RC_BSR));
1170 if (i & RC_BSR_TOUT)
1171 ERR(("BSR timeout bit set\n"));
1172 else if (i & RC_BSR_TXINT) {
1173 iack = rcin(sc, RC_PILR_TX);
1174 if (iack != (GIVR_IT_TDI | chipid))
1175 ERR(("Bad TX intr ack (%02x != %02x)\n",
1176 iack, GIVR_IT_TDI | chipid));
1177 chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH;
1178 /* If no more data to transmit, disable TX intr */
1179 if (tchans[chan].txptr >= CD180_NFIFO) {
1180 iack = rcin(sc, CD180_IER);
1181 rcout(sc, CD180_IER, iack & ~IER_TxMpty);
1183 for (iack = tchans[chan].txptr;
1184 iack < CD180_NFIFO; iack++)
1185 rcout(sc, CD180_TDR,
1186 tchans[chan].txbuf[iack]);
1187 tchans[chan].txptr = iack;
1189 rcout(sc, CD180_EOIR, 0);
1190 } else if (i & RC_BSR_RXINT) {
1193 iack = rcin(sc, RC_PILR_RX);
1194 if (iack != (GIVR_IT_RGDI | chipid) &&
1195 iack != (GIVR_IT_REI | chipid))
1196 ERR(("Bad RX intr ack (%02x != %02x)\n",
1197 iack, GIVR_IT_RGDI | chipid));
1198 chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH;
1199 ucnt = rcin(sc, CD180_RDCR) & 0xF;
1200 while (ucnt-- > 0) {
1201 iack = rcin(sc, CD180_RCSR);
1202 if (iack & RCSR_Timeout)
1205 ERR(("Bad char chan %d (RCSR = %02X)\n",
1207 if (tchans[chan].rxptr > CD180_NFIFO)
1208 ERR(("Got extra chars chan %d\n",
1210 tchans[chan].rxbuf[tchans[chan].rxptr++] =
1211 rcin(sc, CD180_RDR);
1213 rcout(sc, CD180_EOIR, 0);
1215 rcout(sc, RC_CTOUT, 0);
1216 for (iack = chan = 0; chan < CD180_NCHAN; chan++)
1217 if (tchans[chan].rxptr >= CD180_NFIFO)
1219 if (iack == CD180_NCHAN)
1222 for (chan = 0; chan < CD180_NCHAN; chan++) {
1223 /* Select and reset channel */
1224 rcout(sc, CD180_CAR, chan);
1225 CCRCMD(sc, chan, CCR_ResetChan);
1229 ERR(("looses characters during local loopback\n"));
1230 /* Now, check data */
1231 for (chan = 0; chan < CD180_NCHAN; chan++)
1232 for (i = 0; i < CD180_NFIFO; i++)
1233 if (ctest[i] != tchans[chan].rxbuf[i])
1234 ERR(("data mismatch chan %d ptr %d (%d != %d)\n",
1235 chan, i, ctest[i], tchans[chan].rxbuf[i]));
1236 (void) splx(old_level);
1242 printrcflags(struct rc_chans *rc, char *comment)
1244 struct rc_softc *sc;
1245 u_short f = rc->rc_flags;
1248 printf("rc%d/%d: %s flags: %s%s%s%s%s%s%s%s%s%s%s%s\n",
1249 rc->rc_rcb->rcb_unit, rc->rc_chan, comment,
1250 (f & RC_DTR_OFF)?"DTR_OFF " :"",
1251 (f & RC_ACTOUT) ?"ACTOUT " :"",
1252 (f & RC_RTSFLOW)?"RTSFLOW " :"",
1253 (f & RC_CTSFLOW)?"CTSFLOW " :"",
1254 (f & RC_DORXFER)?"DORXFER " :"",
1255 (f & RC_DOXXFER)?"DOXXFER " :"",
1256 (f & RC_MODCHG) ?"MODCHG " :"",
1257 (f & RC_OSUSP) ?"OSUSP " :"",
1258 (f & RC_OSBUSY) ?"OSBUSY " :"",
1259 (f & RC_WAS_BUFOVFL) ?"BUFOVFL " :"",
1260 (f & RC_WAS_SILOVFL) ?"SILOVFL " :"",
1261 (f & RC_SEND_RDY) ?"SEND_RDY":"");
1263 rcout(sc, CD180_CAR, rc->rc_chan);
1265 printf("rc%d/%d: msvr %02x ier %02x ccsr %02x\n",
1266 rc->rc_rcb->rcb_unit, rc->rc_chan,
1267 rcin(sc, CD180_MSVR),
1268 rcin(sc, CD180_IER),
1269 rcin(sc, CD180_CCSR));
1271 #endif /* RCDEBUG */
1274 rc_discard_output(struct rc_chans *rc)
1277 if (rc->rc_flags & RC_DOXXFER) {
1278 rc->rc_rcb->sc_scheduled_event -= LOTS_OF_EVENTS;
1279 rc->rc_flags &= ~RC_DOXXFER;
1281 rc->rc_optr = rc->rc_obufend;
1282 rc->rc_tp->t_state &= ~TS_BUSY;
1284 ttwwakeup(rc->rc_tp);
1288 rc_wait0(struct rc_softc *sc, int chan, int line)
1292 for (rcnt = 50; rcnt && rcin(sc, CD180_CCR); rcnt--)
1295 device_printf(sc->sc_dev,
1296 "channel %d command timeout, rc.c line: %d\n", chan, line);
1299 static device_method_t rc_methods[] = {
1300 /* Device interface */
1301 DEVMETHOD(device_probe, rc_probe),
1302 DEVMETHOD(device_attach, rc_attach),
1303 DEVMETHOD(device_detach, rc_detach),
1307 static driver_t rc_driver = {
1309 rc_methods, sizeof(struct rc_softc),
1312 DRIVER_MODULE(rc, isa, rc_driver, rc_devclass, 0, 0);