xref: /netbsd/sys/arch/atari/dev/ser.c (revision c4a72b64)
1 /*	$NetBSD: ser.c,v 1.21 2002/10/23 09:10:53 jdolecek Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Leo Weppelman.
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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 /*-
39  * Copyright (c) 1993, 1994, 1995, 1996, 1997
40  *      Charles M. Hannum.  All rights reserved.
41  *
42  * Interrupt processing and hardware flow control partly based on code from
43  * Onno van der Linden and Gordon Ross.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  * 1. Redistributions of source code must retain the above copyright
49  *    notice, this list of conditions and the following disclaimer.
50  * 2. Redistributions in binary form must reproduce the above copyright
51  *    notice, this list of conditions and the following disclaimer in the
52  *    documentation and/or other materials provided with the distribution.
53  * 3. All advertising materials mentioning features or use of this software
54  *    must display the following acknowledgement:
55  *      This product includes software developed by Charles M. Hannum.
56  * 4. The name of the author may not be used to endorse or promote products
57  *    derived from this software without specific prior written permission.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69  */
70 
71 /*
72  * Copyright (c) 1991 The Regents of the University of California.
73  * All rights reserved.
74  *
75  * Redistribution and use in source and binary forms, with or without
76  * modification, are permitted provided that the following conditions
77  * are met:
78  * 1. Redistributions of source code must retain the above copyright
79  *    notice, this list of conditions and the following disclaimer.
80  * 2. Redistributions in binary form must reproduce the above copyright
81  *    notice, this list of conditions and the following disclaimer in the
82  *    documentation and/or other materials provided with the distribution.
83  * 3. All advertising materials mentioning features or use of this software
84  *    must display the following acknowledgement:
85  *      This product includes software developed by the University of
86  *      California, Berkeley and its contributors.
87  * 4. Neither the name of the University nor the names of its contributors
88  *    may be used to endorse or promote products derived from this software
89  *    without specific prior written permission.
90  *
91  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
92  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
94  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
95  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
96  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
97  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
98  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
99  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
100  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
101  * SUCH DAMAGE.
102  *
103  *      @(#)com.c       7.5 (Berkeley) 5/16/91
104  */
105 
106 #include "opt_ddb.h"
107 #include "opt_mbtype.h"
108 #include "opt_serconsole.h"
109 
110 #include <sys/param.h>
111 #include <sys/systm.h>
112 #include <sys/ioctl.h>
113 #include <sys/select.h>
114 #include <sys/tty.h>
115 #include <sys/proc.h>
116 #include <sys/user.h>
117 #include <sys/conf.h>
118 #include <sys/file.h>
119 #include <sys/uio.h>
120 #include <sys/kernel.h>
121 #include <sys/syslog.h>
122 #include <sys/types.h>
123 #include <sys/device.h>
124 
125 #include <m68k/asm_single.h>
126 
127 #include <machine/iomap.h>
128 #include <machine/mfp.h>
129 #include <atari/atari/intr.h>
130 #include <atari/dev/serreg.h>
131 
132 #if !defined(_MILANHW_)
133 #include <atari/dev/ym2149reg.h>
134 #else
135 	/* MILAN has no ym2149 */
136 #define ym2149_dtr(set) {					\
137 	if (set)						\
138 		single_inst_bset_b(MFP->mf_gpip, 0x08);		\
139 	else single_inst_bclr_b(MFP->mf_gpip, 0x08);		\
140 }
141 
142 #define ym2149_rts(set) {					\
143 	if (set)						\
144 		single_inst_bset_b(MFP->mf_gpip, 0x01);		\
145 	else single_inst_bclr_b(MFP->mf_gpip, 0x01);		\
146 }
147 #endif /* _MILANHW_ */
148 
149 /* #define SER_DEBUG */
150 
151 #define	SERUNIT(x)	(minor(x) & 0x7ffff)
152 #define	SERDIALOUT(x)	(minor(x) & 0x80000)
153 
154 /* XXX */
155 #define	CONSBAUD	9600
156 #define	CONSCFLAG	TTYDEF_CFLAG
157 /* end XXX */
158 
159 /* Macros to clear/set/test flags. */
160 #define SET(t, f)	(t) |= (f)
161 #define CLR(t, f)	(t) &= ~(f)
162 #define ISSET(t, f)	((t) & (f))
163 
164 #define	splserial()	spl6()
165 
166 /* Buffer size for character buffer */
167 #define RXBUFSIZE 2048		/* More than enough..			*/
168 #define RXBUFMASK (RXBUFSIZE-1)	/* Only iff previous is a power of 2	*/
169 #define RXHIWAT   (RXBUFSIZE >> 2)
170 
171 struct ser_softc {
172 	struct device	 sc_dev;
173 	struct tty	*sc_tty;
174 
175 	struct callout sc_diag_ch;
176 
177 	int		 sc_overflows;
178 	int		 sc_floods;
179 	int		 sc_errors;
180 
181 	u_char		 sc_hwflags;
182 	u_char		 sc_swflags;
183 
184 	int		 sc_ospeed;		/* delay + timer-d data	*/
185 	u_char		 sc_imra;
186 	u_char		 sc_imrb;
187 	u_char		 sc_ucr;		/* Uart control		*/
188 	u_char		 sc_msr;		/* Modem status		*/
189 	u_char		 sc_tsr;		/* Tranceiver status	*/
190 	u_char		 sc_rsr;		/* Receiver status	*/
191 	u_char		 sc_mcr;		/* (Pseudo) Modem ctrl. */
192 
193 	u_char		 sc_msr_delta;
194 	u_char		 sc_msr_mask;
195 	u_char		 sc_mcr_active;
196 	u_char		 sc_mcr_dtr, sc_mcr_rts, sc_msr_cts, sc_msr_dcd;
197 
198 	int		 sc_r_hiwat;
199  	volatile u_int	 sc_rbget;
200  	volatile u_int	 sc_rbput;
201 	volatile u_int	 sc_rbavail;
202  	u_char		 sc_rbuf[RXBUFSIZE];
203 	u_char		 sc_lbuf[RXBUFSIZE];
204 
205 	volatile u_char	 sc_rx_blocked;
206 	volatile u_char	 sc_rx_ready;
207 	volatile u_char	 sc_tx_busy;
208 	volatile u_char	 sc_tx_done;
209 	volatile u_char	 sc_tx_stopped;
210 	volatile u_char	 sc_st_check;
211 
212  	u_char		*sc_tba;
213  	int		 sc_tbc;
214 	int		 sc_heldtbc;
215 
216 	volatile u_char	 sc_heldchange;
217 };
218 
219 /*
220  * For sc_hwflags:
221  */
222 #define	SER_HW_CONSOLE	0x01
223 
224 void	ser_break __P((struct ser_softc *, int));
225 void	ser_hwiflow __P((struct ser_softc *, int));
226 void	ser_iflush __P((struct ser_softc *));
227 void	ser_loadchannelregs __P((struct ser_softc *));
228 void	ser_modem __P((struct ser_softc *, int));
229 void	serdiag __P((void *));
230 int	serhwiflow __P((struct tty *, int));
231 void	serinit __P((int));
232 void	serinitcons __P((int));
233 int	baud;
234 int	sermintr __P((void *));
235 int	sertrintr __P((void *));
236 int	serparam __P((struct tty *, struct termios *));
237 void	serstart __P((struct tty *));
238 
239 struct consdev;
240 void	sercnprobe	__P((struct consdev *));
241 void	sercninit	__P((struct consdev *));
242 int	sercngetc	__P((dev_t));
243 void	sercnputc	__P((dev_t, int));
244 void	sercnpollc	__P((dev_t, int));
245 
246 static void sermsrint __P((struct ser_softc *, struct tty*));
247 static void serrxint __P((struct ser_softc *, struct tty*));
248 static void ser_shutdown __P((struct ser_softc *));
249 static int serspeed __P((long));
250 static void sersoft __P((void *));
251 static void sertxint __P((struct ser_softc *, struct tty*));
252 
253 static volatile int ser_softintr_scheduled = 0;
254 
255 /*
256  * Autoconfig stuff
257  */
258 static void serattach __P((struct device *, struct device *, void *));
259 static int  sermatch __P((struct device *, struct cfdata *, void *));
260 
261 CFATTACH_DECL(ser, sizeof(struct ser_softc),
262     sermatch, serattach, NULL, NULL);
263 
264 extern struct cfdriver ser_cd;
265 
266 dev_type_open(seropen);
267 dev_type_close(serclose);
268 dev_type_read(serread);
269 dev_type_write(serwrite);
270 dev_type_ioctl(serioctl);
271 dev_type_stop(serstop);
272 dev_type_tty(sertty);
273 dev_type_poll(serpoll);
274 
275 const struct cdevsw ser_cdevsw = {
276 	seropen, serclose, serread, serwrite, serioctl,
277 	serstop, sertty, serpoll, nommap, ttykqfilter, D_TTY
278 };
279 
280 /*ARGSUSED*/
281 static	int
282 sermatch(pdp, cfp, auxp)
283 struct	device	*pdp;
284 struct	cfdata	*cfp;
285 void		*auxp;
286 {
287 	static int	ser_matched = 0;
288 
289 	/* Match at most one ser unit */
290 	if (strcmp((char *)auxp, "ser") || ser_matched)
291 		return 0;
292 
293 	ser_matched = 1;
294 	return 1;
295 }
296 
297 /*ARGSUSED*/
298 static void
299 serattach(pdp, dp, auxp)
300 struct	device *pdp, *dp;
301 void	*auxp;
302 {
303 	struct ser_softc *sc = (void *)dp;
304 
305 	if (intr_establish(1, USER_VEC, 0, (hw_ifun_t)sermintr, sc) == NULL)
306 		printf("serattach: Can't establish interrupt (1)\n");
307 	if (intr_establish(2, USER_VEC, 0, (hw_ifun_t)sermintr, sc) == NULL)
308 		printf("serattach: Can't establish interrupt (2)\n");
309 	if (intr_establish(14, USER_VEC, 0, (hw_ifun_t)sermintr, sc) == NULL)
310 		printf("serattach: Can't establish interrupt (14)\n");
311 	if (intr_establish(9, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL)
312 		printf("serattach: Can't establish interrupt (9)\n");
313 	if (intr_establish(10, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL)
314 		printf("serattach: Can't establish interrupt (10)\n");
315 	if (intr_establish(11, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL)
316 		printf("serattach: Can't establish interrupt (11)\n");
317 	if (intr_establish(12, USER_VEC, 0, (hw_ifun_t)sertrintr, sc) == NULL)
318 		printf("serattach: Can't establish interrupt (12)\n");
319 
320 	ym2149_rts(1);
321 	ym2149_dtr(1);
322 
323 	/*
324 	 * Enable but mask interrupts...
325 	 * XXX: Look at edge-sensitivity for DCD/CTS interrupts.
326 	 */
327 	MFP->mf_ierb |= IB_SCTS|IB_SDCD;
328 	MFP->mf_iera |= IA_RRDY|IA_RERR|IA_TRDY|IA_TERR;
329 	MFP->mf_imrb &= ~(IB_SCTS|IB_SDCD);
330 	MFP->mf_imra &= ~(IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
331 
332 	callout_init(&sc->sc_diag_ch);
333 
334 #if SERCONSOLE > 0
335 	/*
336 	 * Activate serial console when DCD present...
337 	 */
338 	if (!(MFP->mf_gpip & MCR_DCD))
339 		SET(sc->sc_hwflags, SER_HW_CONSOLE);
340 #endif /* SERCONSOLE > 0 */
341 
342 	printf("\n");
343 	if (ISSET(sc->sc_hwflags, SER_HW_CONSOLE)) {
344 		serinit(CONSBAUD);
345 		printf("%s: console\n", sc->sc_dev.dv_xname);
346 	}
347 }
348 
349 #ifdef SER_DEBUG
350 void serstatus __P((struct ser_softc *, char *));
351 void
352 serstatus(sc, str)
353 	struct ser_softc *sc;
354 	char *str;
355 {
356 	struct tty *tp = sc->sc_tty;
357 
358 	printf("%s: %s %sclocal  %sdcd %sts_carr_on %sdtr %stx_stopped\n",
359 	    sc->sc_dev.dv_xname, str,
360 	    ISSET(tp->t_cflag, CLOCAL) ? "+" : "-",
361 	    ISSET(sc->sc_msr, MCR_DCD) ? "+" : "-",
362 	    ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-",
363 	    ISSET(sc->sc_mcr, MCR_DTR) ? "+" : "-",
364 	    sc->sc_tx_stopped ? "+" : "-");
365 
366 	printf("%s: %s %scrtscts %scts %sts_ttstop  %srts %srx_blocked\n",
367 	    sc->sc_dev.dv_xname, str,
368 	    ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-",
369 	    ISSET(sc->sc_msr, MCR_CTS) ? "+" : "-",
370 	    ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-",
371 	    ISSET(sc->sc_mcr, MCR_RTS) ? "+" : "-",
372 	    sc->sc_rx_blocked ? "+" : "-");
373 }
374 #endif /* SER_DEBUG */
375 
376 int
377 seropen(dev, flag, mode, p)
378 	dev_t dev;
379 	int flag, mode;
380 	struct proc *p;
381 {
382 	int unit = SERUNIT(dev);
383 	struct ser_softc *sc;
384 	struct tty *tp;
385 	int s, s2;
386 	int error = 0;
387 
388 	if (unit >= ser_cd.cd_ndevs)
389 		return (ENXIO);
390 	sc = ser_cd.cd_devs[unit];
391 	if (!sc)
392 		return (ENXIO);
393 
394 	if (!sc->sc_tty) {
395 		tp = sc->sc_tty = ttymalloc();
396 		tty_attach(tp);
397 	} else
398 		tp = sc->sc_tty;
399 
400 	if (ISSET(tp->t_state, TS_ISOPEN) &&
401 	    ISSET(tp->t_state, TS_XCLUDE) &&
402 	    p->p_ucred->cr_uid != 0)
403 		return (EBUSY);
404 
405 	s = spltty();
406 
407 	/*
408 	 * Do the following if this is a first open.
409 	 */
410 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
411 	    struct termios t;
412 
413 	    /* Turn on interrupts. */
414 	    sc->sc_imra = IA_RRDY|IA_RERR|IA_TRDY|IA_TERR;
415 	    sc->sc_imrb = IB_SCTS|IB_SDCD;
416 	    single_inst_bset_b(MFP->mf_imra, sc->sc_imra);
417 	    single_inst_bset_b(MFP->mf_imrb, sc->sc_imrb);
418 
419 	    /* Fetch the current modem control status, needed later. */
420 	    sc->sc_msr = ~MFP->mf_gpip & (IO_SDCD|IO_SCTS|IO_SRI);
421 
422 	    /* Add some entry points needed by the tty layer. */
423 	    tp->t_oproc = serstart;
424 	    tp->t_param = serparam;
425 	    tp->t_hwiflow = serhwiflow;
426 	    tp->t_dev = dev;
427 
428 	    /*
429 	     * Initialize the termios status to the defaults.  Add in the
430 	     * sticky bits from TIOCSFLAGS.
431 	     */
432 	    t.c_ispeed = 0;
433 	    if (ISSET(sc->sc_hwflags, SER_HW_CONSOLE)) {
434 		    t.c_ospeed = CONSBAUD;
435 		    t.c_cflag  = CONSCFLAG;
436 	    }
437 	    else {
438 		    t.c_ospeed = TTYDEF_SPEED;
439 		    t.c_cflag = TTYDEF_CFLAG;
440 	    }
441 	    if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
442 		    SET(t.c_cflag, CLOCAL);
443 	    if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
444 		    SET(t.c_cflag, CRTSCTS);
445 	    if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
446 		    SET(t.c_cflag, MDMBUF);
447 	    tp->t_iflag = TTYDEF_IFLAG;
448 	    tp->t_oflag = TTYDEF_OFLAG;
449 	    tp->t_lflag = TTYDEF_LFLAG;
450 	    ttychars(tp);
451 	    (void) serparam(tp, &t);
452 	    ttsetwater(tp);
453 
454 	    s2 = splserial();
455 
456 	    /*
457 	     * Turn on DTR.  We must always do this, even if carrier is not
458 	     * present, because otherwise we'd have to use TIOCSDTR
459 	     * immediately after setting CLOCAL.  We will drop DTR only on
460 	     * the next high-low transition of DCD, or by explicit request.
461 	     */
462 	    ser_modem(sc, 1);
463 
464 	    /* Clear the input ring, and unblock. */
465 	    sc->sc_rbput = sc->sc_rbget = 0;
466 	    sc->sc_rbavail = RXBUFSIZE;
467 	    ser_iflush(sc);
468 	    sc->sc_rx_blocked = 0;
469 	    ser_hwiflow(sc, 0);
470 
471 #ifdef SER_DEBUG
472 	    serstatus(sc, "seropen  ");
473 #endif
474 
475 	    splx(s2);
476 	}
477 
478 	splx(s);
479 
480 	error = ttyopen(tp, SERDIALOUT(dev), ISSET(flag, O_NONBLOCK));
481 	if (error)
482 		goto bad;
483 
484 	error = (*tp->t_linesw->l_open)(dev, tp);
485         if (error)
486 		goto bad;
487 
488 	return (0);
489 
490 bad:
491 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
492 		/*
493 		 * We failed to open the device, and nobody else had it opened.
494 		 * Clean up the state as appropriate.
495 		 */
496 		ser_shutdown(sc);
497 	}
498 
499 	return (error);
500 }
501 
502 int
503 serclose(dev, flag, mode, p)
504 	dev_t		dev;
505 	int		flag, mode;
506 	struct proc	*p;
507 {
508 	int unit = SERUNIT(dev);
509 	struct ser_softc *sc = ser_cd.cd_devs[unit];
510 	struct tty *tp = sc->sc_tty;
511 
512 	/* XXX This is for cons.c. */
513 	if (!ISSET(tp->t_state, TS_ISOPEN))
514 		return (0);
515 
516 	(*tp->t_linesw->l_close)(tp, flag);
517 	ttyclose(tp);
518 
519 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
520 		/*
521 		 * Although we got a last close, the device may still be in
522 		 * use; e.g. if this was the dialout node, and there are still
523 		 * processes waiting for carrier on the non-dialout node.
524 		 */
525 		ser_shutdown(sc);
526 	}
527 
528 	return (0);
529 }
530 
531 int
532 serread(dev, uio, flag)
533 	dev_t dev;
534 	struct uio *uio;
535 	int flag;
536 {
537 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(dev)];
538 	struct tty *tp = sc->sc_tty;
539 
540 	return ((*tp->t_linesw->l_read)(tp, uio, flag));
541 }
542 
543 int
544 serwrite(dev, uio, flag)
545 	dev_t dev;
546 	struct uio *uio;
547 	int flag;
548 {
549 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(dev)];
550 	struct tty *tp = sc->sc_tty;
551 
552 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
553 }
554 
555 int
556 serpoll(dev, events, p)
557 	dev_t dev;
558 	int events;
559 	struct proc *p;
560 {
561 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(dev)];
562 	struct tty *tp = sc->sc_tty;
563 
564 	return ((*tp->t_linesw->l_poll)(tp, events, p));
565 }
566 
567 struct tty *
568 sertty(dev)
569 	dev_t dev;
570 {
571 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(dev)];
572 	struct tty *tp = sc->sc_tty;
573 
574 	return (tp);
575 }
576 
577 int
578 serioctl(dev, cmd, data, flag, p)
579 	dev_t dev;
580 	u_long cmd;
581 	caddr_t data;
582 	int flag;
583 	struct proc *p;
584 {
585 	int unit = SERUNIT(dev);
586 	struct ser_softc *sc = ser_cd.cd_devs[unit];
587 	struct tty *tp = sc->sc_tty;
588 	int error;
589 
590 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
591 	if (error != EPASSTHROUGH)
592 		return (error);
593 
594 	error = ttioctl(tp, cmd, data, flag, p);
595 	if (error != EPASSTHROUGH)
596 		return (error);
597 
598 	switch (cmd) {
599 	case TIOCSBRK:
600 		ser_break(sc, 1);
601 		break;
602 
603 	case TIOCCBRK:
604 		ser_break(sc, 0);
605 		break;
606 
607 	case TIOCSDTR:
608 		ser_modem(sc, 1);
609 		break;
610 
611 	case TIOCCDTR:
612 		ser_modem(sc, 0);
613 		break;
614 
615 	case TIOCGFLAGS:
616 		*(int *)data = sc->sc_swflags;
617 		break;
618 
619 	case TIOCSFLAGS:
620 		error = suser(p->p_ucred, &p->p_acflag);
621 		if (error)
622 			return (error);
623 		sc->sc_swflags = *(int *)data;
624 		break;
625 
626 	case TIOCMSET:
627 	case TIOCMBIS:
628 	case TIOCMBIC:
629 	case TIOCMGET:
630 	default:
631 		return (EPASSTHROUGH);
632 	}
633 
634 #ifdef SER_DEBUG
635 		serstatus(sc, "serioctl ");
636 #endif
637 
638 	return (0);
639 }
640 
641 void
642 ser_break(sc, onoff)
643 	struct ser_softc *sc;
644 	int onoff;
645 {
646 	int s;
647 
648 	s = splserial();
649 	if (onoff)
650 		SET(sc->sc_tsr, TSR_SBREAK);
651 	else
652 		CLR(sc->sc_tsr, TSR_SBREAK);
653 
654 	if (!sc->sc_heldchange) {
655 		if (sc->sc_tx_busy) {
656 			sc->sc_heldtbc = sc->sc_tbc;
657 			sc->sc_tbc = 0;
658 			sc->sc_heldchange = 1;
659 		} else
660 			ser_loadchannelregs(sc);
661 	}
662 	splx(s);
663 }
664 
665 void
666 ser_modem(sc, onoff)
667 	struct ser_softc *sc;
668 	int onoff;
669 {
670 	int s;
671 
672 	s = splserial();
673 	if (onoff)
674 		SET(sc->sc_mcr, sc->sc_mcr_dtr);
675 	else
676 		CLR(sc->sc_mcr, sc->sc_mcr_dtr);
677 
678 	if (!sc->sc_heldchange) {
679 		if (sc->sc_tx_busy) {
680 			sc->sc_heldtbc = sc->sc_tbc;
681 			sc->sc_tbc = 0;
682 			sc->sc_heldchange = 1;
683 		} else
684 			ser_loadchannelregs(sc);
685 	}
686 	splx(s);
687 }
688 
689 int
690 serparam(tp, t)
691 	struct tty *tp;
692 	struct termios *t;
693 {
694 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)];
695 	int ospeed = serspeed(t->c_ospeed);
696 	u_char ucr;
697 	int s;
698 
699 	/* check requested parameters */
700 	if (ospeed < 0)
701 		return (EINVAL);
702 	if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
703 		return (EINVAL);
704 
705 	sc->sc_rsr = RSR_ENAB;
706 	sc->sc_tsr = TSR_ENAB;
707 
708 	ucr = UCR_CLKDIV;
709 
710 	switch (ISSET(t->c_cflag, CSIZE)) {
711 	case CS5:
712 		SET(ucr, UCR_5BITS);
713 		break;
714 	case CS6:
715 		SET(ucr, UCR_6BITS);
716 		break;
717 	case CS7:
718 		SET(ucr, UCR_7BITS);
719 		break;
720 	case CS8:
721 		SET(ucr, UCR_8BITS);
722 		break;
723 	}
724 	if (ISSET(t->c_cflag, PARENB)) {
725 		SET(ucr, UCR_PENAB);
726 		if (!ISSET(t->c_cflag, PARODD))
727 			SET(ucr, UCR_PEVEN);
728 	}
729 	if (ISSET(t->c_cflag, CSTOPB))
730 		SET(ucr, UCR_STOPB2);
731 	else
732 		SET(ucr, UCR_STOPB1);
733 
734 	s = splserial();
735 
736 	sc->sc_ucr = ucr;
737 
738 	/*
739 	 * For the console, always force CLOCAL and !HUPCL, so that the port
740 	 * is always active.
741 	 */
742 	if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
743 	    ISSET(sc->sc_hwflags, SER_HW_CONSOLE)) {
744 		SET(t->c_cflag, CLOCAL);
745 		CLR(t->c_cflag, HUPCL);
746 	}
747 
748 	/*
749 	 * If we're not in a mode that assumes a connection is present, then
750 	 * ignore carrier changes.
751 	 */
752 	if (ISSET(t->c_cflag, CLOCAL | MDMBUF))
753 		sc->sc_msr_dcd = 0;
754 	else
755 		sc->sc_msr_dcd = MCR_DCD;
756 	/*
757 	 * Set the flow control pins depending on the current flow control
758 	 * mode.
759 	 */
760 	if (ISSET(t->c_cflag, CRTSCTS)) {
761 		sc->sc_mcr_dtr = MCR_DTR;
762 		sc->sc_mcr_rts = MCR_RTS;
763 		sc->sc_msr_cts = MCR_CTS;
764 		sc->sc_r_hiwat = RXHIWAT;
765 	} else if (ISSET(t->c_cflag, MDMBUF)) {
766 		/*
767 		 * For DTR/DCD flow control, make sure we don't toggle DTR for
768 		 * carrier detection.
769 		 */
770 		sc->sc_mcr_dtr = 0;
771 		sc->sc_mcr_rts = MCR_DTR;
772 		sc->sc_msr_cts = MCR_DCD;
773 		sc->sc_r_hiwat = RXHIWAT;
774 	} else {
775 		/*
776 		 * If no flow control, then always set RTS.  This will make
777 		 * the other side happy if it mistakenly thinks we're doing
778 		 * RTS/CTS flow control.
779 		 */
780 		sc->sc_mcr_dtr = MCR_DTR | MCR_RTS;
781 		sc->sc_mcr_rts = 0;
782 		sc->sc_msr_cts = 0;
783 		sc->sc_r_hiwat = 0;
784 		if (ISSET(sc->sc_mcr, MCR_DTR))
785 			SET(sc->sc_mcr, MCR_RTS);
786 		else
787 			CLR(sc->sc_mcr, MCR_RTS);
788 	}
789 	sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd;
790 
791 #if 0
792 	if (ospeed == 0)
793 		CLR(sc->sc_mcr, sc->sc_mcr_dtr);
794 	else
795 		SET(sc->sc_mcr, sc->sc_mcr_dtr);
796 #endif
797 
798 	sc->sc_ospeed = ospeed;
799 
800 	/* and copy to tty */
801 	tp->t_ispeed = 0;
802 	tp->t_ospeed = t->c_ospeed;
803 	tp->t_cflag = t->c_cflag;
804 
805 	if (!sc->sc_heldchange) {
806 		if (sc->sc_tx_busy) {
807 			sc->sc_heldtbc = sc->sc_tbc;
808 			sc->sc_tbc = 0;
809 			sc->sc_heldchange = 1;
810 		} else
811 			ser_loadchannelregs(sc);
812 	}
813 
814 	splx(s);
815 
816 	/*
817 	 * Update the tty layer's idea of the carrier bit, in case we changed
818 	 * CLOCAL or MDMBUF.  We don't hang up here; we only do that if we
819 	 * lose carrier while carrier detection is on.
820 	 */
821 	(void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, MCR_DCD));
822 
823 #ifdef SER_DEBUG
824 	serstatus(sc, "serparam ");
825 #endif
826 
827 	/* XXXXX FIX ME */
828 	/* Block or unblock as needed. */
829 	if (!ISSET(t->c_cflag, CHWFLOW)) {
830 		if (sc->sc_rx_blocked) {
831 			sc->sc_rx_blocked = 0;
832 			ser_hwiflow(sc, 0);
833 		}
834 		if (sc->sc_tx_stopped) {
835 			sc->sc_tx_stopped = 0;
836 			serstart(tp);
837 		}
838 	} else {
839 #if 0
840 		sermsrint(sc, tp);
841 #endif
842 	}
843 
844 	return (0);
845 }
846 
847 void
848 ser_iflush(sc)
849 	struct ser_softc *sc;
850 {
851 	u_char	tmp;
852 
853 	/* flush any pending I/O */
854 	while (ISSET(MFP->mf_rsr, RSR_CIP|RSR_BFULL))
855 		tmp = MFP->mf_udr;
856 }
857 
858 void
859 ser_loadchannelregs(sc)
860 	struct ser_softc *sc;
861 {
862 	/* XXXXX necessary? */
863 	ser_iflush(sc);
864 
865 	/*
866 	 * No interrupts please...
867 	 */
868 if((MFP->mf_imra & (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR)) != sc->sc_imra) {
869 printf("loadchannelregs: mf_imra: %x sc_imra: %x\n", (u_int)MFP->mf_imra,
870 						     (u_int)sc->sc_imra);
871 }
872 if((MFP->mf_imrb & (IB_SCTS|IB_SDCD)) != sc->sc_imrb) {
873 printf("loadchannelregs: mf_imrb: %x sc_imrb: %x\n", (u_int)MFP->mf_imrb,
874 						     (u_int)sc->sc_imrb);
875 }
876 	single_inst_bclr_b(MFP->mf_imra, IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
877 	single_inst_bclr_b(MFP->mf_imrb, IB_SCTS|IB_SDCD);
878 
879 	MFP->mf_ucr = sc->sc_ucr;
880 	MFP->mf_rsr = sc->sc_rsr;
881 	MFP->mf_tsr = sc->sc_tsr;
882 
883 	single_inst_bclr_b(MFP->mf_tcdcr, 0x07);
884 	MFP->mf_tddr  = sc->sc_ospeed;
885 	single_inst_bset_b(MFP->mf_tcdcr, (sc->sc_ospeed >> 8) & 0x0f);
886 
887 	sc->sc_mcr_active = sc->sc_mcr;
888 
889 	if (machineid & ATARI_HADES) {
890 		/* PCB fault, wires exchanged..... */
891 		ym2149_rts(!(sc->sc_mcr_active & MCR_DTR));
892 		ym2149_dtr(!(sc->sc_mcr_active & MCR_RTS));
893 	}
894 	else {
895 		ym2149_rts(!(sc->sc_mcr_active & MCR_RTS));
896 		ym2149_dtr(!(sc->sc_mcr_active & MCR_DTR));
897 	}
898 
899 	single_inst_bset_b(MFP->mf_imra, sc->sc_imra);
900 	single_inst_bset_b(MFP->mf_imrb, sc->sc_imrb);
901 }
902 
903 int
904 serhwiflow(tp, block)
905 	struct tty *tp;
906 	int block;
907 {
908 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)];
909 	int s;
910 
911 	if (sc->sc_mcr_rts == 0)
912 		return (0);
913 
914 	s = splserial();
915 	if (block) {
916 		/*
917 		 * The tty layer is asking us to block input.
918 		 * If we already did it, just return TRUE.
919 		 */
920 		if (sc->sc_rx_blocked)
921 			goto out;
922 		sc->sc_rx_blocked = 1;
923 	} else {
924 		/*
925 		 * The tty layer is asking us to resume input.
926 		 * The input ring is always empty by now.
927 		 */
928 		sc->sc_rx_blocked = 0;
929 	}
930 	ser_hwiflow(sc, block);
931 out:
932 	splx(s);
933 	return (1);
934 }
935 
936 /*
937  * (un)block input via hw flowcontrol
938  */
939 void
940 ser_hwiflow(sc, block)
941 	struct ser_softc *sc;
942 	int block;
943 {
944 	if (sc->sc_mcr_rts == 0)
945 		return;
946 
947 	if (block) {
948 		CLR(sc->sc_mcr, sc->sc_mcr_rts);
949 		CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
950 	} else {
951 		SET(sc->sc_mcr, sc->sc_mcr_rts);
952 		SET(sc->sc_mcr_active, sc->sc_mcr_rts);
953 	}
954 	if (machineid & ATARI_HADES) {
955 		/* PCB fault, wires exchanged..... */
956 		ym2149_dtr(sc->sc_mcr_active & MCR_RTS);
957 	}
958 	else {
959 		ym2149_rts(sc->sc_mcr_active & MCR_RTS);
960 	}
961 }
962 
963 void
964 serstart(tp)
965 	struct tty *tp;
966 {
967 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)];
968 	int s;
969 
970 	s = spltty();
971 	if (ISSET(tp->t_state, TS_BUSY))
972 		goto out;
973 	if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP))
974 		goto stopped;
975 
976 	if (sc->sc_tx_stopped)
977 		goto stopped;
978 
979 	if (tp->t_outq.c_cc <= tp->t_lowat) {
980 		if (ISSET(tp->t_state, TS_ASLEEP)) {
981 			CLR(tp->t_state, TS_ASLEEP);
982 			wakeup(&tp->t_outq);
983 		}
984 		selwakeup(&tp->t_wsel);
985 		if (tp->t_outq.c_cc == 0)
986 			goto stopped;
987 	}
988 
989 	/* Grab the first contiguous region of buffer space. */
990 	{
991 		u_char *tba;
992 		int tbc;
993 
994 		tba = tp->t_outq.c_cf;
995 		tbc = ndqb(&tp->t_outq, 0);
996 
997 		(void)splserial();
998 
999 		sc->sc_tba = tba;
1000 		sc->sc_tbc = tbc;
1001 	}
1002 
1003 	SET(tp->t_state, TS_BUSY);
1004 	sc->sc_tx_busy = 1;
1005 
1006 	/* Enable transmit completion interrupts if necessary. */
1007 	if (!ISSET(sc->sc_imra, IA_TRDY)) {
1008 		SET(sc->sc_imra, IA_TRDY|IA_TERR);
1009 		single_inst_bset_b(MFP->mf_imra, IA_TRDY|IA_TERR);
1010 	}
1011 
1012 	/* Output the first char */
1013 	MFP->mf_udr = *sc->sc_tba;
1014 	sc->sc_tbc --;
1015 	sc->sc_tba ++;
1016 
1017 	splx(s);
1018 	return;
1019 
1020 stopped:
1021 	/* Disable transmit completion interrupts if necessary. */
1022 	if (ISSET(sc->sc_imra, IA_TRDY)) {
1023 		CLR(sc->sc_imra, IA_TRDY|IA_TERR);
1024 		single_inst_bclr_b(MFP->mf_imra, IA_TRDY|IA_TERR);
1025 	}
1026 out:
1027 	splx(s);
1028 	return;
1029 }
1030 
1031 /*
1032  * Stop output on a line.
1033  */
1034 void
1035 serstop(tp, flag)
1036 	struct tty *tp;
1037 	int flag;
1038 {
1039 	struct ser_softc *sc = ser_cd.cd_devs[SERUNIT(tp->t_dev)];
1040 	int s;
1041 
1042 	s = splserial();
1043 	if (ISSET(tp->t_state, TS_BUSY)) {
1044 		/* Stop transmitting at the next chunk. */
1045 		sc->sc_tbc = 0;
1046 		sc->sc_heldtbc = 0;
1047 		if (!ISSET(tp->t_state, TS_TTSTOP))
1048 			SET(tp->t_state, TS_FLUSH);
1049 	}
1050 	splx(s);
1051 }
1052 
1053 void
1054 serdiag(arg)
1055 	void *arg;
1056 {
1057 	struct ser_softc *sc = arg;
1058 	int overflows, floods;
1059 	int s;
1060 
1061 	s = splserial();
1062 	overflows = sc->sc_overflows;
1063 	sc->sc_overflows = 0;
1064 	floods = sc->sc_floods;
1065 	sc->sc_floods = 0;
1066 	sc->sc_errors = 0;
1067 	splx(s);
1068 
1069 	log(LOG_WARNING,
1070 	    "%s: %d silo overflow%s, %d ibuf flood%s\n",
1071 	    sc->sc_dev.dv_xname,
1072 	    overflows, overflows == 1 ? "" : "s",
1073 	    floods, floods == 1 ? "" : "s");
1074 }
1075 
1076 static
1077 void ser_shutdown(sc)
1078 	struct ser_softc *sc;
1079 {
1080 	int	s;
1081 	struct tty *tp = sc->sc_tty;
1082 
1083 
1084 	s = splserial();
1085 
1086 	/* If we were asserting flow control, then deassert it. */
1087 	sc->sc_rx_blocked = 1;
1088 	ser_hwiflow(sc, 1);
1089 
1090 	/* Clear any break condition set with TIOCSBRK. */
1091 	ser_break(sc, 0);
1092 
1093 	/*
1094 	 * Hang up if necessary.  Wait a bit, so the other side has time to
1095 	 * notice even if we immediately open the port again.
1096 	 */
1097 	if (ISSET(tp->t_cflag, HUPCL)) {
1098 		ser_modem(sc, 0);
1099 		(void) tsleep(sc, TTIPRI, ttclos, hz);
1100 	}
1101 
1102 	/* Turn off interrupts. */
1103 	CLR(sc->sc_imra, IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
1104 	CLR(sc->sc_imrb, IB_SCTS|IB_SDCD);
1105 	single_inst_bclr_b(MFP->mf_imrb, IB_SCTS|IB_SDCD);
1106 	single_inst_bclr_b(MFP->mf_imra, IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
1107 	splx(s);
1108 }
1109 
1110 static void
1111 serrxint(sc, tp)
1112 	struct ser_softc	*sc;
1113 	struct tty		*tp;
1114 {
1115 	u_int	get, cc, scc;
1116 	int	code;
1117 	u_char	rsr;
1118 	int	s;
1119 	static int lsrmap[8] = {
1120 		0,      TTY_PE,
1121 		TTY_FE, TTY_PE|TTY_FE,
1122 		TTY_FE, TTY_PE|TTY_FE,
1123 		TTY_FE, TTY_PE|TTY_FE
1124 	};
1125 
1126 	get = sc->sc_rbget;
1127 	scc = cc = RXBUFSIZE - sc->sc_rbavail;
1128 
1129 	if (cc == RXBUFSIZE) {
1130 		sc->sc_floods++;
1131 		if (sc->sc_errors++ == 0)
1132 			callout_reset(&sc->sc_diag_ch, 60 * hz, serdiag, sc);
1133 	}
1134 
1135 	while (cc--) {
1136 		rsr = sc->sc_lbuf[get];
1137 		if (ISSET(rsr, RSR_BREAK)) {
1138 #ifdef DDB
1139 			if (ISSET(sc->sc_hwflags, SER_HW_CONSOLE))
1140 				Debugger();
1141 #endif
1142 		}
1143 		else if (ISSET(rsr, RSR_OERR)) {
1144 			sc->sc_overflows++;
1145 			if (sc->sc_errors++ == 0)
1146 				callout_reset(&sc->sc_diag_ch, 60 * hz,
1147 				    serdiag, sc);
1148 		}
1149 		code = sc->sc_rbuf[get] |
1150 		    lsrmap[(rsr & (RSR_BREAK|RSR_FERR|RSR_PERR)) >> 3];
1151 		(*tp->t_linesw->l_rint)(code, tp);
1152 		get = (get + 1) & RXBUFMASK;
1153 	}
1154 
1155 	sc->sc_rbget = get;
1156 	s = splserial();
1157 	sc->sc_rbavail += scc;
1158 	/*
1159 	 * Buffers should be ok again, release possible block, but only if the
1160 	 * tty layer isn't blocking too.
1161 	 */
1162 	if (sc->sc_rx_blocked && !ISSET(tp->t_state, TS_TBLOCK)) {
1163 		sc->sc_rx_blocked = 0;
1164 		ser_hwiflow(sc, 0);
1165 	}
1166 	splx(s);
1167 }
1168 
1169 static void
1170 sertxint(sc, tp)
1171 	struct ser_softc	*sc;
1172 	struct tty		*tp;
1173 {
1174 
1175 	CLR(tp->t_state, TS_BUSY);
1176 	if (ISSET(tp->t_state, TS_FLUSH))
1177 		CLR(tp->t_state, TS_FLUSH);
1178 	else
1179 		ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
1180 	(*tp->t_linesw->l_start)(tp);
1181 }
1182 
1183 static void
1184 sermsrint(sc, tp)
1185 	struct ser_softc	*sc;
1186 	struct tty		*tp;
1187 {
1188 	u_char msr, delta;
1189 	int s;
1190 
1191 	s = splserial();
1192 	msr = sc->sc_msr;
1193 	delta = sc->sc_msr_delta;
1194 	sc->sc_msr_delta = 0;
1195 	splx(s);
1196 
1197 	if (ISSET(delta, sc->sc_msr_dcd)) {
1198 		/*
1199 		 * Inform the tty layer that carrier detect changed.
1200 		 */
1201 		(void) (*tp->t_linesw->l_modem)(tp, ISSET(msr, MCR_DCD));
1202 	}
1203 
1204 	if (ISSET(delta, sc->sc_msr_cts)) {
1205 		/* Block or unblock output according to flow control. */
1206 		if (ISSET(msr, sc->sc_msr_cts)) {
1207 			sc->sc_tx_stopped = 0;
1208 			(*tp->t_linesw->l_start)(tp);
1209 		} else {
1210 			sc->sc_tx_stopped = 1;
1211 			serstop(tp, 0);
1212 		}
1213 	}
1214 
1215 #ifdef SER_DEBUG
1216 	serstatus(sc, "sermsrint");
1217 #endif
1218 }
1219 
1220 void
1221 sersoft(arg)
1222 	void *arg;
1223 {
1224 	struct ser_softc *sc = arg;
1225 	struct tty	*tp;
1226 
1227 	ser_softintr_scheduled = 0;
1228 
1229 	tp = sc->sc_tty;
1230 	if (tp == NULL)
1231 		return;
1232 
1233 	if (!ISSET(tp->t_state, TS_ISOPEN) && (tp->t_wopen == 0))
1234 		return;
1235 
1236 	if (sc->sc_rx_ready) {
1237 		sc->sc_rx_ready = 0;
1238 		serrxint(sc, tp);
1239 	}
1240 
1241 	if (sc->sc_st_check) {
1242 		sc->sc_st_check = 0;
1243 		sermsrint(sc, tp);
1244 	}
1245 
1246 	if (sc->sc_tx_done) {
1247 		sc->sc_tx_done = 0;
1248 		sertxint(sc, tp);
1249 	}
1250 }
1251 
1252 int
1253 sermintr(arg)
1254 void	*arg;
1255 {
1256 	struct ser_softc *sc = arg;
1257 	u_char	msr, delta;
1258 
1259 	msr = ~MFP->mf_gpip;
1260 	delta = msr ^ sc->sc_msr;
1261 	sc->sc_msr  = sc->sc_msr & ~(MCR_CTS|MCR_DCD|MCR_RI);
1262 	sc->sc_msr |= msr & (MCR_CTS|MCR_DCD|MCR_RI);
1263 
1264 	if (ISSET(delta, sc->sc_msr_mask)) {
1265 		sc->sc_msr_delta |= delta;
1266 
1267 		/*
1268 		 * Stop output immediately if we lose the output
1269 		 * flow control signal or carrier detect.
1270 		 */
1271 		if (ISSET(~msr, sc->sc_msr_mask)) {
1272 			sc->sc_tbc = 0;
1273 			sc->sc_heldtbc = 0;
1274 #ifdef SER_DEBUG
1275 			serstatus(sc, "sermintr  ");
1276 #endif
1277 		}
1278 
1279 		sc->sc_st_check = 1;
1280 	}
1281 	if (!ser_softintr_scheduled)
1282 		add_sicallback((si_farg)sersoft, sc, 0);
1283 	return 1;
1284 }
1285 
1286 int
1287 sertrintr(arg)
1288 	void	*arg;
1289 {
1290 	struct ser_softc *sc = arg;
1291 	u_int	put, cc;
1292 	u_char	rsr, tsr;
1293 
1294 	put = sc->sc_rbput;
1295 	cc = sc->sc_rbavail;
1296 
1297 	rsr = MFP->mf_rsr;
1298 	if (ISSET(rsr, RSR_BFULL|RSR_BREAK)) {
1299 		for (; ISSET(rsr, RSR_BFULL|RSR_BREAK) && cc > 0; cc--) {
1300 			sc->sc_rbuf[put] = MFP->mf_udr;
1301 			sc->sc_lbuf[put] = rsr;
1302 			put = (put + 1) & RXBUFMASK;
1303 			if ((rsr & RSR_BREAK) && (MFP->mf_rsr & RSR_BREAK))
1304 				rsr = 0;
1305 			else rsr = MFP->mf_rsr;
1306 		}
1307 		/*
1308 		 * Current string of incoming characters ended because
1309 		 * no more data was available. Schedule a receive event
1310 		 * if any data was received. Drop any characters that
1311 		 * we couldn't handle.
1312 		 */
1313 		sc->sc_rbput    = put;
1314 		sc->sc_rbavail  = cc;
1315 		sc->sc_rx_ready = 1;
1316 		/*
1317 		 * See if we are in danger of overflowing a buffer. If
1318 		 * so, use hardware flow control to ease the pressure.
1319 		 */
1320 		if (sc->sc_rx_blocked == 0 &&
1321 		    cc < sc->sc_r_hiwat) {
1322 			sc->sc_rx_blocked = 1;
1323 			ser_hwiflow(sc, 1);
1324 		}
1325 		/*
1326 		 * If we're out of space, throw away any further input.
1327 		 */
1328 		if (!cc) {
1329 			while (ISSET(rsr, RSR_BFULL|RSR_BREAK)) {
1330 				rsr = MFP->mf_udr;
1331 				rsr = MFP->mf_rsr;
1332 			}
1333 		}
1334 	}
1335 
1336 	/*
1337 	 * Done handling any receive interrupts. See if data can be
1338 	 * transmitted as well. Schedule tx done event if no data left
1339 	 * and tty was marked busy.
1340 	 */
1341 	tsr = MFP->mf_tsr;
1342 	if (ISSET(tsr, TSR_BE)) {
1343 		/*
1344 		 * If we've delayed a parameter change, do it now, and restart
1345 		 * output.
1346 		 */
1347 		if (sc->sc_heldchange) {
1348 			ser_loadchannelregs(sc);
1349 			sc->sc_heldchange = 0;
1350 			sc->sc_tbc = sc->sc_heldtbc;
1351 			sc->sc_heldtbc = 0;
1352 		}
1353 		/* Output the next character, if any. */
1354 		if (sc->sc_tbc > 0) {
1355 			MFP->mf_udr = *sc->sc_tba;
1356 			sc->sc_tbc --;
1357 			sc->sc_tba ++;
1358 		} else if (sc->sc_tx_busy) {
1359 			sc->sc_tx_busy = 0;
1360 			sc->sc_tx_done = 1;
1361 		}
1362 	}
1363 
1364 	if (!ser_softintr_scheduled)
1365 		add_sicallback((si_farg)sersoft, sc, 0);
1366 	return 1;
1367 }
1368 
1369 static int
1370 serspeed(speed)
1371 	long speed;
1372 {
1373 #define	divrnd(n, q)	(((n)*2/(q)+1)/2)	/* divide and round off */
1374 
1375 	int div, x, err;
1376 
1377 	if (speed <= 0)
1378 		return (-1);
1379 
1380 	for (div = 4; div <= 64; div *= 4) {
1381 		x = divrnd((SER_FREQ / div), speed);
1382 
1383 		/*
1384 		 * The value must fit in the timer-d dataregister. If
1385 		 * not, try another delay-mode.
1386 		 */
1387 		if ((x/2) > 255)
1388 			continue;
1389 
1390 		/*
1391 		 * Baudrate to high for the interface or cannot be made
1392 		 * within tolerance.
1393 		 */
1394 		if (x <= 0)
1395 			return (-1);
1396 
1397 		err = divrnd((SER_FREQ / div) * 1000, speed * x) - 1000;
1398 		if (err < 0)
1399 			err = -err;
1400 		if (err > SER_TOLERANCE)
1401 			continue;
1402 
1403 		/*
1404 		 * Translate 'div' to delay-code
1405 		 */
1406 		if (div == 4)
1407 			div = 1;
1408 		else if (div == 16)
1409 			div = 3;
1410 		else if (div == 64)
1411 			div = 5;
1412 
1413 		return ((x/2) | (div << 8));
1414 	}
1415 	return (-1);
1416 
1417 #undef	divrnd
1418 }
1419 
1420 /*
1421  * Following are all routines needed for SER to act as console
1422  */
1423 #include <dev/cons.h>
1424 
1425 void
1426 sercnprobe(cp)
1427 	struct consdev *cp;
1428 {
1429 	/*
1430 	 * Activate serial console when DCD present...
1431 	 */
1432 	if (MFP->mf_gpip & MCR_DCD) {
1433 		cp->cn_pri = CN_DEAD;
1434 		return;
1435 	}
1436 
1437 	/* initialize required fields */
1438 	/* XXX: LWP What unit? */
1439 	cp->cn_dev = makedev(cdevsw_lookup_major(&ser_cdevsw), 0);
1440 #if SERCONSOLE > 0
1441 	cp->cn_pri = CN_REMOTE;	/* Force a serial port console */
1442 #else
1443 	cp->cn_pri = CN_NORMAL;
1444 #endif /* SERCONSOLE > 0 */
1445 }
1446 
1447 void
1448 sercninit(cp)
1449 	struct consdev *cp;
1450 {
1451 	serinitcons(CONSBAUD);
1452 }
1453 
1454 /*
1455  * Initialize UART to known state.
1456  */
1457 void
1458 serinit(baud)
1459 int	baud;
1460 {
1461 	int ospeed = serspeed(baud);
1462 
1463 	MFP->mf_ucr = UCR_CLKDIV|UCR_8BITS|UCR_STOPB1;
1464 	MFP->mf_rsr = RSR_ENAB;
1465 	MFP->mf_tsr = TSR_ENAB;
1466 
1467 	single_inst_bclr_b(MFP->mf_tcdcr, 0x07);
1468 	MFP->mf_tddr  = ospeed;
1469 	single_inst_bset_b(MFP->mf_tcdcr, (ospeed >> 8) & 0x0f);
1470 }
1471 
1472 /*
1473  * Set UART for console use. Do normal init, then enable interrupts.
1474  */
1475 void
1476 serinitcons(baud)
1477 int	baud;
1478 {
1479 	serinit(baud);
1480 
1481 	/* Set rts/dtr */
1482 	ym2149_rts(0);
1483 	ym2149_dtr(0);
1484 
1485 	single_inst_bset_b(MFP->mf_imra, (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR));
1486 }
1487 
1488 int
1489 sercngetc(dev)
1490 	dev_t dev;
1491 {
1492 	u_char	stat, c;
1493 	int	s;
1494 
1495 	s = splserial();
1496 	while (!ISSET(stat = MFP->mf_rsr, RSR_BFULL)) {
1497 		if (!ISSET(stat, RSR_ENAB)) /* XXX */
1498 			MFP->mf_rsr |= RSR_ENAB;
1499 		if (stat & (RSR_FERR|RSR_PERR|RSR_OERR))
1500 			c = MFP->mf_udr;
1501 	}
1502 	c = MFP->mf_udr;
1503 	splx(s);
1504 	return c;
1505 }
1506 
1507 u_int s_imra;
1508 u_int s_stat1, s_stat2, s_stat3;
1509 void
1510 sercnputc(dev, c)
1511 	dev_t dev;
1512 	int c;
1513 {
1514 	int	timo;
1515 	u_char	stat, imra;
1516 
1517 	/* Mask serial interrupts */
1518 	imra  = MFP->mf_imra & (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
1519 	single_inst_bclr_b(MFP->mf_imra, imra);
1520 s_imra = imra;
1521 
1522 	/* wait for any pending transmission to finish */
1523 	timo = 50000;
1524 s_stat1 = MFP->mf_tsr;
1525 	while (!ISSET(stat = MFP->mf_tsr, TSR_BE) && --timo)
1526 		;
1527 	MFP->mf_udr = c;
1528 	/* wait for this transmission to complete */
1529 	timo = 1500000;
1530 s_stat2 = MFP->mf_tsr;
1531 	while (!ISSET(stat = MFP->mf_tsr, TSR_BE) && --timo)
1532 		;
1533 
1534 s_stat3 = MFP->mf_tsr;
1535 	/* Clear pending serial interrupts and re-enable */
1536 	MFP->mf_ipra = (u_int8_t)~imra;
1537 	single_inst_bset_b(MFP->mf_imra, imra);
1538 }
1539 
1540 void
1541 sercnpollc(dev, on)
1542 	dev_t dev;
1543 	int on;
1544 {
1545 
1546 }
1547