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