1 /* $NetBSD: epcom.c,v 1.18 2008/06/11 22:37:21 cegger Exp $ */
3 * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Ichiro FUKUHARA and Naoto Shimazaki.
12 * This code is derived from software contributed to The NetBSD Foundation
13 * by IWAMOTO Toshihiro.
15 * This code is derived from software contributed to The NetBSD Foundation
16 * by Charles M. Hannum.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
41 * Copyright (c) 1991 The Regents of the University of California.
42 * All rights reserved.
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * @(#)com.c 7.5 (Berkeley) 5/16/91
72 * TODO: hardware flow control
75 #include <sys/cdefs.h>
76 __KERNEL_RCSID(0, "$NetBSD: epcom.c,v 1.18 2008/06/11 22:37:21 cegger Exp $");
83 #if NRND > 0 && defined(RND_COM)
88 * Override cnmagic(9) macro before including <sys/systm.h>.
89 * We need to know if cn_check_magic triggered debugger, so set a flag.
90 * Callers of cn_check_magic must declare int cn_trapped = 0;
91 * XXX: this is *ugly*!
97 } while (/* CONSTCOND */ 0)
100 #include <sys/param.h>
101 #include <sys/systm.h>
102 #include <sys/types.h>
103 #include <sys/conf.h>
104 #include <sys/file.h>
105 #include <sys/device.h>
106 #include <sys/kernel.h>
107 #include <sys/malloc.h>
110 #include <sys/vnode.h>
111 #include <sys/kauth.h>
113 #include <machine/intr.h>
114 #include <machine/bus.h>
116 #include <arm/ep93xx/epcomreg.h>
117 #include <arm/ep93xx/epcomvar.h>
118 #include <arm/ep93xx/ep93xxreg.h>
119 #include <arm/ep93xx/ep93xxvar.h>
121 #include <dev/cons.h>
123 static int epcomparam(struct tty
*, struct termios
*);
124 static void epcomstart(struct tty
*);
125 static int epcomhwiflow(struct tty
*, int);
127 static u_int
cflag2lcrhi(tcflag_t
);
128 static void epcom_iflush(struct epcom_softc
*);
129 static void epcom_set(struct epcom_softc
*);
131 int epcomcngetc(dev_t
);
132 void epcomcnputc(dev_t
, int);
133 void epcomcnpollc(dev_t
, int);
135 static void epcomsoft(void* arg
);
136 inline static void epcom_txsoft(struct epcom_softc
*, struct tty
*);
137 inline static void epcom_rxsoft(struct epcom_softc
*, struct tty
*);
139 void epcomcnprobe(struct consdev
*);
140 void epcomcninit(struct consdev
*);
142 static struct epcom_cons_softc
{
143 bus_space_tag_t sc_iot
;
144 bus_space_handle_t sc_ioh
;
145 bus_addr_t sc_hwbase
;
151 static struct cnm_state epcom_cnm_state
;
153 extern struct cfdriver epcom_cd
;
155 dev_type_open(epcomopen
);
156 dev_type_close(epcomclose
);
157 dev_type_read(epcomread
);
158 dev_type_write(epcomwrite
);
159 dev_type_ioctl(epcomioctl
);
160 dev_type_stop(epcomstop
);
161 dev_type_tty(epcomtty
);
162 dev_type_poll(epcompoll
);
164 const struct cdevsw epcom_cdevsw
= {
165 epcomopen
, epcomclose
, epcomread
, epcomwrite
, epcomioctl
,
166 epcomstop
, epcomtty
, epcompoll
, nommap
, ttykqfilter
, D_TTY
169 struct consdev epcomcons
= {
170 NULL
, NULL
, epcomcngetc
, epcomcnputc
, epcomcnpollc
, NULL
,
171 NULL
, NULL
, NODEV
, CN_NORMAL
174 #ifndef DEFAULT_COMSPEED
175 #define DEFAULT_COMSPEED 115200
178 #define COMUNIT_MASK 0x7ffff
179 #define COMDIALOUT_MASK 0x80000
181 #define COMUNIT(x) (minor(x) & COMUNIT_MASK)
182 #define COMDIALOUT(x) (minor(x) & COMDIALOUT_MASK)
184 #define COM_ISALIVE(sc) ((sc)->enabled != 0 && \
185 device_is_active(&(sc)->sc_dev))
188 epcom_attach_subr(struct epcom_softc
*sc
)
192 if (sc
->sc_iot
== epcomcn_sc
.sc_iot
193 && sc
->sc_hwbase
== epcomcn_sc
.sc_hwbase
) {
194 epcomcn_sc
.sc_attached
= 1;
195 sc
->sc_lcrlo
= EPCOMSPEED2BRD(epcomcn_sc
.sc_ospeed
) & 0xff;
196 sc
->sc_lcrmid
= EPCOMSPEED2BRD(epcomcn_sc
.sc_ospeed
) >> 8;
198 /* Make sure the console is always "hardwired". */
199 delay(10000); /* wait for output to finish */
200 SET(sc
->sc_hwflags
, COM_HW_CONSOLE
);
201 SET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
);
205 tp
->t_oproc
= epcomstart
;
206 tp
->t_param
= epcomparam
;
207 tp
->t_hwiflow
= epcomhwiflow
;
210 sc
->sc_rbuf
= malloc(EPCOM_RING_SIZE
<< 1, M_DEVBUF
, M_NOWAIT
);
211 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
212 sc
->sc_rbavail
= EPCOM_RING_SIZE
;
213 if (sc
->sc_rbuf
== NULL
) {
214 printf("%s: unable to allocate ring buffer\n",
215 sc
->sc_dev
.dv_xname
);
218 sc
->sc_ebuf
= sc
->sc_rbuf
+ (EPCOM_RING_SIZE
<< 1);
221 sc
->sc_lcrlo
= EPCOMSPEED2BRD(DEFAULT_COMSPEED
) & 0xff;
222 sc
->sc_lcrmid
= EPCOMSPEED2BRD(DEFAULT_COMSPEED
) >> 8;
223 sc
->sc_lcrhi
= cflag2lcrhi(CS8
); /* 8N1 */
227 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
230 /* locate the major number */
231 maj
= cdevsw_lookup_major(&epcom_cdevsw
);
233 cn_tab
->cn_dev
= makedev(maj
, device_unit(&sc
->sc_dev
));
235 aprint_normal("%s: console\n", sc
->sc_dev
.dv_xname
);
238 sc
->sc_si
= softint_establish(SOFTINT_SERIAL
, epcomsoft
, sc
);
240 #if NRND > 0 && defined(RND_COM)
241 rnd_attach_source(&sc
->rnd_source
, sc
->sc_dev
.dv_xname
,
245 /* if there are no enable/disable functions, assume the device
250 /* XXX configure register */
253 SET(sc
->sc_hwflags
, COM_HW_DEV_OK
);
257 epcomparam(struct tty
*tp
, struct termios
*t
)
259 struct epcom_softc
*sc
260 = device_lookup_private(&epcom_cd
, COMUNIT(tp
->t_dev
));
263 if (COM_ISALIVE(sc
) == 0)
266 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
270 * For the console, always force CLOCAL and !HUPCL, so that the port
273 if (ISSET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
274 ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
275 SET(t
->c_cflag
, CLOCAL
);
276 CLR(t
->c_cflag
, HUPCL
);
280 * If there were no changes, don't do anything. This avoids dropping
281 * input and improves performance when all we did was frob things like
284 if (tp
->t_ospeed
== t
->c_ospeed
&&
285 tp
->t_cflag
== t
->c_cflag
)
290 sc
->sc_lcrhi
= cflag2lcrhi(t
->c_cflag
);
291 sc
->sc_lcrlo
= EPCOMSPEED2BRD(t
->c_ospeed
) & 0xff;
292 sc
->sc_lcrmid
= EPCOMSPEED2BRD(t
->c_ospeed
) >> 8;
294 /* And copy to tty. */
296 tp
->t_ospeed
= t
->c_ospeed
;
297 tp
->t_cflag
= t
->c_cflag
;
303 * Update the tty layer's idea of the carrier bit.
304 * We tell tty the carrier is always on.
306 (void) (*tp
->t_linesw
->l_modem
)(tp
, 1);
310 comstatus(sc
, "comparam ");
313 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
314 if (sc
->sc_tx_stopped
) {
315 sc
->sc_tx_stopped
= 0;
324 epcomhwiflow(struct tty
*tp
, int block
)
330 epcom_filltx(struct epcom_softc
*sc
)
332 bus_space_tag_t iot
= sc
->sc_iot
;
333 bus_space_handle_t ioh
= sc
->sc_ioh
;
337 while ((bus_space_read_4(iot
, ioh
, EPCOM_Flag
) & Flag_TXFF
) == 0) {
340 bus_space_write_4(iot
, ioh
, EPCOM_Data
,
341 0xff & *(sc
->sc_tba
+ n
));
349 epcomstart(struct tty
*tp
)
351 struct epcom_softc
*sc
352 = device_lookup_private(&epcom_cd
, COMUNIT(tp
->t_dev
));
355 if (COM_ISALIVE(sc
) == 0)
359 if (ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
))
361 if (sc
->sc_tx_stopped
)
366 /* Grab the first contiguous region of buffer space. */
371 tba
= tp
->t_outq
.c_cf
;
372 tbc
= ndqb(&tp
->t_outq
, 0);
380 SET(tp
->t_state
, TS_BUSY
);
383 /* Output the first chunk of the contiguous buffer. */
386 if (!ISSET(sc
->sc_ctrl
, Ctrl_TIE
)) {
387 SET(sc
->sc_ctrl
, Ctrl_TIE
);
397 epcom_break(struct epcom_softc
*sc
, int onoff
)
400 SET(sc
->sc_lcrhi
, LinCtrlHigh_BRK
);
402 CLR(sc
->sc_lcrhi
, LinCtrlHigh_BRK
);
407 epcom_shutdown(struct epcom_softc
*sc
)
413 /* Turn off interrupts. */
414 CLR(sc
->sc_ctrl
, (Ctrl_TIE
|Ctrl_RTIE
|Ctrl_RIE
));
416 /* Clear any break condition set with TIOCSBRK. */
423 panic("epcom_shutdown: not enabled?");
432 epcomopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
434 struct epcom_softc
*sc
;
439 sc
= device_lookup_private(&epcom_cd
, COMUNIT(dev
));
440 if (sc
== NULL
|| !ISSET(sc
->sc_hwflags
, COM_HW_DEV_OK
) ||
444 if (!device_is_active(&sc
->sc_dev
))
449 * If this is the kgdb port, no other use is permitted.
451 if (ISSET(sc
->sc_hwflags
, COM_HW_KGDB
))
457 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
463 * Do the following iff this is a first open.
465 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
473 if ((*sc
->enable
)(sc
)) {
476 printf("%s: device enable failed\n",
477 sc
->sc_dev
.dv_xname
);
482 /* XXXXXXXXXXXXXXX */
487 /* Turn on interrupts. */
488 SET(sc
->sc_ctrl
, (Ctrl_UARTE
|Ctrl_RIE
|Ctrl_RTIE
));
492 /* Fetch the current modem control status, needed later. */
493 sc
->sc_msr
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, com_msr
);
495 /* Clear PPS capture state on first open. */
497 sc
->ppsparam
.mode
= 0;
503 * Initialize the termios status to the defaults. Add in the
504 * sticky bits from TIOCSFLAGS.
507 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
508 t
.c_ospeed
= epcomcn_sc
.sc_ospeed
;
509 t
.c_cflag
= epcomcn_sc
.sc_cflag
;
511 t
.c_ospeed
= TTYDEF_SPEED
;
512 t
.c_cflag
= TTYDEF_CFLAG
;
514 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CLOCAL
))
515 SET(t
.c_cflag
, CLOCAL
);
516 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
517 SET(t
.c_cflag
, CRTSCTS
);
518 if (ISSET(sc
->sc_swflags
, TIOCFLAG_MDMBUF
))
519 SET(t
.c_cflag
, MDMBUF
);
520 /* Make sure epcomparam() will do something. */
522 (void) epcomparam(tp
, &t
);
523 tp
->t_iflag
= TTYDEF_IFLAG
;
524 tp
->t_oflag
= TTYDEF_OFLAG
;
525 tp
->t_lflag
= TTYDEF_LFLAG
;
531 /* Clear the input ring, and unblock. */
532 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
533 sc
->sc_rbavail
= EPCOM_RING_SIZE
;
535 CLR(sc
->sc_rx_flags
, RX_ANY_BLOCK
);
539 comstatus(sc
, "epcomopen ");
547 error
= ttyopen(tp
, COMDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
551 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
558 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
560 * We failed to open the device, and nobody else had it opened.
561 * Clean up the state as appropriate.
570 epcomclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
572 struct epcom_softc
*sc
= device_lookup_private(&epcom_cd
, COMUNIT(dev
));
573 struct tty
*tp
= sc
->sc_tty
;
575 /* XXX This is for cons.c. */
576 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
579 (*tp
->t_linesw
->l_close
)(tp
, flag
);
582 if (COM_ISALIVE(sc
) == 0)
585 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
587 * Although we got a last close, the device may still be in
588 * use; e.g. if this was the dialout node, and there are still
589 * processes waiting for carrier on the non-dialout node.
598 epcomread(dev_t dev
, struct uio
*uio
, int flag
)
600 struct epcom_softc
*sc
= device_lookup_private(&epcom_cd
, COMUNIT(dev
));
601 struct tty
*tp
= sc
->sc_tty
;
603 if (COM_ISALIVE(sc
) == 0)
606 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flag
));
610 epcomwrite(dev_t dev
, struct uio
*uio
, int flag
)
612 struct epcom_softc
*sc
= device_lookup_private(&epcom_cd
, COMUNIT(dev
));
613 struct tty
*tp
= sc
->sc_tty
;
615 if (COM_ISALIVE(sc
) == 0)
618 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
622 epcompoll(dev_t dev
, int events
, struct lwp
*l
)
624 struct epcom_softc
*sc
= device_lookup_private(&epcom_cd
, COMUNIT(dev
));
625 struct tty
*tp
= sc
->sc_tty
;
627 if (COM_ISALIVE(sc
) == 0)
630 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
636 struct epcom_softc
*sc
= device_lookup_private(&epcom_cd
, COMUNIT(dev
));
637 struct tty
*tp
= sc
->sc_tty
;
643 epcomioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
645 struct epcom_softc
*sc
= device_lookup_private(&epcom_cd
, COMUNIT(dev
));
646 struct tty
*tp
= sc
->sc_tty
;
650 if (COM_ISALIVE(sc
) == 0)
653 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
654 if (error
!= EPASSTHROUGH
)
657 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
658 if (error
!= EPASSTHROUGH
)
675 *(int *)data
= sc
->sc_swflags
;
679 error
= kauth_authorize_device_tty(l
->l_cred
,
680 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
683 sc
->sc_swflags
= *(int *)data
;
687 error
= EPASSTHROUGH
;
697 * Stop output on a line.
700 epcomstop(struct tty
*tp
, int flag
)
702 struct epcom_softc
*sc
703 = device_lookup_private(&epcom_cd
, COMUNIT(tp
->t_dev
));
707 if (ISSET(tp
->t_state
, TS_BUSY
)) {
708 /* Stop transmitting at the next chunk. */
710 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
711 SET(tp
->t_state
, TS_FLUSH
);
717 cflag2lcrhi(tcflag_t cflag
)
721 switch (cflag
& CSIZE
) {
733 lcrhi
|= (cflag
& PARENB
) ? LinCtrlHigh_PEN
: 0;
734 lcrhi
|= (cflag
& PARODD
) ? 0 : LinCtrlHigh_EPS
;
735 lcrhi
|= (cflag
& CSTOPB
) ? LinCtrlHigh_STP2
: 0;
736 lcrhi
|= LinCtrlHigh_FEN
; /* FIFO always enabled */
742 epcom_iflush(struct epcom_softc
*sc
)
744 bus_space_tag_t iot
= sc
->sc_iot
;
745 bus_space_handle_t ioh
= sc
->sc_ioh
;
755 /* flush any pending I/O */
756 while ((bus_space_read_4(iot
, ioh
, EPCOM_Flag
) & Flag_RXFE
) == 0
763 bus_space_read_4(iot
, ioh
, EPCOM_Data
);
766 printf("%s: com_iflush timeout %02x\n", sc
->sc_dev
.dv_xname
,
772 epcom_set(struct epcom_softc
*sc
)
774 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, EPCOM_LinCtrlLow
,
776 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, EPCOM_LinCtrlMid
,
778 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, EPCOM_LinCtrlHigh
,
780 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, EPCOM_Ctrl
,
785 epcomcnattach(bus_space_tag_t iot
, bus_addr_t iobase
, bus_space_handle_t ioh
,
786 int ospeed
, tcflag_t cflag
)
788 u_int lcrlo
, lcrmid
, lcrhi
, ctrl
, pwrcnt
;
789 bus_space_handle_t syscon_ioh
;
792 cn_init_magic(&epcom_cnm_state
);
793 cn_set_magic("\047\001");
795 epcomcn_sc
.sc_iot
= iot
;
796 epcomcn_sc
.sc_ioh
= ioh
;
797 epcomcn_sc
.sc_hwbase
= iobase
;
798 epcomcn_sc
.sc_ospeed
= ospeed
;
799 epcomcn_sc
.sc_cflag
= cflag
;
801 lcrhi
= cflag2lcrhi(cflag
);
802 lcrlo
= EPCOMSPEED2BRD(ospeed
) & 0xff;
803 lcrmid
= EPCOMSPEED2BRD(ospeed
) >> 8;
806 bus_space_map(iot
, EP93XX_APB_HWBASE
+ EP93XX_APB_SYSCON
,
807 EP93XX_APB_SYSCON_SIZE
, 0, &syscon_ioh
);
808 pwrcnt
= bus_space_read_4(iot
, syscon_ioh
, EP93XX_SYSCON_PwrCnt
);
809 pwrcnt
&= ~(PwrCnt_UARTBAUD
);
810 bus_space_write_4(iot
, syscon_ioh
, EP93XX_SYSCON_PwrCnt
, pwrcnt
);
811 bus_space_unmap(iot
, syscon_ioh
, EP93XX_APB_SYSCON_SIZE
);
813 bus_space_write_4(iot
, ioh
, EPCOM_LinCtrlLow
, lcrlo
);
814 bus_space_write_4(iot
, ioh
, EPCOM_LinCtrlMid
, lcrmid
);
815 bus_space_write_4(iot
, ioh
, EPCOM_LinCtrlHigh
, lcrhi
);
816 bus_space_write_4(iot
, ioh
, EPCOM_Ctrl
, ctrl
);
822 epcomcnprobe(struct consdev
*cp
)
824 cp
->cn_pri
= CN_REMOTE
;
828 epcomcnpollc(dev_t dev
, int on
)
833 epcomcnputc(dev_t dev
, int c
)
836 bus_space_tag_t iot
= epcomcn_sc
.sc_iot
;
837 bus_space_handle_t ioh
= epcomcn_sc
.sc_ioh
;
841 while((bus_space_read_4(iot
, ioh
, EPCOM_Flag
) & Flag_TXFF
) != 0)
844 bus_space_write_4(iot
, ioh
, EPCOM_Data
, c
);
848 while((bus_space_read_4(iot
, ioh
, EPCOM_Flag
) & Flag_TXFE
) == 0)
857 epcomcngetc(dev_t dev
)
861 bus_space_tag_t iot
= epcomcn_sc
.sc_iot
;
862 bus_space_handle_t ioh
= epcomcn_sc
.sc_ioh
;
866 while((bus_space_read_4(iot
, ioh
, EPCOM_Flag
) & Flag_RXFE
) != 0)
869 c
= bus_space_read_4(iot
, ioh
, EPCOM_Data
);
870 sts
= bus_space_read_4(iot
, ioh
, EPCOM_RXSts
);
871 if (ISSET(sts
, RXSts_BE
)) c
= CNC_BREAK
;
873 extern int db_active
;
877 int cn_trapped
= 0; /* unused */
879 cn_check_magic(dev
, c
, epcom_cnm_state
);
888 epcom_txsoft(struct epcom_softc
*sc
, struct tty
*tp
)
890 CLR(tp
->t_state
, TS_BUSY
);
891 if (ISSET(tp
->t_state
, TS_FLUSH
))
892 CLR(tp
->t_state
, TS_FLUSH
);
894 ndflush(&tp
->t_outq
, (int)(sc
->sc_tba
- tp
->t_outq
.c_cf
));
895 (*tp
->t_linesw
->l_start
)(tp
);
899 epcom_rxsoft(struct epcom_softc
*sc
, struct tty
*tp
)
901 int (*rint
)(int, struct tty
*) = tp
->t_linesw
->l_rint
;
910 scc
= cc
= EPCOM_RING_SIZE
- sc
->sc_rbavail
;
912 if (cc
== EPCOM_RING_SIZE
) {
914 if (sc
->sc_errors
++ == 0)
915 callout_reset(&sc
->sc_diag_callout
, 60 * hz
,
922 if (ISSET(sts
, RXSts_OE
| RXSts_FE
| RXSts_PE
| RXSts_BE
)) {
924 if (ISSET(lsr
, DR_ROR
)) {
926 if (sc
->sc_errors
++ == 0)
927 callout_reset(&sc
->sc_diag_callout
,
928 60 * hz
, comdiag
, sc
);
931 if (ISSET(sts
, (RXSts_FE
|RXSts_BE
)))
933 if (ISSET(sts
, RXSts_PE
))
936 if ((*rint
)(code
, tp
) == -1) {
938 * The line discipline's buffer is out of space.
940 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
942 * We're either not using flow control, or the
943 * line discipline didn't tell us to block for
944 * some reason. Either way, we have no way to
945 * know when there's more space available, so
946 * just drop the rest of the data.
950 get
-= EPCOM_RING_SIZE
<< 1;
954 * Don't schedule any more receive processing
955 * until the line discipline tells us there's
956 * space available (through comhwiflow()).
957 * Leave the rest of the data in the input
960 SET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
974 cc
= sc
->sc_rbavail
+= scc
- cc
;
975 /* Buffers should be ok again, release possible block. */
977 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
978 CLR(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
979 SET(sc
->sc_ctrl
, (Ctrl_RIE
|Ctrl_RTIE
));
982 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
)) {
983 CLR(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
996 struct epcom_softc
*sc
= arg
;
998 if (COM_ISALIVE(sc
) == 0)
1001 if (sc
->sc_rx_ready
) {
1002 sc
->sc_rx_ready
= 0;
1003 epcom_rxsoft(sc
, sc
->sc_tty
);
1005 if (sc
->sc_tx_done
) {
1007 epcom_txsoft(sc
, sc
->sc_tty
);
1012 epcomintr(void* arg
)
1014 struct epcom_softc
*sc
= arg
;
1015 bus_space_tag_t iot
= sc
->sc_iot
;
1016 bus_space_handle_t ioh
= sc
->sc_ioh
;
1023 intr
= bus_space_read_4(iot
, ioh
, EPCOM_IntIDIntClr
);
1025 if (COM_ISALIVE(sc
) == 0)
1026 panic("intr on disabled epcom");
1028 flagr
= bus_space_read_4(iot
, ioh
, EPCOM_Flag
);
1032 cc
= sc
->sc_rbavail
;
1034 if (!(ISSET(flagr
, Flag_RXFE
))) {
1035 if (!ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1037 if (ISSET(flagr
, Flag_RXFE
))
1039 c
= bus_space_read_4(iot
, ioh
, EPCOM_Data
);
1040 csts
= bus_space_read_4(iot
, ioh
, EPCOM_RXSts
);
1041 if (ISSET(csts
, RXSts_BE
)) {
1044 cn_check_magic(sc
->sc_tty
->t_dev
,
1045 CNC_BREAK
, epcom_cnm_state
);
1048 #if defined(KGDB) && !defined(DDB)
1049 if (ISSET(sc
->sc_hwflags
, COM_HW_KGDB
)){
1057 cn_check_magic(sc
->sc_tty
->t_dev
,
1058 (c
& 0xff), epcom_cnm_state
);
1065 put
[1] = csts
& 0xf;
1071 flagr
= bus_space_read_4(iot
, ioh
, EPCOM_Flag
);
1075 * Current string of incoming characters ended because
1076 * no more data was available or we ran out of space.
1077 * Schedule a receive event if any data was received.
1078 * If we're out of space, turn off receive interrupts.
1081 sc
->sc_rbavail
= cc
;
1082 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
))
1083 sc
->sc_rx_ready
= 1;
1086 * See if we are in danger of overflowing a buffer. If
1087 * so, use hardware flow control to ease the pressure.
1090 /* but epcom cannot. X-( */
1093 * If we're out of space, disable receive interrupts
1094 * until the queue has drained a bit.
1097 SET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1098 CLR(sc
->sc_ctrl
, (Ctrl_RIE
|Ctrl_RTIE
));
1103 panic("epcomintr: we shouldn't reach here");
1105 CLR(sc
->sc_ctrl
, (Ctrl_RIE
|Ctrl_RTIE
));
1111 * Done handling any receive interrupts. See if data can be
1112 * transmitted as well. Schedule tx done event if no data left
1113 * and tty was marked busy.
1116 if (!ISSET(flagr
, Flag_TXFF
) && sc
->sc_tbc
> 0) {
1117 /* Output the next chunk of the contiguous buffer, if any. */
1120 /* Disable transmit completion interrupts if necessary. */
1121 if (ISSET(sc
->sc_ctrl
, Ctrl_TIE
)) {
1122 CLR(sc
->sc_ctrl
, Ctrl_TIE
);
1125 if (sc
->sc_tx_busy
) {
1131 /* Wake up the poller. */
1132 softint_schedule(sc
->sc_si
);
1134 #if 0 /* XXX: broken */
1135 #if NRND > 0 && defined(RND_COM)
1136 rnd_add_uint32(&sc
->rnd_source
, intr
^ flagr
);