1 /* $NetBSD: plcom.c,v 1.30 2009/11/21 20:32:28 rmind Exp $ */
4 * Copyright (c) 2001 ARM Ltd
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the company may not be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
32 * All rights reserved.
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Charles M. Hannum.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
60 * Copyright (c) 1991 The Regents of the University of California.
61 * All rights reserved.
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
66 * 1. Redistributions of source code must retain the above copyright
67 * notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in the
70 * documentation and/or other materials provided with the distribution.
71 * 3. Neither the name of the University nor the names of its contributors
72 * may be used to endorse or promote products derived from this software
73 * without specific prior written permission.
75 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
76 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
77 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
78 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
79 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
80 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
81 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
82 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
83 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
84 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87 * @(#)com.c 7.5 (Berkeley) 5/16/91
91 * COM driver for the Prime Cell PL010 UART, which is similar to the 16C550,
92 * but has a completely different programmer's model.
93 * Derived from the NS16550AF com driver.
96 #include <sys/cdefs.h>
97 __KERNEL_RCSID(0, "$NetBSD: plcom.c,v 1.30 2009/11/21 20:32:28 rmind Exp $");
99 #include "opt_plcom.h"
101 #include "opt_kgdb.h"
102 #include "opt_lockdebug.h"
103 #include "opt_multiprocessor.h"
106 #if NRND > 0 && defined(RND_COM)
111 * Override cnmagic(9) macro before including <sys/systm.h>.
112 * We need to know if cn_check_magic triggered debugger, so set a flag.
113 * Callers of cn_check_magic must declare int cn_trapped = 0;
114 * XXX: this is *ugly*!
118 console_debugger(); \
120 } while (/* CONSTCOND */ 0)
122 #include <sys/param.h>
123 #include <sys/systm.h>
124 #include <sys/ioctl.h>
125 #include <sys/select.h>
127 #include <sys/proc.h>
128 #include <sys/conf.h>
129 #include <sys/file.h>
131 #include <sys/kernel.h>
132 #include <sys/syslog.h>
133 #include <sys/types.h>
134 #include <sys/device.h>
135 #include <sys/malloc.h>
136 #include <sys/timepps.h>
137 #include <sys/vnode.h>
138 #include <sys/kauth.h>
139 #include <sys/intr.h>
142 #include <evbarm/dev/plcomreg.h>
143 #include <evbarm/dev/plcomvar.h>
145 #include <dev/cons.h>
147 static void plcom_enable_debugport (struct plcom_softc
*);
149 void plcom_config (struct plcom_softc
*);
150 void plcom_shutdown (struct plcom_softc
*);
151 int plcomspeed (long, long);
152 static u_char
cflag2lcr (tcflag_t
);
153 int plcomparam (struct tty
*, struct termios
*);
154 void plcomstart (struct tty
*);
155 int plcomhwiflow (struct tty
*, int);
157 void plcom_loadchannelregs (struct plcom_softc
*);
158 void plcom_hwiflow (struct plcom_softc
*);
159 void plcom_break (struct plcom_softc
*, int);
160 void plcom_modem (struct plcom_softc
*, int);
161 void tiocm_to_plcom (struct plcom_softc
*, u_long
, int);
162 int plcom_to_tiocm (struct plcom_softc
*);
163 void plcom_iflush (struct plcom_softc
*);
165 int plcom_common_getc (dev_t
, bus_space_tag_t
, bus_space_handle_t
);
166 void plcom_common_putc (dev_t
, bus_space_tag_t
, bus_space_handle_t
, int);
168 int plcominit (bus_space_tag_t
, bus_addr_t
, int, int, tcflag_t
,
169 bus_space_handle_t
*);
171 dev_type_open(plcomopen
);
172 dev_type_close(plcomclose
);
173 dev_type_read(plcomread
);
174 dev_type_write(plcomwrite
);
175 dev_type_ioctl(plcomioctl
);
176 dev_type_stop(plcomstop
);
177 dev_type_tty(plcomtty
);
178 dev_type_poll(plcompoll
);
180 int plcomcngetc (dev_t
);
181 void plcomcnputc (dev_t
, int);
182 void plcomcnpollc (dev_t
, int);
184 #define integrate static inline
185 void plcomsoft (void *);
186 integrate
void plcom_rxsoft (struct plcom_softc
*, struct tty
*);
187 integrate
void plcom_txsoft (struct plcom_softc
*, struct tty
*);
188 integrate
void plcom_stsoft (struct plcom_softc
*, struct tty
*);
189 integrate
void plcom_schedrx (struct plcom_softc
*);
190 void plcomdiag (void *);
192 extern struct cfdriver plcom_cd
;
194 const struct cdevsw plcom_cdevsw
= {
195 plcomopen
, plcomclose
, plcomread
, plcomwrite
, plcomioctl
,
196 plcomstop
, plcomtty
, plcompoll
, nommap
, ttykqfilter
, D_TTY
200 * Make this an option variable one can patch.
201 * But be warned: this must be a power of 2!
203 u_int plcom_rbuf_size
= PLCOM_RING_SIZE
;
205 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
206 u_int plcom_rbuf_hiwat
= (PLCOM_RING_SIZE
* 1) / 4;
207 u_int plcom_rbuf_lowat
= (PLCOM_RING_SIZE
* 3) / 4;
209 static int plcomconsunit
= -1;
210 static bus_space_tag_t plcomconstag
;
211 static bus_space_handle_t plcomconsioh
;
212 static int plcomconsattached
;
213 static int plcomconsrate
;
214 static tcflag_t plcomconscflag
;
215 static struct cnm_state plcom_cnm_state
;
222 PPS_HARDPPSONASSERT
| PPS_HARDPPSONCLEAR
|
223 #endif /* PPS_SYNC */
224 PPS_OFFSETASSERT
| PPS_OFFSETCLEAR
;
227 #include <sys/kgdb.h>
229 static int plcom_kgdb_unit
;
230 static bus_space_tag_t plcom_kgdb_iot
;
231 static bus_space_handle_t plcom_kgdb_ioh
;
232 static int plcom_kgdb_attached
;
234 int plcom_kgdb_getc (void *);
235 void plcom_kgdb_putc (void *, int);
238 #define PLCOMUNIT_MASK 0x7ffff
239 #define PLCOMDIALOUT_MASK 0x80000
241 #define PLCOMUNIT(x) (minor(x) & PLCOMUNIT_MASK)
242 #define PLCOMDIALOUT(x) (minor(x) & PLCOMDIALOUT_MASK)
244 #define PLCOM_ISALIVE(sc) ((sc)->enabled != 0 && \
245 device_is_active(&(sc)->sc_dev))
247 #define BR BUS_SPACE_BARRIER_READ
248 #define BW BUS_SPACE_BARRIER_WRITE
249 #define PLCOM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, PLCOM_UART_SIZE, (f))
251 #define PLCOM_LOCK(sc) simple_lock(&(sc)->sc_lock)
252 #define PLCOM_UNLOCK(sc) simple_unlock(&(sc)->sc_lock)
255 plcomspeed(long speed
, long frequency
)
257 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
267 x
= divrnd(frequency
/ 16, speed
);
270 err
= divrnd(((quad_t
)frequency
) * 1000 / 16, speed
* x
) - 1000;
273 if (err
> PLCOM_TOLERANCE
)
283 void plcomstatus (struct plcom_softc
*, char *);
285 plcomstatus(struct plcom_softc
*sc
, char *str
)
287 struct tty
*tp
= sc
->sc_tty
;
289 printf("%s: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n",
290 sc
->sc_dev
.dv_xname
, str
,
291 ISSET(tp
->t_cflag
, CLOCAL
) ? "+" : "-",
292 ISSET(sc
->sc_msr
, MSR_DCD
) ? "+" : "-",
293 ISSET(tp
->t_state
, TS_CARR_ON
) ? "+" : "-",
294 ISSET(sc
->sc_mcr
, MCR_DTR
) ? "+" : "-",
295 sc
->sc_tx_stopped
? "+" : "-");
297 printf("%s: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n",
298 sc
->sc_dev
.dv_xname
, str
,
299 ISSET(tp
->t_cflag
, CRTSCTS
) ? "+" : "-",
300 ISSET(sc
->sc_msr
, MSR_CTS
) ? "+" : "-",
301 ISSET(tp
->t_state
, TS_TTSTOP
) ? "+" : "-",
302 ISSET(sc
->sc_mcr
, MCR_RTS
) ? "+" : "-",
308 plcomprobe1(bus_space_tag_t iot
, bus_space_handle_t ioh
)
312 /* Disable the UART. */
313 bus_space_write_1(iot
, ioh
, plcom_cr
, 0);
314 /* Make sure the FIFO is off. */
315 bus_space_write_1(iot
, ioh
, plcom_lcr
, LCR_8BITS
);
316 /* Disable interrupts. */
317 bus_space_write_1(iot
, ioh
, plcom_iir
, 0);
319 /* Make sure we swallow anything in the receiving register. */
320 data
= bus_space_read_1(iot
, ioh
, plcom_dr
);
322 if (bus_space_read_1(iot
, ioh
, plcom_lcr
) != LCR_8BITS
)
325 data
= bus_space_read_1(iot
, ioh
, plcom_fr
) & (FR_RXFF
| FR_RXFE
);
334 plcom_enable_debugport(struct plcom_softc
*sc
)
338 /* Turn on line break interrupt, set carrier. */
341 sc
->sc_cr
= CR_RIE
| CR_RTIE
| CR_UARTEN
;
342 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, plcom_cr
, sc
->sc_cr
);
343 SET(sc
->sc_mcr
, MCR_DTR
| MCR_RTS
);
344 /* XXX device_unit() abuse */
345 sc
->sc_set_mcr(sc
->sc_set_mcr_arg
, device_unit(&sc
->sc_dev
),
352 plcom_attach_subr(struct plcom_softc
*sc
)
354 int unit
= sc
->sc_iounit
;
355 bus_space_tag_t iot
= sc
->sc_iot
;
356 bus_space_handle_t ioh
= sc
->sc_ioh
;
359 callout_init(&sc
->sc_diag_callout
, 0);
360 simple_lock_init(&sc
->sc_lock
);
362 /* Disable interrupts before configuring the device. */
365 if (plcomconstag
&& unit
== plcomconsunit
) {
366 plcomconsattached
= 1;
371 /* Make sure the console is always "hardwired". */
372 delay(1000); /* wait for output to finish */
373 SET(sc
->sc_hwflags
, PLCOM_HW_CONSOLE
);
374 SET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
);
375 /* Must re-enable the console immediately, or we will
376 hang when trying to print. */
377 sc
->sc_cr
= CR_UARTEN
;
380 bus_space_write_1(iot
, ioh
, plcom_cr
, sc
->sc_cr
);
382 /* The PL010 has a 16-byte fifo, but the tx interrupt triggers when
383 there is space for 8 more bytes. */
387 if (ISSET(sc
->sc_hwflags
, PLCOM_HW_TXFIFO_DISABLE
)) {
389 printf("%s: txfifo disabled\n", sc
->sc_dev
.dv_xname
);
392 if (sc
->sc_fifolen
> 1)
393 SET(sc
->sc_hwflags
, PLCOM_HW_FIFO
);
396 tp
->t_oproc
= plcomstart
;
397 tp
->t_param
= plcomparam
;
398 tp
->t_hwiflow
= plcomhwiflow
;
401 sc
->sc_rbuf
= malloc(plcom_rbuf_size
<< 1, M_DEVBUF
, M_NOWAIT
);
402 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
403 sc
->sc_rbavail
= plcom_rbuf_size
;
404 if (sc
->sc_rbuf
== NULL
) {
405 printf("%s: unable to allocate ring buffer\n",
406 sc
->sc_dev
.dv_xname
);
409 sc
->sc_ebuf
= sc
->sc_rbuf
+ (plcom_rbuf_size
<< 1);
413 if (ISSET(sc
->sc_hwflags
, PLCOM_HW_CONSOLE
)) {
416 /* locate the major number */
417 maj
= cdevsw_lookup_major(&plcom_cdevsw
);
419 cn_tab
->cn_dev
= makedev(maj
, device_unit(&sc
->sc_dev
));
421 printf("%s: console\n", sc
->sc_dev
.dv_xname
);
426 * Allow kgdb to "take over" this port. If this is
427 * the kgdb device, it has exclusive use.
429 if (iot
== plcom_kgdb_iot
&& unit
== plcom_kgdb_unit
) {
430 plcom_kgdb_attached
= 1;
432 SET(sc
->sc_hwflags
, PLCOM_HW_KGDB
);
433 printf("%s: kgdb\n", sc
->sc_dev
.dv_xname
);
437 sc
->sc_si
= softint_establish(SOFTINT_SERIAL
, plcomsoft
, sc
);
439 #if NRND > 0 && defined(RND_COM)
440 rnd_attach_source(&sc
->rnd_source
, sc
->sc_dev
.dv_xname
,
444 /* if there are no enable/disable functions, assume the device
451 SET(sc
->sc_hwflags
, PLCOM_HW_DEV_OK
);
455 plcom_config(struct plcom_softc
*sc
)
457 bus_space_tag_t iot
= sc
->sc_iot
;
458 bus_space_handle_t ioh
= sc
->sc_ioh
;
460 /* Disable interrupts before configuring the device. */
462 bus_space_write_1(iot
, ioh
, plcom_cr
, sc
->sc_cr
);
464 if (ISSET(sc
->sc_hwflags
, PLCOM_HW_CONSOLE
|PLCOM_HW_KGDB
))
465 plcom_enable_debugport(sc
);
469 plcom_detach(struct device
*self
, int flags
)
471 struct plcom_softc
*sc
= (struct plcom_softc
*)self
;
474 if (sc
->sc_hwflags
& (PLCOM_HW_CONSOLE
|PLCOM_HW_KGDB
))
477 if (sc
->disable
!= NULL
&& sc
->enabled
!= 0) {
482 /* locate the major number */
483 maj
= cdevsw_lookup_major(&plcom_cdevsw
);
485 /* Nuke the vnodes for any open instances. */
486 mn
= device_unit(self
);
487 vdevgone(maj
, mn
, mn
, VCHR
);
489 mn
|= PLCOMDIALOUT_MASK
;
490 vdevgone(maj
, mn
, mn
, VCHR
);
492 /* Free the receive buffer. */
493 free(sc
->sc_rbuf
, M_DEVBUF
);
495 /* Detach and free the tty. */
496 tty_detach(sc
->sc_tty
);
499 /* Unhook the soft interrupt handler. */
500 softint_disestablish(sc
->sc_si
);
502 #if NRND > 0 && defined(RND_COM)
503 /* Unhook the entropy source. */
504 rnd_detach_source(&sc
->rnd_source
);
511 plcom_activate(device_t self
, enum devact act
)
513 struct plcom_softc
*sc
= device_private(self
);
516 case DVACT_DEACTIVATE
:
525 plcom_shutdown(struct plcom_softc
*sc
)
527 struct tty
*tp
= sc
->sc_tty
;
533 /* If we were asserting flow control, then deassert it. */
534 SET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
537 /* Clear any break condition set with TIOCSBRK. */
540 /* Turn off PPS capture on last close. */
541 mutex_spin_enter(&timecounter_lock
);
543 sc
->ppsparam
.mode
= 0;
544 mutex_spin_exit(&timecounter_lock
);
547 * Hang up if necessary. Wait a bit, so the other side has time to
548 * notice even if we immediately open the port again.
549 * Avoid tsleeping above splhigh().
551 if (ISSET(tp
->t_cflag
, HUPCL
)) {
555 /* XXX tsleep will only timeout */
556 (void) tsleep(sc
, TTIPRI
, ttclos
, hz
);
561 /* Turn off interrupts. */
562 if (ISSET(sc
->sc_hwflags
, PLCOM_HW_CONSOLE
))
563 /* interrupt on break */
564 sc
->sc_cr
= CR_RIE
| CR_RTIE
| CR_UARTEN
;
567 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, plcom_cr
, sc
->sc_cr
);
572 panic("plcom_shutdown: not enabled?");
582 plcomopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
584 struct plcom_softc
*sc
;
589 sc
= device_lookup_private(&plcom_cd
, PLCOMUNIT(dev
));
590 if (sc
== NULL
|| !ISSET(sc
->sc_hwflags
, PLCOM_HW_DEV_OK
) ||
594 if (!device_is_active(&sc
->sc_dev
))
599 * If this is the kgdb port, no other use is permitted.
601 if (ISSET(sc
->sc_hwflags
, PLCOM_HW_KGDB
))
607 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
613 * Do the following iff this is a first open.
615 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
624 if ((*sc
->enable
)(sc
)) {
628 printf("%s: device enable failed\n",
629 sc
->sc_dev
.dv_xname
);
636 /* Turn on interrupts. */
637 /* IER_ERXRDY | IER_ERLS | IER_EMSC; */
638 sc
->sc_cr
= CR_RIE
| CR_RTIE
| CR_MSIE
| CR_UARTEN
;
639 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, plcom_cr
, sc
->sc_cr
);
641 /* Fetch the current modem control status, needed later. */
642 sc
->sc_msr
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, plcom_fr
);
644 /* Clear PPS capture state on first open. */
646 mutex_spin_enter(&timecounter_lock
);
648 sc
->ppsparam
.mode
= 0;
649 mutex_spin_exit(&timecounter_lock
);
655 * Initialize the termios status to the defaults. Add in the
656 * sticky bits from TIOCSFLAGS.
659 if (ISSET(sc
->sc_hwflags
, PLCOM_HW_CONSOLE
)) {
660 t
.c_ospeed
= plcomconsrate
;
661 t
.c_cflag
= plcomconscflag
;
663 t
.c_ospeed
= TTYDEF_SPEED
;
664 t
.c_cflag
= TTYDEF_CFLAG
;
666 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CLOCAL
))
667 SET(t
.c_cflag
, CLOCAL
);
668 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
669 SET(t
.c_cflag
, CRTSCTS
);
670 if (ISSET(sc
->sc_swflags
, TIOCFLAG_MDMBUF
))
671 SET(t
.c_cflag
, MDMBUF
);
672 /* Make sure plcomparam() will do something. */
674 (void) plcomparam(tp
, &t
);
675 tp
->t_iflag
= TTYDEF_IFLAG
;
676 tp
->t_oflag
= TTYDEF_OFLAG
;
677 tp
->t_lflag
= TTYDEF_LFLAG
;
685 * Turn on DTR. We must always do this, even if carrier is not
686 * present, because otherwise we'd have to use TIOCSDTR
687 * immediately after setting CLOCAL, which applications do not
688 * expect. We always assert DTR while the device is open
689 * unless explicitly requested to deassert it.
693 /* Clear the input ring, and unblock. */
694 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
695 sc
->sc_rbavail
= plcom_rbuf_size
;
697 CLR(sc
->sc_rx_flags
, RX_ANY_BLOCK
);
702 plcomstatus(sc
, "plcomopen ");
711 error
= ttyopen(tp
, PLCOMDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
715 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
722 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
724 * We failed to open the device, and nobody else had it opened.
725 * Clean up the state as appropriate.
734 plcomclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
736 struct plcom_softc
*sc
=
737 device_lookup_private(&plcom_cd
, PLCOMUNIT(dev
));
738 struct tty
*tp
= sc
->sc_tty
;
740 /* XXX This is for cons.c. */
741 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
744 (*tp
->t_linesw
->l_close
)(tp
, flag
);
747 if (PLCOM_ISALIVE(sc
) == 0)
750 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
752 * Although we got a last close, the device may still be in
753 * use; e.g. if this was the dialout node, and there are still
754 * processes waiting for carrier on the non-dialout node.
763 plcomread(dev_t dev
, struct uio
*uio
, int flag
)
765 struct plcom_softc
*sc
=
766 device_lookup_private(&plcom_cd
, PLCOMUNIT(dev
));
767 struct tty
*tp
= sc
->sc_tty
;
769 if (PLCOM_ISALIVE(sc
) == 0)
772 return (*tp
->t_linesw
->l_read
)(tp
, uio
, flag
);
776 plcomwrite(dev_t dev
, struct uio
*uio
, int flag
)
778 struct plcom_softc
*sc
=
779 device_lookup_private(&plcom_cd
, PLCOMUNIT(dev
));
780 struct tty
*tp
= sc
->sc_tty
;
782 if (PLCOM_ISALIVE(sc
) == 0)
785 return (*tp
->t_linesw
->l_write
)(tp
, uio
, flag
);
789 plcompoll(dev_t dev
, int events
, struct lwp
*l
)
791 struct plcom_softc
*sc
=
792 device_lookup_private(&plcom_cd
, PLCOMUNIT(dev
));
793 struct tty
*tp
= sc
->sc_tty
;
795 if (PLCOM_ISALIVE(sc
) == 0)
798 return (*tp
->t_linesw
->l_poll
)(tp
, events
, l
);
804 struct plcom_softc
*sc
=
805 device_lookup_private(&plcom_cd
, PLCOMUNIT(dev
));
806 struct tty
*tp
= sc
->sc_tty
;
812 plcomioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
814 struct plcom_softc
*sc
=
815 device_lookup_private(&plcom_cd
, PLCOMUNIT(dev
));
816 struct tty
*tp
= sc
->sc_tty
;
820 if (PLCOM_ISALIVE(sc
) == 0)
823 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
824 if (error
!= EPASSTHROUGH
)
827 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
828 if (error
!= EPASSTHROUGH
)
854 *(int *)data
= sc
->sc_swflags
;
858 error
= kauth_authorize_device_tty(l
->l_cred
,
859 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
862 sc
->sc_swflags
= *(int *)data
;
868 tiocm_to_plcom(sc
, cmd
, *(int *)data
);
872 *(int *)data
= plcom_to_tiocm(sc
);
878 case PPS_IOC_DESTROY
:
881 case PPS_IOC_GETPARAMS
: {
883 pp
= (pps_params_t
*)data
;
884 mutex_spin_enter(&timecounter_lock
);
886 mutex_spin_exit(&timecounter_lock
);
890 case PPS_IOC_SETPARAMS
: {
893 pp
= (pps_params_t
*)data
;
894 mutex_spin_enter(&timecounter_lock
);
895 if (pp
->mode
& ~ppscap
) {
897 mutex_spin_exit(&timecounter_lock
);
902 * Compute msr masks from user-specified timestamp state.
904 mode
= sc
->ppsparam
.mode
;
906 if (mode
& PPS_HARDPPSONASSERT
) {
907 mode
|= PPS_CAPTUREASSERT
;
908 /* XXX revoke any previous HARDPPS source */
910 if (mode
& PPS_HARDPPSONCLEAR
) {
911 mode
|= PPS_CAPTURECLEAR
;
912 /* XXX revoke any previous HARDPPS source */
914 #endif /* PPS_SYNC */
915 switch (mode
& PPS_CAPTUREBOTH
) {
920 case PPS_CAPTUREASSERT
:
921 sc
->sc_ppsmask
= MSR_DCD
;
922 sc
->sc_ppsassert
= MSR_DCD
;
923 sc
->sc_ppsclear
= -1;
926 case PPS_CAPTURECLEAR
:
927 sc
->sc_ppsmask
= MSR_DCD
;
928 sc
->sc_ppsassert
= -1;
932 case PPS_CAPTUREBOTH
:
933 sc
->sc_ppsmask
= MSR_DCD
;
934 sc
->sc_ppsassert
= MSR_DCD
;
942 mutex_spin_exit(&timecounter_lock
);
947 *(int*)data
= ppscap
;
950 case PPS_IOC_FETCH
: {
952 pi
= (pps_info_t
*)data
;
953 mutex_spin_enter(&timecounter_lock
);
955 mutex_spin_exit(&timecounter_lock
);
959 case TIOCDCDTIMESTAMP
: /* XXX old, overloaded API used by xntpd v3 */
961 * Some GPS clocks models use the falling rather than
962 * rising edge as the on-the-second signal.
963 * The old API has no way to specify PPS polarity.
965 mutex_spin_enter(&timecounter_lock
);
966 sc
->sc_ppsmask
= MSR_DCD
;
967 #ifndef PPS_TRAILING_EDGE
968 sc
->sc_ppsassert
= MSR_DCD
;
969 sc
->sc_ppsclear
= -1;
970 TIMESPEC_TO_TIMEVAL((struct timeval
*)data
,
971 &sc
->ppsinfo
.assert_timestamp
);
973 sc
->sc_ppsassert
= -1
975 TIMESPEC_TO_TIMEVAL((struct timeval
*)data
,
976 &sc
->ppsinfo
.clear_timestamp
);
978 mutex_spin_exit(&timecounter_lock
);
982 error
= EPASSTHROUGH
;
991 plcomstatus(sc
, "plcomioctl ");
998 plcom_schedrx(struct plcom_softc
*sc
)
1001 sc
->sc_rx_ready
= 1;
1003 /* Wake up the poller. */
1004 softint_schedule(sc
->sc_si
);
1008 plcom_break(struct plcom_softc
*sc
, int onoff
)
1012 SET(sc
->sc_lcr
, LCR_BRK
);
1014 CLR(sc
->sc_lcr
, LCR_BRK
);
1016 if (!sc
->sc_heldchange
) {
1017 if (sc
->sc_tx_busy
) {
1018 sc
->sc_heldtbc
= sc
->sc_tbc
;
1020 sc
->sc_heldchange
= 1;
1022 plcom_loadchannelregs(sc
);
1027 plcom_modem(struct plcom_softc
*sc
, int onoff
)
1030 if (sc
->sc_mcr_dtr
== 0)
1034 SET(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
1036 CLR(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
1038 if (!sc
->sc_heldchange
) {
1039 if (sc
->sc_tx_busy
) {
1040 sc
->sc_heldtbc
= sc
->sc_tbc
;
1042 sc
->sc_heldchange
= 1;
1044 plcom_loadchannelregs(sc
);
1049 tiocm_to_plcom(struct plcom_softc
*sc
, u_long how
, int ttybits
)
1054 if (ISSET(ttybits
, TIOCM_DTR
))
1055 SET(plcombits
, MCR_DTR
);
1056 if (ISSET(ttybits
, TIOCM_RTS
))
1057 SET(plcombits
, MCR_RTS
);
1061 CLR(sc
->sc_mcr
, plcombits
);
1065 SET(sc
->sc_mcr
, plcombits
);
1069 CLR(sc
->sc_mcr
, MCR_DTR
| MCR_RTS
);
1070 SET(sc
->sc_mcr
, plcombits
);
1074 if (!sc
->sc_heldchange
) {
1075 if (sc
->sc_tx_busy
) {
1076 sc
->sc_heldtbc
= sc
->sc_tbc
;
1078 sc
->sc_heldchange
= 1;
1080 plcom_loadchannelregs(sc
);
1085 plcom_to_tiocm(struct plcom_softc
*sc
)
1090 plcombits
= sc
->sc_mcr
;
1091 if (ISSET(plcombits
, MCR_DTR
))
1092 SET(ttybits
, TIOCM_DTR
);
1093 if (ISSET(plcombits
, MCR_RTS
))
1094 SET(ttybits
, TIOCM_RTS
);
1096 plcombits
= sc
->sc_msr
;
1097 if (ISSET(plcombits
, MSR_DCD
))
1098 SET(ttybits
, TIOCM_CD
);
1099 if (ISSET(plcombits
, MSR_CTS
))
1100 SET(ttybits
, TIOCM_CTS
);
1101 if (ISSET(plcombits
, MSR_DSR
))
1102 SET(ttybits
, TIOCM_DSR
);
1105 SET(ttybits
, TIOCM_LE
);
1111 cflag2lcr(tcflag_t cflag
)
1115 switch (ISSET(cflag
, CSIZE
)) {
1117 SET(lcr
, LCR_5BITS
);
1120 SET(lcr
, LCR_6BITS
);
1123 SET(lcr
, LCR_7BITS
);
1126 SET(lcr
, LCR_8BITS
);
1129 if (ISSET(cflag
, PARENB
)) {
1131 if (!ISSET(cflag
, PARODD
))
1134 if (ISSET(cflag
, CSTOPB
))
1141 plcomparam(struct tty
*tp
, struct termios
*t
)
1143 struct plcom_softc
*sc
=
1144 device_lookup_private(&plcom_cd
, PLCOMUNIT(tp
->t_dev
));
1149 if (PLCOM_ISALIVE(sc
) == 0)
1152 ospeed
= plcomspeed(t
->c_ospeed
, sc
->sc_frequency
);
1154 /* Check requested parameters. */
1157 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
1161 * For the console, always force CLOCAL and !HUPCL, so that the port
1164 if (ISSET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
1165 ISSET(sc
->sc_hwflags
, PLCOM_HW_CONSOLE
)) {
1166 SET(t
->c_cflag
, CLOCAL
);
1167 CLR(t
->c_cflag
, HUPCL
);
1171 * If there were no changes, don't do anything. This avoids dropping
1172 * input and improves performance when all we did was frob things like
1175 if (tp
->t_ospeed
== t
->c_ospeed
&&
1176 tp
->t_cflag
== t
->c_cflag
)
1179 lcr
= ISSET(sc
->sc_lcr
, LCR_BRK
) | cflag2lcr(t
->c_cflag
);
1187 * PL010 has a fixed-length FIFO trigger point.
1189 if (ISSET(sc
->sc_hwflags
, PLCOM_HW_FIFO
))
1195 SET(sc
->sc_lcr
, LCR_FEN
);
1198 * If we're not in a mode that assumes a connection is present, then
1199 * ignore carrier changes.
1201 if (ISSET(t
->c_cflag
, CLOCAL
| MDMBUF
))
1204 sc
->sc_msr_dcd
= MSR_DCD
;
1206 * Set the flow control pins depending on the current flow control
1209 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
1210 sc
->sc_mcr_dtr
= MCR_DTR
;
1211 sc
->sc_mcr_rts
= MCR_RTS
;
1212 sc
->sc_msr_cts
= MSR_CTS
;
1213 } else if (ISSET(t
->c_cflag
, MDMBUF
)) {
1215 * For DTR/DCD flow control, make sure we don't toggle DTR for
1216 * carrier detection.
1219 sc
->sc_mcr_rts
= MCR_DTR
;
1220 sc
->sc_msr_cts
= MSR_DCD
;
1223 * If no flow control, then always set RTS. This will make
1224 * the other side happy if it mistakenly thinks we're doing
1225 * RTS/CTS flow control.
1227 sc
->sc_mcr_dtr
= MCR_DTR
| MCR_RTS
;
1230 if (ISSET(sc
->sc_mcr
, MCR_DTR
))
1231 SET(sc
->sc_mcr
, MCR_RTS
);
1233 CLR(sc
->sc_mcr
, MCR_RTS
);
1235 sc
->sc_msr_mask
= sc
->sc_msr_cts
| sc
->sc_msr_dcd
;
1239 CLR(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
1241 SET(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
1244 sc
->sc_dlbl
= ospeed
;
1245 sc
->sc_dlbh
= ospeed
>> 8;
1247 /* And copy to tty. */
1249 tp
->t_ospeed
= t
->c_ospeed
;
1250 tp
->t_cflag
= t
->c_cflag
;
1252 if (!sc
->sc_heldchange
) {
1253 if (sc
->sc_tx_busy
) {
1254 sc
->sc_heldtbc
= sc
->sc_tbc
;
1256 sc
->sc_heldchange
= 1;
1258 plcom_loadchannelregs(sc
);
1261 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
1262 /* Disable the high water mark. */
1265 if (ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
)) {
1266 CLR(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1269 if (ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
)) {
1270 CLR(sc
->sc_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
);
1274 sc
->sc_r_hiwat
= plcom_rbuf_hiwat
;
1275 sc
->sc_r_lowat
= plcom_rbuf_lowat
;
1282 * Update the tty layer's idea of the carrier bit, in case we changed
1283 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1286 (void) (*tp
->t_linesw
->l_modem
)(tp
, ISSET(sc
->sc_msr
, MSR_DCD
));
1290 plcomstatus(sc
, "plcomparam ");
1293 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
1294 if (sc
->sc_tx_stopped
) {
1295 sc
->sc_tx_stopped
= 0;
1304 plcom_iflush(struct plcom_softc
*sc
)
1306 bus_space_tag_t iot
= sc
->sc_iot
;
1307 bus_space_handle_t ioh
= sc
->sc_ioh
;
1317 /* flush any pending I/O */
1318 while (! ISSET(bus_space_read_1(iot
, ioh
, plcom_fr
), FR_RXFE
)
1325 bus_space_read_1(iot
, ioh
, plcom_dr
);
1328 printf("%s: plcom_iflush timeout %02x\n", sc
->sc_dev
.dv_xname
,
1334 plcom_loadchannelregs(struct plcom_softc
*sc
)
1336 bus_space_tag_t iot
= sc
->sc_iot
;
1337 bus_space_handle_t ioh
= sc
->sc_ioh
;
1339 /* XXXXX necessary? */
1342 bus_space_write_1(iot
, ioh
, plcom_cr
, 0);
1344 bus_space_write_1(iot
, ioh
, plcom_dlbl
, sc
->sc_dlbl
);
1345 bus_space_write_1(iot
, ioh
, plcom_dlbh
, sc
->sc_dlbh
);
1346 bus_space_write_1(iot
, ioh
, plcom_lcr
, sc
->sc_lcr
);
1347 /* XXX device_unit() abuse */
1348 sc
->sc_set_mcr(sc
->sc_set_mcr_arg
, device_unit(&sc
->sc_dev
),
1349 sc
->sc_mcr_active
= sc
->sc_mcr
);
1351 bus_space_write_1(iot
, ioh
, plcom_cr
, sc
->sc_cr
);
1355 plcomhwiflow(struct tty
*tp
, int block
)
1357 struct plcom_softc
*sc
=
1358 device_lookup_private(&plcom_cd
, PLCOMUNIT(tp
->t_dev
));
1361 if (PLCOM_ISALIVE(sc
) == 0)
1364 if (sc
->sc_mcr_rts
== 0)
1371 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1372 SET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
);
1376 if (ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
)) {
1377 CLR(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1380 if (ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1381 CLR(sc
->sc_rx_flags
, RX_TTY_BLOCKED
);
1392 * (un)block input via hw flowcontrol
1395 plcom_hwiflow(struct plcom_softc
*sc
)
1397 if (sc
->sc_mcr_rts
== 0)
1400 if (ISSET(sc
->sc_rx_flags
, RX_ANY_BLOCK
)) {
1401 CLR(sc
->sc_mcr
, sc
->sc_mcr_rts
);
1402 CLR(sc
->sc_mcr_active
, sc
->sc_mcr_rts
);
1404 SET(sc
->sc_mcr
, sc
->sc_mcr_rts
);
1405 SET(sc
->sc_mcr_active
, sc
->sc_mcr_rts
);
1407 /* XXX device_unit() abuse */
1408 sc
->sc_set_mcr(sc
->sc_set_mcr_arg
, device_unit(&sc
->sc_dev
),
1414 plcomstart(struct tty
*tp
)
1416 struct plcom_softc
*sc
=
1417 device_lookup_private(&plcom_cd
, PLCOMUNIT(tp
->t_dev
));
1418 bus_space_tag_t iot
= sc
->sc_iot
;
1419 bus_space_handle_t ioh
= sc
->sc_ioh
;
1422 if (PLCOM_ISALIVE(sc
) == 0)
1426 if (ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
))
1428 if (sc
->sc_tx_stopped
)
1434 /* Grab the first contiguous region of buffer space. */
1439 tba
= tp
->t_outq
.c_cf
;
1440 tbc
= ndqb(&tp
->t_outq
, 0);
1449 SET(tp
->t_state
, TS_BUSY
);
1452 /* Enable transmit completion interrupts if necessary. */
1453 if (!ISSET(sc
->sc_cr
, CR_TIE
)) {
1454 SET(sc
->sc_cr
, CR_TIE
);
1455 bus_space_write_1(iot
, ioh
, plcom_cr
, sc
->sc_cr
);
1458 /* Output the first chunk of the contiguous buffer. */
1463 if (n
> sc
->sc_fifolen
)
1465 bus_space_write_multi_1(iot
, ioh
, plcom_dr
, sc
->sc_tba
, n
);
1476 * Stop output on a line.
1479 plcomstop(struct tty
*tp
, int flag
)
1481 struct plcom_softc
*sc
=
1482 device_lookup_private(&plcom_cd
, PLCOMUNIT(tp
->t_dev
));
1487 if (ISSET(tp
->t_state
, TS_BUSY
)) {
1488 /* Stop transmitting at the next chunk. */
1491 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
1492 SET(tp
->t_state
, TS_FLUSH
);
1499 plcomdiag(void *arg
)
1501 struct plcom_softc
*sc
= arg
;
1502 int overflows
, floods
;
1507 overflows
= sc
->sc_overflows
;
1508 sc
->sc_overflows
= 0;
1509 floods
= sc
->sc_floods
;
1515 log(LOG_WARNING
, "%s: %d silo overflow%s, %d ibuf flood%s\n",
1516 sc
->sc_dev
.dv_xname
,
1517 overflows
, overflows
== 1 ? "" : "s",
1518 floods
, floods
== 1 ? "" : "s");
1522 plcom_rxsoft(struct plcom_softc
*sc
, struct tty
*tp
)
1524 int (*rint
) (int, struct tty
*) = tp
->t_linesw
->l_rint
;
1533 scc
= cc
= plcom_rbuf_size
- sc
->sc_rbavail
;
1535 if (cc
== plcom_rbuf_size
) {
1537 if (sc
->sc_errors
++ == 0)
1538 callout_reset(&sc
->sc_diag_callout
, 60 * hz
,
1545 if (ISSET(rsr
, RSR_OE
| RSR_BE
| RSR_FE
| RSR_PE
)) {
1546 if (ISSET(rsr
, RSR_OE
)) {
1548 if (sc
->sc_errors
++ == 0)
1549 callout_reset(&sc
->sc_diag_callout
,
1550 60 * hz
, plcomdiag
, sc
);
1552 if (ISSET(rsr
, RSR_BE
| RSR_FE
))
1554 if (ISSET(rsr
, RSR_PE
))
1557 if ((*rint
)(code
, tp
) == -1) {
1559 * The line discipline's buffer is out of space.
1561 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1563 * We're either not using flow control, or the
1564 * line discipline didn't tell us to block for
1565 * some reason. Either way, we have no way to
1566 * know when there's more space available, so
1567 * just drop the rest of the data.
1571 get
-= plcom_rbuf_size
<< 1;
1575 * Don't schedule any more receive processing
1576 * until the line discipline tells us there's
1577 * space available (through plcomhwiflow()).
1578 * Leave the rest of the data in the input
1581 SET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1596 cc
= sc
->sc_rbavail
+= scc
- cc
;
1597 /* Buffers should be ok again, release possible block. */
1598 if (cc
>= sc
->sc_r_lowat
) {
1599 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1600 CLR(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1601 SET(sc
->sc_cr
, CR_RIE
| CR_RTIE
);
1602 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, plcom_cr
, sc
->sc_cr
);
1604 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
)) {
1605 CLR(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
1615 plcom_txsoft(struct plcom_softc
*sc
, struct tty
*tp
)
1618 CLR(tp
->t_state
, TS_BUSY
);
1619 if (ISSET(tp
->t_state
, TS_FLUSH
))
1620 CLR(tp
->t_state
, TS_FLUSH
);
1622 ndflush(&tp
->t_outq
, (int)(sc
->sc_tba
- tp
->t_outq
.c_cf
));
1623 (*tp
->t_linesw
->l_start
)(tp
);
1627 plcom_stsoft(struct plcom_softc
*sc
, struct tty
*tp
)
1635 delta
= sc
->sc_msr_delta
;
1636 sc
->sc_msr_delta
= 0;
1640 if (ISSET(delta
, sc
->sc_msr_dcd
)) {
1642 * Inform the tty layer that carrier detect changed.
1644 (void) (*tp
->t_linesw
->l_modem
)(tp
, ISSET(msr
, MSR_DCD
));
1647 if (ISSET(delta
, sc
->sc_msr_cts
)) {
1648 /* Block or unblock output according to flow control. */
1649 if (ISSET(msr
, sc
->sc_msr_cts
)) {
1650 sc
->sc_tx_stopped
= 0;
1651 (*tp
->t_linesw
->l_start
)(tp
);
1653 sc
->sc_tx_stopped
= 1;
1659 plcomstatus(sc
, "plcom_stsoft");
1664 plcomsoft(void *arg
)
1666 struct plcom_softc
*sc
= arg
;
1669 if (PLCOM_ISALIVE(sc
) == 0)
1674 if (sc
->sc_rx_ready
) {
1675 sc
->sc_rx_ready
= 0;
1676 plcom_rxsoft(sc
, tp
);
1679 if (sc
->sc_st_check
) {
1680 sc
->sc_st_check
= 0;
1681 plcom_stsoft(sc
, tp
);
1684 if (sc
->sc_tx_done
) {
1686 plcom_txsoft(sc
, tp
);
1691 plcomintr(void *arg
)
1693 struct plcom_softc
*sc
= arg
;
1694 bus_space_tag_t iot
= sc
->sc_iot
;
1695 bus_space_handle_t ioh
= sc
->sc_ioh
;
1700 if (PLCOM_ISALIVE(sc
) == 0)
1704 iir
= bus_space_read_1(iot
, ioh
, plcom_iir
);
1705 if (! ISSET(iir
, IIR_IMASK
)) {
1712 cc
= sc
->sc_rbavail
;
1715 u_char msr
, delta
, fr
;
1717 fr
= bus_space_read_1(iot
, ioh
, plcom_fr
);
1719 if (!ISSET(fr
, FR_RXFE
) &&
1720 !ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1723 put
[0] = bus_space_read_1(iot
, ioh
,
1725 rsr
= bus_space_read_1(iot
, ioh
, plcom_rsr
);
1726 /* Clear any error status. */
1728 (RSR_BE
| RSR_OE
| RSR_PE
| RSR_FE
)))
1729 bus_space_write_1(iot
, ioh
, plcom_ecr
,
1731 if (ISSET(rsr
, RSR_BE
)) {
1733 cn_check_magic(sc
->sc_tty
->t_dev
,
1734 CNC_BREAK
, plcom_cnm_state
);
1738 if (ISSET(sc
->sc_hwflags
,
1748 cn_check_magic(sc
->sc_tty
->t_dev
,
1749 put
[0], plcom_cnm_state
);
1751 fr
= bus_space_read_1(iot
, ioh
,
1753 if (ISSET(fr
, FR_RXFE
))
1763 fr
= bus_space_read_1(iot
, ioh
, plcom_fr
);
1764 if (ISSET(fr
, FR_RXFE
))
1769 * Current string of incoming characters ended because
1770 * no more data was available or we ran out of space.
1771 * Schedule a receive event if any data was received.
1772 * If we're out of space, turn off receive interrupts.
1775 sc
->sc_rbavail
= cc
;
1776 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
))
1777 sc
->sc_rx_ready
= 1;
1780 * See if we are in danger of overflowing a buffer. If
1781 * so, use hardware flow control to ease the pressure.
1783 if (!ISSET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
) &&
1784 cc
< sc
->sc_r_hiwat
) {
1785 SET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
1790 * If we're out of space, disable receive interrupts
1791 * until the queue has drained a bit.
1794 SET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1795 CLR(sc
->sc_cr
, CR_RIE
| CR_RTIE
);
1796 bus_space_write_1(iot
, ioh
, plcom_cr
,
1800 if (ISSET(iir
, IIR_RIS
)) {
1801 bus_space_write_1(iot
, ioh
, plcom_cr
, 0);
1803 bus_space_write_1(iot
, ioh
, plcom_cr
,
1809 msr
= bus_space_read_1(iot
, ioh
, plcom_fr
);
1810 delta
= msr
^ sc
->sc_msr
;
1812 /* Clear any pending modem status interrupt. */
1814 bus_space_write_1(iot
, ioh
, plcom_icr
, 0);
1816 * Pulse-per-second (PSS) signals on edge of DCD?
1817 * Process these even if line discipline is ignoring DCD.
1819 if (delta
& sc
->sc_ppsmask
) {
1821 mutex_spin_enter(&timecounter_lock
);
1822 if ((msr
& sc
->sc_ppsmask
) == sc
->sc_ppsassert
) {
1823 /* XXX nanotime() */
1825 TIMEVAL_TO_TIMESPEC(&tv
,
1826 &sc
->ppsinfo
.assert_timestamp
);
1827 if (sc
->ppsparam
.mode
& PPS_OFFSETASSERT
) {
1828 timespecadd(&sc
->ppsinfo
.assert_timestamp
,
1829 &sc
->ppsparam
.assert_offset
,
1830 &sc
->ppsinfo
.assert_timestamp
);
1834 if (sc
->ppsparam
.mode
& PPS_HARDPPSONASSERT
)
1835 hardpps(&tv
, tv
.tv_usec
);
1837 sc
->ppsinfo
.assert_sequence
++;
1838 sc
->ppsinfo
.current_mode
= sc
->ppsparam
.mode
;
1840 } else if ((msr
& sc
->sc_ppsmask
) == sc
->sc_ppsclear
) {
1841 /* XXX nanotime() */
1843 TIMEVAL_TO_TIMESPEC(&tv
,
1844 &sc
->ppsinfo
.clear_timestamp
);
1845 if (sc
->ppsparam
.mode
& PPS_OFFSETCLEAR
) {
1846 timespecadd(&sc
->ppsinfo
.clear_timestamp
,
1847 &sc
->ppsparam
.clear_offset
,
1848 &sc
->ppsinfo
.clear_timestamp
);
1852 if (sc
->ppsparam
.mode
& PPS_HARDPPSONCLEAR
)
1853 hardpps(&tv
, tv
.tv_usec
);
1855 sc
->ppsinfo
.clear_sequence
++;
1856 sc
->ppsinfo
.current_mode
= sc
->ppsparam
.mode
;
1858 mutex_spin_exit(&timecounter_lock
);
1862 * Process normal status changes
1864 if (ISSET(delta
, sc
->sc_msr_mask
)) {
1865 SET(sc
->sc_msr_delta
, delta
);
1868 * Stop output immediately if we lose the output
1869 * flow control signal or carrier detect.
1871 if (ISSET(~msr
, sc
->sc_msr_mask
)) {
1876 plcomstatus(sc
, "plcomintr ");
1880 sc
->sc_st_check
= 1;
1884 * Done handling any receive interrupts. See if data
1885 * can be * transmitted as well. Schedule tx done
1886 * event if no data left * and tty was marked busy.
1888 if (ISSET(iir
, IIR_TIS
)) {
1890 * If we've delayed a parameter change, do it
1891 * now, and restart * output.
1893 if (sc
->sc_heldchange
) {
1894 plcom_loadchannelregs(sc
);
1895 sc
->sc_heldchange
= 0;
1896 sc
->sc_tbc
= sc
->sc_heldtbc
;
1901 * Output the next chunk of the contiguous
1904 if (sc
->sc_tbc
> 0) {
1908 if (n
> sc
->sc_fifolen
)
1910 bus_space_write_multi_1(iot
, ioh
, plcom_dr
,
1916 * Disable transmit plcompletion
1917 * interrupts if necessary.
1919 if (ISSET(sc
->sc_cr
, CR_TIE
)) {
1920 CLR(sc
->sc_cr
, CR_TIE
);
1921 bus_space_write_1(iot
, ioh
, plcom_cr
,
1924 if (sc
->sc_tx_busy
) {
1930 } while (ISSET((iir
= bus_space_read_1(iot
, ioh
, plcom_iir
)),
1935 /* Wake up the poller. */
1936 softint_schedule(sc
->sc_si
);
1938 #if NRND > 0 && defined(RND_COM)
1939 rnd_add_uint32(&sc
->rnd_source
, iir
| rsr
);
1946 * The following functions are polled getc and putc routines, shared
1947 * by the console and kgdb glue.
1949 * The read-ahead code is so that you can detect pending in-band
1950 * cn_magic in polled mode while doing output rather than having to
1951 * wait until the kernel decides it needs input.
1954 #define MAX_READAHEAD 20
1955 static int plcom_readahead
[MAX_READAHEAD
];
1956 static int plcom_readaheadcount
= 0;
1959 plcom_common_getc(dev_t dev
, bus_space_tag_t iot
, bus_space_handle_t ioh
)
1961 int s
= splserial();
1964 /* got a character from reading things earlier */
1965 if (plcom_readaheadcount
> 0) {
1968 c
= plcom_readahead
[0];
1969 for (i
= 1; i
< plcom_readaheadcount
; i
++) {
1970 plcom_readahead
[i
-1] = plcom_readahead
[i
];
1972 plcom_readaheadcount
--;
1977 /* block until a character becomes available */
1978 while (ISSET(stat
= bus_space_read_1(iot
, ioh
, plcom_fr
), FR_RXFE
))
1981 c
= bus_space_read_1(iot
, ioh
, plcom_dr
);
1982 stat
= bus_space_read_1(iot
, ioh
, plcom_iir
);
1984 int cn_trapped
= 0; /* unused */
1986 extern int db_active
;
1989 cn_check_magic(dev
, c
, plcom_cnm_state
);
1996 plcom_common_putc(dev_t dev
, bus_space_tag_t iot
, bus_space_handle_t ioh
,
1999 int s
= splserial();
2003 if (plcom_readaheadcount
< MAX_READAHEAD
2004 && !ISSET(stat
= bus_space_read_1(iot
, ioh
, plcom_fr
), FR_RXFE
)) {
2006 cin
= bus_space_read_1(iot
, ioh
, plcom_dr
);
2007 stat
= bus_space_read_1(iot
, ioh
, plcom_iir
);
2008 cn_check_magic(dev
, cin
, plcom_cnm_state
);
2009 plcom_readahead
[plcom_readaheadcount
++] = cin
;
2012 /* wait for any pending transmission to finish */
2014 while (!ISSET(bus_space_read_1(iot
, ioh
, plcom_fr
), FR_TXFE
) && --timo
)
2017 bus_space_write_1(iot
, ioh
, plcom_dr
, c
);
2018 PLCOM_BARRIER(iot
, ioh
, BR
| BW
);
2020 /* wait for this transmission to complete */
2022 while (!ISSET(bus_space_read_1(iot
, ioh
, plcom_fr
), FR_TXFE
) && --timo
)
2029 * Initialize UART for use as console or KGDB line.
2032 plcominit(bus_space_tag_t iot
, bus_addr_t iobase
, int rate
, int frequency
,
2033 tcflag_t cflag
, bus_space_handle_t
*iohp
)
2035 bus_space_handle_t ioh
;
2037 if (bus_space_map(iot
, iobase
, PLCOM_UART_SIZE
, 0, &ioh
))
2038 return ENOMEM
; /* ??? */
2040 rate
= plcomspeed(rate
, frequency
);
2041 bus_space_write_1(iot
, ioh
, plcom_cr
, 0);
2042 bus_space_write_1(iot
, ioh
, plcom_dlbl
, rate
);
2043 bus_space_write_1(iot
, ioh
, plcom_dlbh
, rate
>> 8);
2044 bus_space_write_1(iot
, ioh
, plcom_lcr
, cflag2lcr(cflag
) | LCR_FEN
);
2045 bus_space_write_1(iot
, ioh
, plcom_cr
, CR_UARTEN
);
2048 /* Ought to do something like this, but we have no sc to
2050 /* XXX device_unit() abuse */
2051 sc
->sc_set_mcr(sc
->sc_set_mcr_arg
, device_unit(&sc
->sc_dev
),
2060 * Following are all routines needed for PLCOM to act as console
2062 struct consdev plcomcons
= {
2063 NULL
, NULL
, plcomcngetc
, plcomcnputc
, plcomcnpollc
, NULL
,
2064 NULL
, NULL
, NODEV
, CN_NORMAL
2069 plcomcnattach(bus_space_tag_t iot
, bus_addr_t iobase
, int rate
, int frequency
,
2070 tcflag_t cflag
, int unit
)
2074 res
= plcominit(iot
, iobase
, rate
, frequency
, cflag
, &plcomconsioh
);
2078 cn_tab
= &plcomcons
;
2079 cn_init_magic(&plcom_cnm_state
);
2080 cn_set_magic("\047\001"); /* default magic is BREAK */
2083 plcomconsunit
= unit
;
2084 plcomconsrate
= rate
;
2085 plcomconscflag
= cflag
;
2093 bus_space_unmap(plcomconstag
, plcomconsioh
, PLCOM_UART_SIZE
);
2094 plcomconstag
= NULL
;
2100 plcomcngetc(dev_t dev
)
2102 return plcom_common_getc(dev
, plcomconstag
, plcomconsioh
);
2106 * Console kernel output character routine.
2109 plcomcnputc(dev_t dev
, int c
)
2111 plcom_common_putc(dev
, plcomconstag
, plcomconsioh
, c
);
2115 plcomcnpollc(dev_t dev
, int on
)
2122 plcom_kgdb_attach(bus_space_tag_t iot
, bus_addr_t iobase
, int rate
,
2123 int frequency
, tcflag_t cflag
, int unit
)
2127 if (iot
== plcomconstag
&& iobase
== plcomconsunit
)
2128 return EBUSY
; /* cannot share with console */
2130 res
= plcominit(iot
, iobase
, rate
, frequency
, cflag
, &plcom_kgdb_ioh
);
2134 kgdb_attach(plcom_kgdb_getc
, plcom_kgdb_putc
, NULL
);
2135 kgdb_dev
= 123; /* unneeded, only to satisfy some tests */
2137 plcom_kgdb_iot
= iot
;
2138 plcom_kgdb_unit
= unit
;
2145 plcom_kgdb_getc(void *arg
)
2147 return plcom_common_getc(NODEV
, plcom_kgdb_iot
, plcom_kgdb_ioh
);
2152 plcom_kgdb_putc(void *arg
, int c
)
2154 plcom_common_putc(NODEV
, plcom_kgdb_iot
, plcom_kgdb_ioh
, c
);
2158 /* helper function to identify the plcom ports used by
2159 console or KGDB (and not yet autoconf attached) */
2161 plcom_is_console(bus_space_tag_t iot
, int unit
,
2162 bus_space_handle_t
*ioh
)
2164 bus_space_handle_t help
;
2166 if (!plcomconsattached
&&
2167 iot
== plcomconstag
&& unit
== plcomconsunit
)
2168 help
= plcomconsioh
;
2170 else if (!plcom_kgdb_attached
&&
2171 iot
== plcom_kgdb_iot
&& unit
== plcom_kgdb_unit
)
2172 help
= plcom_kgdb_ioh
;