1 /* $NetBSD: ixp12x0_com.c,v 1.35 2009/03/14 14:45:55 dsl Exp $ */
3 * Copyright (c) 1998, 1999, 2001, 2002 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Ichiro FUKUHARA and Naoto Shimazaki.
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by IWAMOTO Toshihiro.
12 * This code is derived from software contributed to The NetBSD Foundation
13 * by Charles M. Hannum.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1991 The Regents of the University of California.
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * @(#)com.c 7.5 (Berkeley) 5/16/91
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: ixp12x0_com.c,v 1.35 2009/03/14 14:45:55 dsl Exp $");
75 #if NRND > 0 && defined(RND_COM)
79 #include <sys/param.h>
80 #include <sys/systm.h>
81 #include <sys/types.h>
84 #include <sys/device.h>
85 #include <sys/kernel.h>
86 #include <sys/malloc.h>
89 #include <sys/vnode.h>
90 #include <sys/kauth.h>
92 #include <machine/intr.h>
93 #include <machine/bus.h>
95 #include <arm/ixp12x0/ixp12x0_comreg.h>
96 #include <arm/ixp12x0/ixp12x0_comvar.h>
97 #include <arm/ixp12x0/ixp12x0reg.h>
98 #include <arm/ixp12x0/ixp12x0var.h>
100 #include <arm/ixp12x0/ixpsipvar.h>
102 #include <dev/cons.h>
105 static int ixpcomparam(struct tty
*, struct termios
*);
106 static void ixpcomstart(struct tty
*);
107 static int ixpcomhwiflow(struct tty
*, int);
109 static u_int
cflag2cr(tcflag_t
);
110 static void ixpcom_iflush(struct ixpcom_softc
*);
111 static void ixpcom_set_cr(struct ixpcom_softc
*);
113 int ixpcomcngetc(dev_t
);
114 void ixpcomcnputc(dev_t
, int);
115 void ixpcomcnpollc(dev_t
, int);
117 static void ixpcomsoft(void* arg
);
118 inline static void ixpcom_txsoft(struct ixpcom_softc
*, struct tty
*);
119 inline static void ixpcom_rxsoft(struct ixpcom_softc
*, struct tty
*);
121 void ixpcomcnprobe(struct consdev
*);
122 void ixpcomcninit(struct consdev
*);
124 u_int32_t ixpcom_cr
= 0; /* tell cr to *_intr.c */
125 u_int32_t ixpcom_imask
= 0; /* intrrupt mask from *_intr.c */
128 static struct ixpcom_cons_softc
{
129 bus_space_tag_t sc_iot
;
130 bus_space_handle_t sc_ioh
;
131 bus_addr_t sc_baseaddr
;
137 static struct cnm_state ixpcom_cnm_state
;
139 struct ixpcom_softc
* ixpcom_sc
= NULL
;
141 extern struct cfdriver ixpcom_cd
;
143 dev_type_open(ixpcomopen
);
144 dev_type_close(ixpcomclose
);
145 dev_type_read(ixpcomread
);
146 dev_type_write(ixpcomwrite
);
147 dev_type_ioctl(ixpcomioctl
);
148 dev_type_stop(ixpcomstop
);
149 dev_type_tty(ixpcomtty
);
150 dev_type_poll(ixpcompoll
);
152 const struct cdevsw ixpcom_cdevsw
= {
153 ixpcomopen
, ixpcomclose
, ixpcomread
, ixpcomwrite
, ixpcomioctl
,
154 ixpcomstop
, ixpcomtty
, ixpcompoll
, nommap
, ttykqfilter
, D_TTY
157 struct consdev ixpcomcons
= {
158 NULL
, NULL
, ixpcomcngetc
, ixpcomcnputc
, ixpcomcnpollc
, NULL
,
159 NULL
, NULL
, NODEV
, CN_NORMAL
162 #ifndef DEFAULT_COMSPEED
163 #define DEFAULT_COMSPEED 38400
166 #define COMUNIT_MASK 0x7ffff
167 #define COMDIALOUT_MASK 0x80000
169 #define COMUNIT(x) (minor(x) & COMUNIT_MASK)
170 #define COMDIALOUT(x) (minor(x) & COMDIALOUT_MASK)
172 #define COM_ISALIVE(sc) ((sc)->enabled != 0 && \
173 device_is_active(&(sc)->sc_dev))
175 #define COM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, COM_NPORTS, (f))
177 #define COM_LOCK(sc);
178 #define COM_UNLOCK(sc);
180 #define CFLAGS2CR_MASK (CR_PE | CR_OES | CR_SBS | CR_DSS | CR_BRD)
183 ixpcom_attach_subr(struct ixpcom_softc
*sc
)
189 /* force to use ixpcom0 for console */
190 if (sc
->sc_iot
== ixpcomcn_sc
.sc_iot
191 && sc
->sc_baseaddr
== ixpcomcn_sc
.sc_baseaddr
) {
192 ixpcomcn_sc
.sc_attached
= 1;
193 sc
->sc_speed
= IXPCOMSPEED2BRD(ixpcomcn_sc
.sc_ospeed
);
195 /* Make sure the console is always "hardwired". */
196 /* XXX IXPCOM_SR should be checked */
197 delay(10000); /* wait for output to finish */
198 SET(sc
->sc_hwflags
, COM_HW_CONSOLE
);
199 SET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
);
203 tp
->t_oproc
= ixpcomstart
;
204 tp
->t_param
= ixpcomparam
;
205 tp
->t_hwiflow
= ixpcomhwiflow
;
208 sc
->sc_rbuf
= malloc(IXPCOM_RING_SIZE
<< 1, M_DEVBUF
, M_NOWAIT
);
209 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
210 sc
->sc_rbavail
= IXPCOM_RING_SIZE
;
211 if (sc
->sc_rbuf
== NULL
) {
212 printf("%s: unable to allocate ring buffer\n",
213 sc
->sc_dev
.dv_xname
);
216 sc
->sc_ebuf
= sc
->sc_rbuf
+ (IXPCOM_RING_SIZE
<< 1);
219 sc
->sc_rie
= sc
->sc_xie
= 0;
220 ixpcom_cr
= IXPCOMSPEED2BRD(DEFAULT_COMSPEED
)
221 | CR_UE
| sc
->sc_rie
| sc
->sc_xie
| DSS_8BIT
;
225 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
228 /* locate the major number */
229 maj
= cdevsw_lookup_major(&ixpcom_cdevsw
);
231 cn_tab
->cn_dev
= makedev(maj
, device_unit(&sc
->sc_dev
));
233 aprint_normal("%s: console\n", sc
->sc_dev
.dv_xname
);
236 sc
->sc_si
= softint_establish(SOFTINT_SERIAL
, ixpcomsoft
, sc
);
238 #if NRND > 0 && defined(RND_COM)
239 rnd_attach_source(&sc
->rnd_source
, sc
->sc_dev
.dv_xname
,
243 /* if there are no enable/disable functions, assume the device
248 /* XXX configure register */
251 SET(sc
->sc_hwflags
, COM_HW_DEV_OK
);
255 ixpcomparam(struct tty
*tp
, struct termios
*t
)
257 struct ixpcom_softc
*sc
258 = device_lookup_private(&ixpcom_cd
, COMUNIT(tp
->t_dev
));
262 if (COM_ISALIVE(sc
) == 0)
265 cr
= IXPCOMSPEED2BRD(t
->c_ospeed
);
267 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
271 * For the console, always force CLOCAL and !HUPCL, so that the port
274 if (ISSET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
275 ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
276 SET(t
->c_cflag
, CLOCAL
);
277 CLR(t
->c_cflag
, HUPCL
);
281 * If there were no changes, don't do anything. This avoids dropping
282 * input and improves performance when all we did was frob things like
285 if (tp
->t_ospeed
== t
->c_ospeed
&&
286 tp
->t_cflag
== t
->c_cflag
)
289 cr
|= cflag2cr(t
->c_cflag
);
294 ixpcom_cr
= (ixpcom_cr
& ~CFLAGS2CR_MASK
) | cr
;
297 * ixpcom don't have any hardware flow control.
301 /* And copy to tty. */
303 tp
->t_ospeed
= t
->c_ospeed
;
304 tp
->t_cflag
= t
->c_cflag
;
306 if (!sc
->sc_heldchange
) {
307 if (sc
->sc_tx_busy
) {
308 sc
->sc_heldtbc
= sc
->sc_tbc
;
310 sc
->sc_heldchange
= 1;
319 * Update the tty layer's idea of the carrier bit.
320 * We tell tty the carrier is always on.
322 (void) (*tp
->t_linesw
->l_modem
)(tp
, 1);
326 comstatus(sc
, "comparam ");
329 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
330 if (sc
->sc_tx_stopped
) {
331 sc
->sc_tx_stopped
= 0;
340 ixpcomhwiflow(struct tty
*tp
, int block
)
346 ixpcom_filltx(struct ixpcom_softc
*sc
)
348 bus_space_tag_t iot
= sc
->sc_iot
;
349 bus_space_handle_t ioh
= sc
->sc_ioh
;
353 while (bus_space_read_4(iot
, ioh
, IXPCOM_SR
) & SR_TXR
) {
356 bus_space_write_4(iot
, ioh
, IXPCOM_DR
,
357 0xff & *(sc
->sc_tba
+ n
));
365 ixpcomstart(struct tty
*tp
)
367 struct ixpcom_softc
*sc
368 = device_lookup_private(&ixpcom_cd
, COMUNIT(tp
->t_dev
));
371 if (COM_ISALIVE(sc
) == 0)
375 if (ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
))
377 if (sc
->sc_tx_stopped
)
383 /* Grab the first contiguous region of buffer space. */
388 tba
= tp
->t_outq
.c_cf
;
389 tbc
= ndqb(&tp
->t_outq
, 0);
398 SET(tp
->t_state
, TS_BUSY
);
401 /* Enable transmit completion interrupts if necessary. */
402 if (!ISSET(sc
->sc_xie
, CR_XIE
)) {
403 SET(sc
->sc_xie
, CR_XIE
);
407 /* Output the first chunk of the contiguous buffer. */
417 ixpcom_break(struct ixpcom_softc
*sc
, int onoff
)
420 SET(ixpcom_cr
, CR_BRK
);
422 CLR(ixpcom_cr
, CR_BRK
);
423 if (!sc
->sc_heldchange
) {
424 if (sc
->sc_tx_busy
) {
425 sc
->sc_heldtbc
= sc
->sc_tbc
;
427 sc
->sc_heldchange
= 1;
434 ixpcom_shutdown(struct ixpcom_softc
*sc
)
441 /* Clear any break condition set with TIOCSBRK. */
444 /* Turn off interrupts. */
445 sc
->sc_rie
= sc
->sc_xie
= 0;
451 panic("ixpcom_shutdown: not enabled?");
461 ixpcomopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
463 struct ixpcom_softc
*sc
;
468 sc
= device_lookup_private(&ixpcom_cd
, COMUNIT(dev
));
469 if (sc
== NULL
|| !ISSET(sc
->sc_hwflags
, COM_HW_DEV_OK
) ||
473 if (!device_is_active(&sc
->sc_dev
))
478 * If this is the kgdb port, no other use is permitted.
480 if (ISSET(sc
->sc_hwflags
, COM_HW_KGDB
))
486 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
492 * Do the following iff this is a first open.
494 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
503 if ((*sc
->enable
)(sc
)) {
507 printf("%s: device enable failed\n",
508 sc
->sc_dev
.dv_xname
);
513 /* XXXXXXXXXXXXXXX */
518 /* Turn on interrupts. */
519 SET(sc
->sc_rie
, CR_RIE
);
523 /* Fetch the current modem control status, needed later. */
524 sc
->sc_msr
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, com_msr
);
526 /* Clear PPS capture state on first open. */
528 sc
->ppsparam
.mode
= 0;
535 * Initialize the termios status to the defaults. Add in the
536 * sticky bits from TIOCSFLAGS.
539 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
540 t
.c_ospeed
= ixpcomcn_sc
.sc_ospeed
;
541 t
.c_cflag
= ixpcomcn_sc
.sc_cflag
;
543 t
.c_ospeed
= TTYDEF_SPEED
;
544 t
.c_cflag
= TTYDEF_CFLAG
;
546 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CLOCAL
))
547 SET(t
.c_cflag
, CLOCAL
);
548 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
549 SET(t
.c_cflag
, CRTSCTS
);
550 if (ISSET(sc
->sc_swflags
, TIOCFLAG_MDMBUF
))
551 SET(t
.c_cflag
, MDMBUF
);
552 /* Make sure ixpcomparam() will do something. */
554 (void) ixpcomparam(tp
, &t
);
555 tp
->t_iflag
= TTYDEF_IFLAG
;
556 tp
->t_oflag
= TTYDEF_OFLAG
;
557 tp
->t_lflag
= TTYDEF_LFLAG
;
564 /* Clear the input ring, and unblock. */
565 sc
->sc_rbput
= sc
->sc_rbget
= sc
->sc_rbuf
;
566 sc
->sc_rbavail
= IXPCOM_RING_SIZE
;
568 CLR(sc
->sc_rx_flags
, RX_ANY_BLOCK
);
572 comstatus(sc
, "ixpcomopen ");
581 error
= ttyopen(tp
, COMDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
585 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
592 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
594 * We failed to open the device, and nobody else had it opened.
595 * Clean up the state as appropriate.
604 ixpcomclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
606 struct ixpcom_softc
*sc
= device_lookup_private(&ixpcom_cd
, COMUNIT(dev
));
607 struct tty
*tp
= sc
->sc_tty
;
609 /* XXX This is for cons.c. */
610 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
613 (*tp
->t_linesw
->l_close
)(tp
, flag
);
616 if (COM_ISALIVE(sc
) == 0)
619 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
621 * Although we got a last close, the device may still be in
622 * use; e.g. if this was the dialout node, and there are still
623 * processes waiting for carrier on the non-dialout node.
632 ixpcomread(dev_t dev
, struct uio
*uio
, int flag
)
634 struct ixpcom_softc
*sc
= device_lookup_private(&ixpcom_cd
, COMUNIT(dev
));
635 struct tty
*tp
= sc
->sc_tty
;
637 if (COM_ISALIVE(sc
) == 0)
640 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flag
));
644 ixpcomwrite(dev_t dev
, struct uio
*uio
, int flag
)
646 struct ixpcom_softc
*sc
= device_lookup_private(&ixpcom_cd
, COMUNIT(dev
));
647 struct tty
*tp
= sc
->sc_tty
;
649 if (COM_ISALIVE(sc
) == 0)
652 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
656 ixpcompoll(dev_t dev
, int events
, struct lwp
*l
)
658 struct ixpcom_softc
*sc
= device_lookup_private(&ixpcom_cd
, COMUNIT(dev
));
659 struct tty
*tp
= sc
->sc_tty
;
661 if (COM_ISALIVE(sc
) == 0)
664 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
670 struct ixpcom_softc
*sc
= device_lookup_private(&ixpcom_cd
, COMUNIT(dev
));
671 struct tty
*tp
= sc
->sc_tty
;
677 ixpcomioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
679 struct ixpcom_softc
*sc
= device_lookup_private(&ixpcom_cd
, COMUNIT(dev
));
680 struct tty
*tp
= sc
->sc_tty
;
684 if (COM_ISALIVE(sc
) == 0)
687 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
688 if (error
!= EPASSTHROUGH
)
691 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
692 if (error
!= EPASSTHROUGH
)
710 *(int *)data
= sc
->sc_swflags
;
714 error
= kauth_authorize_device_tty(l
->l_cred
,
715 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
718 sc
->sc_swflags
= *(int *)data
;
722 error
= EPASSTHROUGH
;
733 * Stop output on a line.
736 ixpcomstop(struct tty
*tp
, int flag
)
738 struct ixpcom_softc
*sc
739 = device_lookup_private(&ixpcom_cd
, COMUNIT(tp
->t_dev
));
744 if (ISSET(tp
->t_state
, TS_BUSY
)) {
745 /* Stop transmitting at the next chunk. */
748 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
749 SET(tp
->t_state
, TS_FLUSH
);
756 cflag2cr(tcflag_t cflag
)
760 cr
= (cflag
& PARENB
) ? CR_PE
: 0;
761 cr
|= (cflag
& PARODD
) ? CR_OES
: 0;
762 cr
|= (cflag
& CSTOPB
) ? CR_SBS
: 0;
763 cr
|= ((cflag
& CSIZE
) == CS8
) ? DSS_8BIT
: 0;
769 ixpcom_iflush(struct ixpcom_softc
*sc
)
771 bus_space_tag_t iot
= sc
->sc_iot
;
772 bus_space_handle_t ioh
= sc
->sc_ioh
;
782 /* flush any pending I/O */
783 while (ISSET(bus_space_read_4(iot
, ioh
, IXPCOM_SR
), SR_RXR
)
790 bus_space_read_4(iot
, ioh
, IXPCOM_DR
);
793 printf("%s: com_iflush timeout %02x\n", sc
->sc_dev
.dv_xname
,
799 ixpcom_set_cr(struct ixpcom_softc
*sc
)
802 ixpcom_cr
&= ~(CR_RIE
| CR_XIE
);
803 ixpcom_cr
|= sc
->sc_rie
| sc
->sc_xie
;
804 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, IXPCOM_CR
,
805 ixpcom_cr
& ~ixpcom_imask
);
809 ixpcomcnattach(bus_space_tag_t iot
, bus_addr_t iobase
, bus_space_handle_t ioh
, int ospeed
, tcflag_t cflag
)
813 cn_tab
= &ixpcomcons
;
814 cn_init_magic(&ixpcom_cnm_state
);
818 * ixpcom cannot detect a break. It can only detect framing
819 * errors. And, a sequence of "framing error, framing error"
820 * meens a break. So I made this hack:
822 * 1. Set default magic is a sequence of "BREAK, BREAK".
823 * 2. Tell cn_check_magic() a "framing error" as BREAK.
825 * see ixpcom_intr() too.
828 /* default magic is a couple of BREAK. */
829 cn_set_magic("\047\001\047\001");
831 ixpcomcn_sc
.sc_iot
= iot
;
832 ixpcomcn_sc
.sc_ioh
= ioh
;
833 ixpcomcn_sc
.sc_baseaddr
= iobase
;
834 ixpcomcn_sc
.sc_ospeed
= ospeed
;
835 ixpcomcn_sc
.sc_cflag
= cflag
;
837 cr
= cflag2cr(cflag
);
838 cr
|= IXPCOMSPEED2BRD(ospeed
);
842 /* enable the UART */
843 bus_space_write_4(iot
, iobase
, IXPCOM_CR
, cr
);
849 ixpcomcnprobe(struct consdev
*cp
)
851 cp
->cn_pri
= CN_REMOTE
;
855 ixpcomcnpollc(dev_t dev
, int on
)
860 ixpcomcnputc(dev_t dev
, int c
)
863 bus_space_tag_t iot
= ixpcomcn_sc
.sc_iot
;
864 bus_space_handle_t ioh
= ixpcomcn_sc
.sc_ioh
;
868 while(!(bus_space_read_4(iot
, ioh
, IXPCOM_SR
) & SR_TXR
))
871 bus_space_write_4(iot
, ioh
, IXPCOM_DR
, c
);
875 while(!(bus_space_read_4(iot
, ioh
, IXPCOM_SR
) & SR_TXE
))
884 ixpcomcngetc(dev_t dev
)
888 bus_space_tag_t iot
= ixpcomcn_sc
.sc_iot
;
889 bus_space_handle_t ioh
= ixpcomcn_sc
.sc_ioh
;
893 while(!(bus_space_read_4(iot
, ioh
, IXPCOM_SR
) & SR_RXR
))
896 c
= bus_space_read_4(iot
, ioh
, IXPCOM_DR
);
904 ixpcom_txsoft(struct ixpcom_softc
*sc
, struct tty
*tp
)
906 CLR(tp
->t_state
, TS_BUSY
);
907 if (ISSET(tp
->t_state
, TS_FLUSH
))
908 CLR(tp
->t_state
, TS_FLUSH
);
910 ndflush(&tp
->t_outq
, (int)(sc
->sc_tba
- tp
->t_outq
.c_cf
));
911 (*tp
->t_linesw
->l_start
)(tp
);
915 ixpcom_rxsoft(struct ixpcom_softc
*sc
, struct tty
*tp
)
917 int (*rint
)(int, struct tty
*) = tp
->t_linesw
->l_rint
;
926 scc
= cc
= IXPCOM_RING_SIZE
- sc
->sc_rbavail
;
928 if (cc
== IXPCOM_RING_SIZE
) {
930 if (sc
->sc_errors
++ == 0)
931 callout_reset(&sc
->sc_diag_callout
, 60 * hz
,
938 if (ISSET(lsr
, DR_ROR
| DR_FRE
| DR_PRE
)) {
940 if (ISSET(lsr
, DR_ROR
)) {
942 if (sc
->sc_errors
++ == 0)
943 callout_reset(&sc
->sc_diag_callout
,
944 60 * hz
, comdiag
, sc
);
947 if (ISSET(lsr
, DR_FRE
))
949 if (ISSET(lsr
, DR_PRE
))
952 if ((*rint
)(code
, tp
) == -1) {
954 * The line discipline's buffer is out of space.
956 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
958 * We're either not using flow control, or the
959 * line discipline didn't tell us to block for
960 * some reason. Either way, we have no way to
961 * know when there's more space available, so
962 * just drop the rest of the data.
966 get
-= IXPCOM_RING_SIZE
<< 1;
970 * Don't schedule any more receive processing
971 * until the line discipline tells us there's
972 * space available (through comhwiflow()).
973 * Leave the rest of the data in the input
976 SET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
991 cc
= sc
->sc_rbavail
+= scc
- cc
;
992 /* Buffers should be ok again, release possible block. */
994 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
995 CLR(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
996 SET(sc
->sc_rie
, CR_RIE
);
999 if (ISSET(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
)) {
1000 CLR(sc
->sc_rx_flags
, RX_IBUF_BLOCKED
);
1012 ixpcomsoft(void* arg
)
1014 struct ixpcom_softc
*sc
= arg
;
1016 if (COM_ISALIVE(sc
) == 0)
1019 if (sc
->sc_rx_ready
) {
1020 sc
->sc_rx_ready
= 0;
1021 ixpcom_rxsoft(sc
, sc
->sc_tty
);
1023 if (sc
->sc_tx_done
) {
1025 ixpcom_txsoft(sc
, sc
->sc_tty
);
1030 ixpcomintr(void* arg
)
1032 struct ixpcom_softc
*sc
= arg
;
1033 bus_space_tag_t iot
= sc
->sc_iot
;
1034 bus_space_handle_t ioh
= sc
->sc_ioh
;
1041 if (COM_ISALIVE(sc
) == 0)
1045 cr
= bus_space_read_4(iot
, ioh
, IXPCOM_CR
) & CR_UE
;
1052 sr
= bus_space_read_4(iot
, ioh
, IXPCOM_SR
);
1053 if (!ISSET(sr
, SR_TXR
| SR_RXR
))
1059 * ixpcom cannot detect a break. It can only detect framing
1060 * errors. And, a sequence of "framing error, framing error"
1061 * meens a break. So I made this hack:
1063 * 1. Set default magic is a sequence of "BREAK, BREAK".
1064 * 2. Tell cn_check_magic() a "framing error" as BREAK.
1066 * see ixpcomcnattach() too.
1069 if (ISSET(sr
, SR_FRE
)) {
1070 cn_check_magic(sc
->sc_tty
->t_dev
,
1071 CNC_BREAK
, ixpcom_cnm_state
);
1076 cc
= sc
->sc_rbavail
;
1078 if (ISSET(sr
, SR_RXR
)) {
1079 if (!ISSET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1081 if (!ISSET(sr
, SR_RXR
))
1083 c
= bus_space_read_4(iot
, ioh
, IXPCOM_DR
);
1084 if (ISSET(c
, DR_FRE
)) {
1085 cn_check_magic(sc
->sc_tty
->t_dev
,
1090 put
[1] = (c
>> 8) & 0xff;
1091 cn_check_magic(sc
->sc_tty
->t_dev
,
1092 put
[0], ixpcom_cnm_state
);
1098 sr
= bus_space_read_4(iot
, ioh
, IXPCOM_SR
);
1102 * Current string of incoming characters ended because
1103 * no more data was available or we ran out of space.
1104 * Schedule a receive event if any data was received.
1105 * If we're out of space, turn off receive interrupts.
1108 sc
->sc_rbavail
= cc
;
1109 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
))
1110 sc
->sc_rx_ready
= 1;
1113 * See if we are in danger of overflowing a buffer. If
1114 * so, use hardware flow control to ease the pressure.
1117 /* but ixpcom cannot. X-( */
1120 * If we're out of space, disable receive interrupts
1121 * until the queue has drained a bit.
1124 SET(sc
->sc_rx_flags
, RX_IBUF_OVERFLOWED
);
1125 CLR(sc
->sc_rie
, CR_RIE
);
1130 panic("ixpcomintr: we shouldn't reach here");
1132 CLR(sc
->sc_rie
, CR_RIE
);
1138 * Done handling any receive interrupts. See if data can be
1139 * transmitted as well. Schedule tx done event if no data left
1140 * and tty was marked busy.
1142 sr
= bus_space_read_4(iot
, ioh
, IXPCOM_SR
);
1143 if (ISSET(sr
, SR_TXR
)) {
1145 * If we've delayed a parameter change, do it now, and restart
1148 if (sc
->sc_heldchange
) {
1150 sc
->sc_heldchange
= 0;
1151 sc
->sc_tbc
= sc
->sc_heldtbc
;
1155 /* Output the next chunk of the contiguous buffer, if any. */
1156 if (sc
->sc_tbc
> 0) {
1159 /* Disable transmit completion interrupts if necessary. */
1160 if (ISSET(sc
->sc_xie
, CR_XIE
)) {
1161 CLR(sc
->sc_xie
, CR_XIE
);
1164 if (sc
->sc_tx_busy
) {
1172 /* Wake up the poller. */
1173 softint_schedule(sc
->sc_si
);
1175 #if NRND > 0 && defined(RND_COM)
1176 rnd_add_uint32(&sc
->rnd_source
, iir
| lsr
);