xref: /netbsd-src/sys/dev/ic/clmpcc.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: clmpcc.c,v 1.48 2014/03/25 15:51:58 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Steve C. Woodford.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Cirrus Logic CD2400/CD2401 Four Channel Multi-Protocol Comms. Controller.
34  */
35 
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: clmpcc.c,v 1.48 2014/03/25 15:51:58 christos Exp $");
38 
39 #include "opt_ddb.h"
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/ioctl.h>
44 #include <sys/select.h>
45 #include <sys/tty.h>
46 #include <sys/proc.h>
47 #include <sys/conf.h>
48 #include <sys/file.h>
49 #include <sys/uio.h>
50 #include <sys/kernel.h>
51 #include <sys/syslog.h>
52 #include <sys/device.h>
53 #include <sys/malloc.h>
54 #include <sys/kauth.h>
55 #include <sys/intr.h>
56 
57 #include <sys/bus.h>
58 #include <machine/param.h>
59 
60 #include <dev/ic/clmpccreg.h>
61 #include <dev/ic/clmpccvar.h>
62 #include <dev/cons.h>
63 
64 
65 #if defined(CLMPCC_ONLY_BYTESWAP_LOW) && defined(CLMPCC_ONLY_BYTESWAP_HIGH)
66 #error	"CLMPCC_ONLY_BYTESWAP_LOW and CLMPCC_ONLY_BYTESWAP_HIGH are mutually exclusive."
67 #endif
68 
69 
70 static int	clmpcc_init(struct clmpcc_softc *sc);
71 static void	clmpcc_shutdown(struct clmpcc_chan *);
72 static int	clmpcc_speed(struct clmpcc_softc *, speed_t, int *, int *);
73 static int	clmpcc_param(struct tty *, struct termios *);
74 static void	clmpcc_set_params(struct clmpcc_chan *);
75 static void	clmpcc_start(struct tty *);
76 static int 	clmpcc_modem_control(struct clmpcc_chan *, int, int);
77 
78 #define	CLMPCCUNIT(x)		(minor(x) & 0x7fffc)
79 #define CLMPCCCHAN(x)		(minor(x) & 0x00003)
80 #define	CLMPCCDIALOUT(x)	(minor(x) & 0x80000)
81 
82 /*
83  * These should be in a header file somewhere...
84  */
85 #define	ISCLR(v, f)	(((v) & (f)) == 0)
86 
87 extern struct cfdriver clmpcc_cd;
88 
89 dev_type_open(clmpccopen);
90 dev_type_close(clmpccclose);
91 dev_type_read(clmpccread);
92 dev_type_write(clmpccwrite);
93 dev_type_ioctl(clmpccioctl);
94 dev_type_stop(clmpccstop);
95 dev_type_tty(clmpcctty);
96 dev_type_poll(clmpccpoll);
97 
98 const struct cdevsw clmpcc_cdevsw = {
99 	.d_open = clmpccopen,
100 	.d_close = clmpccclose,
101 	.d_read = clmpccread,
102 	.d_write = clmpccwrite,
103 	.d_ioctl = clmpccioctl,
104 	.d_stop = clmpccstop,
105 	.d_tty = clmpcctty,
106 	.d_poll = clmpccpoll,
107 	.d_mmap = nommap,
108 	.d_kqfilter = ttykqfilter,
109 	.d_flag = D_TTY
110 };
111 
112 /*
113  * Make this an option variable one can patch.
114  */
115 u_int clmpcc_ibuf_size = CLMPCC_RING_SIZE;
116 
117 
118 /*
119  * Things needed when the device is used as a console
120  */
121 static struct clmpcc_softc *cons_sc = NULL;
122 static int cons_chan;
123 static int cons_rate;
124 
125 static int	clmpcc_common_getc(struct clmpcc_softc *, int);
126 static void	clmpcc_common_putc(struct clmpcc_softc *, int, int);
127 int		clmpcccngetc(dev_t);
128 void		clmpcccnputc(dev_t, int);
129 
130 
131 /*
132  * Convenience functions, inlined for speed
133  */
134 #define	integrate   static inline
135 integrate u_int8_t  clmpcc_rdreg(struct clmpcc_softc *, u_int);
136 integrate void      clmpcc_wrreg(struct clmpcc_softc *, u_int, u_int);
137 integrate u_int8_t  clmpcc_rdreg_odd(struct clmpcc_softc *, u_int);
138 integrate void      clmpcc_wrreg_odd(struct clmpcc_softc *, u_int, u_int);
139 integrate void      clmpcc_wrtx_multi(struct clmpcc_softc *, u_int8_t *,
140 					u_int);
141 integrate u_int8_t  clmpcc_select_channel(struct clmpcc_softc *, u_int);
142 integrate void      clmpcc_channel_cmd(struct clmpcc_softc *,int,int);
143 integrate void      clmpcc_enable_transmitter(struct clmpcc_chan *);
144 
145 #define clmpcc_rd_msvr(s)	clmpcc_rdreg_odd(s,CLMPCC_REG_MSVR)
146 #define clmpcc_wr_msvr(s,r,v)	clmpcc_wrreg_odd(s,r,v)
147 #define clmpcc_wr_pilr(s,r,v)	clmpcc_wrreg_odd(s,r,v)
148 #define clmpcc_rd_rxdata(s)	clmpcc_rdreg_odd(s,CLMPCC_REG_RDR)
149 #define clmpcc_wr_txdata(s,v)	clmpcc_wrreg_odd(s,CLMPCC_REG_TDR,v)
150 
151 
152 integrate u_int8_t
153 clmpcc_rdreg(struct clmpcc_softc *sc, u_int offset)
154 {
155 #if !defined(CLMPCC_ONLY_BYTESWAP_LOW) && !defined(CLMPCC_ONLY_BYTESWAP_HIGH)
156 	offset ^= sc->sc_byteswap;
157 #elif defined(CLMPCC_ONLY_BYTESWAP_HIGH)
158 	offset ^= CLMPCC_BYTESWAP_HIGH;
159 #endif
160 	return bus_space_read_1(sc->sc_iot, sc->sc_ioh, offset);
161 }
162 
163 integrate void
164 clmpcc_wrreg(struct clmpcc_softc *sc, u_int offset, u_int val)
165 {
166 #if !defined(CLMPCC_ONLY_BYTESWAP_LOW) && !defined(CLMPCC_ONLY_BYTESWAP_HIGH)
167 	offset ^= sc->sc_byteswap;
168 #elif defined(CLMPCC_ONLY_BYTESWAP_HIGH)
169 	offset ^= CLMPCC_BYTESWAP_HIGH;
170 #endif
171 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, offset, val);
172 }
173 
174 integrate u_int8_t
175 clmpcc_rdreg_odd(struct clmpcc_softc *sc, u_int offset)
176 {
177 #if !defined(CLMPCC_ONLY_BYTESWAP_LOW) && !defined(CLMPCC_ONLY_BYTESWAP_HIGH)
178 	offset ^= (sc->sc_byteswap & 2);
179 #elif defined(CLMPCC_ONLY_BYTESWAP_HIGH)
180 	offset ^= (CLMPCC_BYTESWAP_HIGH & 2);
181 #endif
182 	return bus_space_read_1(sc->sc_iot, sc->sc_ioh, offset);
183 }
184 
185 integrate void
186 clmpcc_wrreg_odd(struct clmpcc_softc *sc, u_int offset, u_int val)
187 {
188 #if !defined(CLMPCC_ONLY_BYTESWAP_LOW) && !defined(CLMPCC_ONLY_BYTESWAP_HIGH)
189 	offset ^= (sc->sc_byteswap & 2);
190 #elif defined(CLMPCC_ONLY_BYTESWAP_HIGH)
191 	offset ^= (CLMPCC_BYTESWAP_HIGH & 2);
192 #endif
193 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, offset, val);
194 }
195 
196 integrate void
197 clmpcc_wrtx_multi(struct clmpcc_softc *sc, u_int8_t *buff, u_int count)
198 {
199 	u_int offset = CLMPCC_REG_TDR;
200 
201 #if !defined(CLMPCC_ONLY_BYTESWAP_LOW) && !defined(CLMPCC_ONLY_BYTESWAP_HIGH)
202 	offset ^= (sc->sc_byteswap & 2);
203 #elif defined(CLMPCC_ONLY_BYTESWAP_HIGH)
204 	offset ^= (CLMPCC_BYTESWAP_HIGH & 2);
205 #endif
206 	bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh, offset, buff, count);
207 }
208 
209 integrate u_int8_t
210 clmpcc_select_channel(struct clmpcc_softc *sc, u_int new_chan)
211 {
212 	u_int old_chan = clmpcc_rdreg_odd(sc, CLMPCC_REG_CAR);
213 
214 	clmpcc_wrreg_odd(sc, CLMPCC_REG_CAR, new_chan);
215 
216 	return old_chan;
217 }
218 
219 integrate void
220 clmpcc_channel_cmd(struct clmpcc_softc *sc, int chan, int cmd)
221 {
222 	int i;
223 
224 	for (i = 5000; i; i--) {
225 		if ( clmpcc_rdreg(sc, CLMPCC_REG_CCR) == 0 )
226 			break;
227 		delay(1);
228 	}
229 
230 	if ( i == 0 )
231 		printf("%s: channel %d command timeout (idle)\n",
232 			device_xname(sc->sc_dev), chan);
233 
234 	clmpcc_wrreg(sc, CLMPCC_REG_CCR, cmd);
235 }
236 
237 integrate void
238 clmpcc_enable_transmitter(struct clmpcc_chan *ch)
239 {
240 	u_int old;
241 	int s;
242 
243 	old = clmpcc_select_channel(ch->ch_sc, ch->ch_car);
244 
245 	s = splserial();
246 	clmpcc_wrreg(ch->ch_sc, CLMPCC_REG_IER,
247 		clmpcc_rdreg(ch->ch_sc, CLMPCC_REG_IER) | CLMPCC_IER_TX_EMPTY);
248 	SET(ch->ch_tty->t_state, TS_BUSY);
249 	splx(s);
250 
251 	clmpcc_select_channel(ch->ch_sc, old);
252 }
253 
254 static int
255 clmpcc_speed(struct clmpcc_softc *sc, speed_t speed, int *cor, int *bpr)
256 {
257 	int c, co, br;
258 
259 	for (co = 0, c = 8; c <= 2048; co++, c *= 4) {
260 		br = ((sc->sc_clk / c) / speed) - 1;
261 		if ( br < 0x100 ) {
262 			*cor = co;
263 			*bpr = br;
264 			return 0;
265 		}
266 	}
267 
268 	return -1;
269 }
270 
271 void
272 clmpcc_attach(struct clmpcc_softc *sc)
273 {
274 	struct clmpcc_chan *ch;
275 	struct tty *tp;
276 	int chan;
277 
278 	if ( cons_sc != NULL &&
279 	     sc->sc_iot == cons_sc->sc_iot && sc->sc_ioh == cons_sc->sc_ioh )
280 		cons_sc = sc;
281 
282 	/* Initialise the chip */
283 	clmpcc_init(sc);
284 
285 	printf(": Cirrus Logic CD240%c Serial Controller\n",
286 		(clmpcc_rd_msvr(sc) & CLMPCC_MSVR_PORT_ID) ? '0' : '1');
287 
288 	sc->sc_softintr_cookie =
289 	    softint_establish(SOFTINT_SERIAL, clmpcc_softintr, sc);
290 	if (sc->sc_softintr_cookie == NULL)
291 		panic("clmpcc_attach: softintr_establish");
292 	memset(&(sc->sc_chans[0]), 0, sizeof(sc->sc_chans));
293 
294 	for (chan = 0; chan < CLMPCC_NUM_CHANS; chan++) {
295 		ch = &sc->sc_chans[chan];
296 
297 		ch->ch_sc = sc;
298 		ch->ch_car = chan;
299 
300 		tp = tty_alloc();
301 		tp->t_oproc = clmpcc_start;
302 		tp->t_param = clmpcc_param;
303 
304 		ch->ch_tty = tp;
305 
306 		ch->ch_ibuf = malloc(clmpcc_ibuf_size * 2, M_DEVBUF, M_NOWAIT);
307 		if ( ch->ch_ibuf == NULL ) {
308 			aprint_error_dev(sc->sc_dev, "(%d): unable to allocate ring buffer\n",
309 		    		chan);
310 			return;
311 		}
312 
313 		ch->ch_ibuf_end = &(ch->ch_ibuf[clmpcc_ibuf_size * 2]);
314 		ch->ch_ibuf_rd = ch->ch_ibuf_wr = ch->ch_ibuf;
315 
316 		tty_attach(tp);
317 	}
318 
319 	aprint_error_dev(sc->sc_dev, "%d channels available",
320 					    CLMPCC_NUM_CHANS);
321 	if ( cons_sc == sc ) {
322 		printf(", console on channel %d.\n", cons_chan);
323 		SET(sc->sc_chans[cons_chan].ch_flags, CLMPCC_FLG_IS_CONSOLE);
324 		SET(sc->sc_chans[cons_chan].ch_openflags, TIOCFLAG_SOFTCAR);
325 	} else
326 		printf(".\n");
327 }
328 
329 static int
330 clmpcc_init(struct clmpcc_softc *sc)
331 {
332 	u_int tcor = 0, tbpr = 0;
333 	u_int rcor = 0, rbpr = 0;
334 	u_int msvr_rts, msvr_dtr;
335 	u_int ccr;
336 	int is_console;
337 	int i;
338 
339 	/*
340 	 * All we're really concerned about here is putting the chip
341 	 * into a quiescent state so that it won't do anything until
342 	 * clmpccopen() is called. (Except the console channel.)
343 	 */
344 
345 	/*
346 	 * If the chip is acting as console, set all channels to the supplied
347 	 * console baud rate. Otherwise, plump for 9600.
348 	 */
349 	if ( cons_sc &&
350 	     sc->sc_ioh == cons_sc->sc_ioh && sc->sc_iot == cons_sc->sc_iot ) {
351 		clmpcc_speed(sc, cons_rate, &tcor, &tbpr);
352 		clmpcc_speed(sc, cons_rate, &rcor, &rbpr);
353 		is_console = 1;
354 	} else {
355 		clmpcc_speed(sc, 9600, &tcor, &tbpr);
356 		clmpcc_speed(sc, 9600, &rcor, &rbpr);
357 		is_console = 0;
358 	}
359 
360 	/* Allow any pending output to be sent */
361 	delay(10000);
362 
363 	/* Send the Reset All command  to channel 0 (resets all channels!) */
364 	clmpcc_channel_cmd(sc, 0, CLMPCC_CCR_T0_RESET_ALL);
365 
366 	delay(1000);
367 
368 	/*
369 	 * The chip will set it's firmware revision register to a non-zero
370 	 * value to indicate completion of reset.
371 	 */
372 	for (i = 10000; clmpcc_rdreg(sc, CLMPCC_REG_GFRCR) == 0 && i; i--)
373 		delay(1);
374 
375 	if ( i == 0 ) {
376 		/*
377 		 * Watch out... If this chip is console, the message
378 		 * probably won't be sent since we just reset it!
379 		 */
380 		aprint_error_dev(sc->sc_dev, "Failed to reset chip\n");
381 		return -1;
382 	}
383 
384 	for (i = 0; i < CLMPCC_NUM_CHANS; i++) {
385 		clmpcc_select_channel(sc, i);
386 
387 		/* All interrupts are disabled to begin with */
388 		clmpcc_wrreg(sc, CLMPCC_REG_IER, 0);
389 
390 		/* Make sure the channel interrupts on the correct vectors */
391 		clmpcc_wrreg(sc, CLMPCC_REG_LIVR, sc->sc_vector_base);
392 		clmpcc_wr_pilr(sc, CLMPCC_REG_RPILR, sc->sc_rpilr);
393 		clmpcc_wr_pilr(sc, CLMPCC_REG_TPILR, sc->sc_tpilr);
394 		clmpcc_wr_pilr(sc, CLMPCC_REG_MPILR, sc->sc_mpilr);
395 
396 		/* Receive timer prescaler set to 1ms */
397 		clmpcc_wrreg(sc, CLMPCC_REG_TPR,
398 				 CLMPCC_MSEC_TO_TPR(sc->sc_clk, 1));
399 
400 		/* We support Async mode only */
401 		clmpcc_wrreg(sc, CLMPCC_REG_CMR, CLMPCC_CMR_ASYNC);
402 
403 		/* Set the required baud rate */
404 		clmpcc_wrreg(sc, CLMPCC_REG_TCOR, CLMPCC_TCOR_CLK(tcor));
405 		clmpcc_wrreg(sc, CLMPCC_REG_TBPR, tbpr);
406 		clmpcc_wrreg(sc, CLMPCC_REG_RCOR, CLMPCC_RCOR_CLK(rcor));
407 		clmpcc_wrreg(sc, CLMPCC_REG_RBPR, rbpr);
408 
409 		/* Always default to 8N1 (XXX what about console?) */
410 		clmpcc_wrreg(sc, CLMPCC_REG_COR1, CLMPCC_COR1_CHAR_8BITS |
411 						  CLMPCC_COR1_NO_PARITY |
412 						  CLMPCC_COR1_IGNORE_PAR);
413 
414 		clmpcc_wrreg(sc, CLMPCC_REG_COR2, 0);
415 
416 		clmpcc_wrreg(sc, CLMPCC_REG_COR3, CLMPCC_COR3_STOP_1);
417 
418 		clmpcc_wrreg(sc, CLMPCC_REG_COR4, CLMPCC_COR4_DSRzd |
419 						  CLMPCC_COR4_CDzd |
420 						  CLMPCC_COR4_CTSzd);
421 
422 		clmpcc_wrreg(sc, CLMPCC_REG_COR5, CLMPCC_COR5_DSRod |
423 						  CLMPCC_COR5_CDod |
424 						  CLMPCC_COR5_CTSod |
425 						  CLMPCC_COR5_FLOW_NORM);
426 
427 		clmpcc_wrreg(sc, CLMPCC_REG_COR6, 0);
428 		clmpcc_wrreg(sc, CLMPCC_REG_COR7, 0);
429 
430 		/* Set the receive FIFO timeout */
431 		clmpcc_wrreg(sc, CLMPCC_REG_RTPRl, CLMPCC_RTPR_DEFAULT);
432 		clmpcc_wrreg(sc, CLMPCC_REG_RTPRh, 0);
433 
434 		/* At this point, we set up the console differently */
435 		if ( is_console && i == cons_chan ) {
436 			msvr_rts = CLMPCC_MSVR_RTS;
437 			msvr_dtr = CLMPCC_MSVR_DTR;
438 			ccr = CLMPCC_CCR_T0_RX_EN | CLMPCC_CCR_T0_TX_EN;
439 		} else {
440 			msvr_rts = 0;
441 			msvr_dtr = 0;
442 			ccr = CLMPCC_CCR_T0_RX_DIS | CLMPCC_CCR_T0_TX_DIS;
443 		}
444 
445 		clmpcc_wrreg(sc, CLMPCC_REG_MSVR_RTS, msvr_rts);
446 		clmpcc_wrreg(sc, CLMPCC_REG_MSVR_DTR, msvr_dtr);
447 		clmpcc_channel_cmd(sc, i, CLMPCC_CCR_T0_INIT | ccr);
448 		delay(100);
449 	}
450 
451 	return 0;
452 }
453 
454 static void
455 clmpcc_shutdown(struct clmpcc_chan *ch)
456 {
457 	int oldch;
458 
459 	oldch = clmpcc_select_channel(ch->ch_sc, ch->ch_car);
460 
461 	/* Turn off interrupts. */
462 	clmpcc_wrreg(ch->ch_sc, CLMPCC_REG_IER, 0);
463 
464 	if ( ISCLR(ch->ch_flags, CLMPCC_FLG_IS_CONSOLE) ) {
465 		/* Disable the transmitter and receiver */
466 		clmpcc_channel_cmd(ch->ch_sc, ch->ch_car, CLMPCC_CCR_T0_RX_DIS |
467 							  CLMPCC_CCR_T0_TX_DIS);
468 
469 		/* Drop RTS and DTR */
470 		clmpcc_modem_control(ch, TIOCM_RTS | TIOCM_DTR, DMBIS);
471 	}
472 
473 	clmpcc_select_channel(ch->ch_sc, oldch);
474 }
475 
476 int
477 clmpccopen(dev_t dev, int flag, int mode, struct lwp *l)
478 {
479 	struct clmpcc_softc *sc;
480 	struct clmpcc_chan *ch;
481 	struct tty *tp;
482 	int oldch;
483 	int error;
484 
485 	sc = device_lookup_private(&clmpcc_cd, CLMPCCUNIT(dev));
486 	if (sc == NULL)
487 		return (ENXIO);
488 
489 	ch = &sc->sc_chans[CLMPCCCHAN(dev)];
490 
491 	tp = ch->ch_tty;
492 
493 	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
494 		return EBUSY;
495 
496 	/*
497 	 * Do the following iff this is a first open.
498 	 */
499 	if ( ISCLR(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0 ) {
500 
501 		ttychars(tp);
502 
503 		tp->t_dev = dev;
504 		tp->t_iflag = TTYDEF_IFLAG;
505 		tp->t_oflag = TTYDEF_OFLAG;
506 		tp->t_lflag = TTYDEF_LFLAG;
507 		tp->t_cflag = TTYDEF_CFLAG;
508 		tp->t_ospeed = tp->t_ispeed = TTYDEF_SPEED;
509 
510 		if ( ISSET(ch->ch_openflags, TIOCFLAG_CLOCAL) )
511 			SET(tp->t_cflag, CLOCAL);
512 		if ( ISSET(ch->ch_openflags, TIOCFLAG_CRTSCTS) )
513 			SET(tp->t_cflag, CRTSCTS);
514 		if ( ISSET(ch->ch_openflags, TIOCFLAG_MDMBUF) )
515 			SET(tp->t_cflag, MDMBUF);
516 
517 		/*
518 		 * Override some settings if the channel is being
519 		 * used as the console.
520 		 */
521 		if ( ISSET(ch->ch_flags, CLMPCC_FLG_IS_CONSOLE) ) {
522 			tp->t_ospeed = tp->t_ispeed = cons_rate;
523 			SET(tp->t_cflag, CLOCAL);
524 			CLR(tp->t_cflag, CRTSCTS);
525 			CLR(tp->t_cflag, HUPCL);
526 		}
527 
528 		ch->ch_control = 0;
529 
530 		clmpcc_param(tp, &tp->t_termios);
531 		ttsetwater(tp);
532 
533 		/* Clear the input ring */
534 		ch->ch_ibuf_rd = ch->ch_ibuf_wr = ch->ch_ibuf;
535 
536 		/* Select the channel */
537 		oldch = clmpcc_select_channel(sc, ch->ch_car);
538 
539 		/* Reset it */
540 		clmpcc_channel_cmd(sc, ch->ch_car, CLMPCC_CCR_T0_CLEAR |
541 						   CLMPCC_CCR_T0_RX_EN |
542 						   CLMPCC_CCR_T0_TX_EN);
543 
544 		/* Enable receiver and modem change interrupts. */
545 		clmpcc_wrreg(sc, CLMPCC_REG_IER, CLMPCC_IER_MODEM |
546 						 CLMPCC_IER_RET |
547 						 CLMPCC_IER_RX_FIFO);
548 
549 		/* Raise RTS and DTR */
550 		clmpcc_modem_control(ch, TIOCM_RTS | TIOCM_DTR, DMBIS);
551 
552 		clmpcc_select_channel(sc, oldch);
553 	}
554 
555 	error = ttyopen(tp, CLMPCCDIALOUT(dev), ISSET(flag, O_NONBLOCK));
556 	if (error)
557 		goto bad;
558 
559 	error = (*tp->t_linesw->l_open)(dev, tp);
560 	if (error)
561 		goto bad;
562 
563 	return 0;
564 
565 bad:
566 	if ( ISCLR(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0 ) {
567 		/*
568 		 * We failed to open the device, and nobody else had it opened.
569 		 * Clean up the state as appropriate.
570 		 */
571 		clmpcc_shutdown(ch);
572 	}
573 
574 	return error;
575 }
576 
577 int
578 clmpccclose(dev_t dev, int flag, int mode, struct lwp *l)
579 {
580 	struct clmpcc_softc	*sc =
581 		device_lookup_private(&clmpcc_cd, CLMPCCUNIT(dev));
582 	struct clmpcc_chan	*ch = &sc->sc_chans[CLMPCCCHAN(dev)];
583 	struct tty		*tp = ch->ch_tty;
584 	int s;
585 
586 	if ( ISCLR(tp->t_state, TS_ISOPEN) )
587 		return 0;
588 
589 	(*tp->t_linesw->l_close)(tp, flag);
590 
591 	s = spltty();
592 
593 	if ( ISCLR(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0 ) {
594 		/*
595 		 * Although we got a last close, the device may still be in
596 		 * use; e.g. if this was the dialout node, and there are still
597 		 * processes waiting for carrier on the non-dialout node.
598 		 */
599 		clmpcc_shutdown(ch);
600 	}
601 
602 	ttyclose(tp);
603 
604 	splx(s);
605 
606 	return 0;
607 }
608 
609 int
610 clmpccread(dev_t dev, struct uio *uio, int flag)
611 {
612 	struct clmpcc_softc *sc = device_lookup_private(&clmpcc_cd, CLMPCCUNIT(dev));
613 	struct tty *tp = sc->sc_chans[CLMPCCCHAN(dev)].ch_tty;
614 
615 	return ((*tp->t_linesw->l_read)(tp, uio, flag));
616 }
617 
618 int
619 clmpccwrite(dev_t dev, struct uio *uio, int flag)
620 {
621 	struct clmpcc_softc *sc = device_lookup_private(&clmpcc_cd, CLMPCCUNIT(dev));
622 	struct tty *tp = sc->sc_chans[CLMPCCCHAN(dev)].ch_tty;
623 
624 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
625 }
626 
627 int
628 clmpccpoll(dev_t dev, int events, struct lwp *l)
629 {
630 	struct clmpcc_softc *sc = device_lookup_private(&clmpcc_cd, CLMPCCUNIT(dev));
631 	struct tty *tp = sc->sc_chans[CLMPCCCHAN(dev)].ch_tty;
632 
633 	return ((*tp->t_linesw->l_poll)(tp, events, l));
634 }
635 
636 struct tty *
637 clmpcctty(dev_t dev)
638 {
639 	struct clmpcc_softc *sc = device_lookup_private(&clmpcc_cd, CLMPCCUNIT(dev));
640 
641 	return (sc->sc_chans[CLMPCCCHAN(dev)].ch_tty);
642 }
643 
644 int
645 clmpccioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
646 {
647 	struct clmpcc_softc *sc = device_lookup_private(&clmpcc_cd, CLMPCCUNIT(dev));
648 	struct clmpcc_chan *ch = &sc->sc_chans[CLMPCCCHAN(dev)];
649 	struct tty *tp = ch->ch_tty;
650 	int error;
651 
652 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
653 	if (error != EPASSTHROUGH)
654 		return error;
655 
656 	error = ttioctl(tp, cmd, data, flag, l);
657 	if (error != EPASSTHROUGH)
658 		return error;
659 
660 	error = 0;
661 
662 	switch (cmd) {
663 	case TIOCSBRK:
664 		SET(ch->ch_flags, CLMPCC_FLG_START_BREAK);
665 		clmpcc_enable_transmitter(ch);
666 		break;
667 
668 	case TIOCCBRK:
669 		SET(ch->ch_flags, CLMPCC_FLG_END_BREAK);
670 		clmpcc_enable_transmitter(ch);
671 		break;
672 
673 	case TIOCSDTR:
674 		clmpcc_modem_control(ch, TIOCM_DTR, DMBIS);
675 		break;
676 
677 	case TIOCCDTR:
678 		clmpcc_modem_control(ch, TIOCM_DTR, DMBIC);
679 		break;
680 
681 	case TIOCMSET:
682 		clmpcc_modem_control(ch, *((int *)data), DMSET);
683 		break;
684 
685 	case TIOCMBIS:
686 		clmpcc_modem_control(ch, *((int *)data), DMBIS);
687 		break;
688 
689 	case TIOCMBIC:
690 		clmpcc_modem_control(ch, *((int *)data), DMBIC);
691 		break;
692 
693 	case TIOCMGET:
694 		*((int *)data) = clmpcc_modem_control(ch, 0, DMGET);
695 		break;
696 
697 	case TIOCGFLAGS:
698 		*((int *)data) = ch->ch_openflags;
699 		break;
700 
701 	case TIOCSFLAGS:
702 		error = kauth_authorize_device_tty(l->l_cred,
703 		    KAUTH_DEVICE_TTY_PRIVSET, tp);
704 		if ( error )
705 			break;
706 		ch->ch_openflags = *((int *)data) &
707 			(TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
708 			 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
709 		if ( ISSET(ch->ch_flags, CLMPCC_FLG_IS_CONSOLE) )
710 			SET(ch->ch_openflags, TIOCFLAG_SOFTCAR);
711 		break;
712 
713 	default:
714 		error = EPASSTHROUGH;
715 		break;
716 	}
717 
718 	return error;
719 }
720 
721 int
722 clmpcc_modem_control(struct clmpcc_chan *ch, int bits, int howto)
723 {
724 	struct clmpcc_softc *sc = ch->ch_sc;
725 	struct tty *tp = ch->ch_tty;
726 	int oldch;
727 	int msvr;
728 	int rbits = 0;
729 
730 	oldch = clmpcc_select_channel(sc, ch->ch_car);
731 
732 	switch ( howto ) {
733 	case DMGET:
734 		msvr = clmpcc_rd_msvr(sc);
735 
736 		if ( sc->sc_swaprtsdtr ) {
737 			rbits |= (msvr & CLMPCC_MSVR_RTS) ? TIOCM_DTR : 0;
738 			rbits |= (msvr & CLMPCC_MSVR_DTR) ? TIOCM_RTS : 0;
739 		} else {
740 			rbits |= (msvr & CLMPCC_MSVR_RTS) ? TIOCM_RTS : 0;
741 			rbits |= (msvr & CLMPCC_MSVR_DTR) ? TIOCM_DTR : 0;
742 		}
743 
744 		rbits |= (msvr & CLMPCC_MSVR_CTS) ? TIOCM_CTS : 0;
745 		rbits |= (msvr & CLMPCC_MSVR_CD)  ? TIOCM_CD  : 0;
746 		rbits |= (msvr & CLMPCC_MSVR_DSR) ? TIOCM_DSR : 0;
747 		break;
748 
749 	case DMSET:
750 		if ( sc->sc_swaprtsdtr ) {
751 		    if ( ISCLR(tp->t_cflag, CRTSCTS) )
752 			clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_DTR,
753 					bits & TIOCM_RTS ? CLMPCC_MSVR_DTR : 0);
754 		    clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_RTS,
755 				bits & TIOCM_DTR ? CLMPCC_MSVR_RTS : 0);
756 		} else {
757 		    if ( ISCLR(tp->t_cflag, CRTSCTS) )
758 			clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_RTS,
759 					bits & TIOCM_RTS ? CLMPCC_MSVR_RTS : 0);
760 		    clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_DTR,
761 				bits & TIOCM_DTR ? CLMPCC_MSVR_DTR : 0);
762 		}
763 		break;
764 
765 	case DMBIS:
766 		if ( sc->sc_swaprtsdtr ) {
767 		    if ( ISCLR(tp->t_cflag, CRTSCTS) && ISSET(bits, TIOCM_RTS) )
768 			clmpcc_wr_msvr(sc,CLMPCC_REG_MSVR_DTR, CLMPCC_MSVR_DTR);
769 		    if ( ISSET(bits, TIOCM_DTR) )
770 			clmpcc_wr_msvr(sc,CLMPCC_REG_MSVR_RTS, CLMPCC_MSVR_RTS);
771 		} else {
772 		    if ( ISCLR(tp->t_cflag, CRTSCTS) && ISSET(bits, TIOCM_RTS) )
773 			clmpcc_wr_msvr(sc,CLMPCC_REG_MSVR_RTS, CLMPCC_MSVR_RTS);
774 		    if ( ISSET(bits, TIOCM_DTR) )
775 			clmpcc_wr_msvr(sc,CLMPCC_REG_MSVR_DTR, CLMPCC_MSVR_DTR);
776 		}
777 		break;
778 
779 	case DMBIC:
780 		if ( sc->sc_swaprtsdtr ) {
781 		    if ( ISCLR(tp->t_cflag, CRTSCTS) && ISCLR(bits, TIOCM_RTS) )
782 			clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_DTR, 0);
783 		    if ( ISCLR(bits, TIOCM_DTR) )
784 			clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_RTS, 0);
785 		} else {
786 		    if ( ISCLR(tp->t_cflag, CRTSCTS) && ISCLR(bits, TIOCM_RTS) )
787 			clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_RTS, 0);
788 		    if ( ISCLR(bits, TIOCM_DTR) )
789 			clmpcc_wr_msvr(sc, CLMPCC_REG_MSVR_DTR, 0);
790 		}
791 		break;
792 	}
793 
794 	clmpcc_select_channel(sc, oldch);
795 
796 	return rbits;
797 }
798 
799 static int
800 clmpcc_param(struct tty *tp, struct termios *t)
801 {
802 	struct clmpcc_softc *sc =
803 	    device_lookup_private(&clmpcc_cd, CLMPCCUNIT(tp->t_dev));
804 	struct clmpcc_chan *ch = &sc->sc_chans[CLMPCCCHAN(tp->t_dev)];
805 	u_char cor;
806 	u_char oldch;
807 	int oclk = 0, obpr = 0;
808 	int iclk = 0, ibpr = 0;
809 	int s;
810 
811 	/* Check requested parameters. */
812 	if ( t->c_ospeed && clmpcc_speed(sc, t->c_ospeed, &oclk, &obpr) < 0 )
813 		return EINVAL;
814 
815 	if ( t->c_ispeed && clmpcc_speed(sc, t->c_ispeed, &iclk, &ibpr) < 0 )
816 		return EINVAL;
817 
818 	/*
819 	 * For the console, always force CLOCAL and !HUPCL, so that the port
820 	 * is always active.
821 	 */
822 	if ( ISSET(ch->ch_openflags, TIOCFLAG_SOFTCAR) ||
823 	     ISSET(ch->ch_flags, CLMPCC_FLG_IS_CONSOLE) ) {
824 		SET(t->c_cflag, CLOCAL);
825 		CLR(t->c_cflag, HUPCL);
826 	}
827 
828 	CLR(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS);
829 
830 	/* If ospeed it zero, hangup the line */
831 	clmpcc_modem_control(ch, TIOCM_DTR, t->c_ospeed == 0 ? DMBIC : DMBIS);
832 
833 	if ( t->c_ospeed ) {
834 		ch->ch_tcor = CLMPCC_TCOR_CLK(oclk);
835 		ch->ch_tbpr = obpr;
836 	} else {
837 		ch->ch_tcor = 0;
838 		ch->ch_tbpr = 0;
839 	}
840 
841 	if ( t->c_ispeed ) {
842 		ch->ch_rcor = CLMPCC_RCOR_CLK(iclk);
843 		ch->ch_rbpr = ibpr;
844 	} else {
845 		ch->ch_rcor = 0;
846 		ch->ch_rbpr = 0;
847 	}
848 
849 	/* Work out value to use for COR1 */
850 	cor = 0;
851 	if ( ISSET(t->c_cflag, PARENB) ) {
852 		cor |= CLMPCC_COR1_NORM_PARITY;
853 		if ( ISSET(t->c_cflag, PARODD) )
854 			cor |= CLMPCC_COR1_ODD_PARITY;
855 	}
856 
857 	if ( ISCLR(t->c_cflag, INPCK) )
858 		cor |= CLMPCC_COR1_IGNORE_PAR;
859 
860 	switch ( t->c_cflag & CSIZE ) {
861 	  case CS5:
862 		cor |= CLMPCC_COR1_CHAR_5BITS;
863 		break;
864 
865 	  case CS6:
866 		cor |= CLMPCC_COR1_CHAR_6BITS;
867 		break;
868 
869 	  case CS7:
870 		cor |= CLMPCC_COR1_CHAR_7BITS;
871 		break;
872 
873 	  case CS8:
874 		cor |= CLMPCC_COR1_CHAR_8BITS;
875 		break;
876 	}
877 
878 	ch->ch_cor1 = cor;
879 
880 	/*
881 	 * The only interesting bit in COR2 is 'CTS Automatic Enable'
882 	 * when hardware flow control is in effect.
883 	 */
884 	ch->ch_cor2 = ISSET(t->c_cflag, CRTSCTS) ? CLMPCC_COR2_CtsAE : 0;
885 
886 	/* COR3 needs to be set to the number of stop bits... */
887 	ch->ch_cor3 = ISSET(t->c_cflag, CSTOPB) ? CLMPCC_COR3_STOP_2 :
888 						  CLMPCC_COR3_STOP_1;
889 
890 	/*
891 	 * COR4 contains the FIFO threshold setting.
892 	 * We adjust the threshold depending on the input speed...
893 	 */
894 	if ( t->c_ispeed <= 1200 )
895 		ch->ch_cor4 = CLMPCC_COR4_FIFO_LOW;
896 	else if ( t->c_ispeed <= 19200 )
897 		ch->ch_cor4 = CLMPCC_COR4_FIFO_MED;
898 	else
899 		ch->ch_cor4 = CLMPCC_COR4_FIFO_HIGH;
900 
901 	/*
902 	 * If chip is used with CTS and DTR swapped, we can enable
903 	 * automatic hardware flow control.
904 	 */
905 	if ( sc->sc_swaprtsdtr && ISSET(t->c_cflag, CRTSCTS) )
906 		ch->ch_cor5 = CLMPCC_COR5_FLOW_NORM;
907 	else
908 		ch->ch_cor5 = 0;
909 
910 	s = splserial();
911 	oldch = clmpcc_select_channel(sc, ch->ch_car);
912 
913 	/*
914 	 * COR2 needs to be set immediately otherwise we might never get
915 	 * a Tx EMPTY interrupt to change the other parameters.
916 	 */
917 	if ( clmpcc_rdreg(sc, CLMPCC_REG_COR2) != ch->ch_cor2 )
918 		clmpcc_wrreg(sc, CLMPCC_REG_COR2, ch->ch_cor2);
919 
920 	if ( ISCLR(ch->ch_tty->t_state, TS_BUSY) )
921 		clmpcc_set_params(ch);
922 	else
923 		SET(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS);
924 
925 	clmpcc_select_channel(sc, oldch);
926 
927 	splx(s);
928 
929 	return 0;
930 }
931 
932 static void
933 clmpcc_set_params(struct clmpcc_chan *ch)
934 {
935 	struct clmpcc_softc *sc = ch->ch_sc;
936 	u_char r1;
937 	u_char r2;
938 
939 	if ( ch->ch_tcor || ch->ch_tbpr ) {
940 		r1 = clmpcc_rdreg(sc, CLMPCC_REG_TCOR);
941 		r2 = clmpcc_rdreg(sc, CLMPCC_REG_TBPR);
942 		/* Only write Tx rate if it really has changed */
943 		if ( ch->ch_tcor != r1 || ch->ch_tbpr != r2 ) {
944 			clmpcc_wrreg(sc, CLMPCC_REG_TCOR, ch->ch_tcor);
945 			clmpcc_wrreg(sc, CLMPCC_REG_TBPR, ch->ch_tbpr);
946 		}
947 	}
948 
949 	if ( ch->ch_rcor || ch->ch_rbpr ) {
950 		r1 = clmpcc_rdreg(sc, CLMPCC_REG_RCOR);
951 		r2 = clmpcc_rdreg(sc, CLMPCC_REG_RBPR);
952 		/* Only write Rx rate if it really has changed */
953 		if ( ch->ch_rcor != r1 || ch->ch_rbpr != r2 ) {
954 			clmpcc_wrreg(sc, CLMPCC_REG_RCOR, ch->ch_rcor);
955 			clmpcc_wrreg(sc, CLMPCC_REG_RBPR, ch->ch_rbpr);
956 		}
957 	}
958 
959 	if ( clmpcc_rdreg(sc, CLMPCC_REG_COR1) != ch->ch_cor1 ) {
960 		clmpcc_wrreg(sc, CLMPCC_REG_COR1, ch->ch_cor1);
961 		/* Any change to COR1 requires an INIT command */
962 		SET(ch->ch_flags, CLMPCC_FLG_NEED_INIT);
963 	}
964 
965 	if ( clmpcc_rdreg(sc, CLMPCC_REG_COR3) != ch->ch_cor3 )
966 		clmpcc_wrreg(sc, CLMPCC_REG_COR3, ch->ch_cor3);
967 
968 	r1 = clmpcc_rdreg(sc, CLMPCC_REG_COR4);
969 	if ( ch->ch_cor4 != (r1 & CLMPCC_COR4_FIFO_MASK) ) {
970 		/*
971 		 * Note: If the FIFO has changed, we always set it to
972 		 * zero here and disable the Receive Timeout interrupt.
973 		 * It's up to the Rx Interrupt handler to pick the
974 		 * appropriate moment to write the new FIFO length.
975 		 */
976 		clmpcc_wrreg(sc, CLMPCC_REG_COR4, r1 & ~CLMPCC_COR4_FIFO_MASK);
977 		r1 = clmpcc_rdreg(sc, CLMPCC_REG_IER);
978 		clmpcc_wrreg(sc, CLMPCC_REG_IER, r1 & ~CLMPCC_IER_RET);
979 		SET(ch->ch_flags, CLMPCC_FLG_FIFO_CLEAR);
980 	}
981 
982 	r1 = clmpcc_rdreg(sc, CLMPCC_REG_COR5);
983 	if ( ch->ch_cor5 != (r1 & CLMPCC_COR5_FLOW_MASK) ) {
984 		r1 &= ~CLMPCC_COR5_FLOW_MASK;
985 		clmpcc_wrreg(sc, CLMPCC_REG_COR5, r1 | ch->ch_cor5);
986 	}
987 }
988 
989 static void
990 clmpcc_start(struct tty *tp)
991 {
992 	struct clmpcc_softc *sc =
993 	    device_lookup_private(&clmpcc_cd, CLMPCCUNIT(tp->t_dev));
994 	struct clmpcc_chan *ch = &sc->sc_chans[CLMPCCCHAN(tp->t_dev)];
995 	u_int oldch;
996 	int s;
997 
998 	s = spltty();
999 
1000 	if ( ISCLR(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY) ) {
1001 		ttypull(tp);
1002 		if ( ISSET(ch->ch_flags, CLMPCC_FLG_START_BREAK |
1003 					 CLMPCC_FLG_END_BREAK) ||
1004 		     tp->t_outq.c_cc > 0 ) {
1005 
1006 			if ( ISCLR(ch->ch_flags, CLMPCC_FLG_START_BREAK |
1007 						 CLMPCC_FLG_END_BREAK) ) {
1008 				ch->ch_obuf_addr = tp->t_outq.c_cf;
1009 				ch->ch_obuf_size = ndqb(&tp->t_outq, 0);
1010 			}
1011 
1012 			/* Enable TX empty interrupts */
1013 			oldch = clmpcc_select_channel(ch->ch_sc, ch->ch_car);
1014 			clmpcc_wrreg(ch->ch_sc, CLMPCC_REG_IER,
1015 				clmpcc_rdreg(ch->ch_sc, CLMPCC_REG_IER) |
1016 					     CLMPCC_IER_TX_EMPTY);
1017 			clmpcc_select_channel(ch->ch_sc, oldch);
1018 			SET(tp->t_state, TS_BUSY);
1019 		}
1020 	}
1021 
1022 	splx(s);
1023 }
1024 
1025 /*
1026  * Stop output on a line.
1027  */
1028 void
1029 clmpccstop(struct tty *tp, int flag)
1030 {
1031 	struct clmpcc_softc *sc =
1032 	    device_lookup_private(&clmpcc_cd, CLMPCCUNIT(tp->t_dev));
1033 	struct clmpcc_chan *ch = &sc->sc_chans[CLMPCCCHAN(tp->t_dev)];
1034 	int s;
1035 
1036 	s = splserial();
1037 
1038 	if ( ISSET(tp->t_state, TS_BUSY) ) {
1039 		if ( ISCLR(tp->t_state, TS_TTSTOP) )
1040 			SET(tp->t_state, TS_FLUSH);
1041 		ch->ch_obuf_size = 0;
1042 	}
1043 	splx(s);
1044 }
1045 
1046 /*
1047  * RX interrupt routine
1048  */
1049 int
1050 clmpcc_rxintr(void *arg)
1051 {
1052 	struct clmpcc_softc *sc = (struct clmpcc_softc *)arg;
1053 	struct clmpcc_chan *ch;
1054 	u_int8_t *put, *end, rxd;
1055 	u_char errstat;
1056 	u_char fc, tc;
1057 	u_char risr;
1058 	u_char rir;
1059 #ifdef DDB
1060 	int saw_break = 0;
1061 #endif
1062 
1063 	/* Receive interrupt active? */
1064 	rir = clmpcc_rdreg(sc, CLMPCC_REG_RIR);
1065 
1066 	/*
1067 	 * If we're using auto-vectored interrupts, we have to
1068 	 * verify if the chip is generating the interrupt.
1069 	 */
1070 	if ( sc->sc_vector_base == 0 && (rir & CLMPCC_RIR_RACT) == 0 )
1071 		return 0;
1072 
1073 	/* Get pointer to interrupting channel's data structure */
1074 	ch = &sc->sc_chans[rir & CLMPCC_RIR_RCN_MASK];
1075 
1076 	/* Get the interrupt status register */
1077 	risr = clmpcc_rdreg(sc, CLMPCC_REG_RISRl);
1078 	if ( risr & CLMPCC_RISR_TIMEOUT ) {
1079 		u_char reg;
1080 		/*
1081 		 * Set the FIFO threshold to zero, and disable
1082 		 * further receive timeout interrupts.
1083 		 */
1084 		reg = clmpcc_rdreg(sc, CLMPCC_REG_COR4);
1085 		clmpcc_wrreg(sc, CLMPCC_REG_COR4, reg & ~CLMPCC_COR4_FIFO_MASK);
1086 		reg = clmpcc_rdreg(sc, CLMPCC_REG_IER);
1087 		clmpcc_wrreg(sc, CLMPCC_REG_IER, reg & ~CLMPCC_IER_RET);
1088 		clmpcc_wrreg(sc, CLMPCC_REG_REOIR, CLMPCC_REOIR_NO_TRANS);
1089 		SET(ch->ch_flags, CLMPCC_FLG_FIFO_CLEAR);
1090 		return 1;
1091 	}
1092 
1093 	/* How many bytes are waiting in the FIFO?  */
1094 	fc = tc = clmpcc_rdreg(sc, CLMPCC_REG_RFOC) & CLMPCC_RFOC_MASK;
1095 
1096 #ifdef DDB
1097 	/*
1098 	 * Allow BREAK on the console to drop to the debugger.
1099 	 */
1100 	if ( ISSET(ch->ch_flags, CLMPCC_FLG_IS_CONSOLE) &&
1101 	     risr & CLMPCC_RISR_BREAK ) {
1102 		saw_break = 1;
1103 	}
1104 #endif
1105 
1106 	if ( ISCLR(ch->ch_tty->t_state, TS_ISOPEN) && fc ) {
1107 		/* Just get rid of the data */
1108 		while ( fc-- )
1109 			(void) clmpcc_rd_rxdata(sc);
1110 		goto rx_done;
1111 	}
1112 
1113 	put = ch->ch_ibuf_wr;
1114 	end = ch->ch_ibuf_end;
1115 
1116 	/*
1117 	 * Note: The chip is completely hosed WRT these error
1118 	 *       conditions; there seems to be no way to associate
1119 	 *       the error with the correct character in the FIFO.
1120 	 *       We compromise by tagging the first character we read
1121 	 *       with the error. Not perfect, but there's no other way.
1122 	 */
1123 	errstat = 0;
1124 	if ( risr & CLMPCC_RISR_PARITY )
1125 		errstat |= TTY_PE;
1126 	if ( risr & (CLMPCC_RISR_FRAMING | CLMPCC_RISR_BREAK) )
1127 		errstat |= TTY_FE;
1128 
1129 	/*
1130 	 * As long as there are characters in the FIFO, and we
1131 	 * have space for them...
1132 	 */
1133 	while ( fc > 0 ) {
1134 
1135 		*put++ = rxd = clmpcc_rd_rxdata(sc);
1136 		*put++ = errstat;
1137 
1138 		if ( put >= end )
1139 			put = ch->ch_ibuf;
1140 
1141 		if ( put == ch->ch_ibuf_rd ) {
1142 			put -= 2;
1143 			if ( put < ch->ch_ibuf )
1144 				put = end - 2;
1145 		}
1146 
1147 		errstat = 0;
1148 		fc--;
1149 	}
1150 
1151 	ch->ch_ibuf_wr = put;
1152 
1153 #if 0
1154 	if ( sc->sc_swaprtsdtr == 0 &&
1155 	     ISSET(cy->cy_tty->t_cflag, CRTSCTS) && cc < ch->ch_r_hiwat) {
1156 		/*
1157 		 * If RTS/DTR are not physically swapped, we have to
1158 		 * do hardware flow control manually
1159 		 */
1160 		clmpcc_wr_msvr(sc, CLMPCC_MSVR_RTS, 0);
1161 	}
1162 #endif
1163 
1164 rx_done:
1165 	if ( fc != tc ) {
1166 		if ( ISSET(ch->ch_flags, CLMPCC_FLG_FIFO_CLEAR) ) {
1167 			u_char reg;
1168 			/*
1169 			 * Set the FIFO threshold to the preset value,
1170 			 * and enable receive timeout interrupts.
1171 			 */
1172 			reg = clmpcc_rdreg(sc, CLMPCC_REG_COR4);
1173 			reg = (reg & ~CLMPCC_COR4_FIFO_MASK) | ch->ch_cor4;
1174 			clmpcc_wrreg(sc, CLMPCC_REG_COR4, reg);
1175 			reg = clmpcc_rdreg(sc, CLMPCC_REG_IER);
1176 			clmpcc_wrreg(sc, CLMPCC_REG_IER, reg | CLMPCC_IER_RET);
1177 			CLR(ch->ch_flags, CLMPCC_FLG_FIFO_CLEAR);
1178 		}
1179 
1180 		clmpcc_wrreg(sc, CLMPCC_REG_REOIR, 0);
1181 		softint_schedule(sc->sc_softintr_cookie);
1182 	} else
1183 		clmpcc_wrreg(sc, CLMPCC_REG_REOIR, CLMPCC_REOIR_NO_TRANS);
1184 
1185 #ifdef DDB
1186 	/*
1187 	 * Only =after= we write REOIR is it safe to drop to the debugger.
1188 	 */
1189 	if ( saw_break )
1190 		Debugger();
1191 #endif
1192 
1193 	return 1;
1194 }
1195 
1196 /*
1197  * Tx interrupt routine
1198  */
1199 int
1200 clmpcc_txintr(void *arg)
1201 {
1202 	struct clmpcc_softc *sc = (struct clmpcc_softc *)arg;
1203 	struct clmpcc_chan *ch;
1204 	u_char ftc, oftc;
1205 	u_char tir, teoir;
1206 	int etcmode = 0;
1207 
1208 	/* Tx interrupt active? */
1209 	tir = clmpcc_rdreg(sc, CLMPCC_REG_TIR);
1210 
1211 	/*
1212 	 * If we're using auto-vectored interrupts, we have to
1213 	 * verify if the chip is generating the interrupt.
1214 	 */
1215 	if ( sc->sc_vector_base == 0 && (tir & CLMPCC_TIR_TACT) == 0 )
1216 		return 0;
1217 
1218 	/* Get pointer to interrupting channel's data structure */
1219 	ch = &sc->sc_chans[tir & CLMPCC_TIR_TCN_MASK];
1220 
1221 	/* Dummy read of the interrupt status register */
1222 	(void) clmpcc_rdreg(sc, CLMPCC_REG_TISR);
1223 
1224 	/* Make sure embedded transmit commands are disabled */
1225 	clmpcc_wrreg(sc, CLMPCC_REG_COR2, ch->ch_cor2);
1226 
1227 	ftc = oftc = clmpcc_rdreg(sc, CLMPCC_REG_TFTC);
1228 
1229 	/* Handle a delayed parameter change */
1230 	if ( ISSET(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS) ) {
1231 		CLR(ch->ch_flags, CLMPCC_FLG_UPDATE_PARMS);
1232 		clmpcc_set_params(ch);
1233 	}
1234 
1235 	if ( ch->ch_obuf_size > 0 ) {
1236 		u_int n = min(ch->ch_obuf_size, ftc);
1237 
1238 		clmpcc_wrtx_multi(sc, ch->ch_obuf_addr, n);
1239 
1240 		ftc -= n;
1241 		ch->ch_obuf_size -= n;
1242 		ch->ch_obuf_addr += n;
1243 
1244 	} else {
1245 		/*
1246 		 * Check if we should start/stop a break
1247 		 */
1248 		if ( ISSET(ch->ch_flags, CLMPCC_FLG_START_BREAK) ) {
1249 			CLR(ch->ch_flags, CLMPCC_FLG_START_BREAK);
1250 			/* Enable embedded transmit commands */
1251 			clmpcc_wrreg(sc, CLMPCC_REG_COR2,
1252 					ch->ch_cor2 | CLMPCC_COR2_ETC);
1253 			clmpcc_wr_txdata(sc, CLMPCC_ETC_MAGIC);
1254 			clmpcc_wr_txdata(sc, CLMPCC_ETC_SEND_BREAK);
1255 			ftc -= 2;
1256 			etcmode = 1;
1257 		}
1258 
1259 		if ( ISSET(ch->ch_flags, CLMPCC_FLG_END_BREAK) ) {
1260 			CLR(ch->ch_flags, CLMPCC_FLG_END_BREAK);
1261 			/* Enable embedded transmit commands */
1262 			clmpcc_wrreg(sc, CLMPCC_REG_COR2,
1263 					ch->ch_cor2 | CLMPCC_COR2_ETC);
1264 			clmpcc_wr_txdata(sc, CLMPCC_ETC_MAGIC);
1265 			clmpcc_wr_txdata(sc, CLMPCC_ETC_STOP_BREAK);
1266 			ftc -= 2;
1267 			etcmode = 1;
1268 		}
1269 	}
1270 
1271 	tir = clmpcc_rdreg(sc, CLMPCC_REG_IER);
1272 
1273 	if ( ftc != oftc ) {
1274 		/*
1275 		 * Enable/disable the Tx FIFO threshold interrupt
1276 		 * according to how much data is in the FIFO.
1277 		 * However, always disable the FIFO threshold if
1278 		 * we've left the channel in 'Embedded Transmit
1279 		 * Command' mode.
1280 		 */
1281 		if ( etcmode || ftc >= ch->ch_cor4 )
1282 			tir &= ~CLMPCC_IER_TX_FIFO;
1283 		else
1284 			tir |= CLMPCC_IER_TX_FIFO;
1285 		teoir = 0;
1286 	} else {
1287 		/*
1288 		 * No data was sent.
1289 		 * Disable transmit interrupt.
1290 		 */
1291 		tir &= ~(CLMPCC_IER_TX_EMPTY|CLMPCC_IER_TX_FIFO);
1292 		teoir = CLMPCC_TEOIR_NO_TRANS;
1293 
1294 		/*
1295 		 * Request Tx processing in the soft interrupt handler
1296 		 */
1297 		ch->ch_tx_done = 1;
1298 		softint_schedule(sc->sc_softintr_cookie);
1299 	}
1300 
1301 	clmpcc_wrreg(sc, CLMPCC_REG_IER, tir);
1302 	clmpcc_wrreg(sc, CLMPCC_REG_TEOIR, teoir);
1303 
1304 	return 1;
1305 }
1306 
1307 /*
1308  * Modem change interrupt routine
1309  */
1310 int
1311 clmpcc_mdintr(void *arg)
1312 {
1313 	struct clmpcc_softc *sc = (struct clmpcc_softc *)arg;
1314 	u_char mir;
1315 
1316 	/* Modem status interrupt active? */
1317 	mir = clmpcc_rdreg(sc, CLMPCC_REG_MIR);
1318 
1319 	/*
1320 	 * If we're using auto-vectored interrupts, we have to
1321 	 * verify if the chip is generating the interrupt.
1322 	 */
1323 	if ( sc->sc_vector_base == 0 && (mir & CLMPCC_MIR_MACT) == 0 )
1324 		return 0;
1325 
1326 	/* Dummy read of the interrupt status register */
1327 	(void) clmpcc_rdreg(sc, CLMPCC_REG_MISR);
1328 
1329 	/* Retrieve current status of modem lines. */
1330 	sc->sc_chans[mir & CLMPCC_MIR_MCN_MASK].ch_control |=
1331 		clmpcc_rd_msvr(sc) & CLMPCC_MSVR_CD;
1332 
1333 	clmpcc_wrreg(sc, CLMPCC_REG_MEOIR, 0);
1334 	softint_schedule(sc->sc_softintr_cookie);
1335 
1336 	return 1;
1337 }
1338 
1339 void
1340 clmpcc_softintr(void *arg)
1341 {
1342 	struct clmpcc_softc *sc = (struct clmpcc_softc *)arg;
1343 	struct clmpcc_chan *ch;
1344 	struct tty *tp;
1345 	int (*rint)(int, struct tty *);
1346 	u_char *get;
1347 	u_char reg;
1348 	u_int c;
1349 	int chan;
1350 
1351 	/* Handle Modem state changes too... */
1352 
1353 	for (chan = 0; chan < CLMPCC_NUM_CHANS; chan++) {
1354 		ch = &sc->sc_chans[chan];
1355 		tp = ch->ch_tty;
1356 
1357 		get = ch->ch_ibuf_rd;
1358 		rint = tp->t_linesw->l_rint;
1359 
1360 		/* Squirt buffered incoming data into the tty layer */
1361 		while ( get != ch->ch_ibuf_wr ) {
1362 			c = get[0];
1363 			c |= ((u_int)get[1]) << 8;
1364 			if ( (rint)(c, tp) == -1 ) {
1365 				ch->ch_ibuf_rd = ch->ch_ibuf_wr;
1366 				break;
1367 			}
1368 
1369 			get += 2;
1370 			if ( get == ch->ch_ibuf_end )
1371 				get = ch->ch_ibuf;
1372 
1373 			ch->ch_ibuf_rd = get;
1374 		}
1375 
1376 		/*
1377 		 * Is the transmitter idle and in need of attention?
1378 		 */
1379 		if ( ch->ch_tx_done ) {
1380 			ch->ch_tx_done = 0;
1381 
1382 			if ( ISSET(ch->ch_flags, CLMPCC_FLG_NEED_INIT) ) {
1383 				clmpcc_channel_cmd(sc, ch->ch_car,
1384 						       CLMPCC_CCR_T0_INIT  |
1385 						       CLMPCC_CCR_T0_RX_EN |
1386 					   	       CLMPCC_CCR_T0_TX_EN);
1387 				CLR(ch->ch_flags, CLMPCC_FLG_NEED_INIT);
1388 
1389 				/*
1390 				 * Allow time for the channel to initialise.
1391 				 * (Empirically derived duration; there must
1392 				 * be another way to determine the command
1393 				 * has completed without busy-waiting...)
1394 				 */
1395 				delay(800);
1396 
1397 				/*
1398 				 * Update the tty layer's idea of the carrier
1399 				 * bit, in case we changed CLOCAL or MDMBUF.
1400 				 * We don't hang up here; we only do that by
1401 				 * explicit request.
1402 				 */
1403 				reg = clmpcc_rd_msvr(sc) & CLMPCC_MSVR_CD;
1404 				(*tp->t_linesw->l_modem)(tp, reg != 0);
1405 			}
1406 
1407 			CLR(tp->t_state, TS_BUSY);
1408 			if ( ISSET(tp->t_state, TS_FLUSH) )
1409 				CLR(tp->t_state, TS_FLUSH);
1410 			else
1411 				ndflush(&tp->t_outq,
1412 				     (int)(ch->ch_obuf_addr - tp->t_outq.c_cf));
1413 
1414 			(*tp->t_linesw->l_start)(tp);
1415 		}
1416 	}
1417 }
1418 
1419 
1420 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1421 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1422 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
1423 /*
1424  * Following are all routines needed for a cd240x channel to act as console
1425  */
1426 int
1427 clmpcc_cnattach(struct clmpcc_softc *sc, int chan, int rate)
1428 {
1429 	cons_sc = sc;
1430 	cons_chan = chan;
1431 	cons_rate = rate;
1432 
1433 	return (clmpcc_init(sc));
1434 }
1435 
1436 /*
1437  * The following functions are polled getc and putc routines, for console use.
1438  */
1439 static int
1440 clmpcc_common_getc(struct clmpcc_softc *sc, int chan)
1441 {
1442 	u_char old_chan;
1443 	u_char old_ier;
1444 	u_char ch, rir, risr;
1445 	int s;
1446 
1447 	s = splhigh();
1448 
1449 	/* Save the currently active channel */
1450 	old_chan = clmpcc_select_channel(sc, chan);
1451 
1452 	/*
1453 	 * We have to put the channel into RX interrupt mode before
1454 	 * trying to read the Rx data register. So save the previous
1455 	 * interrupt mode.
1456 	 */
1457 	old_ier = clmpcc_rdreg(sc, CLMPCC_REG_IER);
1458 	clmpcc_wrreg(sc, CLMPCC_REG_IER, CLMPCC_IER_RX_FIFO);
1459 
1460 	/* Loop until we get a character */
1461 	for (;;) {
1462 		/*
1463 		 * The REN bit will be set in the Receive Interrupt Register
1464 		 * when the CD240x has a character to process. Remember,
1465 		 * the RACT bit won't be set until we generate an interrupt
1466 		 * acknowledge cycle via the MD front-end.
1467 		 */
1468 		rir = clmpcc_rdreg(sc, CLMPCC_REG_RIR);
1469 		if ( (rir & CLMPCC_RIR_REN) == 0 )
1470 			continue;
1471 
1472 		/* Acknowledge the request */
1473 		if ( sc->sc_iackhook )
1474 			(sc->sc_iackhook)(sc, CLMPCC_IACK_RX);
1475 
1476 		/*
1477 		 * Determine if the interrupt is for the required channel
1478 		 * and if valid data is available.
1479 		 */
1480 		rir = clmpcc_rdreg(sc, CLMPCC_REG_RIR);
1481 		risr = clmpcc_rdreg(sc, CLMPCC_REG_RISR);
1482 		if ( (rir & CLMPCC_RIR_RCN_MASK) != chan ||
1483 		     risr != 0 ) {
1484 			/* Rx error, or BREAK */
1485 			clmpcc_wrreg(sc, CLMPCC_REG_REOIR,
1486 					 CLMPCC_REOIR_NO_TRANS);
1487 		} else {
1488 			/* Dummy read of the FIFO count register */
1489 			(void) clmpcc_rdreg(sc, CLMPCC_REG_RFOC);
1490 
1491 			/* Fetch the received character */
1492 			ch = clmpcc_rd_rxdata(sc);
1493 
1494 			clmpcc_wrreg(sc, CLMPCC_REG_REOIR, 0);
1495 			break;
1496 		}
1497 	}
1498 
1499 	/* Restore the original IER and CAR register contents */
1500 	clmpcc_wrreg(sc, CLMPCC_REG_IER, old_ier);
1501 	clmpcc_select_channel(sc, old_chan);
1502 
1503 	splx(s);
1504 	return ch;
1505 }
1506 
1507 
1508 static void
1509 clmpcc_common_putc(struct clmpcc_softc *sc, int chan, int c)
1510 {
1511 	u_char old_chan;
1512 	int s = splhigh();
1513 
1514 	/* Save the currently active channel */
1515 	old_chan = clmpcc_select_channel(sc, chan);
1516 
1517 	/*
1518 	 * Since we can only access the Tx Data register from within
1519 	 * the interrupt handler, the easiest way to get console data
1520 	 * onto the wire is using one of the Special Transmit Character
1521 	 * registers.
1522 	 */
1523 	clmpcc_wrreg(sc, CLMPCC_REG_SCHR4, c);
1524 	clmpcc_wrreg(sc, CLMPCC_REG_STCR, CLMPCC_STCR_SSPC(4) |
1525 					  CLMPCC_STCR_SND_SPC);
1526 
1527 	/* Wait until the "Send Special Character" command is accepted */
1528 	while ( clmpcc_rdreg(sc, CLMPCC_REG_STCR) != 0 )
1529 		;
1530 
1531 	/* Restore the previous channel selected */
1532 	clmpcc_select_channel(sc, old_chan);
1533 
1534 	splx(s);
1535 }
1536 
1537 int
1538 clmpcccngetc(dev_t dev)
1539 {
1540 	return clmpcc_common_getc(cons_sc, cons_chan);
1541 }
1542 
1543 /*
1544  * Console kernel output character routine.
1545  */
1546 void
1547 clmpcccnputc(dev_t dev, int c)
1548 {
1549 	if ( c == '\n' )
1550 		clmpcc_common_putc(cons_sc, cons_chan, '\r');
1551 
1552 	clmpcc_common_putc(cons_sc, cons_chan, c);
1553 }
1554