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