ser.c revision 1.15.4.2 1 /* $NetBSD: ser.c,v 1.15.4.2 2002/07/14 17:46:01 gehenna 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
109 #include <sys/param.h>
110 #include <sys/systm.h>
111 #include <sys/ioctl.h>
112 #include <sys/select.h>
113 #include <sys/tty.h>
114 #include <sys/proc.h>
115 #include <sys/user.h>
116 #include <sys/conf.h>
117 #include <sys/file.h>
118 #include <sys/uio.h>
119 #include <sys/kernel.h>
120 #include <sys/syslog.h>
121 #include <sys/types.h>
122 #include <sys/device.h>
123
124 #include <m68k/asm_single.h>
125
126 #include <machine/iomap.h>
127 #include <machine/mfp.h>
128 #include <atari/atari/intr.h>
129 #include <atari/dev/serreg.h>
130
131 #if !defined(_MILANHW_)
132 #include <atari/dev/ym2149reg.h>
133 #else
134 /* MILAN has no ym2149 */
135 #define ym2149_dtr(set) { \
136 if (set) \
137 single_inst_bset_b(MFP->mf_gpip, 0x08); \
138 else single_inst_bclr_b(MFP->mf_gpip, 0x08); \
139 }
140
141 #define ym2149_rts(set) { \
142 if (set) \
143 single_inst_bset_b(MFP->mf_gpip, 0x01); \
144 else single_inst_bclr_b(MFP->mf_gpip, 0x01); \
145 }
146 #endif /* _MILANHW_ */
147
148 /* #define SER_DEBUG */
149
150 #define SERUNIT(x) (minor(x) & 0x7ffff)
151 #define SERDIALOUT(x) (minor(x) & 0x80000)
152
153 /* XXX */
154 #define CONSBAUD 9600
155 #define CONSCFLAG TTYDEF_CFLAG
156 /* end XXX */
157
158 /* Macros to clear/set/test flags. */
159 #define SET(t, f) (t) |= (f)
160 #define CLR(t, f) (t) &= ~(f)
161 #define ISSET(t, f) ((t) & (f))
162
163 #define splserial() spl6()
164
165 /* Buffer size for character buffer */
166 #define RXBUFSIZE 2048 /* More than enough.. */
167 #define RXBUFMASK (RXBUFSIZE-1) /* Only iff previous is a power of 2 */
168 #define RXHIWAT (RXBUFSIZE >> 2)
169
170 struct ser_softc {
171 struct device sc_dev;
172 struct tty *sc_tty;
173
174 struct callout sc_diag_ch;
175
176 int sc_overflows;
177 int sc_floods;
178 int sc_errors;
179
180 u_char sc_hwflags;
181 u_char sc_swflags;
182
183 int sc_ospeed; /* delay + timer-d data */
184 u_char sc_imra;
185 u_char sc_imrb;
186 u_char sc_ucr; /* Uart control */
187 u_char sc_msr; /* Modem status */
188 u_char sc_tsr; /* Tranceiver status */
189 u_char sc_rsr; /* Receiver status */
190 u_char sc_mcr; /* (Pseudo) Modem ctrl. */
191
192 u_char sc_msr_delta;
193 u_char sc_msr_mask;
194 u_char sc_mcr_active;
195 u_char sc_mcr_dtr, sc_mcr_rts, sc_msr_cts, sc_msr_dcd;
196
197 int sc_r_hiwat;
198 volatile u_int sc_rbget;
199 volatile u_int sc_rbput;
200 volatile u_int sc_rbavail;
201 u_char sc_rbuf[RXBUFSIZE];
202 u_char sc_lbuf[RXBUFSIZE];
203
204 volatile u_char sc_rx_blocked;
205 volatile u_char sc_rx_ready;
206 volatile u_char sc_tx_busy;
207 volatile u_char sc_tx_done;
208 volatile u_char sc_tx_stopped;
209 volatile u_char sc_st_check;
210
211 u_char *sc_tba;
212 int sc_tbc;
213 int sc_heldtbc;
214
215 volatile u_char sc_heldchange;
216 };
217
218 /*
219 * For sc_hwflags:
220 */
221 #define SER_HW_CONSOLE 0x01
222
223 void ser_break __P((struct ser_softc *, int));
224 void ser_hwiflow __P((struct ser_softc *, int));
225 void ser_iflush __P((struct ser_softc *));
226 void ser_loadchannelregs __P((struct ser_softc *));
227 void ser_modem __P((struct ser_softc *, int));
228 void serdiag __P((void *));
229 int serhwiflow __P((struct tty *, int));
230 void serinit __P((int));
231 void serinitcons __P((int));
232 int baud;
233 int sermintr __P((void *));
234 int sertrintr __P((void *));
235 int serparam __P((struct tty *, struct termios *));
236 void serstart __P((struct tty *));
237
238 struct consdev;
239 void sercnprobe __P((struct consdev *));
240 void sercninit __P((struct consdev *));
241 int sercngetc __P((dev_t));
242 void sercnputc __P((dev_t, int));
243 void sercnpollc __P((dev_t, int));
244
245 static void sermsrint __P((struct ser_softc *, struct tty*));
246 static void serrxint __P((struct ser_softc *, struct tty*));
247 static void ser_shutdown __P((struct ser_softc *));
248 static int serspeed __P((long));
249 static void sersoft __P((void *));
250 static void sertxint __P((struct ser_softc *, struct tty*));
251
252 static volatile int ser_softintr_scheduled = 0;
253
254 /*
255 * Autoconfig stuff
256 */
257 static void serattach __P((struct device *, struct device *, void *));
258 static int sermatch __P((struct device *, struct cfdata *, void *));
259
260 struct cfattach ser_ca = {
261 sizeof(struct ser_softc), sermatch, serattach
262 };
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, 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 #ifdef SERCONSOLE
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 */
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 #ifdef SERCONSOLE
1441 cp->cn_pri = CN_REMOTE; /* Force a serial port console */
1442 #else
1443 cp->cn_pri = CN_NORMAL;
1444 #endif
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