1 /* $NetBSD: sa11x0_com.c,v 1.45 2009/05/29 14:15:44 rjs Exp $ */
4 * Copyright (c) 1998, 1999, 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by IWAMOTO Toshihiro.
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by Charles M. Hannum.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
36 * Copyright (c) 1991 The Regents of the University of California.
37 * All rights reserved.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * @(#)com.c 7.5 (Berkeley) 5/16/91
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: sa11x0_com.c,v 1.45 2009/05/29 14:15:44 rjs Exp $");
71 #include "opt_ddbparam.h"
73 #include "opt_multiprocessor.h"
74 #include "opt_lockdebug.h"
77 #if NRND > 0 && defined(RND_COM)
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/types.h>
86 #include <sys/device.h>
87 #include <sys/kernel.h>
88 #include <sys/malloc.h>
91 #include <sys/vnode.h>
92 #include <sys/kauth.h>
96 #include <machine/bus.h>
97 #include <arm/sa11x0/sa11x0_reg.h>
98 #include <arm/sa11x0/sa11x0_var.h>
99 #include <arm/sa11x0/sa11x0_comreg.h>
100 #include <arm/sa11x0/sa11x0_comvar.h>
101 #include <arm/sa11x0/sa11x0_gpioreg.h>
104 #include <hpc/include/platid.h>
105 #include <hpc/include/platid_mask.h>
110 dev_type_open(sacomopen
);
111 dev_type_close(sacomclose
);
112 dev_type_read(sacomread
);
113 dev_type_write(sacomwrite
);
114 dev_type_ioctl(sacomioctl
);
115 dev_type_stop(sacomstop
);
116 dev_type_tty(sacomtty
);
117 dev_type_poll(sacompoll
);
119 const struct cdevsw sacom_cdevsw
= {
120 sacomopen
, sacomclose
, sacomread
, sacomwrite
, sacomioctl
,
121 sacomstop
, sacomtty
, sacompoll
, nommap
, ttykqfilter
, D_TTY
124 static int sacom_match(device_t
, cfdata_t
, void *);
125 static void sacom_attach(device_t
, device_t
, void *);
126 static void sacom_filltx(struct sacom_softc
*);
127 static void sacom_attach_subr(struct sacom_softc
*);
128 #if defined(DDB) || defined(KGDB)
129 static void sacom_enable_debugport(struct sacom_softc
*);
131 int sacom_detach(device_t
, int);
132 void sacom_config(struct sacom_softc
*);
133 int sacom_activate(device_t
, enum devact
);
134 void sacom_shutdown(struct sacom_softc
*);
135 static u_int
cflag2cr0(tcflag_t
);
136 int sacomparam(struct tty
*, struct termios
*);
137 void sacomstart(struct tty
*);
138 int sacomhwiflow(struct tty
*, int);
140 void sacom_loadchannelregs(struct sacom_softc
*);
141 void sacom_hwiflow(struct sacom_softc
*);
142 void sacom_break(struct sacom_softc
*, int);
143 void sacom_modem(struct sacom_softc
*, int);
144 void tiocm_to_sacom(struct sacom_softc
*, u_long
, int);
145 int sacom_to_tiocm(struct sacom_softc
*);
146 void sacom_iflush(struct sacom_softc
*);
148 int sacominit(bus_space_tag_t
, bus_addr_t
, int, tcflag_t
,
149 bus_space_handle_t
*);
150 int sacom_is_console(bus_space_tag_t
, bus_addr_t
,
151 bus_space_handle_t
*);
153 void sacomsoft(void *);
155 static inline void sacom_rxsoft(struct sacom_softc
*, struct tty
*);
156 static inline void sacom_txsoft(struct sacom_softc
*, struct tty
*);
157 static inline void sacom_stsoft(struct sacom_softc
*, struct tty
*);
158 static inline void sacom_schedrx(struct sacom_softc
*);
161 /* HPCARM specific functions */
162 static void sacom_j720_init(struct sa11x0_softc
*, struct sacom_softc
*);
165 #define COMUNIT_MASK 0x7ffff
166 #define COMDIALOUT_MASK 0x80000
168 #define COMUNIT(x) (minor(x) & COMUNIT_MASK)
169 #define COMDIALOUT(x) (minor(x) & COMDIALOUT_MASK)
171 #define COM_ISALIVE(sc) ((sc)->enabled != 0 && \
172 device_is_active((sc)->sc_dev))
174 #define COM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, COM_NPORTS, (f))
176 #define COM_UNLOCK(sc)
178 int sacomintr(void *);
179 int sacomcngetc(dev_t
);
180 void sacomcnputc(dev_t
, int);
181 void sacomcnpollc(dev_t
, int);
183 void sacomcnprobe(struct consdev
*);
184 void sacomcninit(struct consdev
*);
186 extern struct bus_space sa11x0_bs_tag
;
188 static bus_space_tag_t sacomconstag
;
189 static bus_space_handle_t sacomconsioh
;
190 static bus_addr_t sacomconsaddr
= SACOM3_BASE
; /* XXX */
192 static int sacomconsattached
;
193 static int sacomconsrate
;
194 static tcflag_t sacomconscflag
;
196 CFATTACH_DECL_NEW(sacom
, sizeof(struct sacom_softc
),
197 sacom_match
, sacom_attach
, NULL
, NULL
);
198 extern struct cfdriver sacom_cd
;
201 struct platid_data sacom_platid_table
[] = {
202 { &platid_mask_MACH_HP_JORNADA_7XX
, sacom_j720_init
},
207 struct consdev sacomcons
= {
208 NULL
, NULL
, sacomcngetc
, sacomcnputc
, sacomcnpollc
, NULL
,
209 NULL
, NULL
, NODEV
, CN_NORMAL
213 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
216 #define CONSPEED 9600
219 #define CONADDR SACOM3_BASE
223 sacom_match(device_t parent
, cfdata_t match
, void *aux
)
230 sacom_attach(device_t parent
, device_t self
, void *aux
)
232 struct sacom_softc
*sc
= device_private(self
);
233 struct sa11x0_attach_args
*sa
= aux
;
236 struct platid_data
*p
;
237 void (*mdinit
)(device_t
, struct sacom_softc
*);
243 sc
->sc_iot
= sa
->sa_iot
;
244 sc
->sc_baseaddr
= sa
->sa_addr
;
246 if (bus_space_map(sa
->sa_iot
, sa
->sa_addr
, sa
->sa_size
, 0,
248 aprint_normal_dev(self
, "unable to map registers\n");
252 switch (sc
->sc_baseaddr
) {
254 aprint_normal_dev(self
, "SA-11x0 UART1\n");
257 aprint_normal_dev(self
, "SA-11x0 UART2 (IRDA)\n");
260 aprint_normal_dev(self
, "SA-11x0 UART3\n");
263 aprint_normal_dev(self
, "unknown SA-11x0 UART\n");
267 sacom_attach_subr(sc
);
270 /* Do hpcarm specific initialization, if any */
271 if ((p
= platid_search_data(&platid
, sacom_platid_table
)) != NULL
) {
273 (mdinit
)(parent
, sc
);
277 sa11x0_intr_establish(0, sa
->sa_intr
, 1, IPL_SERIAL
, sacomintr
, sc
);
281 sacom_attach_subr(struct sacom_softc
*sc
)
283 bus_addr_t iobase
= sc
->sc_baseaddr
;
284 bus_space_tag_t iot
= sc
->sc_iot
;
287 /* XXX Do we need to disable interrupts here? */
289 if (iot
== sacomconstag
&& iobase
== sacomconsaddr
) {
290 sacomconsattached
= 1;
291 sc
->sc_speed
= SACOMSPEED(sacomconsrate
);
293 /* Make sure the console is always "hardwired". */
294 delay(10000); /* wait for output to finish */
295 SET(sc
->sc_hwflags
, COM_HW_CONSOLE
);
296 SET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
);
300 tp
->t_oproc
= sacomstart
;
301 tp
->t_param
= sacomparam
;
302 tp
->t_hwiflow
= sacomhwiflow
;
305 sc
->sc_rbuf
= malloc(SACOM_RING_SIZE
<< 1, M_DEVBUF
, M_NOWAIT
);
306 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
307 sc
->sc_rbavail
= SACOM_RING_SIZE
;
308 if (sc
->sc_rbuf
== NULL
) {
309 aprint_normal_dev(sc
->sc_dev
, "unable to allocate ring buffer\n");
312 sc
->sc_ebuf
= sc
->sc_rbuf
+ (SACOM_RING_SIZE
<< 1);
317 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
320 /* locate the major number */
321 maj
= cdevsw_lookup_major(&sacom_cdevsw
);
323 cn_tab
->cn_dev
= makedev(maj
, device_unit(sc
->sc_dev
));
325 delay(10000); /* XXX */
326 aprint_normal_dev(sc
->sc_dev
, "console\n");
327 delay(10000); /* XXX */
331 sc
->sc_si
= softint_establish(SOFTINT_SERIAL
, sacomsoft
, sc
);
333 #if NRND > 0 && defined(RND_COM)
334 rnd_attach_source(&sc
->rnd_source
, device_xname(sc
->sc_dev
),
338 /* if there are no enable/disable functions, assume the device
345 SET(sc
->sc_hwflags
, COM_HW_DEV_OK
);
348 /* This is necessary when dynamically changing SAIP configuration. */
350 sacom_detach(device_t dev
, int flags
)
352 struct sacom_softc
*sc
= device_private(dev
);
355 if (sc
->sc_hwflags
& (COM_HW_CONSOLE
|COM_HW_KGDB
))
358 if (sc
->disable
!= NULL
&& sc
->enabled
!= 0) {
363 /* locate the major number */
364 maj
= cdevsw_lookup_major(&sacom_cdevsw
);
366 /* Nuke the vnodes for any open instances. */
367 mn
= device_unit(dev
);
368 vdevgone(maj
, mn
, mn
, VCHR
);
370 mn
|= COMDIALOUT_MASK
;
371 vdevgone(maj
, mn
, mn
, VCHR
);
373 /* Free the receive buffer. */
374 free(sc
->sc_rbuf
, M_DEVBUF
);
376 /* Detach and free the tty. */
377 tty_detach(sc
->sc_tty
);
380 /* Unhook the soft interrupt handler. */
381 softint_disestablish(sc
->sc_si
);
383 #if NRND > 0 && defined(RND_COM)
384 /* Unhook the entropy source. */
385 rnd_detach_source(&sc
->rnd_source
);
392 sacom_config(struct sacom_softc
*sc
)
394 bus_space_tag_t iot
= sc
->sc_iot
;
395 bus_space_handle_t ioh
= sc
->sc_ioh
;
397 /* Disable engine before configuring the device. */
399 bus_space_write_4(iot
, ioh
, SACOM_CR3
, sc
->sc_cr3
);
402 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
))
403 sacom_enable_debugport(sc
);
409 sacom_enable_debugport(struct sacom_softc
*sc
)
411 bus_space_tag_t iot
= sc
->sc_iot
;
412 bus_space_handle_t ioh
= sc
->sc_ioh
;
417 sc
->sc_cr3
= CR3_RXE
| CR3_TXE
;
418 bus_space_write_4(iot
, ioh
, SACOM_CR3
, sc
->sc_cr3
);
425 sacom_activate(device_t dev
, enum devact act
)
427 struct sacom_softc
*sc
= device_private(dev
);
430 case DVACT_DEACTIVATE
:
439 sacom_shutdown(struct sacom_softc
*sc
)
441 struct tty
*tp
= sc
->sc_tty
;
447 /* Clear any break condition set with TIOCSBRK. */
451 * Hang up if necessary. Wait a bit, so the other side has time to
452 * notice even if we immediately open the port again.
453 * Avoid tsleeping above splhigh().
455 if (ISSET(tp
->t_cflag
, HUPCL
)) {
459 /* XXX tsleep will only timeout */
460 (void) tsleep(sc
, TTIPRI
, ttclos
, hz
);
465 /* Turn off interrupts. */
467 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, SACOM_CR3
, sc
->sc_cr3
);
472 panic("sacom_shutdown: not enabled?");
482 sacomopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
484 struct sacom_softc
*sc
;
489 sc
= device_lookup_private(&sacom_cd
, COMUNIT(dev
));
490 if (sc
== NULL
|| !ISSET(sc
->sc_hwflags
, COM_HW_DEV_OK
) ||
494 if (!device_is_active(sc
->sc_dev
))
499 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
505 * Do the following iff this is a first open.
507 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
516 if ((*sc
->enable
)(sc
)) {
520 aprint_normal_dev(sc
->sc_dev
, "device enable failed\n");
527 /* Turn on interrupts. */
528 sc
->sc_cr3
= CR3_RXE
| CR3_TXE
| CR3_RIE
| CR3_TIE
;
529 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, SACOM_CR3
,
537 * Initialize the termios status to the defaults. Add in the
538 * sticky bits from TIOCSFLAGS.
541 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
542 t
.c_ospeed
= sacomconsrate
;
543 t
.c_cflag
= sacomconscflag
;
545 t
.c_ospeed
= TTYDEF_SPEED
;
546 t
.c_cflag
= TTYDEF_CFLAG
;
548 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CLOCAL
))
549 SET(t
.c_cflag
, CLOCAL
);
550 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
551 SET(t
.c_cflag
, CRTSCTS
);
552 if (ISSET(sc
->sc_swflags
, TIOCFLAG_MDMBUF
))
553 SET(t
.c_cflag
, MDMBUF
);
554 /* Make sure sacomparam() will do something. */
556 (void) sacomparam(tp
, &t
);
557 tp
->t_iflag
= TTYDEF_IFLAG
;
558 tp
->t_oflag
= TTYDEF_OFLAG
;
559 tp
->t_lflag
= TTYDEF_LFLAG
;
567 * Turn on DTR. We must always do this, even if carrier is not
568 * present, because otherwise we'd have to use TIOCSDTR
569 * immediately after setting CLOCAL, which applications do not
570 * expect. We always assert DTR while the device is open
571 * unless explicitly requested to deassert it.
575 /* Clear the input ring, and unblock. */
576 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
577 sc
->sc_rbavail
= SACOM_RING_SIZE
;
579 CLR(sc
->sc_rx_flags
, RX_ANY_BLOCK
);
584 comstatus(sc
, "sacomopen ");
593 error
= ttyopen(tp
, COMDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
597 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
604 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
606 * We failed to open the device, and nobody else had it opened.
607 * Clean up the state as appropriate.
616 sacomclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
618 struct sacom_softc
*sc
=
619 device_lookup_private(&sacom_cd
, COMUNIT(dev
));
620 struct tty
*tp
= sc
->sc_tty
;
622 /* XXX This is for cons.c. */
623 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
626 (*tp
->t_linesw
->l_close
)(tp
, flag
);
629 if (COM_ISALIVE(sc
) == 0)
632 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
634 * Although we got a last close, the device may still be in
635 * use; e.g. if this was the dialout node, and there are still
636 * processes waiting for carrier on the non-dialout node.
645 sacomread(dev_t dev
, struct uio
*uio
, int flag
)
647 struct sacom_softc
*sc
=
648 device_lookup_private(&sacom_cd
, COMUNIT(dev
));
649 struct tty
*tp
= sc
->sc_tty
;
651 if (COM_ISALIVE(sc
) == 0)
654 return (*tp
->t_linesw
->l_read
)(tp
, uio
, flag
);
658 sacomwrite(dev_t dev
, struct uio
*uio
, int flag
)
660 struct sacom_softc
*sc
=
661 device_lookup_private(&sacom_cd
, COMUNIT(dev
));
662 struct tty
*tp
= sc
->sc_tty
;
664 if (COM_ISALIVE(sc
) == 0)
667 return (*tp
->t_linesw
->l_write
)(tp
, uio
, flag
);
671 sacompoll(dev_t dev
, int events
, struct lwp
*l
)
673 struct sacom_softc
*sc
=
674 device_lookup_private(&sacom_cd
, COMUNIT(dev
));
675 struct tty
*tp
= sc
->sc_tty
;
677 if (COM_ISALIVE(sc
) == 0)
680 return (*tp
->t_linesw
->l_poll
)(tp
, events
, l
);
686 struct sacom_softc
*sc
=
687 device_lookup_private(&sacom_cd
, COMUNIT(dev
));
688 struct tty
*tp
= sc
->sc_tty
;
694 sacomioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
696 struct sacom_softc
*sc
=
697 device_lookup_private(&sacom_cd
, COMUNIT(dev
));
698 struct tty
*tp
= sc
->sc_tty
;
702 if (COM_ISALIVE(sc
) == 0)
705 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
706 if (error
!= EPASSTHROUGH
)
709 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
710 if (error
!= EPASSTHROUGH
)
736 *(int *)data
= sc
->sc_swflags
;
740 error
= kauth_authorize_device_tty(l
->l_cred
,
741 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
744 sc
->sc_swflags
= *(int *)data
;
750 tiocm_to_sacom(sc
, cmd
, *(int *)data
);
754 *(int *)data
= sacom_to_tiocm(sc
);
758 error
= EPASSTHROUGH
;
767 comstatus(sc
, "comioctl ");
774 sacom_schedrx(struct sacom_softc
*sc
)
779 /* Wake up the poller. */
780 softint_schedule(sc
->sc_si
);
784 sacom_break(struct sacom_softc
*sc
, int onoff
)
788 SET(sc
->sc_cr3
, CR3_BRK
);
790 CLR(sc
->sc_cr3
, CR3_BRK
);
792 if (!sc
->sc_heldchange
) {
793 if (sc
->sc_tx_busy
) {
794 sc
->sc_heldtbc
= sc
->sc_tbc
;
796 sc
->sc_heldchange
= 1;
798 sacom_loadchannelregs(sc
);
803 sacom_modem(struct sacom_softc
*sc
, int onoff
)
805 if (!sc
->sc_heldchange
) {
806 if (sc
->sc_tx_busy
) {
807 sc
->sc_heldtbc
= sc
->sc_tbc
;
809 sc
->sc_heldchange
= 1;
811 sacom_loadchannelregs(sc
);
816 tiocm_to_sacom(struct sacom_softc
*sc
, u_long how
, int ttybits
)
821 sacom_to_tiocm(struct sacom_softc
*sc
)
826 SET(ttybits
, TIOCM_LE
);
832 cflag2cr0(tcflag_t cflag
)
836 cr0
= (cflag
& PARENB
) ? CR0_PE
: 0;
837 cr0
|= (cflag
& PARODD
) ? 0 : CR0_OES
;
838 cr0
|= (cflag
& CSTOPB
) ? CR0_SBS
: 0;
839 cr0
|= ((cflag
& CSIZE
) == CS8
) ? CR0_DSS
: 0;
845 sacomparam(struct tty
*tp
, struct termios
*t
)
847 struct sacom_softc
*sc
=
848 device_lookup_private(&sacom_cd
, COMUNIT(tp
->t_dev
));
849 int ospeed
= SACOMSPEED(t
->c_ospeed
);
853 if (COM_ISALIVE(sc
) == 0)
856 /* Check requested parameters. */
859 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
863 * For the console, always force CLOCAL and !HUPCL, so that the port
866 if (ISSET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
867 ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
868 SET(t
->c_cflag
, CLOCAL
);
869 CLR(t
->c_cflag
, HUPCL
);
873 * If there were no changes, don't do anything. This avoids dropping
874 * input and improves performance when all we did was frob things like
877 if (tp
->t_ospeed
== t
->c_ospeed
&&
878 tp
->t_cflag
== t
->c_cflag
)
881 cr0
= cflag2cr0(t
->c_cflag
);
888 sc
->sc_speed
= ospeed
;
890 /* And copy to tty. */
892 tp
->t_ospeed
= t
->c_ospeed
;
893 tp
->t_cflag
= t
->c_cflag
;
895 if (!sc
->sc_heldchange
) {
896 if (sc
->sc_tx_busy
) {
897 sc
->sc_heldtbc
= sc
->sc_tbc
;
899 sc
->sc_heldchange
= 1;
901 sacom_loadchannelregs(sc
);
904 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
905 /* Disable the high water mark. */
906 if (ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
)) {
907 CLR(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
910 if (ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
)) {
911 CLR(sc
->sc_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
);
919 (void) (*tp
->t_linesw
->l_modem
)(tp
, 1);
923 comstatus(sc
, "comparam ");
930 sacom_iflush(struct sacom_softc
*sc
)
932 bus_space_tag_t iot
= sc
->sc_iot
;
933 bus_space_handle_t ioh
= sc
->sc_ioh
;
943 /* flush any pending I/O */
944 if (sc
->sc_cr3
& CR3_RXE
) {
945 while (ISSET(bus_space_read_4(iot
, ioh
, SACOM_SR1
), SR1_RNE
)
952 bus_space_read_4(iot
, ioh
, SACOM_DR
);
955 /* XXX is it good idea to wait TX finish? */
956 if (sc
->sc_cr3
& CR3_TXE
) {
958 while (ISSET(bus_space_read_4(iot
, ioh
, SACOM_SR1
), SR1_TBY
)
965 aprint_debug_dev(sc
->sc_dev
, "sacom_iflush timeout %02x\n", reg
);
970 sacom_loadchannelregs(struct sacom_softc
*sc
)
972 bus_space_tag_t iot
= sc
->sc_iot
;
973 bus_space_handle_t ioh
= sc
->sc_ioh
;
975 /* XXXXX necessary? */
978 /* Need to stop engines first. */
979 bus_space_write_4(iot
, ioh
, SACOM_CR3
, 0);
981 bus_space_write_4(iot
, ioh
, SACOM_CR1
, sc
->sc_speed
>> 8);
982 bus_space_write_4(iot
, ioh
, SACOM_CR2
, sc
->sc_speed
& 0xff);
984 bus_space_write_4(iot
, ioh
, SACOM_CR0
, sc
->sc_cr0
);
985 bus_space_write_4(iot
, ioh
, SACOM_CR3
, sc
->sc_cr3
);
989 sacomhwiflow(struct tty
*tp
, int block
)
992 struct sacom_softc
*sc
=
993 device_lookup_private(&sacom_cd
, COMUNIT(tp
->t_dev
));
996 if (COM_ISALIVE(sc
) == 0)
999 if (sc
->sc_mcr_rts
== 0)
1006 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1007 SET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
);
1011 if (ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
)) {
1012 CLR(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1015 if (ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1016 CLR(sc
->sc_rx_flags
, RX_TTY_BLOCKED
);
1028 * (un)block input via hw flowcontrol
1031 sacom_hwiflow(struct sacom_softc
*sc
)
1034 bus_space_tag_t iot
= sc
->sc_iot
;
1035 bus_space_handle_t ioh
= sc
->sc_ioh
;
1043 sacomstart(struct tty
*tp
)
1045 struct sacom_softc
*sc
=
1046 device_lookup_private(&sacom_cd
, COMUNIT(tp
->t_dev
));
1047 bus_space_tag_t iot
= sc
->sc_iot
;
1048 bus_space_handle_t ioh
= sc
->sc_ioh
;
1051 if (COM_ISALIVE(sc
) == 0)
1055 if (ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
))
1060 /* Grab the first contiguous region of buffer space. */
1065 tba
= tp
->t_outq
.c_cf
;
1066 tbc
= ndqb(&tp
->t_outq
, 0);
1075 SET(tp
->t_state
, TS_BUSY
);
1078 /* Enable transmit completion interrupts if necessary. */
1079 if (!ISSET(sc
->sc_cr3
, CR3_TIE
)) {
1080 SET(sc
->sc_cr3
, CR3_TIE
);
1081 bus_space_write_4(iot
, ioh
, SACOM_CR3
, sc
->sc_cr3
);
1084 /* Output the first chunk of the contiguous buffer. */
1094 sacom_filltx(struct sacom_softc
*sc
)
1096 bus_space_tag_t iot
= sc
->sc_iot
;
1097 bus_space_handle_t ioh
= sc
->sc_ioh
;
1101 while (bus_space_read_4(iot
, ioh
, SACOM_SR1
) & SR1_TNF
) {
1102 if (n
== SACOM_TXFIFOLEN
|| n
== sc
->sc_tbc
)
1104 c
= *(sc
->sc_tba
+ n
);
1106 bus_space_write_4(iot
, ioh
, SACOM_DR
, c
);
1114 * Stop output on a line.
1117 sacomstop(struct tty
*tp
, int flag
)
1119 struct sacom_softc
*sc
=
1120 device_lookup_private(&sacom_cd
, COMUNIT(tp
->t_dev
));
1125 if (ISSET(tp
->t_state
, TS_BUSY
)) {
1126 /* Stop transmitting at the next chunk. */
1129 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
1130 SET(tp
->t_state
, TS_FLUSH
);
1137 sacom_rxsoft(struct sacom_softc
*sc
, struct tty
*tp
)
1139 int (*rint
)(int, struct tty
*) = tp
->t_linesw
->l_rint
;
1148 scc
= cc
= SACOM_RING_SIZE
- sc
->sc_rbavail
;
1153 if (ISSET(sr1
, SR1_FRE
))
1155 if (ISSET(sr1
, SR1_PRE
))
1157 if ((*rint
)(code
, tp
) == -1) {
1159 * The line discipline's buffer is out of space.
1161 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
1163 * We're either not using flow control, or the
1164 * line discipline didn't tell us to block for
1165 * some reason. Either way, we have no way to
1166 * know when there's more space available, so
1167 * just drop the rest of the data.
1171 get
-= SACOM_RING_SIZE
<< 1;
1175 * Don't schedule any more receive processing
1176 * until the line discipline tells us there's
1177 * space available (through comhwiflow()).
1178 * Leave the rest of the data in the input
1181 SET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1196 cc
= sc
->sc_rbavail
+= scc
- cc
;
1197 /* Buffers should be ok again, release possible block. */
1199 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1200 CLR(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1201 SET(sc
->sc_cr3
, CR3_RIE
);
1202 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
,
1203 SACOM_CR3
, sc
->sc_cr3
);
1212 sacom_txsoft(struct sacom_softc
*sc
, struct tty
*tp
)
1215 CLR(tp
->t_state
, TS_BUSY
);
1216 if (ISSET(tp
->t_state
, TS_FLUSH
))
1217 CLR(tp
->t_state
, TS_FLUSH
);
1219 ndflush(&tp
->t_outq
, (int)(sc
->sc_tba
- tp
->t_outq
.c_cf
));
1220 (*tp
->t_linesw
->l_start
)(tp
);
1224 sacom_stsoft(struct sacom_softc
*sc
, struct tty
*tp
)
1229 sacomsoft(void *arg
)
1231 struct sacom_softc
*sc
= arg
;
1234 if (COM_ISALIVE(sc
) == 0)
1239 if (sc
->sc_rx_ready
) {
1240 sc
->sc_rx_ready
= 0;
1241 sacom_rxsoft(sc
, tp
);
1244 if (sc
->sc_st_check
) {
1245 sc
->sc_st_check
= 0;
1246 sacom_stsoft(sc
, tp
);
1249 if (sc
->sc_tx_done
) {
1251 sacom_txsoft(sc
, tp
);
1256 sacomintr(void *arg
)
1258 struct sacom_softc
*sc
= arg
;
1259 bus_space_tag_t iot
= sc
->sc_iot
;
1260 bus_space_handle_t ioh
= sc
->sc_ioh
;
1265 if (COM_ISALIVE(sc
) == 0)
1269 sr0
= bus_space_read_4(iot
, ioh
, SACOM_SR0
);
1274 if (ISSET(sr0
, SR0_EIF
))
1275 /* XXX silently discard error bits */
1276 bus_space_read_4(iot
, ioh
, SACOM_DR
);
1277 if (ISSET(sr0
, SR0_RBB
))
1278 bus_space_write_4(iot
, ioh
, SACOM_SR0
, SR0_RBB
);
1279 if (ISSET(sr0
, SR0_REB
)) {
1280 bus_space_write_4(iot
, ioh
, SACOM_SR0
, SR0_REB
);
1281 #if defined(DDB) || defined(KGDB)
1282 #ifndef DDB_BREAK_CHAR
1283 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
1287 #endif /* DDB || KGDB */
1293 cc
= sc
->sc_rbavail
;
1295 sr1
= bus_space_read_4(iot
, ioh
, SACOM_SR1
);
1296 if (ISSET(sr0
, SR0_RFS
| SR0_RID
)) {
1297 if (!ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1299 if (!ISSET(sr1
, SR1_RNE
)) {
1300 bus_space_write_4(iot
, ioh
, SACOM_SR0
,
1304 put
[0] = bus_space_read_4(iot
, ioh
, SACOM_DR
);
1306 #if defined(DDB) && defined(DDB_BREAK_CHAR)
1307 if (put
[0] == DDB_BREAK_CHAR
&&
1308 ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
1311 sr1
= bus_space_read_4(iot
, ioh
, SACOM_SR1
);
1320 sr1
= bus_space_read_4(iot
, ioh
, SACOM_SR1
);
1324 * Current string of incoming characters ended because
1325 * no more data was available or we ran out of space.
1326 * Schedule a receive event if any data was received.
1327 * If we're out of space, turn off receive interrupts.
1330 sc
->sc_rbavail
= cc
;
1331 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
))
1332 sc
->sc_rx_ready
= 1;
1334 /* XXX do RX hardware flow control */
1337 * If we're out of space, disable receive interrupts
1338 * until the queue has drained a bit.
1341 SET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1342 CLR(sc
->sc_cr3
, CR3_RIE
);
1343 bus_space_write_4(iot
, ioh
, SACOM_CR3
,
1348 panic("sacomintr: we shouldn't reach here");
1350 CLR(sc
->sc_cr3
, CR3_RIE
);
1351 bus_space_write_4(iot
, ioh
, SACOM_CR3
, sc
->sc_cr3
);
1356 * Done handling any receive interrupts. See if data can be
1357 * transmitted as well. Schedule tx done event if no data left
1358 * and tty was marked busy.
1360 sr0
= bus_space_read_4(iot
, ioh
, SACOM_SR0
);
1361 if (ISSET(sr0
, SR0_TFS
)) {
1363 * If we've delayed a parameter change, do it now, and restart
1365 * XXX sacom_loadchannelregs() waits TX completion,
1366 * XXX resulting in ~0.1s hang (300bps, 4 bytes) in worst case
1368 if (sc
->sc_heldchange
) {
1369 sacom_loadchannelregs(sc
);
1370 sc
->sc_heldchange
= 0;
1371 sc
->sc_tbc
= sc
->sc_heldtbc
;
1375 /* Output the next chunk of the contiguous buffer, if any. */
1376 if (sc
->sc_tbc
> 0) {
1379 /* Disable transmit completion interrupts if necessary. */
1380 if (ISSET(sc
->sc_cr3
, CR3_TIE
)) {
1381 CLR(sc
->sc_cr3
, CR3_TIE
);
1382 bus_space_write_4(iot
, ioh
, SACOM_CR3
,
1385 if (sc
->sc_tx_busy
) {
1393 /* Wake up the poller. */
1394 softint_schedule(sc
->sc_si
);
1396 #if NRND > 0 && defined(RND_COM)
1397 rnd_add_uint32(&sc
->rnd_source
, iir
| lsr
);
1403 sacom_j720_init(struct sa11x0_softc
*parent
, struct sacom_softc
*sc
) {
1405 /* XXX this should be done at sc->enable function */
1406 bus_space_write_4(parent
->sc_iot
, parent
->sc_gpioh
,
1407 SAGPIO_PCR
, 0xa0000);
1408 bus_space_write_4(parent
->sc_iot
, parent
->sc_gpioh
,
1412 /* Initialization for serial console */
1414 sacominit(bus_space_tag_t iot
, bus_addr_t iobase
, int baud
, tcflag_t cflag
,
1415 bus_space_handle_t
*iohp
)
1419 if (bus_space_map(iot
, iobase
, SACOM_NPORTS
, 0, iohp
))
1420 aprint_normal("register map failed\n");
1422 /* wait for the Tx queue to drain and disable the UART */
1423 while (bus_space_read_4(iot
, *iohp
, SACOM_SR1
) & SR1_TBY
)
1425 bus_space_write_4(iot
, *iohp
, SACOM_CR3
, 0);
1427 cr0
= cflag2cr0(cflag
);
1428 bus_space_write_4(iot
, *iohp
, SACOM_CR0
, cr0
);
1430 brd
= SACOMSPEED(baud
);
1431 sacomconsrate
= baud
;
1432 sacomconsaddr
= iobase
;
1433 sacomconscflag
= cflag
;
1434 /* XXX assumes little endian */
1435 bus_space_write_4(iot
, *iohp
, SACOM_CR1
, brd
>> 8);
1436 bus_space_write_4(iot
, *iohp
, SACOM_CR2
, brd
& 0xff);
1438 /* enable the UART */
1439 bus_space_write_4(iot
, *iohp
, SACOM_CR3
, CR3_RXE
| CR3_TXE
);
1445 sacomcnprobe(struct consdev
*cp
)
1447 cp
->cn_pri
= CN_REMOTE
;
1451 sacomcninit(struct consdev
*cp
)
1454 /* XXX cp == NULL means that MMU is disabled. */
1455 sacomconsioh
= SACOM3_BASE
;
1456 sacomconstag
= &sa11x0_bs_tag
;
1457 cn_tab
= &sacomcons
;
1461 if (sacominit(&sa11x0_bs_tag
, CONADDR
, CONSPEED
,
1462 CONMODE
, &sacomconsioh
))
1463 panic("can't init serial console @%x", CONADDR
);
1464 cn_tab
= &sacomcons
;
1465 sacomconstag
= &sa11x0_bs_tag
;
1469 sacomcngetc(dev_t dev
)
1473 s
= spltty(); /* XXX do we need this? */
1475 while (!(bus_space_read_4(sacomconstag
, sacomconsioh
, SACOM_SR1
)
1477 #if defined(DDB) || defined(KGDB)
1478 #ifndef DDB_BREAK_CHAR
1480 extern int db_active
;
1482 sr0
= bus_space_read_4(sacomconstag
, sacomconsioh
, SACOM_SR0
);
1483 if (ISSET(sr0
, SR0_RBB
))
1484 bus_space_write_4(sacomconstag
, sacomconsioh
,
1485 SACOM_SR0
, SR0_RBB
);
1486 if (ISSET(sr0
, SR0_REB
)) {
1487 bus_space_write_4(sacomconstag
, sacomconsioh
,
1488 SACOM_SR0
, SR0_REB
);
1493 #endif /* DDB || KGDB */
1496 c
= bus_space_read_4(sacomconstag
, sacomconsioh
, SACOM_DR
);
1504 sacomcnputc(dev_t dev
, int c
)
1508 s
= spltty(); /* XXX do we need this? */
1510 while (!(bus_space_read_4(sacomconstag
, sacomconsioh
, SACOM_SR1
)
1514 bus_space_write_4(sacomconstag
, sacomconsioh
, SACOM_DR
, c
);
1519 sacomcnpollc(dev_t dev
, int on
)
1527 sacomcncharpoll(void)
1531 if (!(bus_space_read_4(sacomconstag
, sacomconsioh
, SACOM_SR1
)
1535 c
= bus_space_read_4(sacomconstag
, sacomconsioh
, SACOM_DR
);
1543 /* helper function to identify the com ports used by
1544 console or KGDB (and not yet autoconf attached) */
1546 sacom_is_console(bus_space_tag_t iot
, bus_addr_t iobase
,
1547 bus_space_handle_t
*ioh
)
1549 bus_space_handle_t help
;
1551 if (!sacomconsattached
&&
1552 iot
== sacomconstag
&& iobase
== sacomconsaddr
)
1553 help
= sacomconsioh
;