epcom.c revision 1.11 1 /* $NetBSD: epcom.c,v 1.11 2006/07/23 22:06:04 ad Exp $ */
2 /*
3 * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Jesse Off
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Ichiro FUKUHARA and Naoto Shimazaki.
11 *
12 * This code is derived from software contributed to The NetBSD Foundation
13 * by IWAMOTO Toshihiro.
14 *
15 * This code is derived from software contributed to The NetBSD Foundation
16 * by Charles M. Hannum.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 * 3. All advertising materials mentioning features or use of this software
27 * must display the following acknowledgement:
28 * This product includes software developed by the NetBSD
29 * Foundation, Inc. and its contributors.
30 * 4. Neither the name of The NetBSD Foundation nor the names of its
31 * contributors may be used to endorse or promote products derived
32 * from this software without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
35 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44 * POSSIBILITY OF SUCH DAMAGE.
45 */
46
47 /*
48 * Copyright (c) 1991 The Regents of the University of California.
49 * All rights reserved.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in the
58 * documentation and/or other materials provided with the distribution.
59 * 3. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * @(#)com.c 7.5 (Berkeley) 5/16/91
76 */
77
78 /*
79 * TODO: hardware flow control
80 */
81
82 #include <sys/cdefs.h>
83 __KERNEL_RCSID(0, "$NetBSD: epcom.c,v 1.11 2006/07/23 22:06:04 ad Exp $");
84
85 #include "opt_ddb.h"
86 #include "opt_kgdb.h"
87 #include "epcom.h"
88
89 #include "rnd.h"
90 #if NRND > 0 && defined(RND_COM)
91 #include <sys/rnd.h>
92 #endif
93
94 /*
95 * Override cnmagic(9) macro before including <sys/systm.h>.
96 * We need to know if cn_check_magic triggered debugger, so set a flag.
97 * Callers of cn_check_magic must declare int cn_trapped = 0;
98 * XXX: this is *ugly*!
99 */
100 #define cn_trap() \
101 do { \
102 console_debugger(); \
103 cn_trapped = 1; \
104 } while (/* CONSTCOND */ 0)
105
106
107 #include <sys/param.h>
108 #include <sys/systm.h>
109 #include <sys/types.h>
110 #include <sys/conf.h>
111 #include <sys/file.h>
112 #include <sys/device.h>
113 #include <sys/kernel.h>
114 #include <sys/malloc.h>
115 #include <sys/tty.h>
116 #include <sys/uio.h>
117 #include <sys/vnode.h>
118 #include <sys/kauth.h>
119
120 #include <machine/intr.h>
121 #include <machine/bus.h>
122
123 #include <arm/ep93xx/epcomreg.h>
124 #include <arm/ep93xx/epcomvar.h>
125 #include <arm/ep93xx/ep93xxreg.h>
126 #include <arm/ep93xx/ep93xxvar.h>
127
128 #include <dev/cons.h>
129
130 static int epcomparam(struct tty *, struct termios *);
131 static void epcomstart(struct tty *);
132 static int epcomhwiflow(struct tty *, int);
133
134 static u_int cflag2lcrhi(tcflag_t);
135 static void epcom_iflush(struct epcom_softc *);
136 static void epcom_set(struct epcom_softc *);
137
138 int epcomcngetc(dev_t);
139 void epcomcnputc(dev_t, int);
140 void epcomcnpollc(dev_t, int);
141
142 static void epcomsoft(void* arg);
143 inline static void epcom_txsoft(struct epcom_softc *, struct tty *);
144 inline static void epcom_rxsoft(struct epcom_softc *, struct tty *);
145
146 void epcomcnprobe(struct consdev *);
147 void epcomcninit(struct consdev *);
148
149 static struct epcom_cons_softc {
150 bus_space_tag_t sc_iot;
151 bus_space_handle_t sc_ioh;
152 bus_addr_t sc_hwbase;
153 int sc_ospeed;
154 tcflag_t sc_cflag;
155 int sc_attached;
156 } epcomcn_sc;
157
158 static struct cnm_state epcom_cnm_state;
159
160 extern struct cfdriver epcom_cd;
161
162 dev_type_open(epcomopen);
163 dev_type_close(epcomclose);
164 dev_type_read(epcomread);
165 dev_type_write(epcomwrite);
166 dev_type_ioctl(epcomioctl);
167 dev_type_stop(epcomstop);
168 dev_type_tty(epcomtty);
169 dev_type_poll(epcompoll);
170
171 const struct cdevsw epcom_cdevsw = {
172 epcomopen, epcomclose, epcomread, epcomwrite, epcomioctl,
173 epcomstop, epcomtty, epcompoll, nommap, ttykqfilter, D_TTY
174 };
175
176 struct consdev epcomcons = {
177 NULL, NULL, epcomcngetc, epcomcnputc, epcomcnpollc, NULL,
178 NULL, NULL, NODEV, CN_NORMAL
179 };
180
181 #ifndef DEFAULT_COMSPEED
182 #define DEFAULT_COMSPEED 115200
183 #endif
184
185 #define COMUNIT_MASK 0x7ffff
186 #define COMDIALOUT_MASK 0x80000
187
188 #define COMUNIT(x) (minor(x) & COMUNIT_MASK)
189 #define COMDIALOUT(x) (minor(x) & COMDIALOUT_MASK)
190
191 #define COM_ISALIVE(sc) ((sc)->enabled != 0 && \
192 device_is_active(&(sc)->sc_dev))
193
194 void
195 epcom_attach_subr(struct epcom_softc *sc)
196 {
197 struct tty *tp;
198
199 if (sc->sc_iot == epcomcn_sc.sc_iot
200 && sc->sc_hwbase == epcomcn_sc.sc_hwbase) {
201 epcomcn_sc.sc_attached = 1;
202 sc->sc_lcrlo = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) & 0xff;
203 sc->sc_lcrmid = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) >> 8;
204
205 /* Make sure the console is always "hardwired". */
206 delay(10000); /* wait for output to finish */
207 SET(sc->sc_hwflags, COM_HW_CONSOLE);
208 SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
209 }
210
211 tp = ttymalloc();
212 tp->t_oproc = epcomstart;
213 tp->t_param = epcomparam;
214 tp->t_hwiflow = epcomhwiflow;
215
216 sc->sc_tty = tp;
217 sc->sc_rbuf = malloc(EPCOM_RING_SIZE << 1, M_DEVBUF, M_NOWAIT);
218 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
219 sc->sc_rbavail = EPCOM_RING_SIZE;
220 if (sc->sc_rbuf == NULL) {
221 printf("%s: unable to allocate ring buffer\n",
222 sc->sc_dev.dv_xname);
223 return;
224 }
225 sc->sc_ebuf = sc->sc_rbuf + (EPCOM_RING_SIZE << 1);
226 sc->sc_tbc = 0;
227
228 sc->sc_lcrlo = EPCOMSPEED2BRD(DEFAULT_COMSPEED) & 0xff;
229 sc->sc_lcrmid = EPCOMSPEED2BRD(DEFAULT_COMSPEED) >> 8;
230 sc->sc_lcrhi = cflag2lcrhi(CS8); /* 8N1 */
231
232 tty_attach(tp);
233
234 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
235 int maj;
236
237 /* locate the major number */
238 maj = cdevsw_lookup_major(&epcom_cdevsw);
239
240 cn_tab->cn_dev = makedev(maj, device_unit(&sc->sc_dev));
241
242 aprint_normal("%s: console\n", sc->sc_dev.dv_xname);
243 }
244
245 sc->sc_si = softintr_establish(IPL_SOFTSERIAL, epcomsoft, sc);
246
247 #if NRND > 0 && defined(RND_COM)
248 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
249 RND_TYPE_TTY, 0);
250 #endif
251
252 /* if there are no enable/disable functions, assume the device
253 is always enabled */
254 if (!sc->enable)
255 sc->enabled = 1;
256
257 /* XXX configure register */
258 /* xxx_config(sc) */
259
260 SET(sc->sc_hwflags, COM_HW_DEV_OK);
261 }
262
263 static int
264 epcomparam(struct tty *tp, struct termios *t)
265 {
266 struct epcom_softc *sc
267 = device_lookup(&epcom_cd, COMUNIT(tp->t_dev));
268 int s;
269
270 if (COM_ISALIVE(sc) == 0)
271 return (EIO);
272
273 if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
274 return (EINVAL);
275
276 /*
277 * For the console, always force CLOCAL and !HUPCL, so that the port
278 * is always active.
279 */
280 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
281 ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
282 SET(t->c_cflag, CLOCAL);
283 CLR(t->c_cflag, HUPCL);
284 }
285
286 /*
287 * If there were no changes, don't do anything. This avoids dropping
288 * input and improves performance when all we did was frob things like
289 * VMIN and VTIME.
290 */
291 if (tp->t_ospeed == t->c_ospeed &&
292 tp->t_cflag == t->c_cflag)
293 return (0);
294
295 s = splserial();
296
297 sc->sc_lcrhi = cflag2lcrhi(t->c_cflag);
298 sc->sc_lcrlo = EPCOMSPEED2BRD(t->c_ospeed) & 0xff;
299 sc->sc_lcrmid = EPCOMSPEED2BRD(t->c_ospeed) >> 8;
300
301 /* And copy to tty. */
302 tp->t_ispeed = 0;
303 tp->t_ospeed = t->c_ospeed;
304 tp->t_cflag = t->c_cflag;
305 epcom_set(sc);
306
307 splx(s);
308
309 /*
310 * Update the tty layer's idea of the carrier bit.
311 * We tell tty the carrier is always on.
312 */
313 (void) (*tp->t_linesw->l_modem)(tp, 1);
314
315 #ifdef COM_DEBUG
316 if (com_debug)
317 comstatus(sc, "comparam ");
318 #endif
319
320 if (!ISSET(t->c_cflag, CHWFLOW)) {
321 if (sc->sc_tx_stopped) {
322 sc->sc_tx_stopped = 0;
323 epcomstart(tp);
324 }
325 }
326
327 return (0);
328 }
329
330 static int
331 epcomhwiflow(struct tty *tp, int block)
332 {
333 return (0);
334 }
335
336 static void
337 epcom_filltx(struct epcom_softc *sc)
338 {
339 bus_space_tag_t iot = sc->sc_iot;
340 bus_space_handle_t ioh = sc->sc_ioh;
341 int n;
342
343 n = 0;
344 while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) == 0) {
345 if (n >= sc->sc_tbc)
346 break;
347 bus_space_write_4(iot, ioh, EPCOM_Data,
348 0xff & *(sc->sc_tba + n));
349 n++;
350 }
351 sc->sc_tbc -= n;
352 sc->sc_tba += n;
353 }
354
355 static void
356 epcomstart(struct tty *tp)
357 {
358 struct epcom_softc *sc
359 = device_lookup(&epcom_cd, COMUNIT(tp->t_dev));
360 int s;
361
362 if (COM_ISALIVE(sc) == 0)
363 return;
364
365 s = spltty();
366 if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
367 goto out;
368 if (sc->sc_tx_stopped)
369 goto out;
370
371 if (tp->t_outq.c_cc <= tp->t_lowat) {
372 if (ISSET(tp->t_state, TS_ASLEEP)) {
373 CLR(tp->t_state, TS_ASLEEP);
374 wakeup(&tp->t_outq);
375 }
376 selwakeup(&tp->t_wsel);
377 if (tp->t_outq.c_cc == 0)
378 goto out;
379 }
380
381 /* Grab the first contiguous region of buffer space. */
382 {
383 u_char *tba;
384 int tbc;
385
386 tba = tp->t_outq.c_cf;
387 tbc = ndqb(&tp->t_outq, 0);
388
389 (void)splserial();
390
391 sc->sc_tba = tba;
392 sc->sc_tbc = tbc;
393 }
394
395 SET(tp->t_state, TS_BUSY);
396 sc->sc_tx_busy = 1;
397
398 /* Output the first chunk of the contiguous buffer. */
399 epcom_filltx(sc);
400
401 if (!ISSET(sc->sc_ctrl, Ctrl_TIE)) {
402 SET(sc->sc_ctrl, Ctrl_TIE);
403 epcom_set(sc);
404 }
405
406 out:
407 splx(s);
408 return;
409 }
410
411 static void
412 epcom_break(struct epcom_softc *sc, int onoff)
413 {
414 if (onoff)
415 SET(sc->sc_lcrhi, LinCtrlHigh_BRK);
416 else
417 CLR(sc->sc_lcrhi, LinCtrlHigh_BRK);
418 epcom_set(sc);
419 }
420
421 static void
422 epcom_shutdown(struct epcom_softc *sc)
423 {
424 int s;
425
426 s = splserial();
427
428 /* Turn off interrupts. */
429 CLR(sc->sc_ctrl, (Ctrl_TIE|Ctrl_RTIE|Ctrl_RIE));
430
431 /* Clear any break condition set with TIOCSBRK. */
432 epcom_break(sc, 0);
433 epcom_set(sc);
434
435 if (sc->disable) {
436 #ifdef DIAGNOSTIC
437 if (!sc->enabled)
438 panic("epcom_shutdown: not enabled?");
439 #endif
440 (*sc->disable)(sc);
441 sc->enabled = 0;
442 }
443 splx(s);
444 }
445
446 int
447 epcomopen(dev_t dev, int flag, int mode, struct lwp *l)
448 {
449 struct epcom_softc *sc;
450 struct tty *tp;
451 int s, s2;
452 int error;
453
454 sc = device_lookup(&epcom_cd, COMUNIT(dev));
455 if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) ||
456 sc->sc_rbuf == NULL)
457 return (ENXIO);
458
459 if (!device_is_active(&sc->sc_dev))
460 return (ENXIO);
461
462 #ifdef KGDB
463 /*
464 * If this is the kgdb port, no other use is permitted.
465 */
466 if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
467 return (EBUSY);
468 #endif
469
470 tp = sc->sc_tty;
471
472 if (ISSET(tp->t_state, TS_ISOPEN) &&
473 ISSET(tp->t_state, TS_XCLUDE) &&
474 kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
475 &l->l_acflag) != 0)
476 return (EBUSY);
477
478 s = spltty();
479
480 /*
481 * Do the following iff this is a first open.
482 */
483 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
484 struct termios t;
485
486 tp->t_dev = dev;
487
488 s2 = splserial();
489
490 if (sc->enable) {
491 if ((*sc->enable)(sc)) {
492 splx(s2);
493 splx(s);
494 printf("%s: device enable failed\n",
495 sc->sc_dev.dv_xname);
496 return (EIO);
497 }
498 sc->enabled = 1;
499 #if 0
500 /* XXXXXXXXXXXXXXX */
501 com_config(sc);
502 #endif
503 }
504
505 /* Turn on interrupts. */
506 SET(sc->sc_ctrl, (Ctrl_UARTE|Ctrl_RIE|Ctrl_RTIE));
507 epcom_set(sc);
508
509 #if 0
510 /* Fetch the current modem control status, needed later. */
511 sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr);
512
513 /* Clear PPS capture state on first open. */
514 sc->sc_ppsmask = 0;
515 sc->ppsparam.mode = 0;
516 #endif
517
518 splx(s2);
519
520 /*
521 * Initialize the termios status to the defaults. Add in the
522 * sticky bits from TIOCSFLAGS.
523 */
524 t.c_ispeed = 0;
525 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
526 t.c_ospeed = epcomcn_sc.sc_ospeed;
527 t.c_cflag = epcomcn_sc.sc_cflag;
528 } else {
529 t.c_ospeed = TTYDEF_SPEED;
530 t.c_cflag = TTYDEF_CFLAG;
531 }
532 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
533 SET(t.c_cflag, CLOCAL);
534 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
535 SET(t.c_cflag, CRTSCTS);
536 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
537 SET(t.c_cflag, MDMBUF);
538 /* Make sure epcomparam() will do something. */
539 tp->t_ospeed = 0;
540 (void) epcomparam(tp, &t);
541 tp->t_iflag = TTYDEF_IFLAG;
542 tp->t_oflag = TTYDEF_OFLAG;
543 tp->t_lflag = TTYDEF_LFLAG;
544 ttychars(tp);
545 ttsetwater(tp);
546
547 s2 = splserial();
548
549 /* Clear the input ring, and unblock. */
550 sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
551 sc->sc_rbavail = EPCOM_RING_SIZE;
552 epcom_iflush(sc);
553 CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
554
555 #ifdef COM_DEBUG
556 if (epcom_debug)
557 comstatus(sc, "epcomopen ");
558 #endif
559
560 splx(s2);
561 }
562
563 splx(s);
564
565 error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
566 if (error)
567 goto bad;
568
569 error = (*tp->t_linesw->l_open)(dev, tp);
570 if (error)
571 goto bad;
572
573 return (0);
574
575 bad:
576 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
577 /*
578 * We failed to open the device, and nobody else had it opened.
579 * Clean up the state as appropriate.
580 */
581 epcom_shutdown(sc);
582 }
583
584 return (error);
585 }
586
587 int
588 epcomclose(dev_t dev, int flag, int mode, struct lwp *l)
589 {
590 struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
591 struct tty *tp = sc->sc_tty;
592
593 /* XXX This is for cons.c. */
594 if (!ISSET(tp->t_state, TS_ISOPEN))
595 return (0);
596
597 (*tp->t_linesw->l_close)(tp, flag);
598 ttyclose(tp);
599
600 if (COM_ISALIVE(sc) == 0)
601 return (0);
602
603 if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
604 /*
605 * Although we got a last close, the device may still be in
606 * use; e.g. if this was the dialout node, and there are still
607 * processes waiting for carrier on the non-dialout node.
608 */
609 epcom_shutdown(sc);
610 }
611
612 return (0);
613 }
614
615 int
616 epcomread(dev_t dev, struct uio *uio, int flag)
617 {
618 struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
619 struct tty *tp = sc->sc_tty;
620
621 if (COM_ISALIVE(sc) == 0)
622 return (EIO);
623
624 return ((*tp->t_linesw->l_read)(tp, uio, flag));
625 }
626
627 int
628 epcomwrite(dev_t dev, struct uio *uio, int flag)
629 {
630 struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
631 struct tty *tp = sc->sc_tty;
632
633 if (COM_ISALIVE(sc) == 0)
634 return (EIO);
635
636 return ((*tp->t_linesw->l_write)(tp, uio, flag));
637 }
638
639 int
640 epcompoll(dev_t dev, int events, struct lwp *l)
641 {
642 struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
643 struct tty *tp = sc->sc_tty;
644
645 if (COM_ISALIVE(sc) == 0)
646 return (EIO);
647
648 return ((*tp->t_linesw->l_poll)(tp, events, l));
649 }
650
651 struct tty *
652 epcomtty(dev_t dev)
653 {
654 struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
655 struct tty *tp = sc->sc_tty;
656
657 return (tp);
658 }
659
660 int
661 epcomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
662 {
663 struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
664 struct tty *tp = sc->sc_tty;
665 int error;
666 int s;
667
668 if (COM_ISALIVE(sc) == 0)
669 return (EIO);
670
671 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
672 if (error != EPASSTHROUGH)
673 return (error);
674
675 error = ttioctl(tp, cmd, data, flag, l);
676 if (error != EPASSTHROUGH)
677 return (error);
678
679 error = 0;
680
681 s = splserial();
682
683 switch (cmd) {
684 case TIOCSBRK:
685 epcom_break(sc, 1);
686 break;
687
688 case TIOCCBRK:
689 epcom_break(sc, 0);
690 break;
691
692 case TIOCGFLAGS:
693 *(int *)data = sc->sc_swflags;
694 break;
695
696 case TIOCSFLAGS:
697 error = kauth_authorize_generic(l->l_cred,
698 KAUTH_GENERIC_ISSUSER, &l->l_acflag);
699 if (error)
700 break;
701 sc->sc_swflags = *(int *)data;
702 break;
703
704 default:
705 error = EPASSTHROUGH;
706 break;
707 }
708
709 splx(s);
710
711 return (error);
712 }
713
714 /*
715 * Stop output on a line.
716 */
717 void
718 epcomstop(struct tty *tp, int flag)
719 {
720 struct epcom_softc *sc
721 = device_lookup(&epcom_cd, COMUNIT(tp->t_dev));
722 int s;
723
724 s = splserial();
725 if (ISSET(tp->t_state, TS_BUSY)) {
726 /* Stop transmitting at the next chunk. */
727 sc->sc_tbc = 0;
728 if (!ISSET(tp->t_state, TS_TTSTOP))
729 SET(tp->t_state, TS_FLUSH);
730 }
731 splx(s);
732 }
733
734 static u_int
735 cflag2lcrhi(tcflag_t cflag)
736 {
737 u_int lcrhi;
738
739 switch (cflag & CSIZE) {
740 case CS7:
741 lcrhi = 0x40;
742 break;
743 case CS6:
744 lcrhi = 0x20;
745 break;
746 case CS8:
747 default:
748 lcrhi = 0x60;
749 break;
750 }
751 lcrhi |= (cflag & PARENB) ? LinCtrlHigh_PEN : 0;
752 lcrhi |= (cflag & PARODD) ? 0 : LinCtrlHigh_EPS;
753 lcrhi |= (cflag & CSTOPB) ? LinCtrlHigh_STP2 : 0;
754 lcrhi |= LinCtrlHigh_FEN; /* FIFO always enabled */
755
756 return (lcrhi);
757 }
758
759 static void
760 epcom_iflush(struct epcom_softc *sc)
761 {
762 bus_space_tag_t iot = sc->sc_iot;
763 bus_space_handle_t ioh = sc->sc_ioh;
764 #ifdef DIAGNOSTIC
765 int reg;
766 #endif
767 int timo;
768
769 #ifdef DIAGNOSTIC
770 reg = 0xffff;
771 #endif
772 timo = 50000;
773 /* flush any pending I/O */
774 while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) == 0
775 && --timo)
776 #ifdef DIAGNOSTIC
777 reg =
778 #else
779 (void)
780 #endif
781 bus_space_read_4(iot, ioh, EPCOM_Data);
782 #ifdef DIAGNOSTIC
783 if (!timo)
784 printf("%s: com_iflush timeout %02x\n", sc->sc_dev.dv_xname,
785 reg);
786 #endif
787 }
788
789 static void
790 epcom_set(struct epcom_softc *sc)
791 {
792 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlLow,
793 sc->sc_lcrlo);
794 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlMid,
795 sc->sc_lcrmid);
796 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlHigh,
797 sc->sc_lcrhi);
798 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_Ctrl,
799 sc->sc_ctrl);
800 }
801
802 int
803 epcomcnattach(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t ioh,
804 int ospeed, tcflag_t cflag)
805 {
806 u_int lcrlo, lcrmid, lcrhi, ctrl, pwrcnt;
807 bus_space_handle_t syscon_ioh;
808
809 cn_tab = &epcomcons;
810 cn_init_magic(&epcom_cnm_state);
811 cn_set_magic("\047\001");
812
813 epcomcn_sc.sc_iot = iot;
814 epcomcn_sc.sc_ioh = ioh;
815 epcomcn_sc.sc_hwbase = iobase;
816 epcomcn_sc.sc_ospeed = ospeed;
817 epcomcn_sc.sc_cflag = cflag;
818
819 lcrhi = cflag2lcrhi(cflag);
820 lcrlo = EPCOMSPEED2BRD(ospeed) & 0xff;
821 lcrmid = EPCOMSPEED2BRD(ospeed) >> 8;
822 ctrl = Ctrl_UARTE;
823
824 bus_space_map(iot, EP93XX_APB_HWBASE + EP93XX_APB_SYSCON,
825 EP93XX_APB_SYSCON_SIZE, 0, &syscon_ioh);
826 pwrcnt = bus_space_read_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt);
827 pwrcnt &= ~(PwrCnt_UARTBAUD);
828 bus_space_write_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt, pwrcnt);
829 bus_space_unmap(iot, syscon_ioh, EP93XX_APB_SYSCON_SIZE);
830
831 bus_space_write_4(iot, ioh, EPCOM_LinCtrlLow, lcrlo);
832 bus_space_write_4(iot, ioh, EPCOM_LinCtrlMid, lcrmid);
833 bus_space_write_4(iot, ioh, EPCOM_LinCtrlHigh, lcrhi);
834 bus_space_write_4(iot, ioh, EPCOM_Ctrl, ctrl);
835
836 return (0);
837 }
838
839 void
840 epcomcnprobe(struct consdev *cp)
841 {
842 cp->cn_pri = CN_REMOTE;
843 }
844
845 void
846 epcomcnpollc(dev_t dev, int on)
847 {
848 }
849
850 void
851 epcomcnputc(dev_t dev, int c)
852 {
853 int s;
854 bus_space_tag_t iot = epcomcn_sc.sc_iot;
855 bus_space_handle_t ioh = epcomcn_sc.sc_ioh;
856
857 s = splserial();
858
859 while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) != 0)
860 ;
861
862 bus_space_write_4(iot, ioh, EPCOM_Data, c);
863
864 #ifdef DEBUG
865 if (c == '\r') {
866 while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFE) == 0)
867 ;
868 }
869 #endif
870
871 splx(s);
872 }
873
874 int
875 epcomcngetc(dev_t dev)
876 {
877 int c, sts;
878 int s;
879 bus_space_tag_t iot = epcomcn_sc.sc_iot;
880 bus_space_handle_t ioh = epcomcn_sc.sc_ioh;
881
882 s = splserial();
883
884 while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) != 0)
885 ;
886
887 c = bus_space_read_4(iot, ioh, EPCOM_Data);
888 sts = bus_space_read_4(iot, ioh, EPCOM_RXSts);
889 if (ISSET(sts, RXSts_BE)) c = CNC_BREAK;
890 #ifdef DDB
891 extern int db_active;
892 if (!db_active)
893 #endif
894 {
895 int cn_trapped = 0; /* unused */
896
897 cn_check_magic(dev, c, epcom_cnm_state);
898 }
899 c &= 0xff;
900 splx(s);
901
902 return (c);
903 }
904
905 inline static void
906 epcom_txsoft(struct epcom_softc *sc, struct tty *tp)
907 {
908 CLR(tp->t_state, TS_BUSY);
909 if (ISSET(tp->t_state, TS_FLUSH))
910 CLR(tp->t_state, TS_FLUSH);
911 else
912 ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
913 (*tp->t_linesw->l_start)(tp);
914 }
915
916 inline static void
917 epcom_rxsoft(struct epcom_softc *sc, struct tty *tp)
918 {
919 int (*rint) __P((int, struct tty *)) = tp->t_linesw->l_rint;
920 u_char *get, *end;
921 u_int cc, scc;
922 u_char sts;
923 int code;
924 int s;
925
926 end = sc->sc_ebuf;
927 get = sc->sc_rbget;
928 scc = cc = EPCOM_RING_SIZE - sc->sc_rbavail;
929 #if 0
930 if (cc == EPCOM_RING_SIZE) {
931 sc->sc_floods++;
932 if (sc->sc_errors++ == 0)
933 callout_reset(&sc->sc_diag_callout, 60 * hz,
934 comdiag, sc);
935 }
936 #endif
937 while (cc) {
938 code = get[0];
939 sts = get[1];
940 if (ISSET(sts, RXSts_OE | RXSts_FE | RXSts_PE | RXSts_BE)) {
941 #if 0
942 if (ISSET(lsr, DR_ROR)) {
943 sc->sc_overflows++;
944 if (sc->sc_errors++ == 0)
945 callout_reset(&sc->sc_diag_callout,
946 60 * hz, comdiag, sc);
947 }
948 #endif
949 if (ISSET(sts, (RXSts_FE|RXSts_BE)))
950 SET(code, TTY_FE);
951 if (ISSET(sts, RXSts_PE))
952 SET(code, TTY_PE);
953 }
954 if ((*rint)(code, tp) == -1) {
955 /*
956 * The line discipline's buffer is out of space.
957 */
958 if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
959 /*
960 * We're either not using flow control, or the
961 * line discipline didn't tell us to block for
962 * some reason. Either way, we have no way to
963 * know when there's more space available, so
964 * just drop the rest of the data.
965 */
966 get += cc << 1;
967 if (get >= end)
968 get -= EPCOM_RING_SIZE << 1;
969 cc = 0;
970 } else {
971 /*
972 * Don't schedule any more receive processing
973 * until the line discipline tells us there's
974 * space available (through comhwiflow()).
975 * Leave the rest of the data in the input
976 * buffer.
977 */
978 SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
979 }
980 break;
981 }
982 get += 2;
983 if (get >= end)
984 get = sc->sc_rbuf;
985 cc--;
986 }
987
988 if (cc != scc) {
989 sc->sc_rbget = get;
990 s = splserial();
991
992 cc = sc->sc_rbavail += scc - cc;
993 /* Buffers should be ok again, release possible block. */
994 if (cc >= 1) {
995 if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
996 CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
997 SET(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE));
998 epcom_set(sc);
999 }
1000 if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
1001 CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
1002 #if 0
1003 com_hwiflow(sc);
1004 #endif
1005 }
1006 }
1007 splx(s);
1008 }
1009 }
1010
1011 static void
1012 epcomsoft(void* arg)
1013 {
1014 struct epcom_softc *sc = arg;
1015
1016 if (COM_ISALIVE(sc) == 0)
1017 return;
1018
1019 if (sc->sc_rx_ready) {
1020 sc->sc_rx_ready = 0;
1021 epcom_rxsoft(sc, sc->sc_tty);
1022 }
1023 if (sc->sc_tx_done) {
1024 sc->sc_tx_done = 0;
1025 epcom_txsoft(sc, sc->sc_tty);
1026 }
1027 }
1028
1029 int
1030 epcomintr(void* arg)
1031 {
1032 struct epcom_softc *sc = arg;
1033 bus_space_tag_t iot = sc->sc_iot;
1034 bus_space_handle_t ioh = sc->sc_ioh;
1035 u_char *put, *end;
1036 u_int cc;
1037 u_int flagr;
1038 u_int intr;
1039 u_int32_t c, csts;
1040
1041 intr = bus_space_read_4(iot, ioh, EPCOM_IntIDIntClr);
1042
1043 if (COM_ISALIVE(sc) == 0)
1044 panic("intr on disabled epcom");
1045
1046 flagr = bus_space_read_4(iot, ioh, EPCOM_Flag);
1047
1048 end = sc->sc_ebuf;
1049 put = sc->sc_rbput;
1050 cc = sc->sc_rbavail;
1051
1052 if (!(ISSET(flagr, Flag_RXFE))) {
1053 if (!ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1054 while (cc > 0) {
1055 if (ISSET(flagr, Flag_RXFE))
1056 break;
1057 c = bus_space_read_4(iot, ioh, EPCOM_Data);
1058 csts = bus_space_read_4(iot, ioh, EPCOM_RXSts);
1059 if (ISSET(csts, RXSts_BE)) {
1060 int cn_trapped = 0;
1061
1062 cn_check_magic(sc->sc_tty->t_dev,
1063 CNC_BREAK, epcom_cnm_state);
1064 if (cn_trapped)
1065 goto next;
1066 #if defined(KGDB) && !defined(DDB)
1067 if (ISSET(sc->sc_hwflags, COM_HW_KGDB)){
1068 kgdb_connect(1);
1069 goto next;
1070 }
1071 #endif
1072 } else {
1073 int cn_trapped = 0;
1074
1075 cn_check_magic(sc->sc_tty->t_dev,
1076 (c & 0xff), epcom_cnm_state);
1077 if (cn_trapped)
1078 goto next;
1079 }
1080
1081
1082 put[0] = c & 0xff;
1083 put[1] = csts & 0xf;
1084 put += 2;
1085 if (put >= end)
1086 put = sc->sc_rbuf;
1087 cc--;
1088 next:
1089 flagr = bus_space_read_4(iot, ioh, EPCOM_Flag);
1090 }
1091
1092 /*
1093 * Current string of incoming characters ended because
1094 * no more data was available or we ran out of space.
1095 * Schedule a receive event if any data was received.
1096 * If we're out of space, turn off receive interrupts.
1097 */
1098 sc->sc_rbput = put;
1099 sc->sc_rbavail = cc;
1100 if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
1101 sc->sc_rx_ready = 1;
1102
1103 /*
1104 * See if we are in danger of overflowing a buffer. If
1105 * so, use hardware flow control to ease the pressure.
1106 */
1107
1108 /* but epcom cannot. X-( */
1109
1110 /*
1111 * If we're out of space, disable receive interrupts
1112 * until the queue has drained a bit.
1113 */
1114 if (!cc) {
1115 SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1116 CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE));
1117 epcom_set(sc);
1118 }
1119 } else {
1120 #ifdef DIAGNOSTIC
1121 panic("epcomintr: we shouldn't reach here");
1122 #endif
1123 CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE));
1124 epcom_set(sc);
1125 }
1126 }
1127
1128 /*
1129 * Done handling any receive interrupts. See if data can be
1130 * transmitted as well. Schedule tx done event if no data left
1131 * and tty was marked busy.
1132 */
1133
1134 if (!ISSET(flagr, Flag_TXFF) && sc->sc_tbc > 0) {
1135 /* Output the next chunk of the contiguous buffer, if any. */
1136 epcom_filltx(sc);
1137 } else {
1138 /* Disable transmit completion interrupts if necessary. */
1139 if (ISSET(sc->sc_ctrl, Ctrl_TIE)) {
1140 CLR(sc->sc_ctrl, Ctrl_TIE);
1141 epcom_set(sc);
1142 }
1143 if (sc->sc_tx_busy) {
1144 sc->sc_tx_busy = 0;
1145 sc->sc_tx_done = 1;
1146 }
1147 }
1148
1149 /* Wake up the poller. */
1150 softintr_schedule(sc->sc_si);
1151
1152 #if 0 /* XXX: broken */
1153 #if NRND > 0 && defined(RND_COM)
1154 rnd_add_uint32(&sc->rnd_source, intr ^ flagr);
1155 #endif
1156 #endif
1157 return (1);
1158 }
1159