Deleted Added
full compact
rc.c (296137) rc.c (298307)
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 *
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 296137 2016-02-27 03:38:01Z jhibbits $
28 * $FreeBSD: head/sys/dev/rc/rc.c 298307 2016-04-19 23:37:24Z pfg $
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 rcin(sc, port) RC_IN(sc, port)
62#define rcout(sc, port, v) RC_OUT(sc, port, v)
63
64#define WAITFORCCR(sc, chan) rc_wait0((sc), (chan), __LINE__)
65
66#define CCRCMD(sc, chan, cmd) do { \
67 WAITFORCCR((sc), (chan)); \
68 rcout((sc), CD180_CCR, (cmd)); \
69} while (0)
70
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
77
78#define RC_FAKEID 0x10
79
80/* Per-channel structure */
81struct rc_chans {
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;
99};
100
101/* Per-board structure */
102struct rc_softc {
103 device_t sc_dev;
104 struct resource *sc_irq;
105 struct resource *sc_port[IOBASE_ADDRS];
106 int sc_irqrid;
107 void *sc_hwicookie;
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;
113 void *sc_swicookie;
114 struct rc_chans sc_channels[CD180_NCHAN]; /* channels */
115};
116
117/* Static prototypes */
118static t_close_t rc_close;
119static void rc_break(struct tty *, int);
120static void rc_release_resources(device_t dev);
121static void rc_intr(void *);
122static void rc_hwreset(struct rc_softc *, unsigned int);
123static int rc_test(struct rc_softc *);
124static void rc_discard_output(struct rc_chans *);
125static int rc_modem(struct tty *, int, int);
126static void rc_start(struct tty *);
127static void rc_stop(struct tty *, int rw);
128static int rc_param(struct tty *, struct termios *);
129static void rc_pollcard(void *);
130static void rc_reinit(struct rc_softc *);
131#ifdef RCDEBUG
132static void printrcflags();
133#endif
134static void rc_wait0(struct rc_softc *sc, int chan, int line);
135
136static devclass_t rc_devclass;
137
138/* Flags */
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 */
151
152/* Table for translation of RCSR status bits to internal form */
153static int rc_rcsrt[16] = {
154 0, TTY_OE, TTY_FE,
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
160};
161
162static int rc_ports[] =
163 { 0x220, 0x240, 0x250, 0x260, 0x2a0, 0x2b0, 0x300, 0x320 };
164static int iobase_addrs[IOBASE_ADDRS] =
165 { 0, 0x400, 0x800, 0xc00, 0x1400, 0x1800, 0x1c00, 0x2000,
166 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x8000 };
167
168/**********************************************/
169
170static int
171rc_probe(device_t dev)
172{
173 u_int port;
174 int i, found;
175
176 /*
177 * We don't know of any PnP ID's for these cards.
178 */
179 if (isa_get_logicalid(dev) != 0)
180 return (ENXIO);
181
182 /*
183 * We have to have an IO port hint that is valid.
184 */
185 port = isa_get_port(dev);
186 if (port == -1)
187 return (ENXIO);
188 found = 0;
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 rcin(sc, port) RC_IN(sc, port)
62#define rcout(sc, port, v) RC_OUT(sc, port, v)
63
64#define WAITFORCCR(sc, chan) rc_wait0((sc), (chan), __LINE__)
65
66#define CCRCMD(sc, chan, cmd) do { \
67 WAITFORCCR((sc), (chan)); \
68 rcout((sc), CD180_CCR, (cmd)); \
69} while (0)
70
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
77
78#define RC_FAKEID 0x10
79
80/* Per-channel structure */
81struct rc_chans {
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;
99};
100
101/* Per-board structure */
102struct rc_softc {
103 device_t sc_dev;
104 struct resource *sc_irq;
105 struct resource *sc_port[IOBASE_ADDRS];
106 int sc_irqrid;
107 void *sc_hwicookie;
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;
113 void *sc_swicookie;
114 struct rc_chans sc_channels[CD180_NCHAN]; /* channels */
115};
116
117/* Static prototypes */
118static t_close_t rc_close;
119static void rc_break(struct tty *, int);
120static void rc_release_resources(device_t dev);
121static void rc_intr(void *);
122static void rc_hwreset(struct rc_softc *, unsigned int);
123static int rc_test(struct rc_softc *);
124static void rc_discard_output(struct rc_chans *);
125static int rc_modem(struct tty *, int, int);
126static void rc_start(struct tty *);
127static void rc_stop(struct tty *, int rw);
128static int rc_param(struct tty *, struct termios *);
129static void rc_pollcard(void *);
130static void rc_reinit(struct rc_softc *);
131#ifdef RCDEBUG
132static void printrcflags();
133#endif
134static void rc_wait0(struct rc_softc *sc, int chan, int line);
135
136static devclass_t rc_devclass;
137
138/* Flags */
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 */
151
152/* Table for translation of RCSR status bits to internal form */
153static int rc_rcsrt[16] = {
154 0, TTY_OE, TTY_FE,
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
160};
161
162static int rc_ports[] =
163 { 0x220, 0x240, 0x250, 0x260, 0x2a0, 0x2b0, 0x300, 0x320 };
164static int iobase_addrs[IOBASE_ADDRS] =
165 { 0, 0x400, 0x800, 0xc00, 0x1400, 0x1800, 0x1c00, 0x2000,
166 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x8000 };
167
168/**********************************************/
169
170static int
171rc_probe(device_t dev)
172{
173 u_int port;
174 int i, found;
175
176 /*
177 * We don't know of any PnP ID's for these cards.
178 */
179 if (isa_get_logicalid(dev) != 0)
180 return (ENXIO);
181
182 /*
183 * We have to have an IO port hint that is valid.
184 */
185 port = isa_get_port(dev);
186 if (port == -1)
187 return (ENXIO);
188 found = 0;
189 for (i = 0; i < sizeof(rc_ports) / sizeof(int); i++)
189 for (i = 0; i < nitems(rc_ports); i++)
190 if (rc_ports[i] == port) {
191 found = 1;
192 break;
193 }
194 if (!found)
195 return (ENXIO);
196
197 /*
198 * We have to have an IRQ hint.
199 */
200 if (isa_get_irq(dev) == -1)
201 return (ENXIO);
202
203 device_set_desc(dev, "SDL Riscom/8");
204 return (0);
205}
206
207static int
208rc_attach(device_t dev)
209{
210 struct rc_chans *rc;
211 struct tty *tp;
212 struct rc_softc *sc;
213 u_int port;
214 int base, chan, error, i, x;
215
216 sc = device_get_softc(dev);
217 sc->sc_dev = dev;
218
219 /*
220 * We need to have IO ports. Lots of them. We need
221 * the following ranges relative to the base port:
222 * 0x0 - 0x10
223 * 0x400 - 0x410
224 * 0x800 - 0x810
225 * 0xc00 - 0xc10
226 * 0x1400 - 0x1410
227 * 0x1800 - 0x1810
228 * 0x1c00 - 0x1c10
229 * 0x2000 - 0x2010
230 * 0x3000 - 0x3010
231 * 0x3400 - 0x3410
232 * 0x3800 - 0x3810
233 * 0x3c00 - 0x3c10
234 * 0x4000 - 0x4010
235 * 0x8000 - 0x8010
236 */
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)
241 return (ENXIO);
242 error = ENOMEM;
243 for (i = 0; i < IOBASE_ADDRS; i++) {
244 x = i;
245 sc->sc_port[i] = bus_alloc_resource_anywhere(dev,
246 SYS_RES_IOPORT, &x, 0x10, RF_ACTIVE);
247 if (x != i) {
248 device_printf(dev, "ioport %d was rid %d\n", i, x);
249 goto fail;
250 }
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);
255 goto fail;
256 }
257 }
258 sc->sc_bt = rman_get_bustag(sc->sc_port[0]);
259 sc->sc_bh = rman_get_bushandle(sc->sc_port[0]);
260
261 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid,
262 RF_ACTIVE);
263 if (sc->sc_irq == NULL) {
264 device_printf(dev, "failed to alloc IRQ\n");
265 goto fail;
266 }
267
268 /*
269 * Now do some actual tests to make sure it works.
270 */
271 error = ENXIO;
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)
275 goto fail;
276 if (rc_test(sc))
277 goto fail;
278
279 /*
280 * Ok, start actually hooking things up.
281 */
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++) {
289 rc->rc_rcb = sc;
290 rc->rc_chan = chan;
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();
297 tp->t_sc = rc;
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, TS_CALLOUT, "m%d", chan + base);
305 }
306
307 error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_TTY, NULL, rc_intr,
308 sc, &sc->sc_hwicookie);
309 if (error) {
310 device_printf(dev, "failed to register interrupt handler\n");
311 goto fail;
312 }
313
314 swi_add(&tty_intr_event, "rc", rc_pollcard, sc, SWI_TTY, 0,
315 &sc->sc_swicookie);
316 return (0);
317
318fail:
319 rc_release_resources(dev);
320 return (error);
321}
322
323static int
324rc_detach(device_t dev)
325{
326 struct rc_softc *sc;
327 struct rc_chans *rc;
328 int error, i;
329
330 sc = device_get_softc(dev);
331
332 rc = sc->sc_channels;
333 for (i = 0; i < CD180_NCHAN; i++, rc++)
334 ttyfree(rc->rc_tp);
335
336 error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie);
337 if (error)
338 device_printf(dev, "failed to deregister interrupt handler\n");
339 swi_remove(sc->sc_swicookie);
340 rc_release_resources(dev);
341
342 return (0);
343}
344
345static void
346rc_release_resources(device_t dev)
347{
348 struct rc_softc *sc;
349 int i;
350
351 sc = device_get_softc(dev);
352 if (sc->sc_irq != NULL) {
353 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
354 sc->sc_irq);
355 sc->sc_irq = NULL;
356 }
357 for (i = 0; i < IOBASE_ADDRS; i++) {
358 if (sc->sc_port[i] == NULL)
359 break;
360 bus_release_resource(dev, SYS_RES_IOPORT, i, sc->sc_port[i]);
361 sc->sc_port[i] = NULL;
362 }
363}
364
365/* RC interrupt handling */
366static void
367rc_intr(void *arg)
368{
369 struct rc_softc *sc;
370 struct rc_chans *rc;
371 int resid, chan;
372 u_char val, iack, bsr, ucnt, *optr;
373 int good_data, t_state;
374
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);
380 return;
381 }
382
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":"");
390#endif
391 if (bsr & RC_BSR_TOUT) {
392 device_printf(sc->sc_dev,
393 "hardware failure, reset board\n");
394 rcout(sc, RC_CTOUT, 0);
395 rc_reinit(sc);
396 return;
397 }
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);
404 goto more_intrs;
405 }
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)
412 ) {
413 if ( ( !(t_state & TS_ISOPEN)
414 || (t_state & TS_TBLOCK)
415 )
416 && (rc->rc_msvr & MSVR_RTS)
417 )
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);
423 }
424 ucnt = rcin(sc, CD180_RDCR) & 0xF;
425 resid = 0;
426
427 if (t_state & TS_ISOPEN) {
428 /* check for input buffer overflow */
429 if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) {
430 resid = ucnt;
431 ucnt = rc->rc_bufend - rc->rc_iptr;
432 resid -= ucnt;
433 if (!(rc->rc_flags & RC_WAS_BUFOVFL)) {
434 rc->rc_flags |= RC_WAS_BUFOVFL;
435 sc->sc_scheduled_event++;
436 }
437 }
438 optr = rc->rc_iptr;
439 /* check foor good data */
440 if (good_data) {
441 while (ucnt-- > 0) {
442 val = rcin(sc, CD180_RDR);
443 optr[0] = val;
444 optr[INPUT_FLAGS_SHIFT] = 0;
445 optr++;
446 sc->sc_scheduled_event++;
447 if (val != 0 && val == rc->rc_tp->t_hotchar)
448 swi_sched(sc->sc_swicookie, 0);
449 }
450 } else {
451 /* Store also status data */
452 while (ucnt-- > 0) {
453 iack = rcin(sc, CD180_RCSR);
454 if (iack & RCSR_Timeout)
455 break;
456 if ( (iack & RCSR_OE)
457 && !(rc->rc_flags & RC_WAS_SILOVFL)) {
458 rc->rc_flags |= RC_WAS_SILOVFL;
459 sc->sc_scheduled_event++;
460 }
461 val = rcin(sc, CD180_RDR);
462 /*
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.
466 */
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)
474 && ((iack & RCSR_FE)
475 || ((iack & RCSR_PE)
476 && (rc->rc_tp->t_iflag & INPCK))))
477 val = 0;
478 else if (val != 0 && val == rc->rc_tp->t_hotchar)
479 swi_sched(sc->sc_swicookie, 0);
480 optr[0] = val;
481 optr[INPUT_FLAGS_SHIFT] = iack;
482 optr++;
483 sc->sc_scheduled_event++;
484 }
485 }
486 }
487 rc->rc_iptr = optr;
488 rc->rc_flags |= RC_DORXFER;
489 } else
490 resid = ucnt;
491 /* Clear FIFO if necessary */
492 while (resid-- > 0) {
493 if (!good_data)
494 iack = rcin(sc, CD180_RCSR);
495 else
496 iack = 0;
497 if (iack & RCSR_Timeout)
498 break;
499 (void) rcin(sc, CD180_RDR);
500 }
501 goto more_intrs;
502 }
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",
507 iack);
508 goto more_intrs;
509 }
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);
515#ifdef RCDEBUG
516 printrcflags(rc, "moint");
517#endif
518 if (rc->rc_flags & RC_CTSFLOW) {
519 if (rc->rc_msvr & MSVR_CTS)
520 rc->rc_flags |= RC_SEND_RDY;
521 else
522 rc->rc_flags &= ~RC_SEND_RDY;
523 } else
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);
529 }
530 goto more_intrs;
531 }
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",
536 iack);
537 goto more_intrs;
538 }
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)
543 )
544 goto more_intrs;
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);
551 rc->rc_pendcmd = 0;
552 goto more_intrs;
553 }
554 optr = rc->rc_optr;
555 resid = rc->rc_obufend - optr;
556 if (resid > CD180_NFIFO)
557 resid = CD180_NFIFO;
558 while (resid-- > 0)
559 rcout(sc, CD180_TDR, *optr++);
560 rc->rc_optr = optr;
561
562 /* output completed? */
563 if (optr >= rc->rc_obufend) {
564 rcout(sc, CD180_IER, rc->rc_ier &= ~IER_TxRdy);
565#ifdef RCDEBUG
566 device_printf(sc->sc_dev,
567 "channel %d: output completed\n",
568 rc->rc_chan);
569#endif
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);
574 }
575 }
576 }
577 more_intrs:
578 rcout(sc, CD180_EOIR, 0); /* end of interrupt */
579 rcout(sc, RC_CTOUT, 0);
580 bsr = ~(rcin(sc, RC_BSR));
581 }
582}
583
584/* Feed characters to output buffer */
585static void
586rc_start(struct tty *tp)
587{
588 struct rc_softc *sc;
589 struct rc_chans *rc;
590 int s;
591
592 rc = tp->t_sc;
593 if (rc->rc_flags & RC_OSBUSY)
594 return;
595 sc = rc->rc_rcb;
596 s = spltty();
597 rc->rc_flags |= RC_OSBUSY;
598 critical_enter();
599 if (tp->t_state & TS_TTSTOP)
600 rc->rc_flags |= RC_OSUSP;
601 else
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)
607 ) {
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);
613 }
614 critical_exit();
615 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
616 goto out;
617#ifdef RCDEBUG
618 printrcflags(rc, "rcstart");
619#endif
620 ttwwakeup(tp);
621#ifdef RCDEBUG
622 printf("rcstart: outq = %d obuf = %d\n",
623 tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr);
624#endif
625 if (tp->t_state & TS_BUSY)
626 goto out; /* output still in progress ... */
627
628 if (tp->t_outq.c_cc > 0) {
629 u_int ocnt;
630
631 tp->t_state |= TS_BUSY;
632 ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf);
633 critical_enter();
634 rc->rc_optr = rc->rc_obuf;
635 rc->rc_obufend = rc->rc_optr + ocnt;
636 critical_exit();
637 if (!(rc->rc_ier & IER_TxRdy)) {
638#ifdef RCDEBUG
639 device_printf(sc->sc_dev,
640 "channel %d: rcstart enable txint\n", rc->rc_chan);
641#endif
642 rcout(sc, CD180_CAR, rc->rc_chan);
643 rcout(sc, CD180_IER, rc->rc_ier |= IER_TxRdy);
644 }
645 }
646out:
647 rc->rc_flags &= ~RC_OSBUSY;
648 (void) splx(s);
649}
650
651/* Handle delayed events. */
652void
653rc_pollcard(void *arg)
654{
655 struct rc_softc *sc;
656 struct rc_chans *rc;
657 struct tty *tp;
658 u_char *tptr, *eptr;
659 int chan, icnt;
660
661 sc = (struct rc_softc *)arg;
662 if (sc->sc_scheduled_event == 0)
663 return;
664 do {
665 rc = sc->sc_channels;
666 for (chan = 0; chan < CD180_NCHAN; rc++, chan++) {
667 tp = rc->rc_tp;
668#ifdef RCDEBUG
669 if (rc->rc_flags & (RC_DORXFER|RC_DOXXFER|RC_MODCHG|
670 RC_WAS_BUFOVFL|RC_WAS_SILOVFL))
671 printrcflags(rc, "rcevent");
672#endif
673 if (rc->rc_flags & RC_WAS_BUFOVFL) {
674 critical_enter();
675 rc->rc_flags &= ~RC_WAS_BUFOVFL;
676 sc->sc_scheduled_event--;
677 critical_exit();
678 device_printf(sc->sc_dev,
679 "channel %d: interrupt-level buffer overflow\n",
680 chan);
681 }
682 if (rc->rc_flags & RC_WAS_SILOVFL) {
683 critical_enter();
684 rc->rc_flags &= ~RC_WAS_SILOVFL;
685 sc->sc_scheduled_event--;
686 critical_exit();
687 device_printf(sc->sc_dev,
688 "channel %d: silo overflow\n", chan);
689 }
690 if (rc->rc_flags & RC_MODCHG) {
691 critical_enter();
692 rc->rc_flags &= ~RC_MODCHG;
693 sc->sc_scheduled_event -= LOTS_OF_EVENTS;
694 critical_exit();
695 ttyld_modem(tp, !!(rc->rc_msvr & MSVR_CD));
696 }
697 if (rc->rc_flags & RC_DORXFER) {
698 critical_enter();
699 rc->rc_flags &= ~RC_DORXFER;
700 eptr = rc->rc_iptr;
701 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE])
702 tptr = &rc->rc_ibuf[RC_IBUFSIZE];
703 else
704 tptr = rc->rc_ibuf;
705 icnt = eptr - tptr;
706 if (icnt > 0) {
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];
711 } else {
712 rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE];
713 rc->rc_bufend = &rc->rc_ibuf[2 * RC_IBUFSIZE];
714 rc->rc_hiwat =
715 &rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER];
716 }
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)
721 ) {
722 rcout(sc, CD180_CAR, chan);
723 rcout(sc, CD180_MSVR,
724 rc->rc_msvr |= MSVR_RTS);
725 }
726 sc->sc_scheduled_event -= icnt;
727 }
728 critical_exit();
729
730 if (icnt <= 0 || !(tp->t_state & TS_ISOPEN))
731 goto done1;
732
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))
738 ttyblock(tp);
739 tk_nin += icnt;
740 tk_rawcc += icnt;
741 tp->t_rawcc += icnt;
742 if (b_to_q(tptr, icnt, &tp->t_rawq))
743 device_printf(sc->sc_dev,
744 "channel %d: tty-level buffer overflow\n",
745 chan);
746 ttwakeup(tp);
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;
751 rc_start(tp);
752 }
753 } else {
754 for (; tptr < eptr; tptr++)
755 ttyld_rint(tp,
756 (tptr[0] |
757 rc_rcsrt[tptr[INPUT_FLAGS_SHIFT] & 0xF]));
758 }
759done1: ;
760 }
761 if (rc->rc_flags & RC_DOXXFER) {
762 critical_enter();
763 sc->sc_scheduled_event -= LOTS_OF_EVENTS;
764 rc->rc_flags &= ~RC_DOXXFER;
765 rc->rc_tp->t_state &= ~TS_BUSY;
766 critical_exit();
767 ttyld_start(tp);
768 }
769 if (sc->sc_scheduled_event == 0)
770 break;
771 }
772 } while (sc->sc_scheduled_event >= LOTS_OF_EVENTS);
773}
774
775static void
776rc_stop(struct tty *tp, int rw)
777{
778 struct rc_softc *sc;
779 struct rc_chans *rc;
780 u_char *tptr, *eptr;
781
782 rc = tp->t_sc;
783 sc = rc->rc_rcb;
784#ifdef RCDEBUG
785 device_printf(sc->sc_dev, "channel %d: rc_stop %s%s\n",
786 rc->rc_chan, (rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":"");
787#endif
788 if (rw & FWRITE)
789 rc_discard_output(rc);
790 critical_enter();
791 if (rw & FREAD) {
792 rc->rc_flags &= ~RC_DORXFER;
793 eptr = rc->rc_iptr;
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];
797 } else {
798 tptr = rc->rc_ibuf;
799 rc->rc_iptr = rc->rc_ibuf;
800 }
801 sc->sc_scheduled_event -= eptr - tptr;
802 }
803 if (tp->t_state & TS_TTSTOP)
804 rc->rc_flags |= RC_OSUSP;
805 else
806 rc->rc_flags &= ~RC_OSUSP;
807 critical_exit();
808}
809
810static void
811rc_close(struct tty *tp)
812{
813 struct rc_chans *rc;
814 struct rc_softc *sc;
815 int s;
816
817 rc = tp->t_sc;
818 sc = rc->rc_rcb;
819 s = spltty();
820 rcout(sc, CD180_CAR, rc->rc_chan);
821
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)
829 ) {
830 CCRCMD(sc, rc->rc_chan, CCR_ResetChan);
831 WAITFORCCR(sc, rc->rc_chan);
832 (void) rc_modem(tp, SER_RTS, 0);
833 ttydtrwaitstart(tp);
834 }
835 rc->rc_flags &= ~RC_ACTOUT;
836 wakeup( &rc->rc_rcb); /* wake bi */
837 wakeup(TSA_CARR_ON(tp));
838 (void) splx(s);
839}
840
841/* Reset the bastard */
842static void
843rc_hwreset(struct rc_softc *sc, u_int chipid)
844{
845 CCRCMD(sc, -1, CCR_HWRESET); /* Hardware reset */
846 DELAY(20000);
847 WAITFORCCR(sc, -1);
848
849 rcout(sc, RC_CTOUT, 0); /* Clear timeout */
850 rcout(sc, CD180_GIVR, chipid);
851 rcout(sc, CD180_GICR, 0);
852
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);
856
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);
861
862 /* Reset DTR */
863 rcout(sc, RC_DTREG, ~0);
864}
865
866/* Set channel parameters */
867static int
868rc_param(struct tty *tp, struct termios *ts)
869{
870 struct rc_softc *sc;
871 struct rc_chans *rc;
872 int idivs, odivs, s, val, cflag, iflag, lflag, inpflow;
873
874 if ( ts->c_ospeed < 0 || ts->c_ospeed > 76800
875 || ts->c_ispeed < 0 || ts->c_ispeed > 76800
876 )
877 return (EINVAL);
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);
882
883 rc = tp->t_sc;
884 sc = rc->rc_rcb;
885 s = spltty();
886
887 /* Select channel */
888 rcout(sc, CD180_CAR, rc->rc_chan);
889
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);
895 }
896
897 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
898 cflag = ts->c_cflag;
899 iflag = ts->c_iflag;
900 lflag = ts->c_lflag;
901
902 if (idivs > 0) {
903 rcout(sc, CD180_RBPRL, idivs & 0xFF);
904 rcout(sc, CD180_RBPRH, idivs >> 8);
905 }
906 if (odivs > 0) {
907 rcout(sc, CD180_TBPRL, odivs & 0xFF);
908 rcout(sc, CD180_TBPRH, odivs >> 8);
909 }
910
911 /* set timeout value */
912 if (ts->c_ispeed > 0) {
913 int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1;
914
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;
919
920 rcout(sc, CD180_RTPR, itm <= 255 ? itm : 255);
921 }
922
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;
927 default:
928 case CS8: val = COR1_8BITS; break;
929 }
930 if (cflag & PARENB) {
931 val |= COR1_NORMPAR;
932 if (cflag & PARODD)
933 val |= COR1_ODDP;
934 if (!(cflag & INPCK))
935 val |= COR1_Ignore;
936 } else
937 val |= COR1_Ignore;
938 if (cflag & CSTOPB)
939 val |= COR1_2SB;
940 rcout(sc, CD180_COR1, val);
941
942 /* Set FIFO threshold */
943 val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2;
944 inpflow = 0;
945 if ( (iflag & IXOFF)
946 && ( ts->c_cc[VSTOP] != _POSIX_VDISABLE
947 && ( ts->c_cc[VSTART] != _POSIX_VDISABLE
948 || (iflag & IXANY)
949 )
950 )
951 ) {
952 inpflow = 1;
953 val |= COR3_SCDE|COR3_FCT;
954 }
955 rcout(sc, CD180_COR3, val);
956
957 /* Initialize on-chip automatic flow control */
958 val = 0;
959 rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY);
960 if (cflag & CCTS_OFLOW) {
961 rc->rc_flags |= RC_CTSFLOW;
962 val |= COR2_CtsAE;
963 } else
964 rc->rc_flags |= RC_SEND_RDY;
965 if (tp->t_state & TS_TTSTOP)
966 rc->rc_flags |= RC_OSUSP;
967 else
968 rc->rc_flags &= ~RC_OSUSP;
969 if (cflag & CRTS_IFLOW)
970 rc->rc_flags |= RC_RTSFLOW;
971 else
972 rc->rc_flags &= ~RC_RTSFLOW;
973
974 if (inpflow) {
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]);
978 val |= COR2_TxIBE;
979 if (iflag & IXANY)
980 val |= COR2_IXM;
981 }
982
983 rcout(sc, CD180_COR2, rc->rc_cor2 = val);
984
985 CCRCMD(sc, rc->rc_chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
986
987 ttyldoptim(tp);
988
989 /* modem ctl */
990 val = cflag & CLOCAL ? 0 : MCOR1_CDzd;
991 if (cflag & CCTS_OFLOW)
992 val |= MCOR1_CTSzd;
993 rcout(sc, CD180_MCOR1, val);
994
995 val = cflag & CLOCAL ? 0 : MCOR2_CDod;
996 if (cflag & CCTS_OFLOW)
997 val |= MCOR2_CTSod;
998 rcout(sc, CD180_MCOR2, val);
999
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);
1004
1005 rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD;
1006 if (cflag & CCTS_OFLOW)
1007 rc->rc_ier |= IER_CTS;
1008 if (cflag & CREAD)
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);
1017 (void) splx(s);
1018 return 0;
1019}
1020
1021/* Re-initialize board after bogus interrupts */
1022static void
1023rc_reinit(struct rc_softc *sc)
1024{
1025 struct rc_chans *rc;
1026 int i;
1027
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);
1032}
1033
1034/* Modem control routines */
1035
1036static int
1037rc_modem(struct tty *tp, int biton, int bitoff)
1038{
1039 struct rc_chans *rc;
1040 struct rc_softc *sc;
1041 u_char *dtr;
1042 u_char msvr;
1043
1044 rc = tp->t_sc;
1045 sc = rc->rc_rcb;
1046 dtr = &sc->sc_dtr;
1047 rcout(sc, CD180_CAR, rc->rc_chan);
1048
1049 if (biton == 0 && bitoff == 0) {
1050 msvr = rc->rc_msvr = rcin(sc, CD180_MSVR);
1051
1052 if (msvr & MSVR_RTS)
1053 biton |= SER_RTS;
1054 if (msvr & MSVR_CTS)
1055 biton |= SER_CTS;
1056 if (msvr & MSVR_DSR)
1057 biton |= SER_DSR;
1058 if (msvr & MSVR_DTR)
1059 biton |= SER_DTR;
1060 if (msvr & MSVR_CD)
1061 biton |= SER_DCD;
1062 if (~rcin(sc, RC_RIREG) & (1 << rc->rc_chan))
1063 biton |= SER_RI;
1064 return biton;
1065 }
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)
1072 msvr |= MSVR_DTR;
1073 if (bitoff & SER_DTR)
1074 msvr &= ~MSVR_DTR;
1075 if (biton & SER_RTS)
1076 msvr |= MSVR_RTS;
1077 if (bitoff & SER_RTS)
1078 msvr &= ~MSVR_RTS;
1079 rcout(sc, CD180_MSVR, msvr);
1080 return 0;
1081}
1082
1083static void
1084rc_break(struct tty *tp, int brk)
1085{
1086 struct rc_chans *rc;
1087
1088 rc = tp->t_sc;
1089
1090 if (brk)
1091 rc->rc_pendcmd = CD180_C_SBRK;
1092 else
1093 rc->rc_pendcmd = CD180_C_EBRK;
1094}
1095
1096#define ERR(s) do { \
1097 device_printf(sc->sc_dev, "%s", ""); \
1098 printf s ; \
1099 printf("\n"); \
1100 (void) splx(old_level); \
1101 return 1; \
1102} while (0)
1103
1104/* Test the board. */
1105int
1106rc_test(struct rc_softc *sc)
1107{
1108 int chan = 0;
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";
1113#define CTLEN 8
1114
1115 struct rtest {
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];
1121
1122 old_level = spltty();
1123
1124 chipid = RC_FAKEID;
1125
1126 /* First, reset board to inital state */
1127 rc_hwreset(sc, chipid);
1128
1129 divs = RC_BRD(19200);
1130
1131 /* Initialize channels */
1132 for (chan = 0; chan < CD180_NCHAN; chan++) {
1133
1134 /* Select and reset channel */
1135 rcout(sc, CD180_CAR, chan);
1136 CCRCMD(sc, chan, CCR_ResetChan);
1137 WAITFORCCR(sc, chan);
1138
1139 /* Set speed */
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);
1144
1145 /* set timeout value */
1146 rcout(sc, CD180_RTPR, 0);
1147
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);
1156
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;
1161 }
1162 tchans[chan].txptr = tchans[chan].rxptr = 0;
1163
1164 /* Now, start transmit */
1165 rcout(sc, CD180_IER, IER_TxMpty|IER_RxData);
1166 }
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);
1182 } else {
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;
1188 }
1189 rcout(sc, CD180_EOIR, 0);
1190 } else if (i & RC_BSR_RXINT) {
1191 u_char ucnt;
1192
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)
1203 break;
1204 if (iack & 0xF)
1205 ERR(("Bad char chan %d (RCSR = %02X)\n",
1206 chan, iack));
1207 if (tchans[chan].rxptr > CD180_NFIFO)
1208 ERR(("Got extra chars chan %d\n",
1209 chan));
1210 tchans[chan].rxbuf[tchans[chan].rxptr++] =
1211 rcin(sc, CD180_RDR);
1212 }
1213 rcout(sc, CD180_EOIR, 0);
1214 }
1215 rcout(sc, RC_CTOUT, 0);
1216 for (iack = chan = 0; chan < CD180_NCHAN; chan++)
1217 if (tchans[chan].rxptr >= CD180_NFIFO)
1218 iack++;
1219 if (iack == CD180_NCHAN)
1220 break;
1221 }
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);
1226 }
1227
1228 if (!rcnt)
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);
1237 return 0;
1238}
1239
1240#ifdef RCDEBUG
1241static void
1242printrcflags(struct rc_chans *rc, char *comment)
1243{
1244 struct rc_softc *sc;
1245 u_short f = rc->rc_flags;
1246
1247 sc = rc->rc_rcb;
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":"");
1262
1263 rcout(sc, CD180_CAR, rc->rc_chan);
1264
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));
1270}
1271#endif /* RCDEBUG */
1272
1273static void
1274rc_discard_output(struct rc_chans *rc)
1275{
1276 critical_enter();
1277 if (rc->rc_flags & RC_DOXXFER) {
1278 rc->rc_rcb->sc_scheduled_event -= LOTS_OF_EVENTS;
1279 rc->rc_flags &= ~RC_DOXXFER;
1280 }
1281 rc->rc_optr = rc->rc_obufend;
1282 rc->rc_tp->t_state &= ~TS_BUSY;
1283 critical_exit();
1284 ttwwakeup(rc->rc_tp);
1285}
1286
1287static void
1288rc_wait0(struct rc_softc *sc, int chan, int line)
1289{
1290 int rcnt;
1291
1292 for (rcnt = 50; rcnt && rcin(sc, CD180_CCR); rcnt--)
1293 DELAY(30);
1294 if (rcnt == 0)
1295 device_printf(sc->sc_dev,
1296 "channel %d command timeout, rc.c line: %d\n", chan, line);
1297}
1298
1299static 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),
1304 { 0, 0 }
1305};
1306
1307static driver_t rc_driver = {
1308 "rc",
1309 rc_methods, sizeof(struct rc_softc),
1310};
1311
1312DRIVER_MODULE(rc, isa, rc_driver, rc_devclass, 0, 0);
190 if (rc_ports[i] == port) {
191 found = 1;
192 break;
193 }
194 if (!found)
195 return (ENXIO);
196
197 /*
198 * We have to have an IRQ hint.
199 */
200 if (isa_get_irq(dev) == -1)
201 return (ENXIO);
202
203 device_set_desc(dev, "SDL Riscom/8");
204 return (0);
205}
206
207static int
208rc_attach(device_t dev)
209{
210 struct rc_chans *rc;
211 struct tty *tp;
212 struct rc_softc *sc;
213 u_int port;
214 int base, chan, error, i, x;
215
216 sc = device_get_softc(dev);
217 sc->sc_dev = dev;
218
219 /*
220 * We need to have IO ports. Lots of them. We need
221 * the following ranges relative to the base port:
222 * 0x0 - 0x10
223 * 0x400 - 0x410
224 * 0x800 - 0x810
225 * 0xc00 - 0xc10
226 * 0x1400 - 0x1410
227 * 0x1800 - 0x1810
228 * 0x1c00 - 0x1c10
229 * 0x2000 - 0x2010
230 * 0x3000 - 0x3010
231 * 0x3400 - 0x3410
232 * 0x3800 - 0x3810
233 * 0x3c00 - 0x3c10
234 * 0x4000 - 0x4010
235 * 0x8000 - 0x8010
236 */
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)
241 return (ENXIO);
242 error = ENOMEM;
243 for (i = 0; i < IOBASE_ADDRS; i++) {
244 x = i;
245 sc->sc_port[i] = bus_alloc_resource_anywhere(dev,
246 SYS_RES_IOPORT, &x, 0x10, RF_ACTIVE);
247 if (x != i) {
248 device_printf(dev, "ioport %d was rid %d\n", i, x);
249 goto fail;
250 }
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);
255 goto fail;
256 }
257 }
258 sc->sc_bt = rman_get_bustag(sc->sc_port[0]);
259 sc->sc_bh = rman_get_bushandle(sc->sc_port[0]);
260
261 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid,
262 RF_ACTIVE);
263 if (sc->sc_irq == NULL) {
264 device_printf(dev, "failed to alloc IRQ\n");
265 goto fail;
266 }
267
268 /*
269 * Now do some actual tests to make sure it works.
270 */
271 error = ENXIO;
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)
275 goto fail;
276 if (rc_test(sc))
277 goto fail;
278
279 /*
280 * Ok, start actually hooking things up.
281 */
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++) {
289 rc->rc_rcb = sc;
290 rc->rc_chan = chan;
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();
297 tp->t_sc = rc;
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, TS_CALLOUT, "m%d", chan + base);
305 }
306
307 error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_TTY, NULL, rc_intr,
308 sc, &sc->sc_hwicookie);
309 if (error) {
310 device_printf(dev, "failed to register interrupt handler\n");
311 goto fail;
312 }
313
314 swi_add(&tty_intr_event, "rc", rc_pollcard, sc, SWI_TTY, 0,
315 &sc->sc_swicookie);
316 return (0);
317
318fail:
319 rc_release_resources(dev);
320 return (error);
321}
322
323static int
324rc_detach(device_t dev)
325{
326 struct rc_softc *sc;
327 struct rc_chans *rc;
328 int error, i;
329
330 sc = device_get_softc(dev);
331
332 rc = sc->sc_channels;
333 for (i = 0; i < CD180_NCHAN; i++, rc++)
334 ttyfree(rc->rc_tp);
335
336 error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie);
337 if (error)
338 device_printf(dev, "failed to deregister interrupt handler\n");
339 swi_remove(sc->sc_swicookie);
340 rc_release_resources(dev);
341
342 return (0);
343}
344
345static void
346rc_release_resources(device_t dev)
347{
348 struct rc_softc *sc;
349 int i;
350
351 sc = device_get_softc(dev);
352 if (sc->sc_irq != NULL) {
353 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
354 sc->sc_irq);
355 sc->sc_irq = NULL;
356 }
357 for (i = 0; i < IOBASE_ADDRS; i++) {
358 if (sc->sc_port[i] == NULL)
359 break;
360 bus_release_resource(dev, SYS_RES_IOPORT, i, sc->sc_port[i]);
361 sc->sc_port[i] = NULL;
362 }
363}
364
365/* RC interrupt handling */
366static void
367rc_intr(void *arg)
368{
369 struct rc_softc *sc;
370 struct rc_chans *rc;
371 int resid, chan;
372 u_char val, iack, bsr, ucnt, *optr;
373 int good_data, t_state;
374
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);
380 return;
381 }
382
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":"");
390#endif
391 if (bsr & RC_BSR_TOUT) {
392 device_printf(sc->sc_dev,
393 "hardware failure, reset board\n");
394 rcout(sc, RC_CTOUT, 0);
395 rc_reinit(sc);
396 return;
397 }
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);
404 goto more_intrs;
405 }
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)
412 ) {
413 if ( ( !(t_state & TS_ISOPEN)
414 || (t_state & TS_TBLOCK)
415 )
416 && (rc->rc_msvr & MSVR_RTS)
417 )
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);
423 }
424 ucnt = rcin(sc, CD180_RDCR) & 0xF;
425 resid = 0;
426
427 if (t_state & TS_ISOPEN) {
428 /* check for input buffer overflow */
429 if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) {
430 resid = ucnt;
431 ucnt = rc->rc_bufend - rc->rc_iptr;
432 resid -= ucnt;
433 if (!(rc->rc_flags & RC_WAS_BUFOVFL)) {
434 rc->rc_flags |= RC_WAS_BUFOVFL;
435 sc->sc_scheduled_event++;
436 }
437 }
438 optr = rc->rc_iptr;
439 /* check foor good data */
440 if (good_data) {
441 while (ucnt-- > 0) {
442 val = rcin(sc, CD180_RDR);
443 optr[0] = val;
444 optr[INPUT_FLAGS_SHIFT] = 0;
445 optr++;
446 sc->sc_scheduled_event++;
447 if (val != 0 && val == rc->rc_tp->t_hotchar)
448 swi_sched(sc->sc_swicookie, 0);
449 }
450 } else {
451 /* Store also status data */
452 while (ucnt-- > 0) {
453 iack = rcin(sc, CD180_RCSR);
454 if (iack & RCSR_Timeout)
455 break;
456 if ( (iack & RCSR_OE)
457 && !(rc->rc_flags & RC_WAS_SILOVFL)) {
458 rc->rc_flags |= RC_WAS_SILOVFL;
459 sc->sc_scheduled_event++;
460 }
461 val = rcin(sc, CD180_RDR);
462 /*
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.
466 */
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)
474 && ((iack & RCSR_FE)
475 || ((iack & RCSR_PE)
476 && (rc->rc_tp->t_iflag & INPCK))))
477 val = 0;
478 else if (val != 0 && val == rc->rc_tp->t_hotchar)
479 swi_sched(sc->sc_swicookie, 0);
480 optr[0] = val;
481 optr[INPUT_FLAGS_SHIFT] = iack;
482 optr++;
483 sc->sc_scheduled_event++;
484 }
485 }
486 }
487 rc->rc_iptr = optr;
488 rc->rc_flags |= RC_DORXFER;
489 } else
490 resid = ucnt;
491 /* Clear FIFO if necessary */
492 while (resid-- > 0) {
493 if (!good_data)
494 iack = rcin(sc, CD180_RCSR);
495 else
496 iack = 0;
497 if (iack & RCSR_Timeout)
498 break;
499 (void) rcin(sc, CD180_RDR);
500 }
501 goto more_intrs;
502 }
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",
507 iack);
508 goto more_intrs;
509 }
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);
515#ifdef RCDEBUG
516 printrcflags(rc, "moint");
517#endif
518 if (rc->rc_flags & RC_CTSFLOW) {
519 if (rc->rc_msvr & MSVR_CTS)
520 rc->rc_flags |= RC_SEND_RDY;
521 else
522 rc->rc_flags &= ~RC_SEND_RDY;
523 } else
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);
529 }
530 goto more_intrs;
531 }
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",
536 iack);
537 goto more_intrs;
538 }
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)
543 )
544 goto more_intrs;
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);
551 rc->rc_pendcmd = 0;
552 goto more_intrs;
553 }
554 optr = rc->rc_optr;
555 resid = rc->rc_obufend - optr;
556 if (resid > CD180_NFIFO)
557 resid = CD180_NFIFO;
558 while (resid-- > 0)
559 rcout(sc, CD180_TDR, *optr++);
560 rc->rc_optr = optr;
561
562 /* output completed? */
563 if (optr >= rc->rc_obufend) {
564 rcout(sc, CD180_IER, rc->rc_ier &= ~IER_TxRdy);
565#ifdef RCDEBUG
566 device_printf(sc->sc_dev,
567 "channel %d: output completed\n",
568 rc->rc_chan);
569#endif
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);
574 }
575 }
576 }
577 more_intrs:
578 rcout(sc, CD180_EOIR, 0); /* end of interrupt */
579 rcout(sc, RC_CTOUT, 0);
580 bsr = ~(rcin(sc, RC_BSR));
581 }
582}
583
584/* Feed characters to output buffer */
585static void
586rc_start(struct tty *tp)
587{
588 struct rc_softc *sc;
589 struct rc_chans *rc;
590 int s;
591
592 rc = tp->t_sc;
593 if (rc->rc_flags & RC_OSBUSY)
594 return;
595 sc = rc->rc_rcb;
596 s = spltty();
597 rc->rc_flags |= RC_OSBUSY;
598 critical_enter();
599 if (tp->t_state & TS_TTSTOP)
600 rc->rc_flags |= RC_OSUSP;
601 else
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)
607 ) {
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);
613 }
614 critical_exit();
615 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
616 goto out;
617#ifdef RCDEBUG
618 printrcflags(rc, "rcstart");
619#endif
620 ttwwakeup(tp);
621#ifdef RCDEBUG
622 printf("rcstart: outq = %d obuf = %d\n",
623 tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr);
624#endif
625 if (tp->t_state & TS_BUSY)
626 goto out; /* output still in progress ... */
627
628 if (tp->t_outq.c_cc > 0) {
629 u_int ocnt;
630
631 tp->t_state |= TS_BUSY;
632 ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf);
633 critical_enter();
634 rc->rc_optr = rc->rc_obuf;
635 rc->rc_obufend = rc->rc_optr + ocnt;
636 critical_exit();
637 if (!(rc->rc_ier & IER_TxRdy)) {
638#ifdef RCDEBUG
639 device_printf(sc->sc_dev,
640 "channel %d: rcstart enable txint\n", rc->rc_chan);
641#endif
642 rcout(sc, CD180_CAR, rc->rc_chan);
643 rcout(sc, CD180_IER, rc->rc_ier |= IER_TxRdy);
644 }
645 }
646out:
647 rc->rc_flags &= ~RC_OSBUSY;
648 (void) splx(s);
649}
650
651/* Handle delayed events. */
652void
653rc_pollcard(void *arg)
654{
655 struct rc_softc *sc;
656 struct rc_chans *rc;
657 struct tty *tp;
658 u_char *tptr, *eptr;
659 int chan, icnt;
660
661 sc = (struct rc_softc *)arg;
662 if (sc->sc_scheduled_event == 0)
663 return;
664 do {
665 rc = sc->sc_channels;
666 for (chan = 0; chan < CD180_NCHAN; rc++, chan++) {
667 tp = rc->rc_tp;
668#ifdef RCDEBUG
669 if (rc->rc_flags & (RC_DORXFER|RC_DOXXFER|RC_MODCHG|
670 RC_WAS_BUFOVFL|RC_WAS_SILOVFL))
671 printrcflags(rc, "rcevent");
672#endif
673 if (rc->rc_flags & RC_WAS_BUFOVFL) {
674 critical_enter();
675 rc->rc_flags &= ~RC_WAS_BUFOVFL;
676 sc->sc_scheduled_event--;
677 critical_exit();
678 device_printf(sc->sc_dev,
679 "channel %d: interrupt-level buffer overflow\n",
680 chan);
681 }
682 if (rc->rc_flags & RC_WAS_SILOVFL) {
683 critical_enter();
684 rc->rc_flags &= ~RC_WAS_SILOVFL;
685 sc->sc_scheduled_event--;
686 critical_exit();
687 device_printf(sc->sc_dev,
688 "channel %d: silo overflow\n", chan);
689 }
690 if (rc->rc_flags & RC_MODCHG) {
691 critical_enter();
692 rc->rc_flags &= ~RC_MODCHG;
693 sc->sc_scheduled_event -= LOTS_OF_EVENTS;
694 critical_exit();
695 ttyld_modem(tp, !!(rc->rc_msvr & MSVR_CD));
696 }
697 if (rc->rc_flags & RC_DORXFER) {
698 critical_enter();
699 rc->rc_flags &= ~RC_DORXFER;
700 eptr = rc->rc_iptr;
701 if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE])
702 tptr = &rc->rc_ibuf[RC_IBUFSIZE];
703 else
704 tptr = rc->rc_ibuf;
705 icnt = eptr - tptr;
706 if (icnt > 0) {
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];
711 } else {
712 rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE];
713 rc->rc_bufend = &rc->rc_ibuf[2 * RC_IBUFSIZE];
714 rc->rc_hiwat =
715 &rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER];
716 }
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)
721 ) {
722 rcout(sc, CD180_CAR, chan);
723 rcout(sc, CD180_MSVR,
724 rc->rc_msvr |= MSVR_RTS);
725 }
726 sc->sc_scheduled_event -= icnt;
727 }
728 critical_exit();
729
730 if (icnt <= 0 || !(tp->t_state & TS_ISOPEN))
731 goto done1;
732
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))
738 ttyblock(tp);
739 tk_nin += icnt;
740 tk_rawcc += icnt;
741 tp->t_rawcc += icnt;
742 if (b_to_q(tptr, icnt, &tp->t_rawq))
743 device_printf(sc->sc_dev,
744 "channel %d: tty-level buffer overflow\n",
745 chan);
746 ttwakeup(tp);
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;
751 rc_start(tp);
752 }
753 } else {
754 for (; tptr < eptr; tptr++)
755 ttyld_rint(tp,
756 (tptr[0] |
757 rc_rcsrt[tptr[INPUT_FLAGS_SHIFT] & 0xF]));
758 }
759done1: ;
760 }
761 if (rc->rc_flags & RC_DOXXFER) {
762 critical_enter();
763 sc->sc_scheduled_event -= LOTS_OF_EVENTS;
764 rc->rc_flags &= ~RC_DOXXFER;
765 rc->rc_tp->t_state &= ~TS_BUSY;
766 critical_exit();
767 ttyld_start(tp);
768 }
769 if (sc->sc_scheduled_event == 0)
770 break;
771 }
772 } while (sc->sc_scheduled_event >= LOTS_OF_EVENTS);
773}
774
775static void
776rc_stop(struct tty *tp, int rw)
777{
778 struct rc_softc *sc;
779 struct rc_chans *rc;
780 u_char *tptr, *eptr;
781
782 rc = tp->t_sc;
783 sc = rc->rc_rcb;
784#ifdef RCDEBUG
785 device_printf(sc->sc_dev, "channel %d: rc_stop %s%s\n",
786 rc->rc_chan, (rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":"");
787#endif
788 if (rw & FWRITE)
789 rc_discard_output(rc);
790 critical_enter();
791 if (rw & FREAD) {
792 rc->rc_flags &= ~RC_DORXFER;
793 eptr = rc->rc_iptr;
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];
797 } else {
798 tptr = rc->rc_ibuf;
799 rc->rc_iptr = rc->rc_ibuf;
800 }
801 sc->sc_scheduled_event -= eptr - tptr;
802 }
803 if (tp->t_state & TS_TTSTOP)
804 rc->rc_flags |= RC_OSUSP;
805 else
806 rc->rc_flags &= ~RC_OSUSP;
807 critical_exit();
808}
809
810static void
811rc_close(struct tty *tp)
812{
813 struct rc_chans *rc;
814 struct rc_softc *sc;
815 int s;
816
817 rc = tp->t_sc;
818 sc = rc->rc_rcb;
819 s = spltty();
820 rcout(sc, CD180_CAR, rc->rc_chan);
821
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)
829 ) {
830 CCRCMD(sc, rc->rc_chan, CCR_ResetChan);
831 WAITFORCCR(sc, rc->rc_chan);
832 (void) rc_modem(tp, SER_RTS, 0);
833 ttydtrwaitstart(tp);
834 }
835 rc->rc_flags &= ~RC_ACTOUT;
836 wakeup( &rc->rc_rcb); /* wake bi */
837 wakeup(TSA_CARR_ON(tp));
838 (void) splx(s);
839}
840
841/* Reset the bastard */
842static void
843rc_hwreset(struct rc_softc *sc, u_int chipid)
844{
845 CCRCMD(sc, -1, CCR_HWRESET); /* Hardware reset */
846 DELAY(20000);
847 WAITFORCCR(sc, -1);
848
849 rcout(sc, RC_CTOUT, 0); /* Clear timeout */
850 rcout(sc, CD180_GIVR, chipid);
851 rcout(sc, CD180_GICR, 0);
852
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);
856
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);
861
862 /* Reset DTR */
863 rcout(sc, RC_DTREG, ~0);
864}
865
866/* Set channel parameters */
867static int
868rc_param(struct tty *tp, struct termios *ts)
869{
870 struct rc_softc *sc;
871 struct rc_chans *rc;
872 int idivs, odivs, s, val, cflag, iflag, lflag, inpflow;
873
874 if ( ts->c_ospeed < 0 || ts->c_ospeed > 76800
875 || ts->c_ispeed < 0 || ts->c_ispeed > 76800
876 )
877 return (EINVAL);
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);
882
883 rc = tp->t_sc;
884 sc = rc->rc_rcb;
885 s = spltty();
886
887 /* Select channel */
888 rcout(sc, CD180_CAR, rc->rc_chan);
889
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);
895 }
896
897 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
898 cflag = ts->c_cflag;
899 iflag = ts->c_iflag;
900 lflag = ts->c_lflag;
901
902 if (idivs > 0) {
903 rcout(sc, CD180_RBPRL, idivs & 0xFF);
904 rcout(sc, CD180_RBPRH, idivs >> 8);
905 }
906 if (odivs > 0) {
907 rcout(sc, CD180_TBPRL, odivs & 0xFF);
908 rcout(sc, CD180_TBPRH, odivs >> 8);
909 }
910
911 /* set timeout value */
912 if (ts->c_ispeed > 0) {
913 int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1;
914
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;
919
920 rcout(sc, CD180_RTPR, itm <= 255 ? itm : 255);
921 }
922
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;
927 default:
928 case CS8: val = COR1_8BITS; break;
929 }
930 if (cflag & PARENB) {
931 val |= COR1_NORMPAR;
932 if (cflag & PARODD)
933 val |= COR1_ODDP;
934 if (!(cflag & INPCK))
935 val |= COR1_Ignore;
936 } else
937 val |= COR1_Ignore;
938 if (cflag & CSTOPB)
939 val |= COR1_2SB;
940 rcout(sc, CD180_COR1, val);
941
942 /* Set FIFO threshold */
943 val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2;
944 inpflow = 0;
945 if ( (iflag & IXOFF)
946 && ( ts->c_cc[VSTOP] != _POSIX_VDISABLE
947 && ( ts->c_cc[VSTART] != _POSIX_VDISABLE
948 || (iflag & IXANY)
949 )
950 )
951 ) {
952 inpflow = 1;
953 val |= COR3_SCDE|COR3_FCT;
954 }
955 rcout(sc, CD180_COR3, val);
956
957 /* Initialize on-chip automatic flow control */
958 val = 0;
959 rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY);
960 if (cflag & CCTS_OFLOW) {
961 rc->rc_flags |= RC_CTSFLOW;
962 val |= COR2_CtsAE;
963 } else
964 rc->rc_flags |= RC_SEND_RDY;
965 if (tp->t_state & TS_TTSTOP)
966 rc->rc_flags |= RC_OSUSP;
967 else
968 rc->rc_flags &= ~RC_OSUSP;
969 if (cflag & CRTS_IFLOW)
970 rc->rc_flags |= RC_RTSFLOW;
971 else
972 rc->rc_flags &= ~RC_RTSFLOW;
973
974 if (inpflow) {
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]);
978 val |= COR2_TxIBE;
979 if (iflag & IXANY)
980 val |= COR2_IXM;
981 }
982
983 rcout(sc, CD180_COR2, rc->rc_cor2 = val);
984
985 CCRCMD(sc, rc->rc_chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
986
987 ttyldoptim(tp);
988
989 /* modem ctl */
990 val = cflag & CLOCAL ? 0 : MCOR1_CDzd;
991 if (cflag & CCTS_OFLOW)
992 val |= MCOR1_CTSzd;
993 rcout(sc, CD180_MCOR1, val);
994
995 val = cflag & CLOCAL ? 0 : MCOR2_CDod;
996 if (cflag & CCTS_OFLOW)
997 val |= MCOR2_CTSod;
998 rcout(sc, CD180_MCOR2, val);
999
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);
1004
1005 rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD;
1006 if (cflag & CCTS_OFLOW)
1007 rc->rc_ier |= IER_CTS;
1008 if (cflag & CREAD)
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);
1017 (void) splx(s);
1018 return 0;
1019}
1020
1021/* Re-initialize board after bogus interrupts */
1022static void
1023rc_reinit(struct rc_softc *sc)
1024{
1025 struct rc_chans *rc;
1026 int i;
1027
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);
1032}
1033
1034/* Modem control routines */
1035
1036static int
1037rc_modem(struct tty *tp, int biton, int bitoff)
1038{
1039 struct rc_chans *rc;
1040 struct rc_softc *sc;
1041 u_char *dtr;
1042 u_char msvr;
1043
1044 rc = tp->t_sc;
1045 sc = rc->rc_rcb;
1046 dtr = &sc->sc_dtr;
1047 rcout(sc, CD180_CAR, rc->rc_chan);
1048
1049 if (biton == 0 && bitoff == 0) {
1050 msvr = rc->rc_msvr = rcin(sc, CD180_MSVR);
1051
1052 if (msvr & MSVR_RTS)
1053 biton |= SER_RTS;
1054 if (msvr & MSVR_CTS)
1055 biton |= SER_CTS;
1056 if (msvr & MSVR_DSR)
1057 biton |= SER_DSR;
1058 if (msvr & MSVR_DTR)
1059 biton |= SER_DTR;
1060 if (msvr & MSVR_CD)
1061 biton |= SER_DCD;
1062 if (~rcin(sc, RC_RIREG) & (1 << rc->rc_chan))
1063 biton |= SER_RI;
1064 return biton;
1065 }
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)
1072 msvr |= MSVR_DTR;
1073 if (bitoff & SER_DTR)
1074 msvr &= ~MSVR_DTR;
1075 if (biton & SER_RTS)
1076 msvr |= MSVR_RTS;
1077 if (bitoff & SER_RTS)
1078 msvr &= ~MSVR_RTS;
1079 rcout(sc, CD180_MSVR, msvr);
1080 return 0;
1081}
1082
1083static void
1084rc_break(struct tty *tp, int brk)
1085{
1086 struct rc_chans *rc;
1087
1088 rc = tp->t_sc;
1089
1090 if (brk)
1091 rc->rc_pendcmd = CD180_C_SBRK;
1092 else
1093 rc->rc_pendcmd = CD180_C_EBRK;
1094}
1095
1096#define ERR(s) do { \
1097 device_printf(sc->sc_dev, "%s", ""); \
1098 printf s ; \
1099 printf("\n"); \
1100 (void) splx(old_level); \
1101 return 1; \
1102} while (0)
1103
1104/* Test the board. */
1105int
1106rc_test(struct rc_softc *sc)
1107{
1108 int chan = 0;
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";
1113#define CTLEN 8
1114
1115 struct rtest {
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];
1121
1122 old_level = spltty();
1123
1124 chipid = RC_FAKEID;
1125
1126 /* First, reset board to inital state */
1127 rc_hwreset(sc, chipid);
1128
1129 divs = RC_BRD(19200);
1130
1131 /* Initialize channels */
1132 for (chan = 0; chan < CD180_NCHAN; chan++) {
1133
1134 /* Select and reset channel */
1135 rcout(sc, CD180_CAR, chan);
1136 CCRCMD(sc, chan, CCR_ResetChan);
1137 WAITFORCCR(sc, chan);
1138
1139 /* Set speed */
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);
1144
1145 /* set timeout value */
1146 rcout(sc, CD180_RTPR, 0);
1147
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);
1156
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;
1161 }
1162 tchans[chan].txptr = tchans[chan].rxptr = 0;
1163
1164 /* Now, start transmit */
1165 rcout(sc, CD180_IER, IER_TxMpty|IER_RxData);
1166 }
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);
1182 } else {
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;
1188 }
1189 rcout(sc, CD180_EOIR, 0);
1190 } else if (i & RC_BSR_RXINT) {
1191 u_char ucnt;
1192
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)
1203 break;
1204 if (iack & 0xF)
1205 ERR(("Bad char chan %d (RCSR = %02X)\n",
1206 chan, iack));
1207 if (tchans[chan].rxptr > CD180_NFIFO)
1208 ERR(("Got extra chars chan %d\n",
1209 chan));
1210 tchans[chan].rxbuf[tchans[chan].rxptr++] =
1211 rcin(sc, CD180_RDR);
1212 }
1213 rcout(sc, CD180_EOIR, 0);
1214 }
1215 rcout(sc, RC_CTOUT, 0);
1216 for (iack = chan = 0; chan < CD180_NCHAN; chan++)
1217 if (tchans[chan].rxptr >= CD180_NFIFO)
1218 iack++;
1219 if (iack == CD180_NCHAN)
1220 break;
1221 }
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);
1226 }
1227
1228 if (!rcnt)
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);
1237 return 0;
1238}
1239
1240#ifdef RCDEBUG
1241static void
1242printrcflags(struct rc_chans *rc, char *comment)
1243{
1244 struct rc_softc *sc;
1245 u_short f = rc->rc_flags;
1246
1247 sc = rc->rc_rcb;
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":"");
1262
1263 rcout(sc, CD180_CAR, rc->rc_chan);
1264
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));
1270}
1271#endif /* RCDEBUG */
1272
1273static void
1274rc_discard_output(struct rc_chans *rc)
1275{
1276 critical_enter();
1277 if (rc->rc_flags & RC_DOXXFER) {
1278 rc->rc_rcb->sc_scheduled_event -= LOTS_OF_EVENTS;
1279 rc->rc_flags &= ~RC_DOXXFER;
1280 }
1281 rc->rc_optr = rc->rc_obufend;
1282 rc->rc_tp->t_state &= ~TS_BUSY;
1283 critical_exit();
1284 ttwwakeup(rc->rc_tp);
1285}
1286
1287static void
1288rc_wait0(struct rc_softc *sc, int chan, int line)
1289{
1290 int rcnt;
1291
1292 for (rcnt = 50; rcnt && rcin(sc, CD180_CCR); rcnt--)
1293 DELAY(30);
1294 if (rcnt == 0)
1295 device_printf(sc->sc_dev,
1296 "channel %d command timeout, rc.c line: %d\n", chan, line);
1297}
1298
1299static 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),
1304 { 0, 0 }
1305};
1306
1307static driver_t rc_driver = {
1308 "rc",
1309 rc_methods, sizeof(struct rc_softc),
1310};
1311
1312DRIVER_MODULE(rc, isa, rc_driver, rc_devclass, 0, 0);