1 /* $NetBSD: sscom.c,v 1.31 2009/12/06 21:35:05 dyoung Exp $ */
4 * Copyright (c) 2002, 2003 Fujitsu Component Limited
5 * Copyright (c) 2002, 2003 Genetec Corporation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of The Fujitsu Component Limited nor the name of
17 * Genetec corporation may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
21 * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
25 * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
37 * All rights reserved.
39 * This code is derived from software contributed to The NetBSD Foundation
40 * by Charles M. Hannum.
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
51 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
52 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
65 * Copyright (c) 1991 The Regents of the University of California.
66 * All rights reserved.
68 * Redistribution and use in source and binary forms, with or without
69 * modification, are permitted provided that the following conditions
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.
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
92 * @(#)com.c 7.5 (Berkeley) 5/16/91
96 * Support integrated UARTs of Samsung S3C2800/2400X/2410X
97 * Derived from sys/dev/ic/com.c
100 #include <sys/cdefs.h>
101 __KERNEL_RCSID(0, "$NetBSD: sscom.c,v 1.31 2009/12/06 21:35:05 dyoung Exp $");
103 #include "opt_sscom.h"
105 #include "opt_kgdb.h"
106 #include "opt_multiprocessor.h"
107 #include "opt_lockdebug.h"
110 #if NRND > 0 && defined(RND_COM)
115 * Override cnmagic(9) macro before including <sys/systm.h>.
116 * We need to know if cn_check_magic triggered debugger, so set a flag.
117 * Callers of cn_check_magic must declare int cn_trapped = 0;
118 * XXX: this is *ugly*!
122 console_debugger(); \
124 } while (/* CONSTCOND */ 0)
126 #include <sys/param.h>
127 #include <sys/systm.h>
128 #include <sys/ioctl.h>
129 #include <sys/select.h>
131 #include <sys/proc.h>
132 #include <sys/conf.h>
133 #include <sys/file.h>
135 #include <sys/kernel.h>
136 #include <sys/syslog.h>
137 #include <sys/types.h>
138 #include <sys/device.h>
139 #include <sys/malloc.h>
140 #include <sys/timepps.h>
141 #include <sys/vnode.h>
142 #include <sys/kauth.h>
143 #include <sys/intr.h>
146 #include <arm/s3c2xx0/s3c2xx0reg.h>
147 #include <arm/s3c2xx0/s3c2xx0var.h>
148 #if defined(SSCOM_S3C2410) || defined(SSCOM_S3C2400)
149 #include <arm/s3c2xx0/s3c24x0reg.h>
150 #elif defined(SSCOM_S3C2800)
151 #include <arm/s3c2xx0/s3c2800reg.h>
153 #include <arm/s3c2xx0/sscom_var.h>
154 #include <dev/cons.h>
156 dev_type_open(sscomopen
);
157 dev_type_close(sscomclose
);
158 dev_type_read(sscomread
);
159 dev_type_write(sscomwrite
);
160 dev_type_ioctl(sscomioctl
);
161 dev_type_stop(sscomstop
);
162 dev_type_tty(sscomtty
);
163 dev_type_poll(sscompoll
);
165 int sscomcngetc (dev_t
);
166 void sscomcnputc (dev_t
, int);
167 void sscomcnpollc (dev_t
, int);
169 #define integrate static inline
170 void sscomsoft (void *);
172 integrate
void sscom_rxsoft (struct sscom_softc
*, struct tty
*);
173 integrate
void sscom_txsoft (struct sscom_softc
*, struct tty
*);
174 integrate
void sscom_stsoft (struct sscom_softc
*, struct tty
*);
175 integrate
void sscom_schedrx (struct sscom_softc
*);
176 static void sscom_modem(struct sscom_softc
*, int);
177 static void sscom_break(struct sscom_softc
*, int);
178 static void sscom_iflush(struct sscom_softc
*);
179 static void sscom_hwiflow(struct sscom_softc
*);
180 static void sscom_loadchannelregs(struct sscom_softc
*);
181 static void tiocm_to_sscom(struct sscom_softc
*, u_long
, int);
182 static int sscom_to_tiocm(struct sscom_softc
*);
183 static void tiocm_to_sscom(struct sscom_softc
*, u_long
, int);
184 static int sscom_to_tiocm(struct sscom_softc
*);
185 static void sscom_iflush(struct sscom_softc
*);
187 static int sscomhwiflow(struct tty
*tp
, int block
);
188 static int sscom_init(bus_space_tag_t
, const struct sscom_uart_info
*,
189 int, int, tcflag_t
, bus_space_handle_t
*);
191 extern struct cfdriver sscom_cd
;
193 const struct cdevsw sscom_cdevsw
= {
194 sscomopen
, sscomclose
, sscomread
, sscomwrite
, sscomioctl
,
195 sscomstop
, sscomtty
, sscompoll
, nommap
, ttykqfilter
, D_TTY
199 * Make this an option variable one can patch.
200 * But be warned: this must be a power of 2!
202 u_int sscom_rbuf_size
= SSCOM_RING_SIZE
;
204 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
205 u_int sscom_rbuf_hiwat
= (SSCOM_RING_SIZE
* 1) / 4;
206 u_int sscom_rbuf_lowat
= (SSCOM_RING_SIZE
* 3) / 4;
208 static int sscomconsunit
= -1;
209 static bus_space_tag_t sscomconstag
;
210 static bus_space_handle_t sscomconsioh
;
211 static int sscomconsattached
;
212 static int sscomconsrate
;
213 static tcflag_t sscomconscflag
;
214 static struct cnm_state sscom_cnm_state
;
217 #include <sys/kgdb.h>
219 static int sscom_kgdb_unit
= -1;
220 static bus_space_tag_t sscom_kgdb_iot
;
221 static bus_space_handle_t sscom_kgdb_ioh
;
222 static int sscom_kgdb_attached
;
224 int sscom_kgdb_getc (void *);
225 void sscom_kgdb_putc (void *, int);
228 #define SSCOMUNIT_MASK 0x7f
229 #define SSCOMDIALOUT_MASK 0x80
231 #define SSCOMUNIT(x) (minor(x) & SSCOMUNIT_MASK)
232 #define SSCOMDIALOUT(x) (minor(x) & SSCOMDIALOUT_MASK)
235 #define SSCOM_ISALIVE(sc) ((sc)->enabled != 0 && \
236 device_is_active(&(sc)->sc_dev))
238 #define SSCOM_ISALIVE(sc) device_is_active(&(sc)->sc_dev)
241 #define BR BUS_SPACE_BARRIER_READ
242 #define BW BUS_SPACE_BARRIER_WRITE
243 #define SSCOM_BARRIER(t, h, f) /* no-op */
245 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(SSCOM_MPLOCK)
247 #define SSCOM_LOCK(sc) simple_lock(&(sc)->sc_lock)
248 #define SSCOM_UNLOCK(sc) simple_unlock(&(sc)->sc_lock)
252 #define SSCOM_LOCK(sc)
253 #define SSCOM_UNLOCK(sc)
257 #ifndef SSCOM_TOLERANCE
258 #define SSCOM_TOLERANCE 30 /* XXX: baud rate tolerance, in 0.1% units */
262 #define UCON_RXINT_MASK \
263 (UCON_RXMODE_MASK|UCON_ERRINT|UCON_TOINT|UCON_RXINT_TYPE)
264 #define UCON_RXINT_ENABLE \
265 (UCON_RXMODE_INT|UCON_ERRINT|UCON_TOINT|UCON_RXINT_TYPE_LEVEL)
266 #define UCON_TXINT_MASK (UCON_TXMODE_MASK|UCON_TXINT_TYPE)
267 #define UCON_TXINT_ENABLE (UCON_TXMODE_INT|UCON_TXINT_TYPE_LEVEL)
269 /* we don't want tx interrupt on debug port, but it is needed to
270 have transmitter active */
271 #define UCON_DEBUGPORT (UCON_RXINT_ENABLE|UCON_TXINT_ENABLE)
275 __sscom_output_chunk(struct sscom_softc
*sc
, int ufstat
)
278 bus_space_tag_t iot
= sc
->sc_iot
;
279 bus_space_handle_t ioh
= sc
->sc_ioh
;
282 space
= 16 - ((ufstat
& UFSTAT_TXCOUNT
) >> UFSTAT_TXCOUNT_SHIFT
);
288 bus_space_write_multi_1(iot
, ioh
, SSCOM_UTXH
, sc
->sc_tba
, n
);
295 sscom_output_chunk(struct sscom_softc
*sc
)
297 int ufstat
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, SSCOM_UFSTAT
);
299 if (!(ufstat
& UFSTAT_TXFULL
))
300 __sscom_output_chunk(sc
, ufstat
);
304 sscomspeed(long speed
, long frequency
)
306 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
312 x
= divrnd(frequency
/ 16, speed
);
315 err
= divrnd(((quad_t
)frequency
) * 1000 / 16, speed
* x
) - 1000;
318 if (err
> SSCOM_TOLERANCE
)
325 void sscomstatus (struct sscom_softc
*, const char *);
331 sscomstatus(struct sscom_softc
*sc
, const char *str
)
333 struct tty
*tp
= sc
->sc_tty
;
334 int umstat
= bus_space_read_1(sc
->sc_iot
, sc
->sc_iot
, SSCOM_UMSTAT
);
335 int umcon
= bus_space_read_1(sc
->sc_iot
, sc
->sc_iot
, SSCOM_UMCON
);
337 printf("%s: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n",
338 sc
->sc_dev
.dv_xname
, str
,
339 ISSET(tp
->t_cflag
, CLOCAL
) ? "+" : "-",
341 ISSET(tp
->t_state
, TS_CARR_ON
) ? "+" : "-",
343 sc
->sc_tx_stopped
? "+" : "-");
345 printf("%s: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n",
346 sc
->sc_dev
.dv_xname
, str
,
347 ISSET(tp
->t_cflag
, CRTSCTS
) ? "+" : "-",
348 ISSET(umstat
, UMSTAT_CTS
) ? "+" : "-",
349 ISSET(tp
->t_state
, TS_TTSTOP
) ? "+" : "-",
350 ISSET(umcon
, UMCON_RTS
) ? "+" : "-",
354 #define sscom_debug 0
358 sscom_enable_debugport(struct sscom_softc
*sc
)
362 /* Turn on line break interrupt, set carrier. */
365 sc
->sc_ucon
= UCON_DEBUGPORT
;
366 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, SSCOM_UCON
, sc
->sc_ucon
);
367 sc
->sc_umcon
= UMCON_RTS
|UMCON_DTR
;
368 sc
->set_modem_control(sc
);
369 sscom_enable_rxint(sc
);
370 sscom_disable_txint(sc
);
376 sscom_set_modem_control(struct sscom_softc
*sc
)
379 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
,
380 SSCOM_UMCON
, sc
->sc_umcon
& UMCON_HW_MASK
);
385 sscom_read_modem_status(struct sscom_softc
*sc
)
389 msts
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, SSCOM_UMSTAT
);
391 /* DCD and DSR are always on */
392 return (msts
& UMSTAT_CTS
) | MSTS_DCD
| MSTS_DSR
;
396 sscom_attach_subr(struct sscom_softc
*sc
)
398 int unit
= sc
->sc_unit
;
399 bus_space_tag_t iot
= sc
->sc_iot
;
400 bus_space_handle_t ioh
= sc
->sc_ioh
;
403 callout_init(&sc
->sc_diag_callout
, 0);
404 #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(SSCOM_MPLOCK)
405 simple_lock_init(&sc
->sc_lock
);
408 sc
->sc_ucon
= UCON_RXINT_ENABLE
|UCON_TXINT_ENABLE
;
411 * set default for modem control hook
413 if (sc
->set_modem_control
== NULL
)
414 sc
->set_modem_control
= sscom_set_modem_control
;
415 if (sc
->read_modem_status
== NULL
)
416 sc
->read_modem_status
= sscom_read_modem_status
;
418 /* Disable interrupts before configuring the device. */
419 sscom_disable_txrxint(sc
);
423 * Allow kgdb to "take over" this port. If this is
424 * the kgdb device, it has exclusive use.
426 if (unit
== sscom_kgdb_unit
) {
427 SET(sc
->sc_hwflags
, SSCOM_HW_KGDB
);
428 sc
->sc_ucon
= UCON_DEBUGPORT
;
432 if (unit
== sscomconsunit
) {
433 sscomconsattached
= 1;
438 /* Make sure the console is always "hardwired". */
439 delay(1000); /* XXX: wait for output to finish */
440 SET(sc
->sc_hwflags
, SSCOM_HW_CONSOLE
);
441 SET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
);
443 sc
->sc_ucon
= UCON_DEBUGPORT
;
446 bus_space_write_1(iot
, ioh
, SSCOM_UFCON
,
447 UFCON_TXTRIGGER_8
|UFCON_RXTRIGGER_8
|UFCON_FIFO_ENABLE
|
448 UFCON_TXFIFO_RESET
|UFCON_RXFIFO_RESET
);
450 bus_space_write_1(iot
, ioh
, SSCOM_UCON
, sc
->sc_ucon
);
453 if (ISSET(sc
->sc_hwflags
, SSCOM_HW_KGDB
)) {
454 sscom_kgdb_attached
= 1;
455 printf("%s: kgdb\n", sc
->sc_dev
.dv_xname
);
456 sscom_enable_debugport(sc
);
464 tp
->t_oproc
= sscomstart
;
465 tp
->t_param
= sscomparam
;
466 tp
->t_hwiflow
= sscomhwiflow
;
469 sc
->sc_rbuf
= malloc(sscom_rbuf_size
<< 1, M_DEVBUF
, M_NOWAIT
);
470 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
471 sc
->sc_rbavail
= sscom_rbuf_size
;
472 if (sc
->sc_rbuf
== NULL
) {
473 printf("%s: unable to allocate ring buffer\n",
474 sc
->sc_dev
.dv_xname
);
477 sc
->sc_ebuf
= sc
->sc_rbuf
+ (sscom_rbuf_size
<< 1);
481 if (ISSET(sc
->sc_hwflags
, SSCOM_HW_CONSOLE
)) {
484 /* locate the major number */
485 maj
= cdevsw_lookup_major(&sscom_cdevsw
);
487 cn_tab
->cn_dev
= makedev(maj
, device_unit(&sc
->sc_dev
));
489 printf("%s: console (major=%d)\n", sc
->sc_dev
.dv_xname
, maj
);
493 sc
->sc_si
= softint_establish(SOFTINT_SERIAL
, sscomsoft
, sc
);
495 #if NRND > 0 && defined(RND_COM)
496 rnd_attach_source(&sc
->rnd_source
, sc
->sc_dev
.dv_xname
,
500 /* if there are no enable/disable functions, assume the device
503 if (ISSET(sc
->sc_hwflags
, SSCOM_HW_CONSOLE
))
504 sscom_enable_debugport(sc
);
506 sscom_disable_txrxint(sc
);
508 SET(sc
->sc_hwflags
, SSCOM_HW_DEV_OK
);
512 sscom_detach(device_t self
, int flags
)
514 struct sscom_softc
*sc
= device_private(self
);
516 if (sc
->sc_hwflags
& (SSCOM_HW_CONSOLE
|SSCOM_HW_KGDB
))
523 sscom_activate(device_t self
, enum devact act
)
526 struct sscom_softc
*sc
= device_private(self
);
530 case DVACT_DEACTIVATE
:
541 sscom_shutdown(struct sscom_softc
*sc
)
544 struct tty
*tp
= sc
->sc_tty
;
550 /* If we were asserting flow control, then deassert it. */
551 SET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
554 /* Clear any break condition set with TIOCSBRK. */
558 * Hang up if necessary. Wait a bit, so the other side has time to
559 * notice even if we immediately open the port again.
560 * Avoid tsleeping above splhigh().
562 if (ISSET(tp
->t_cflag
, HUPCL
)) {
566 /* XXX tsleep will only timeout */
567 (void) tsleep(sc
, TTIPRI
, ttclos
, hz
);
572 if (ISSET(sc
->sc_hwflags
, SSCOM_HW_CONSOLE
))
573 /* interrupt on break */
574 sc
->sc_ucon
= UCON_DEBUGPORT
;
577 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, SSCOM_UCON
, sc
->sc_ucon
);
581 panic("sscom_shutdown: not enabled?");
590 sscomopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
592 struct sscom_softc
*sc
;
597 sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(dev
));
598 if (sc
== NULL
|| !ISSET(sc
->sc_hwflags
, SSCOM_HW_DEV_OK
) ||
602 if (!device_is_active(&sc
->sc_dev
))
607 * If this is the kgdb port, no other use is permitted.
609 if (ISSET(sc
->sc_hwflags
, SSCOM_HW_KGDB
))
615 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
621 * Do the following iff this is a first open.
623 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
631 /* Turn on interrupts. */
632 sscom_enable_txrxint(sc
);
634 /* Fetch the current modem control status, needed later. */
635 sc
->sc_msts
= sc
->read_modem_status(sc
);
638 /* Clear PPS capture state on first open. */
640 sc
->ppsparam
.mode
= 0;
647 * Initialize the termios status to the defaults. Add in the
648 * sticky bits from TIOCSFLAGS.
651 if (ISSET(sc
->sc_hwflags
, SSCOM_HW_CONSOLE
)) {
652 t
.c_ospeed
= sscomconsrate
;
653 t
.c_cflag
= sscomconscflag
;
655 t
.c_ospeed
= TTYDEF_SPEED
;
656 t
.c_cflag
= TTYDEF_CFLAG
;
658 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CLOCAL
))
659 SET(t
.c_cflag
, CLOCAL
);
660 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
661 SET(t
.c_cflag
, CRTSCTS
);
662 if (ISSET(sc
->sc_swflags
, TIOCFLAG_MDMBUF
))
663 SET(t
.c_cflag
, MDMBUF
);
664 /* Make sure sscomparam() will do something. */
666 (void) sscomparam(tp
, &t
);
667 tp
->t_iflag
= TTYDEF_IFLAG
;
668 tp
->t_oflag
= TTYDEF_OFLAG
;
669 tp
->t_lflag
= TTYDEF_LFLAG
;
677 * Turn on DTR. We must always do this, even if carrier is not
678 * present, because otherwise we'd have to use TIOCSDTR
679 * immediately after setting CLOCAL, which applications do not
680 * expect. We always assert DTR while the device is open
681 * unless explicitly requested to deassert it.
685 /* Clear the input ring, and unblock. */
686 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
687 sc
->sc_rbavail
= sscom_rbuf_size
;
689 CLR(sc
->sc_rx_flags
, RX_ANY_BLOCK
);
693 sscomstatus(sc
, "sscomopen ");
701 error
= ttyopen(tp
, SSCOMDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
705 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
712 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
714 * We failed to open the device, and nobody else had it opened.
715 * Clean up the state as appropriate.
724 sscomclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
726 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(dev
));
727 struct tty
*tp
= sc
->sc_tty
;
729 /* XXX This is for cons.c. */
730 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
733 (*tp
->t_linesw
->l_close
)(tp
, flag
);
736 if (SSCOM_ISALIVE(sc
) == 0)
739 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
741 * Although we got a last close, the device may still be in
742 * use; e.g. if this was the dialout node, and there are still
743 * processes waiting for carrier on the non-dialout node.
752 sscomread(dev_t dev
, struct uio
*uio
, int flag
)
754 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(dev
));
755 struct tty
*tp
= sc
->sc_tty
;
757 if (SSCOM_ISALIVE(sc
) == 0)
760 return (*tp
->t_linesw
->l_read
)(tp
, uio
, flag
);
764 sscomwrite(dev_t dev
, struct uio
*uio
, int flag
)
766 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(dev
));
767 struct tty
*tp
= sc
->sc_tty
;
769 if (SSCOM_ISALIVE(sc
) == 0)
772 return (*tp
->t_linesw
->l_write
)(tp
, uio
, flag
);
776 sscompoll(dev_t dev
, int events
, struct lwp
*l
)
778 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(dev
));
779 struct tty
*tp
= sc
->sc_tty
;
781 if (SSCOM_ISALIVE(sc
) == 0)
784 return (*tp
->t_linesw
->l_poll
)(tp
, events
, l
);
790 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(dev
));
791 struct tty
*tp
= sc
->sc_tty
;
797 sscomioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
799 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(dev
));
800 struct tty
*tp
= sc
->sc_tty
;
804 if (SSCOM_ISALIVE(sc
) == 0)
807 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
808 if (error
!= EPASSTHROUGH
)
811 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
812 if (error
!= EPASSTHROUGH
)
838 *(int *)data
= sc
->sc_swflags
;
842 error
= kauth_authorize_device_tty(l
->l_cred
,
843 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
846 sc
->sc_swflags
= *(int *)data
;
852 tiocm_to_sscom(sc
, cmd
, *(int *)data
);
856 *(int *)data
= sscom_to_tiocm(sc
);
860 error
= EPASSTHROUGH
;
868 sscomstatus(sc
, "sscomioctl ");
874 sscom_schedrx(struct sscom_softc
*sc
)
879 /* Wake up the poller. */
880 softint_schedule(sc
->sc_si
);
884 sscom_break(struct sscom_softc
*sc
, int onoff
)
888 SET(sc
->sc_ucon
, UCON_SBREAK
);
890 CLR(sc
->sc_ucon
, UCON_SBREAK
);
892 if (!sc
->sc_heldchange
) {
893 if (sc
->sc_tx_busy
) {
894 sc
->sc_heldtbc
= sc
->sc_tbc
;
896 sc
->sc_heldchange
= 1;
898 sscom_loadchannelregs(sc
);
903 sscom_modem(struct sscom_softc
*sc
, int onoff
)
906 SET(sc
->sc_umcon
, UMCON_DTR
);
908 CLR(sc
->sc_umcon
, UMCON_DTR
);
910 if (!sc
->sc_heldchange
) {
911 if (sc
->sc_tx_busy
) {
912 sc
->sc_heldtbc
= sc
->sc_tbc
;
914 sc
->sc_heldchange
= 1;
916 sscom_loadchannelregs(sc
);
921 tiocm_to_sscom(struct sscom_softc
*sc
, u_long how
, int ttybits
)
926 if (ISSET(ttybits
, TIOCM_DTR
))
927 sscombits
= UMCON_DTR
;
928 if (ISSET(ttybits
, TIOCM_RTS
))
929 SET(sscombits
, UMCON_RTS
);
933 CLR(sc
->sc_umcon
, sscombits
);
937 SET(sc
->sc_umcon
, sscombits
);
941 CLR(sc
->sc_umcon
, UMCON_DTR
);
942 SET(sc
->sc_umcon
, sscombits
);
946 if (!sc
->sc_heldchange
) {
947 if (sc
->sc_tx_busy
) {
948 sc
->sc_heldtbc
= sc
->sc_tbc
;
950 sc
->sc_heldchange
= 1;
952 sscom_loadchannelregs(sc
);
957 sscom_to_tiocm(struct sscom_softc
*sc
)
962 sscombits
= sc
->sc_umcon
;
964 if (ISSET(sscombits
, MCR_DTR
))
965 SET(ttybits
, TIOCM_DTR
);
967 if (ISSET(sscombits
, UMCON_RTS
))
968 SET(ttybits
, TIOCM_RTS
);
970 sscombits
= sc
->sc_msts
;
971 if (ISSET(sscombits
, MSTS_DCD
))
972 SET(ttybits
, TIOCM_CD
);
973 if (ISSET(sscombits
, MSTS_DSR
))
974 SET(ttybits
, TIOCM_DSR
);
975 if (ISSET(sscombits
, MSTS_CTS
))
976 SET(ttybits
, TIOCM_CTS
);
978 if (sc
->sc_ucon
!= 0)
979 SET(ttybits
, TIOCM_LE
);
985 cflag2lcr(tcflag_t cflag
)
987 u_char lcr
= ULCON_PARITY_NONE
;
989 switch (cflag
& (PARENB
|PARODD
)) {
990 case PARENB
|PARODD
: lcr
= ULCON_PARITY_ODD
; break;
991 case PARENB
: lcr
= ULCON_PARITY_EVEN
;
994 switch (ISSET(cflag
, CSIZE
)) {
996 SET(lcr
, ULCON_LENGTH_5
);
999 SET(lcr
, ULCON_LENGTH_6
);
1002 SET(lcr
, ULCON_LENGTH_7
);
1005 SET(lcr
, ULCON_LENGTH_8
);
1008 if (ISSET(cflag
, CSTOPB
))
1009 SET(lcr
, ULCON_STOP
);
1015 sscomparam(struct tty
*tp
, struct termios
*t
)
1017 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(tp
->t_dev
));
1022 if (SSCOM_ISALIVE(sc
) == 0)
1025 ospeed
= sscomspeed(t
->c_ospeed
, sc
->sc_frequency
);
1027 /* Check requested parameters. */
1030 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
1034 * For the console, always force CLOCAL and !HUPCL, so that the port
1037 if (ISSET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
1038 ISSET(sc
->sc_hwflags
, SSCOM_HW_CONSOLE
)) {
1039 SET(t
->c_cflag
, CLOCAL
);
1040 CLR(t
->c_cflag
, HUPCL
);
1044 * If there were no changes, don't do anything. This avoids dropping
1045 * input and improves performance when all we did was frob things like
1048 if (tp
->t_ospeed
== t
->c_ospeed
&&
1049 tp
->t_cflag
== t
->c_cflag
)
1052 lcr
= cflag2lcr(t
->c_cflag
);
1060 * If we're not in a mode that assumes a connection is present, then
1061 * ignore carrier changes.
1063 if (ISSET(t
->c_cflag
, CLOCAL
| MDMBUF
))
1066 sc
->sc_msr_dcd
= MSTS_DCD
;
1069 * Set the flow control pins depending on the current flow control
1072 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
1073 sc
->sc_mcr_dtr
= UMCON_DTR
;
1074 sc
->sc_mcr_rts
= UMCON_RTS
;
1075 sc
->sc_msr_cts
= MSTS_CTS
;
1077 else if (ISSET(t
->c_cflag
, MDMBUF
)) {
1079 * For DTR/DCD flow control, make sure we don't toggle DTR for
1080 * carrier detection.
1083 sc
->sc_mcr_rts
= UMCON_DTR
;
1084 sc
->sc_msr_cts
= MSTS_DCD
;
1088 * If no flow control, then always set RTS. This will make
1089 * the other side happy if it mistakenly thinks we're doing
1090 * RTS/CTS flow control.
1092 sc
->sc_mcr_dtr
= UMCON_DTR
| UMCON_RTS
;
1095 if (ISSET(sc
->sc_umcon
, UMCON_DTR
))
1096 SET(sc
->sc_umcon
, UMCON_RTS
);
1098 CLR(sc
->sc_umcon
, UMCON_RTS
);
1100 sc
->sc_msr_mask
= sc
->sc_msr_cts
| sc
->sc_msr_dcd
;
1103 CLR(sc
->sc_umcon
, sc
->sc_mcr_dtr
);
1105 SET(sc
->sc_umcon
, sc
->sc_mcr_dtr
);
1107 sc
->sc_ubrdiv
= ospeed
;
1109 /* And copy to tty. */
1111 tp
->t_ospeed
= t
->c_ospeed
;
1112 tp
->t_cflag
= t
->c_cflag
;
1114 if (!sc
->sc_heldchange
) {
1115 if (sc
->sc_tx_busy
) {
1116 sc
->sc_heldtbc
= sc
->sc_tbc
;
1118 sc
->sc_heldchange
= 1;
1120 sscom_loadchannelregs(sc
);
1123 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
1124 /* Disable the high water mark. */
1127 if (ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
)) {
1128 CLR(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1131 if (ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
)) {
1132 CLR(sc
->sc_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
);
1136 sc
->sc_r_hiwat
= sscom_rbuf_hiwat
;
1137 sc
->sc_r_lowat
= sscom_rbuf_lowat
;
1144 * Update the tty layer's idea of the carrier bit, in case we changed
1145 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1148 (void) (*tp
->t_linesw
->l_modem
)(tp
, ISSET(sc
->sc_msts
, MSTS_DCD
));
1151 sscomstatus(sc
, "sscomparam ");
1153 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
1154 if (sc
->sc_tx_stopped
) {
1155 sc
->sc_tx_stopped
= 0;
1164 sscom_iflush(struct sscom_softc
*sc
)
1166 bus_space_tag_t iot
= sc
->sc_iot
;
1167 bus_space_handle_t ioh
= sc
->sc_ioh
;
1172 /* flush any pending I/O */
1173 while ( sscom_rxrdy(iot
, ioh
) && --timo
)
1174 (void)sscom_getc(iot
,ioh
);
1177 printf("%s: sscom_iflush timeout\n", sc
->sc_dev
.dv_xname
);
1182 sscom_loadchannelregs(struct sscom_softc
*sc
)
1184 bus_space_tag_t iot
= sc
->sc_iot
;
1185 bus_space_handle_t ioh
= sc
->sc_ioh
;
1187 /* XXXXX necessary? */
1190 bus_space_write_2(iot
, ioh
, SSCOM_UCON
, 0);
1193 if (ISSET(sc
->sc_hwflags
, COM_HW_FLOW
)) {
1194 bus_space_write_1(iot
, ioh
, com_lcr
, LCR_EERS
);
1195 bus_space_write_1(iot
, ioh
, com_efr
, sc
->sc_efr
);
1199 bus_space_write_2(iot
, ioh
, SSCOM_UBRDIV
, sc
->sc_ubrdiv
);
1200 bus_space_write_1(iot
, ioh
, SSCOM_ULCON
, sc
->sc_ulcon
);
1201 sc
->set_modem_control(sc
);
1202 bus_space_write_2(iot
, ioh
, SSCOM_UCON
, sc
->sc_ucon
);
1206 sscomhwiflow(struct tty
*tp
, int block
)
1208 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(tp
->t_dev
));
1211 if (SSCOM_ISALIVE(sc
) == 0)
1214 if (sc
->sc_mcr_rts
== 0)
1221 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1222 SET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
);
1226 if (ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
)) {
1227 CLR(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1230 if (ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1231 CLR(sc
->sc_rx_flags
, RX_TTY_BLOCKED
);
1242 * (un)block input via hw flowcontrol
1245 sscom_hwiflow(struct sscom_softc
*sc
)
1247 if (sc
->sc_mcr_rts
== 0)
1250 if (ISSET(sc
->sc_rx_flags
, RX_ANY_BLOCK
)) {
1251 CLR(sc
->sc_umcon
, sc
->sc_mcr_rts
);
1252 CLR(sc
->sc_mcr_active
, sc
->sc_mcr_rts
);
1254 SET(sc
->sc_umcon
, sc
->sc_mcr_rts
);
1255 SET(sc
->sc_mcr_active
, sc
->sc_mcr_rts
);
1257 sc
->set_modem_control(sc
);
1262 sscomstart(struct tty
*tp
)
1264 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(tp
->t_dev
));
1267 if (SSCOM_ISALIVE(sc
) == 0)
1271 if (ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
))
1273 if (sc
->sc_tx_stopped
)
1278 /* Grab the first contiguous region of buffer space. */
1283 tba
= tp
->t_outq
.c_cf
;
1284 tbc
= ndqb(&tp
->t_outq
, 0);
1293 SET(tp
->t_state
, TS_BUSY
);
1296 /* Output the first chunk of the contiguous buffer. */
1297 sscom_output_chunk(sc
);
1299 /* Enable transmit completion interrupts if necessary. */
1300 if ((sc
->sc_hwflags
& SSCOM_HW_TXINT
) == 0)
1301 sscom_enable_txint(sc
);
1310 * Stop output on a line.
1313 sscomstop(struct tty
*tp
, int flag
)
1315 struct sscom_softc
*sc
= device_lookup_private(&sscom_cd
, SSCOMUNIT(tp
->t_dev
));
1320 if (ISSET(tp
->t_state
, TS_BUSY
)) {
1321 /* Stop transmitting at the next chunk. */
1324 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
1325 SET(tp
->t_state
, TS_FLUSH
);
1332 sscomdiag(void *arg
)
1334 struct sscom_softc
*sc
= arg
;
1335 int overflows
, floods
;
1340 overflows
= sc
->sc_overflows
;
1341 sc
->sc_overflows
= 0;
1342 floods
= sc
->sc_floods
;
1348 log(LOG_WARNING
, "%s: %d silo overflow%s, %d ibuf flood%s\n",
1349 sc
->sc_dev
.dv_xname
,
1350 overflows
, overflows
== 1 ? "" : "s",
1351 floods
, floods
== 1 ? "" : "s");
1355 sscom_rxsoft(struct sscom_softc
*sc
, struct tty
*tp
)
1357 int (*rint
) (int, struct tty
*) = tp
->t_linesw
->l_rint
;
1366 scc
= cc
= sscom_rbuf_size
- sc
->sc_rbavail
;
1368 if (cc
== sscom_rbuf_size
) {
1370 if (sc
->sc_errors
++ == 0)
1371 callout_reset(&sc
->sc_diag_callout
, 60 * hz
,
1379 if (ISSET(rsr
, UERSTAT_OVERRUN
)) {
1381 if (sc
->sc_errors
++ == 0)
1382 callout_reset(&sc
->sc_diag_callout
,
1383 60 * hz
, sscomdiag
, sc
);
1385 if (ISSET(rsr
, UERSTAT_BREAK
| UERSTAT_FRAME
))
1387 if (ISSET(rsr
, UERSTAT_PARITY
))
1390 if ((*rint
)(code
, tp
) == -1) {
1392 * The line discipline's buffer is out of space.
1394 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1396 * We're either not using flow control, or the
1397 * line discipline didn't tell us to block for
1398 * some reason. Either way, we have no way to
1399 * know when there's more space available, so
1400 * just drop the rest of the data.
1404 get
-= sscom_rbuf_size
<< 1;
1408 * Don't schedule any more receive processing
1409 * until the line discipline tells us there's
1410 * space available (through sscomhwiflow()).
1411 * Leave the rest of the data in the input
1414 SET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1429 cc
= sc
->sc_rbavail
+= scc
- cc
;
1430 /* Buffers should be ok again, release possible block. */
1431 if (cc
>= sc
->sc_r_lowat
) {
1432 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1433 CLR(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1434 sscom_enable_rxint(sc
);
1435 sc
->sc_ucon
|= UCON_ERRINT
;
1436 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, SSCOM_UCON
,
1440 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
)) {
1441 CLR(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
1451 sscom_txsoft(struct sscom_softc
*sc
, struct tty
*tp
)
1454 CLR(tp
->t_state
, TS_BUSY
);
1455 if (ISSET(tp
->t_state
, TS_FLUSH
))
1456 CLR(tp
->t_state
, TS_FLUSH
);
1458 ndflush(&tp
->t_outq
, (int)(sc
->sc_tba
- tp
->t_outq
.c_cf
));
1459 (*tp
->t_linesw
->l_start
)(tp
);
1463 sscom_stsoft(struct sscom_softc
*sc
, struct tty
*tp
)
1471 delta
= sc
->sc_msr_delta
;
1472 sc
->sc_msr_delta
= 0;
1476 if (ISSET(delta
, sc
->sc_msr_dcd
)) {
1478 * Inform the tty layer that carrier detect changed.
1480 (void) (*tp
->t_linesw
->l_modem
)(tp
, ISSET(msr
, MSTS_DCD
));
1483 if (ISSET(delta
, sc
->sc_msr_cts
)) {
1484 /* Block or unblock output according to flow control. */
1485 if (ISSET(msr
, sc
->sc_msr_cts
)) {
1486 sc
->sc_tx_stopped
= 0;
1487 (*tp
->t_linesw
->l_start
)(tp
);
1489 sc
->sc_tx_stopped
= 1;
1494 sscomstatus(sc
, "sscom_stsoft");
1498 sscomsoft(void *arg
)
1500 struct sscom_softc
*sc
= arg
;
1503 if (SSCOM_ISALIVE(sc
) == 0)
1509 if (sc
->sc_rx_ready
) {
1510 sc
->sc_rx_ready
= 0;
1511 sscom_rxsoft(sc
, tp
);
1514 if (sc
->sc_st_check
) {
1515 sc
->sc_st_check
= 0;
1516 sscom_stsoft(sc
, tp
);
1519 if (sc
->sc_tx_done
) {
1521 sscom_txsoft(sc
, tp
);
1528 sscomrxintr(void *arg
)
1530 struct sscom_softc
*sc
= arg
;
1531 bus_space_tag_t iot
= sc
->sc_iot
;
1532 bus_space_handle_t ioh
= sc
->sc_ioh
;
1536 if (SSCOM_ISALIVE(sc
) == 0)
1543 cc
= sc
->sc_rbavail
;
1550 ufstat
= bus_space_read_2(iot
, ioh
, SSCOM_UFSTAT
);
1552 /* XXX: break interrupt with no character? */
1554 if ( (ufstat
& (UFSTAT_RXCOUNT
|UFSTAT_RXFULL
)) &&
1555 !ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1560 /* get status and received character.
1561 read status register first */
1562 uerstat
= sscom_geterr(iot
, ioh
);
1563 put
[0] = sscom_getc(iot
, ioh
);
1565 if (ISSET(uerstat
, UERSTAT_BREAK
)) {
1566 int con_trapped
= 0;
1567 cn_check_magic(sc
->sc_tty
->t_dev
,
1568 CNC_BREAK
, sscom_cnm_state
);
1572 if (ISSET(sc
->sc_hwflags
,
1581 cn_check_magic(sc
->sc_tty
->t_dev
,
1582 put
[0], sscom_cnm_state
);
1590 ufstat
= bus_space_read_2(iot
, ioh
, SSCOM_UFSTAT
);
1591 if ( (ufstat
& (UFSTAT_RXFULL
|UFSTAT_RXCOUNT
)) == 0 )
1596 * Current string of incoming characters ended because
1597 * no more data was available or we ran out of space.
1598 * Schedule a receive event if any data was received.
1599 * If we're out of space, turn off receive interrupts.
1602 sc
->sc_rbavail
= cc
;
1603 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
))
1604 sc
->sc_rx_ready
= 1;
1607 * See if we are in danger of overflowing a buffer. If
1608 * so, use hardware flow control to ease the pressure.
1610 if (!ISSET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
) &&
1611 cc
< sc
->sc_r_hiwat
) {
1612 SET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
1617 * If we're out of space, disable receive interrupts
1618 * until the queue has drained a bit.
1621 SET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1622 sscom_disable_rxint(sc
);
1623 sc
->sc_ucon
&= ~UCON_ERRINT
;
1624 bus_space_write_2(iot
, ioh
, SSCOM_UCON
, sc
->sc_ucon
);
1629 msts
= sc
->read_modem_status(sc
);
1630 delta
= msts
^ sc
->sc_msts
;
1635 * Pulse-per-second (PSS) signals on edge of DCD?
1636 * Process these even if line discipline is ignoring DCD.
1638 if (delta
& sc
->sc_ppsmask
) {
1640 if ((msr
& sc
->sc_ppsmask
) == sc
->sc_ppsassert
) {
1641 /* XXX nanotime() */
1643 TIMEVAL_TO_TIMESPEC(&tv
,
1644 &sc
->ppsinfo
.assert_timestamp
);
1645 if (sc
->ppsparam
.mode
& PPS_OFFSETASSERT
) {
1646 timespecadd(&sc
->ppsinfo
.assert_timestamp
,
1647 &sc
->ppsparam
.assert_offset
,
1648 &sc
->ppsinfo
.assert_timestamp
);
1652 if (sc
->ppsparam
.mode
& PPS_HARDPPSONASSERT
)
1653 hardpps(&tv
, tv
.tv_usec
);
1655 sc
->ppsinfo
.assert_sequence
++;
1656 sc
->ppsinfo
.current_mode
= sc
->ppsparam
.mode
;
1658 } else if ((msr
& sc
->sc_ppsmask
) == sc
->sc_ppsclear
) {
1659 /* XXX nanotime() */
1661 TIMEVAL_TO_TIMESPEC(&tv
,
1662 &sc
->ppsinfo
.clear_timestamp
);
1663 if (sc
->ppsparam
.mode
& PPS_OFFSETCLEAR
) {
1664 timespecadd(&sc
->ppsinfo
.clear_timestamp
,
1665 &sc
->ppsparam
.clear_offset
,
1666 &sc
->ppsinfo
.clear_timestamp
);
1670 if (sc
->ppsparam
.mode
& PPS_HARDPPSONCLEAR
)
1671 hardpps(&tv
, tv
.tv_usec
);
1673 sc
->ppsinfo
.clear_sequence
++;
1674 sc
->ppsinfo
.current_mode
= sc
->ppsparam
.mode
;
1680 * Process normal status changes
1682 if (ISSET(delta
, sc
->sc_msr_mask
)) {
1683 SET(sc
->sc_msr_delta
, delta
);
1686 * Stop output immediately if we lose the output
1687 * flow control signal or carrier detect.
1689 if (ISSET(~msts
, sc
->sc_msr_mask
)) {
1694 sscomstatus(sc
, "sscomintr ");
1698 sc
->sc_st_check
= 1;
1702 * Done handling any receive interrupts.
1706 * If we've delayed a parameter change, do it
1707 * now, and restart * output.
1709 if ((ufstat
& UFSTAT_TXCOUNT
) == 0) {
1710 /* XXX: we should check transmitter empty also */
1712 if (sc
->sc_heldchange
) {
1713 sscom_loadchannelregs(sc
);
1714 sc
->sc_heldchange
= 0;
1715 sc
->sc_tbc
= sc
->sc_heldtbc
;
1725 /* Wake up the poller. */
1726 softint_schedule(sc
->sc_si
);
1728 #if NRND > 0 && defined(RND_COM)
1729 rnd_add_uint32(&sc
->rnd_source
, iir
| rsr
);
1736 sscomtxintr(void *arg
)
1738 struct sscom_softc
*sc
= arg
;
1739 bus_space_tag_t iot
= sc
->sc_iot
;
1740 bus_space_handle_t ioh
= sc
->sc_ioh
;
1743 if (SSCOM_ISALIVE(sc
) == 0)
1748 ufstat
= bus_space_read_2(iot
, ioh
, SSCOM_UFSTAT
);
1751 * If we've delayed a parameter change, do it
1752 * now, and restart * output.
1754 if (sc
->sc_heldchange
&& (ufstat
& UFSTAT_TXCOUNT
) == 0) {
1755 /* XXX: we should check transmitter empty also */
1756 sscom_loadchannelregs(sc
);
1757 sc
->sc_heldchange
= 0;
1758 sc
->sc_tbc
= sc
->sc_heldtbc
;
1763 * See if data can be transmitted as well. Schedule tx
1764 * done event if no data left and tty was marked busy.
1766 if (!ISSET(ufstat
,UFSTAT_TXFULL
)) {
1768 * Output the next chunk of the contiguous
1771 if (sc
->sc_tbc
> 0) {
1772 __sscom_output_chunk(sc
, ufstat
);
1776 * Disable transmit sscompletion
1777 * interrupts if necessary.
1779 if (sc
->sc_hwflags
& SSCOM_HW_TXINT
)
1780 sscom_disable_txint(sc
);
1781 if (sc
->sc_tx_busy
) {
1790 /* Wake up the poller. */
1791 softint_schedule(sc
->sc_si
);
1793 #if NRND > 0 && defined(RND_COM)
1794 rnd_add_uint32(&sc
->rnd_source
, iir
| rsr
);
1801 #if defined(KGDB) || defined(SSCOM0CONSOLE) || defined(SSCOM1CONSOLE)
1803 * Initialize UART for use as console or KGDB line.
1806 sscom_init(bus_space_tag_t iot
, const struct sscom_uart_info
*config
,
1807 int rate
, int frequency
, tcflag_t cflag
, bus_space_handle_t
*iohp
)
1809 bus_space_handle_t ioh
;
1810 bus_addr_t iobase
= config
->iobase
;
1812 if (bus_space_map(iot
, iobase
, SSCOM_SIZE
, 0, &ioh
))
1813 return ENOMEM
; /* ??? */
1815 bus_space_write_2(iot
, ioh
, SSCOM_UCON
, 0);
1816 bus_space_write_1(iot
, ioh
, SSCOM_UFCON
,
1817 UFCON_TXTRIGGER_8
| UFCON_RXTRIGGER_8
|
1818 UFCON_TXFIFO_RESET
| UFCON_RXFIFO_RESET
|
1819 UFCON_FIFO_ENABLE
);
1820 /* tx/rx fifo reset are auto-cleared */
1822 rate
= sscomspeed(rate
, frequency
);
1823 bus_space_write_2(iot
, ioh
, SSCOM_UBRDIV
, rate
);
1824 bus_space_write_2(iot
, ioh
, SSCOM_ULCON
, cflag2lcr(cflag
));
1827 bus_space_write_2(iot
, ioh
, SSCOM_UCON
,
1828 UCON_TXMODE_INT
|UCON_RXMODE_INT
);
1829 bus_space_write_2(iot
, ioh
, SSCOM_UMCON
, UMCON_RTS
);
1837 #if defined(SSCOM0CONSOLE) || defined(SSCOM1CONSOLE)
1839 * Following are all routines needed for SSCOM to act as console
1841 struct consdev sscomcons
= {
1842 NULL
, NULL
, sscomcngetc
, sscomcnputc
, sscomcnpollc
, NULL
,
1843 NULL
, NULL
, NODEV
, CN_NORMAL
1848 sscom_cnattach(bus_space_tag_t iot
, const struct sscom_uart_info
*config
,
1849 int rate
, int frequency
, tcflag_t cflag
)
1853 res
= sscom_init(iot
, config
, rate
, frequency
, cflag
, &sscomconsioh
);
1857 cn_tab
= &sscomcons
;
1858 cn_init_magic(&sscom_cnm_state
);
1859 cn_set_magic("\047\001"); /* default magic is BREAK */
1862 sscomconsunit
= config
->unit
;
1863 sscomconsrate
= rate
;
1864 sscomconscflag
= cflag
;
1870 sscom_cndetach(void)
1872 bus_space_unmap(sscomconstag
, sscomconsioh
, SSCOM_SIZE
);
1873 sscomconstag
= NULL
;
1879 * The read-ahead code is so that you can detect pending in-band
1880 * cn_magic in polled mode while doing output rather than having to
1881 * wait until the kernel decides it needs input.
1884 #define MAX_READAHEAD 20
1885 static int sscom_readahead
[MAX_READAHEAD
];
1886 static int sscom_readaheadcount
= 0;
1889 sscomcngetc(dev_t dev
)
1891 int s
= splserial();
1894 /* got a character from reading things earlier */
1895 if (sscom_readaheadcount
> 0) {
1898 c
= sscom_readahead
[0];
1899 for (i
= 1; i
< sscom_readaheadcount
; i
++) {
1900 sscom_readahead
[i
-1] = sscom_readahead
[i
];
1902 sscom_readaheadcount
--;
1907 /* block until a character becomes available */
1908 while (!sscom_rxrdy(sscomconstag
, sscomconsioh
))
1911 c
= sscom_getc(sscomconstag
, sscomconsioh
);
1912 stat
= sscom_geterr(sscomconstag
, sscomconsioh
);
1914 int cn_trapped
= 0; /* unused */
1916 extern int db_active
;
1919 cn_check_magic(dev
, c
, sscom_cnm_state
);
1926 * Console kernel output character routine.
1929 sscomcnputc(dev_t dev
, int c
)
1931 int s
= splserial();
1935 if (sscom_readaheadcount
< MAX_READAHEAD
&&
1936 sscom_rxrdy(sscomconstag
, sscomconsioh
)) {
1939 cin
= sscom_getc(sscomconstag
, sscomconsioh
);
1940 stat
= sscom_geterr(sscomconstag
, sscomconsioh
);
1941 cn_check_magic(dev
, cin
, sscom_cnm_state
);
1942 sscom_readahead
[sscom_readaheadcount
++] = cin
;
1945 /* wait for any pending transmission to finish */
1947 while (ISSET(bus_space_read_2(sscomconstag
, sscomconsioh
, SSCOM_UFSTAT
),
1948 UFSTAT_TXFULL
) && --timo
)
1951 bus_space_write_1(sscomconstag
, sscomconsioh
, SSCOM_UTXH
, c
);
1952 SSCOM_BARRIER(sscomconstag
, sscomconsioh
, BR
| BW
);
1955 /* wait for this transmission to complete */
1957 while (!ISSET(bus_space_read_1(sscomconstag
, sscomconsioh
, SSCOM_UTRSTAT
),
1958 UTRSTAT_TXEMPTY
) && --timo
)
1965 sscomcnpollc(dev_t dev
, int on
)
1970 #endif /* SSCOM0CONSOLE||SSCOM1CONSOLE */
1974 sscom_kgdb_attach(bus_space_tag_t iot
, const struct sscom_uart_info
*config
,
1975 int rate
, int frequency
, tcflag_t cflag
)
1979 if (iot
== sscomconstag
&& config
->unit
== sscomconsunit
) {
1980 printf( "console==kgdb_port (%d): kgdb disabled\n", sscomconsunit
);
1981 return EBUSY
; /* cannot share with console */
1984 res
= sscom_init(iot
, config
, rate
, frequency
, cflag
, &sscom_kgdb_ioh
);
1988 kgdb_attach(sscom_kgdb_getc
, sscom_kgdb_putc
, NULL
);
1989 kgdb_dev
= 123; /* unneeded, only to satisfy some tests */
1991 sscom_kgdb_iot
= iot
;
1992 sscom_kgdb_unit
= config
->unit
;
1999 sscom_kgdb_getc(void *arg
)
2003 /* block until a character becomes available */
2004 while (!sscom_rxrdy(sscom_kgdb_iot
, sscom_kgdb_ioh
))
2007 c
= sscom_getc(sscom_kgdb_iot
, sscom_kgdb_ioh
);
2008 stat
= sscom_geterr(sscom_kgdb_iot
, sscom_kgdb_ioh
);
2015 sscom_kgdb_putc(void *arg
, int c
)
2019 /* wait for any pending transmission to finish */
2021 while (ISSET(bus_space_read_2(sscom_kgdb_iot
, sscom_kgdb_ioh
,
2022 SSCOM_UFSTAT
), UFSTAT_TXFULL
) && --timo
)
2025 bus_space_write_1(sscom_kgdb_iot
, sscom_kgdb_ioh
, SSCOM_UTXH
, c
);
2026 SSCOM_BARRIER(sscom_kgdb_iot
, sscom_kgdb_ioh
, BR
| BW
);
2029 /* wait for this transmission to complete */
2031 while (!ISSET(bus_space_read_1(sscom_kgdb_iot
, sscom_kgdb_ioh
,
2032 SSCOM_UTRSTAT
), UTRSTAT_TXEMPTY
) && --timo
)
2038 /* helper function to identify the sscom ports used by
2039 console or KGDB (and not yet autoconf attached) */
2041 sscom_is_console(bus_space_tag_t iot
, int unit
,
2042 bus_space_handle_t
*ioh
)
2044 bus_space_handle_t help
;
2046 if (!sscomconsattached
&&
2047 iot
== sscomconstag
&& unit
== sscomconsunit
)
2048 help
= sscomconsioh
;
2050 else if (!sscom_kgdb_attached
&&
2051 iot
== sscom_kgdb_iot
&& unit
== sscom_kgdb_unit
)
2052 help
= sscom_kgdb_ioh
;