1 /* $NetBSD: txcom.c,v 1.40 2008/06/12 16:50:53 tsutsui Exp $ */
4 * Copyright (c) 1999, 2000, 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: txcom.c,v 1.40 2008/06/12 16:50:53 tsutsui Exp $");
35 #include "opt_tx39uart_debug.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
42 #include <sys/kauth.h>
44 #include <sys/proc.h> /* tsleep/wakeup */
46 #include <sys/ioctl.h>
47 #include <sys/select.h>
52 #include <dev/cons.h> /* consdev */
54 #include <machine/bus.h>
55 #include <machine/config_hook.h>
57 #include <hpcmips/tx/tx39var.h>
58 #include <hpcmips/tx/tx39icureg.h>
59 #include <hpcmips/tx/tx39uartvar.h>
60 #include <hpcmips/tx/tx39uartreg.h>
62 #include <hpcmips/tx/tx39irvar.h>
64 #include <hpcmips/tx/tx39clockreg.h> /* XXX */
67 * UARTA channel has DTR, DSR, RTS, CTS lines. and they wired to MFIO/IO port.
69 #define IS_COM0(s) ((s) == 0)
70 #define IS_COM1(s) ((s) == 1)
71 #define ON ((void *)1)
72 #define OFF ((void *)0)
75 #define DPRINTF_ENABLE
76 #define DPRINTF_DEBUG tx39uart_debug
78 #include <machine/debug.h>
80 #define TXCOM_HW_CONSOLE 0x40
81 #define TXCOM_RING_SIZE 256 /* must be a power of two! */
82 #define TXCOM_RING_MASK (TXCOM_RING_SIZE - 1)
85 tx_chipset_tag_t sc_tc
;
86 int sc_slot
; /* UARTA or UARTB */
100 struct txcom_chip
*sc_chip
;
102 struct callout sc_txsoft_ch
;
103 struct callout sc_rxsoft_ch
;
105 u_int8_t
*sc_tba
; /* transmit buffer address */
106 int sc_tbc
; /* transmit byte count */
108 u_int8_t
*sc_rbuf
; /* receive buffer address */
109 int sc_rbput
; /* receive byte count */
113 extern struct cfdriver txcom_cd
;
115 int txcom_match(struct device
*, struct cfdata
*, void *);
116 void txcom_attach(struct device
*, struct device
*, void *);
117 int txcom_print(void*, const char *);
119 int txcom_txintr(void *);
120 int txcom_rxintr(void *);
121 int txcom_frameerr_intr(void *);
122 int txcom_parityerr_intr(void *);
123 int txcom_break_intr(void *);
125 void txcom_rxsoft(void *);
126 void txcom_txsoft(void *);
128 int txcom_stsoft(void *);
129 int txcom_stsoft2(void *);
130 int txcom_stsoft3(void *);
131 int txcom_stsoft4(void *);
134 void txcom_shutdown(struct txcom_softc
*);
135 void txcom_break(struct txcom_softc
*, int);
136 void txcom_modem(struct txcom_softc
*, int);
137 void txcomstart(struct tty
*);
138 int txcomparam(struct tty
*, struct termios
*);
140 void txcom_reset (struct txcom_chip
*);
141 int txcom_enable (struct txcom_chip
*, bool);
142 void txcom_disable (struct txcom_chip
*);
143 void txcom_setmode (struct txcom_chip
*);
144 void txcom_setbaudrate(struct txcom_chip
*);
145 int txcom_cngetc (dev_t
);
146 void txcom_cnputc (dev_t
, int);
147 void txcom_cnpollc (dev_t
, int);
149 int txcom_dcd_hook(void *, int, long, void *);
150 int txcom_cts_hook(void *, int, long, void *);
153 inline int __txcom_txbufready(struct txcom_chip
*, int);
154 const char *__txcom_slotname(int);
157 void txcom_dump(struct txcom_chip
*);
160 struct consdev txcomcons
= {
161 NULL
, NULL
, txcom_cngetc
, txcom_cnputc
, txcom_cnpollc
, NULL
, NULL
,
162 NULL
, NODEV
, CN_NORMAL
166 struct txcom_chip txcom_chip
;
168 CFATTACH_DECL(txcom
, sizeof(struct txcom_softc
),
169 txcom_match
, txcom_attach
, NULL
, NULL
);
171 dev_type_open(txcomopen
);
172 dev_type_close(txcomclose
);
173 dev_type_read(txcomread
);
174 dev_type_write(txcomwrite
);
175 dev_type_ioctl(txcomioctl
);
176 dev_type_stop(txcomstop
);
177 dev_type_tty(txcomtty
);
178 dev_type_poll(txcompoll
);
180 const struct cdevsw txcom_cdevsw
= {
181 txcomopen
, txcomclose
, txcomread
, txcomwrite
, txcomioctl
,
182 txcomstop
, txcomtty
, txcompoll
, nommap
, ttykqfilter
, D_TTY
186 txcom_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
188 /* if the autoconfiguration got this far, there's a slot here */
193 txcom_attach(struct device
*parent
, struct device
*self
, void *aux
)
195 struct tx39uart_attach_args
*ua
= aux
;
196 struct txcom_softc
*sc
= (void*)self
;
199 struct txcom_chip
*chip
;
202 /* Check this slot used as serial console */
203 console
= (ua
->ua_slot
== txcom_chip
.sc_slot
) &&
204 (txcom_chip
.sc_hwflags
& TXCOM_HW_CONSOLE
);
207 sc
->sc_chip
= &txcom_chip
;
209 if (!(sc
->sc_chip
= malloc(sizeof(struct txcom_chip
),
210 M_DEVBUF
, M_WAITOK
))) {
211 printf(": can't allocate chip\n");
214 memset(sc
->sc_chip
, 0, sizeof(struct txcom_chip
));
218 tc
= chip
->sc_tc
= ua
->ua_tc
;
219 slot
= chip
->sc_slot
= ua
->ua_slot
;
227 if (!(sc
->sc_rbuf
= malloc(TXCOM_RING_SIZE
, M_DEVBUF
, M_WAITOK
))) {
228 printf(": can't allocate buffer.\n");
231 memset(sc
->sc_rbuf
, 0, TXCOM_RING_SIZE
);
234 tp
->t_oproc
= txcomstart
;
235 tp
->t_param
= txcomparam
;
236 tp
->t_hwiflow
= NULL
;
240 if (ISSET(chip
->sc_hwflags
, TXCOM_HW_CONSOLE
)) {
242 /* locate the major number */
243 maj
= cdevsw_lookup_major(&txcom_cdevsw
);
245 cn_tab
->cn_dev
= makedev(maj
, device_unit(&sc
->sc_dev
));
255 #define TXCOMINTR(i, s) MAKEINTR(2, TX39_INTRSTATUS2_UART##i##INT(s))
257 tx_intr_establish(tc
, TXCOMINTR(RX
, slot
), IST_EDGE
, IPL_TTY
,
259 tx_intr_establish(tc
, TXCOMINTR(TX
, slot
), IST_EDGE
, IPL_TTY
,
261 tx_intr_establish(tc
, TXCOMINTR(RXOVERRUN
, slot
), IST_EDGE
, IPL_TTY
,
263 tx_intr_establish(tc
, TXCOMINTR(TXOVERRUN
, slot
), IST_EDGE
, IPL_TTY
,
265 tx_intr_establish(tc
, TXCOMINTR(FRAMEERR
, slot
), IST_EDGE
, IPL_TTY
,
266 txcom_frameerr_intr
, sc
);
267 tx_intr_establish(tc
, TXCOMINTR(PARITYERR
, slot
), IST_EDGE
, IPL_TTY
,
268 txcom_parityerr_intr
, sc
);
269 tx_intr_establish(tc
, TXCOMINTR(BREAK
, slot
), IST_EDGE
, IPL_TTY
,
270 txcom_break_intr
, sc
);
273 * UARTA has external signal line. (its wiring is platform dependent)
276 /* install DCD, CTS hooks. */
277 config_hook(CONFIG_HOOK_EVENT
, CONFIG_HOOK_COM0_DCD
,
278 CONFIG_HOOK_EXCLUSIVE
, txcom_dcd_hook
, sc
);
279 config_hook(CONFIG_HOOK_EVENT
, CONFIG_HOOK_COM0_CTS
,
280 CONFIG_HOOK_EXCLUSIVE
, txcom_cts_hook
, sc
);
284 * UARTB can connect IR module
287 struct txcom_attach_args tca
;
289 tca
.tca_parent
= self
;
290 config_found(self
, &tca
, txcom_print
);
295 txcom_print(void *aux
, const char *pnp
)
297 return pnp
? QUIET
: UNCONF
;
301 txcom_reset(struct txcom_chip
*chip
)
308 slot
= chip
->sc_slot
;
309 ofs
= TX39_UARTCTRL1_REG(slot
);
312 reg
= tx_conf_read(tc
, TX39_CLOCKCTRL_REG
);
313 reg
|= (slot
? TX39_CLOCK_ENUARTBCLK
: TX39_CLOCK_ENUARTACLK
);
314 tx_conf_write(tc
, TX39_CLOCKCTRL_REG
, reg
);
316 /* reset UART module */
317 tx_conf_write(tc
, ofs
, 0);
321 txcom_enable(struct txcom_chip
*chip
, bool console
)
325 int slot
, ofs
, timeout
;
328 slot
= chip
->sc_slot
;
329 ofs
= TX39_UARTCTRL1_REG(slot
);
332 * External power supply (if any)
333 * When serial console, Windows CE already powered on it.
336 config_hook_call(CONFIG_HOOK_POWERCONTROL
,
337 CONFIG_HOOK_POWERCONTROL_COM0
, PWCTL_ON
);
342 reg
= tx_conf_read(tc
, TX39_CLOCKCTRL_REG
);
343 reg
|= (slot
? TX39_CLOCK_ENUARTBCLK
: TX39_CLOCK_ENUARTACLK
);
344 tx_conf_write(tc
, TX39_CLOCKCTRL_REG
, reg
);
347 * XXX Disable DMA (DMA not coded yet)
349 reg
= tx_conf_read(tc
, ofs
);
350 reg
&= ~(TX39_UARTCTRL1_ENDMARX
| TX39_UARTCTRL1_ENDMATX
);
351 tx_conf_write(tc
, ofs
, reg
);
354 reg
= tx_conf_read(tc
, ofs
);
355 reg
|= TX39_UARTCTRL1_ENUART
;
356 reg
&= ~TX39_UARTCTRL1_ENBREAHALT
;
357 tx_conf_write(tc
, ofs
, reg
);
361 while(!(tx_conf_read(tc
, ofs
) & TX39_UARTCTRL1_UARTON
) &&
365 if (timeout
== 0 && !cold
) {
366 printf("%s never power up\n", __txcom_slotname(slot
));
374 txcom_disable(struct txcom_chip
*chip
)
381 slot
= chip
->sc_slot
;
383 reg
= tx_conf_read(tc
, TX39_UARTCTRL1_REG(slot
));
385 reg
&= ~(TX39_UARTCTRL1_ENDMARX
| TX39_UARTCTRL1_ENDMATX
);
388 reg
&= ~TX39_UARTCTRL1_ENUART
;
389 tx_conf_write(tc
, TX39_UARTCTRL1_REG(slot
), reg
);
392 reg
= tx_conf_read(tc
, TX39_CLOCKCTRL_REG
);
393 reg
&= ~(slot
? TX39_CLOCK_ENUARTBCLK
: TX39_CLOCK_ENUARTACLK
);
394 tx_conf_write(tc
, TX39_CLOCKCTRL_REG
, reg
);
399 __txcom_txbufready(struct txcom_chip
*chip
, int retry
)
401 tx_chipset_tag_t tc
= chip
->sc_tc
;
402 int ofs
= TX39_UARTCTRL1_REG(chip
->sc_slot
);
405 if (tx_conf_read(tc
, ofs
) & TX39_UARTCTRL1_EMPTY
)
407 } while(--retry
!= 0);
413 txcom_pulse_mode(struct device
*dev
)
415 struct txcom_softc
*sc
= (void*)dev
;
416 struct txcom_chip
*chip
= sc
->sc_chip
;
417 tx_chipset_tag_t tc
= chip
->sc_tc
;
421 ofs
= TX39_UARTCTRL1_REG(chip
->sc_slot
);
423 reg
= tx_conf_read(tc
, ofs
);
424 /* WindowsCE use this setting */
425 reg
|= TX39_UARTCTRL1_PULSEOPT1
;
426 reg
&= ~TX39_UARTCTRL1_PULSEOPT2
;
427 reg
|= TX39_UARTCTRL1_DTINVERT
;
429 tx_conf_write(tc
, ofs
, reg
);
436 txcom_cngetc(dev_t dev
)
443 tc
= txcom_chip
.sc_tc
;
444 ofs
= TX39_UARTCTRL1_REG(txcom_chip
.sc_slot
);
446 while(!(TX39_UARTCTRL1_RXHOLDFULL
& tx_conf_read(tc
, ofs
)))
449 c
= TX39_UARTRXHOLD_RXDATA(
450 tx_conf_read(tc
, TX39_UARTRXHOLD_REG(txcom_chip
.sc_slot
)));
461 txcom_cnputc(dev_t dev
, int c
)
463 struct txcom_chip
*chip
= &txcom_chip
;
464 tx_chipset_tag_t tc
= chip
->sc_tc
;
469 /* Wait for transmitter to empty */
470 __txcom_txbufready(chip
, -1);
472 tx_conf_write(tc
, TX39_UARTTXHOLD_REG(chip
->sc_slot
),
473 (c
& TX39_UARTTXHOLD_TXDATA_MASK
));
475 __txcom_txbufready(chip
, -1);
481 txcom_cnpollc(dev_t dev
, int on
)
486 txcom_setmode(struct txcom_chip
*chip
)
488 tcflag_t cflag
= chip
->sc_cflag
;
489 int ofs
= TX39_UARTCTRL1_REG(chip
->sc_slot
);
492 reg
= tx_conf_read(chip
->sc_tc
, ofs
);
493 reg
&= ~TX39_UARTCTRL1_ENUART
;
494 tx_conf_write(chip
->sc_tc
, ofs
, reg
);
496 switch (ISSET(cflag
, CSIZE
)) {
498 printf("txcom_setmode: CS7, CS8 only. use CS7");
501 reg
|= TX39_UARTCTRL1_BIT7
;
504 reg
&= ~TX39_UARTCTRL1_BIT7
;
508 if (ISSET(cflag
, PARENB
)) {
509 reg
|= TX39_UARTCTRL1_ENPARITY
;
510 if (ISSET(cflag
, PARODD
)) {
511 reg
&= ~TX39_UARTCTRL1_EVENPARITY
;
513 reg
|= TX39_UARTCTRL1_EVENPARITY
;
516 reg
&= ~TX39_UARTCTRL1_ENPARITY
;
519 if (ISSET(cflag
, CSTOPB
))
520 reg
|= TX39_UARTCTRL1_TWOSTOP
;
522 reg
&= ~TX39_UARTCTRL1_TWOSTOP
;
524 reg
|= TX39_UARTCTRL1_ENUART
;
525 tx_conf_write(chip
->sc_tc
, ofs
, reg
);
529 txcom_setbaudrate(struct txcom_chip
*chip
)
532 int ofs
= TX39_UARTCTRL1_REG(chip
->sc_slot
);
535 if (chip
->sc_speed
== 0)
539 DPRINTF("%d\n", chip
->sc_speed
);
541 reg1
= tx_conf_read(chip
->sc_tc
, ofs
);
542 reg1
&= ~TX39_UARTCTRL1_ENUART
;
543 tx_conf_write(chip
->sc_tc
, ofs
, reg1
);
545 baudrate
= TX39_UARTCLOCKHZ
/ (chip
->sc_speed
* 16) - 1;
546 reg
= TX39_UARTCTRL2_BAUDRATE_SET(0, baudrate
);
548 tx_conf_write(chip
->sc_tc
, TX39_UARTCTRL2_REG(chip
->sc_slot
), reg
);
550 reg1
|= TX39_UARTCTRL1_ENUART
;
551 tx_conf_write(chip
->sc_tc
, ofs
, reg1
);
555 txcom_cnattach(int slot
, int speed
, int cflag
)
559 txcom_chip
.sc_tc
= tx_conf_get_tag();
560 txcom_chip
.sc_slot
= slot
;
561 txcom_chip
.sc_cflag
= cflag
;
562 txcom_chip
.sc_speed
= speed
;
563 txcom_chip
.sc_hwflags
|= TXCOM_HW_CONSOLE
;
565 txcom_reset(&txcom_chip
);
567 txcom_setmode(&txcom_chip
);
568 txcom_setbaudrate(&txcom_chip
);
570 if (txcom_enable(&txcom_chip
, true) != 0)
580 txcom_break(struct txcom_softc
*sc
, int on
)
582 struct txcom_chip
*chip
= sc
->sc_chip
;
584 tx_conf_write(chip
->sc_tc
, TX39_UARTTXHOLD_REG(chip
->sc_slot
),
585 on
? TX39_UARTTXHOLD_BREAK
: 0);
589 txcom_modem(struct txcom_softc
*sc
, int on
)
591 struct txcom_chip
*chip
= sc
->sc_chip
;
592 tx_chipset_tag_t tc
= chip
->sc_tc
;
593 int slot
= chip
->sc_slot
;
598 config_hook_call(CONFIG_HOOK_SET
,
599 CONFIG_HOOK_COM0_DTR
,
603 reg
= tx_conf_read(tc
, TX39_UARTCTRL1_REG(slot
));
604 reg
&= ~TX39_UARTCTRL1_ENUART
;
605 tx_conf_write(tc
, TX39_UARTCTRL1_REG(slot
), reg
);
608 reg
&= ~TX39_UARTCTRL1_DISTXD
;
610 reg
|= TX39_UARTCTRL1_DISTXD
; /* low UARTTXD */
613 reg
|= TX39_UARTCTRL1_ENUART
;
614 tx_conf_write(tc
, TX39_UARTCTRL1_REG(slot
), reg
);
618 txcom_shutdown(struct txcom_softc
*sc
)
620 struct tty
*tp
= sc
->sc_tty
;
623 /* Clear any break condition set with TIOCSBRK. */
627 * Hang up if necessary. Wait a bit, so the other side has time to
628 * notice even if we immediately open the port again.
630 if (ISSET(tp
->t_cflag
, HUPCL
)) {
632 (void) tsleep(sc
, TTIPRI
, ttclos
, hz
);
636 /* Turn off interrupts if not the console. */
637 if (!ISSET(sc
->sc_chip
->sc_hwflags
, TXCOM_HW_CONSOLE
)) {
638 txcom_disable(sc
->sc_chip
);
645 __txcom_slotname(int slot
)
647 static const char *slotname
[] = {"UARTA", "UARTB", "unknown"};
649 if (slot
!= 0 && slot
!= 1)
652 return slotname
[slot
];
656 txcom_frameerr_intr(void *arg
)
658 struct txcom_softc
*sc
= arg
;
660 printf("%s frame error\n", __txcom_slotname(sc
->sc_chip
->sc_slot
));
666 txcom_parityerr_intr(void *arg
)
668 struct txcom_softc
*sc
= arg
;
670 printf("%s parity error\n", __txcom_slotname(sc
->sc_chip
->sc_slot
));
676 txcom_break_intr(void *arg
)
678 struct txcom_softc
*sc
= arg
;
680 printf("%s break\n", __txcom_slotname(sc
->sc_chip
->sc_slot
));
686 txcom_rxintr(void *arg
)
688 struct txcom_softc
*sc
= arg
;
689 struct txcom_chip
*chip
= sc
->sc_chip
;
692 c
= TX39_UARTRXHOLD_RXDATA(
693 tx_conf_read(chip
->sc_tc
,
694 TX39_UARTRXHOLD_REG(chip
->sc_slot
)));
696 sc
->sc_rbuf
[sc
->sc_rbput
] = c
;
697 sc
->sc_rbput
= (sc
->sc_rbput
+ 1) % TXCOM_RING_MASK
;
699 callout_reset(&sc
->sc_rxsoft_ch
, 1, txcom_rxsoft
, sc
);
705 txcom_rxsoft(void *arg
)
707 struct txcom_softc
*sc
= arg
;
708 struct tty
*tp
= sc
->sc_tty
;
709 int (*rint
)(int, struct tty
*);
713 rint
= tp
->t_linesw
->l_rint
;
720 code
= sc
->sc_rbuf
[get
];
722 if ((*rint
)(code
, tp
) == -1) {
724 * The line discipline's buffer is out of space.
727 get
= (get
+ 1) % TXCOM_RING_MASK
;
735 txcom_txintr(void *arg
)
737 struct txcom_softc
*sc
= arg
;
738 struct txcom_chip
*chip
= sc
->sc_chip
;
739 tx_chipset_tag_t tc
= chip
->sc_tc
;
741 if (sc
->sc_tbc
> 0) {
742 tx_conf_write(tc
, TX39_UARTTXHOLD_REG(chip
->sc_slot
),
744 TX39_UARTTXHOLD_TXDATA_MASK
));
748 callout_reset(&sc
->sc_rxsoft_ch
, 1, txcom_txsoft
, sc
);
755 txcom_txsoft(void *arg
)
757 struct txcom_softc
*sc
= arg
;
758 struct tty
*tp
= sc
->sc_tty
;
761 CLR(tp
->t_state
, TS_BUSY
);
762 if (ISSET(tp
->t_state
, TS_FLUSH
)) {
763 CLR(tp
->t_state
, TS_FLUSH
);
765 ndflush(&tp
->t_outq
, (int)(sc
->sc_tba
- tp
->t_outq
.c_cf
));
768 (*tp
->t_linesw
->l_start
)(tp
);
774 txcomopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
776 struct txcom_softc
*sc
;
777 struct txcom_chip
*chip
;
781 sc
= device_lookup_private(&txcom_cd
, minor(dev
));
788 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
793 if (txcom_enable(sc
->sc_chip
, false)) {
798 * Do the following iff this is a first open.
800 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
806 if (ISSET(chip
->sc_hwflags
, TXCOM_HW_CONSOLE
)) {
807 t
.c_ospeed
= chip
->sc_speed
;
808 t
.c_cflag
= chip
->sc_cflag
;
810 t
.c_ospeed
= TTYDEF_SPEED
;
811 t
.c_cflag
= TTYDEF_CFLAG
;
814 if (ISSET(chip
->sc_swflags
, TIOCFLAG_CLOCAL
))
815 SET(t
.c_cflag
, CLOCAL
);
816 if (ISSET(chip
->sc_swflags
, TIOCFLAG_CRTSCTS
))
817 SET(t
.c_cflag
, CRTSCTS
);
818 if (ISSET(chip
->sc_swflags
, TIOCFLAG_MDMBUF
))
819 SET(t
.c_cflag
, MDMBUF
);
821 /* Make sure txcomparam() will do something. */
825 tp
->t_iflag
= TTYDEF_IFLAG
;
826 tp
->t_oflag
= TTYDEF_OFLAG
;
827 tp
->t_lflag
= TTYDEF_LFLAG
;
833 * Turn on DTR. We must always do this, even if carrier is not
834 * present, because otherwise we'd have to use TIOCSDTR
835 * immediately after setting CLOCAL, which applications do not
836 * expect. We always assert DTR while the device is open
837 * unless explicitly requested to deassert it.
841 /* Clear the input ring, and unblock. */
842 sc
->sc_rbget
= sc
->sc_rbput
= 0;
846 #define TXCOMDIALOUT(x) (minor(x) & 0x80000)
847 if ((err
= ttyopen(tp
, TXCOMDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
)))) {
848 DPRINTF("ttyopen failed\n");
851 if ((err
= (*tp
->t_linesw
->l_open
)(dev
, tp
))) {
852 DPRINTF("line dicipline open failed\n");
859 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
861 * We failed to open the device, and nobody else had it opened.
862 * Clean up the state as appropriate.
872 txcomclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
874 struct txcom_softc
*sc
= device_lookup_private(&txcom_cd
, minor(dev
));
875 struct tty
*tp
= sc
->sc_tty
;
877 /* XXX This is for cons.c. */
878 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
881 (*tp
->t_linesw
->l_close
)(tp
, flag
);
884 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
886 * Although we got a last close, the device may still be in
887 * use; e.g. if this was the dialout node, and there are still
888 * processes waiting for carrier on the non-dialout node.
897 txcomread(dev_t dev
, struct uio
*uio
, int flag
)
899 struct txcom_softc
*sc
= device_lookup_private(&txcom_cd
, minor(dev
));
900 struct tty
*tp
= sc
->sc_tty
;
902 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flag
));
906 txcomwrite(dev_t dev
, struct uio
*uio
, int flag
)
908 struct txcom_softc
*sc
= device_lookup_private(&txcom_cd
, minor(dev
));
909 struct tty
*tp
= sc
->sc_tty
;
911 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
915 txcompoll(dev_t dev
, int events
, struct lwp
*l
)
917 struct txcom_softc
*sc
= device_lookup_private(&txcom_cd
, minor(dev
));
918 struct tty
*tp
= sc
->sc_tty
;
920 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
926 struct txcom_softc
*sc
= device_lookup_private(&txcom_cd
, minor(dev
));
932 txcomioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
934 struct txcom_softc
*sc
= device_lookup_private(&txcom_cd
, minor(dev
));
935 struct tty
*tp
= sc
->sc_tty
;
938 err
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
939 if (err
!= EPASSTHROUGH
) {
943 err
= ttioctl(tp
, cmd
, data
, flag
, l
);
944 if (err
!= EPASSTHROUGH
) {
974 *(int *)data
= sc
->sc_chip
->sc_swflags
;
978 err
= kauth_authorize_device_tty(l
->l_cred
,
979 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
983 sc
->sc_chip
->sc_swflags
= *(int *)data
;
994 txcomstop(struct tty
*tp
, int flag
)
996 struct txcom_softc
*sc
;
999 sc
= device_lookup_private(&txcom_cd
, minor(tp
->t_dev
));
1003 if (ISSET(tp
->t_state
, TS_BUSY
)) {
1004 /* Stop transmitting at the next chunk. */
1007 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
1008 SET(tp
->t_state
, TS_FLUSH
);
1015 txcomstart(struct tty
*tp
)
1017 struct txcom_softc
*sc
;
1018 struct txcom_chip
*chip
;
1019 tx_chipset_tag_t tc
;
1023 sc
= device_lookup_private(&txcom_cd
, minor(tp
->t_dev
));
1026 slot
= chip
->sc_slot
;
1030 if (!__txcom_txbufready(chip
, 0) ||
1031 ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
))
1037 sc
->sc_tba
= tp
->t_outq
.c_cf
;
1038 sc
->sc_tbc
= ndqb(&tp
->t_outq
, 0);
1039 SET(tp
->t_state
, TS_BUSY
);
1041 /* Output the first character of the contiguous buffer. */
1042 tx_conf_write(tc
, TX39_UARTTXHOLD_REG(slot
),
1043 (*sc
->sc_tba
& TX39_UARTTXHOLD_TXDATA_MASK
));
1053 * Set TXcom tty parameters from termios.
1056 txcomparam(struct tty
*tp
, struct termios
*t
)
1058 struct txcom_softc
*sc
;
1059 struct txcom_chip
*chip
;
1063 sc
= device_lookup_private(&txcom_cd
, minor(tp
->t_dev
));
1067 ospeed
= t
->c_ospeed
;
1069 /* Check requested parameters. */
1073 if (t
->c_ispeed
&& t
->c_ispeed
!= ospeed
) {
1080 * For the console, always force CLOCAL and !HUPCL, so that the port
1083 if (ISSET(chip
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
1084 ISSET(chip
->sc_hwflags
, TXCOM_HW_CONSOLE
)) {
1085 SET(t
->c_cflag
, CLOCAL
);
1086 CLR(t
->c_cflag
, HUPCL
);
1091 * If we're not in a mode that assumes a connection is present, then
1092 * ignore carrier changes.
1094 if (ISSET(t
->c_cflag
, CLOCAL
| MDMBUF
))
1100 * Only whack the UART when params change.
1101 * Some callers need to clear tp->t_ospeed
1102 * to make sure initialization gets done.
1104 if (tp
->t_ospeed
== ospeed
&& tp
->t_cflag
== t
->c_cflag
) {
1110 chip
->sc_speed
= ospeed
;
1111 chip
->sc_cflag
= t
->c_cflag
;
1113 txcom_setmode(chip
);
1114 txcom_setbaudrate(chip
);
1116 /* And copy to tty. */
1118 tp
->t_ospeed
= chip
->sc_speed
;
1119 tp
->t_cflag
= chip
->sc_cflag
;
1122 * Update the tty layer's idea of the carrier bit, in case we changed
1123 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1126 (void) (*tp
->t_linesw
->l_modem
)(tp
, chip
->sc_dcd
);
1129 * If hardware flow control is disabled, unblock any hard flow
1132 if (!ISSET(chip
->sc_cflag
, CHWFLOW
)) {
1142 txcom_dcd_hook(void *arg
, int type
, long id
, void *msg
)
1144 struct txcom_softc
*sc
= arg
;
1145 struct tty
*tp
= sc
->sc_tty
;
1146 struct txcom_chip
*chip
= sc
->sc_chip
;
1147 int modem
= !(int)msg
; /* p-edge 1, n-edge 0 */
1149 DPRINTF("DCD %s\n", modem
? "ON" : "OFF");
1151 if (modem
&& chip
->sc_dcd
)
1152 (void) (*tp
->t_linesw
->l_modem
)(tp
, chip
->sc_dcd
);
1158 txcom_cts_hook(void *arg
, int type
, long id
, void *msg
)
1160 struct txcom_softc
*sc
= arg
;
1161 struct tty
*tp
= sc
->sc_tty
;
1162 struct txcom_chip
*chip
= sc
->sc_chip
;
1163 int clear
= !(int)msg
; /* p-edge 1, n-edge 0 */
1165 DPRINTF("CTS %s\n", clear
? "ON" : "OFF");
1167 if (chip
->sc_msr_cts
) {
1169 chip
->sc_tx_stopped
= 1;
1171 chip
->sc_tx_stopped
= 0;
1172 (*tp
->t_linesw
->l_start
)(tp
);
1179 #ifdef TX39UARTDEBUG
1181 txcom_dump(struct txcom_chip
*chip
)
1183 tx_chipset_tag_t tc
= chip
->sc_tc
;
1184 int slot
= chip
->sc_slot
;
1187 reg
= tx_conf_read(tc
, TX39_UARTCTRL1_REG(slot
));
1188 #define ISSETPRINT(r, m) \
1189 dbg_bitmask_print(r, TX39_UARTCTRL1_##m, #m)
1190 ISSETPRINT(reg
, UARTON
);
1191 ISSETPRINT(reg
, EMPTY
);
1192 ISSETPRINT(reg
, PRXHOLDFULL
);
1193 ISSETPRINT(reg
, RXHOLDFULL
);
1194 ISSETPRINT(reg
, ENDMARX
);
1195 ISSETPRINT(reg
, ENDMATX
);
1196 ISSETPRINT(reg
, TESTMODE
);
1197 ISSETPRINT(reg
, ENBREAHALT
);
1198 ISSETPRINT(reg
, ENDMATEST
);
1199 ISSETPRINT(reg
, ENDMALOOP
);
1200 ISSETPRINT(reg
, PULSEOPT2
);
1201 ISSETPRINT(reg
, PULSEOPT1
);
1202 ISSETPRINT(reg
, DTINVERT
);
1203 ISSETPRINT(reg
, DISTXD
);
1204 ISSETPRINT(reg
, TWOSTOP
);
1205 ISSETPRINT(reg
, LOOPBACK
);
1206 ISSETPRINT(reg
, BIT7
);
1207 ISSETPRINT(reg
, EVENPARITY
);
1208 ISSETPRINT(reg
, ENPARITY
);
1209 ISSETPRINT(reg
, ENUART
);
1211 #endif /* TX39UARTDEBUG */