Diff below fixes two issues with pluart(4):
1. Output sometimes gets stuck, i.e. when running "systat vm .1" on
the console. It seems that checking TXFE bit in the UARTFR
register in pluart_start() fixes that issue. But I restructured
that function a bit to be closer to comstart() and removed the
(unused) FIFO support code. I hope to add FIFO support later, but
for now it is just a distraction.
2. Tx interrupts aren't counted. To fix that I restructured the
interrupt handler a bit. It now actually looks at the interrupt
status bits.
More fixes and cleanups coming at a later stage.
ok?
Index: dev/ic/pluart.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/pluart.c,v
retrieving revision 1.3
diff -u -p -r1.3 pluart.c
--- dev/ic/pluart.c 19 Jul 2019 00:17:15 -0000 1.3
+++ dev/ic/pluart.c 10 Aug 2019 14:16:43 -0000
@@ -188,26 +188,26 @@ pluart_intr(void *arg)
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
struct tty *tp = sc->sc_tty;
- u_int16_t fr;
+ u_int16_t is;
u_int16_t *p;
u_int16_t c;
- bus_space_write_4(iot, ioh, UART_ICR, -1);
+ is = bus_space_read_4(iot, ioh, UART_RIS);
+ bus_space_write_4(iot, ioh, UART_ICR, is);
if (sc->sc_tty == NULL)
- return(0);
+ return 0;
- fr = bus_space_read_4(iot, ioh, UART_FR);
- if (ISSET(fr, UART_FR_TXFE) && ISSET(tp->t_state, TS_BUSY)) {
+ if (!ISSET(is, UART_IMSC_RXIM) && !ISSET(is, UART_IMSC_TXIM))
+ return 0;
+
+ if (ISSET(is, UART_IMSC_TXIM) && ISSET(tp->t_state, TS_BUSY)) {
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
if (sc->sc_halt > 0)
wakeup(&tp->t_outq);
(*linesw[tp->t_line].l_start)(tp);
}
- if(!ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF))
- return 0;
-
p = sc->sc_ibufp;
while (ISSET(bus_space_read_4(iot, ioh, UART_FR), UART_FR_RXFF)) {
@@ -326,35 +326,22 @@ pluart_start(struct tty *tp)
struct pluart_softc *sc = pluart_cd.cd_devs[DEVUNIT(tp->t_dev)];
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
-
+ u_int16_t fr;
int s;
+
s = spltty();
if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
goto out;
- if (tp->t_outq.c_cc <= tp->t_lowat) {
- if (ISSET(tp->t_state, TS_ASLEEP)) {
- CLR(tp->t_state, TS_ASLEEP);
- wakeup(&tp->t_outq);
- }
- if (tp->t_outq.c_cc == 0)
- goto out;
- selwakeup(&tp->t_wsel);
- }
+ ttwakeupwr(tp);
+ if (tp->t_outq.c_cc == 0)
+ goto out;
SET(tp->t_state, TS_BUSY);
- if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
- u_char buffer[64]; /* largest fifo */
- int i, n;
-
- n = q_to_b(&tp->t_outq, buffer,
- min(sc->sc_fifolen, sizeof buffer));
- for (i = 0; i < n; i++) {
- bus_space_write_4(iot, ioh, UART_DR, buffer[i]);
- }
- bzero(buffer, n);
- } else if (tp->t_outq.c_cc != 0)
+ fr = bus_space_read_4(iot, ioh, UART_FR);
+ while (tp->t_outq.c_cc != 0 && ISSET(fr, UART_FR_TXFE)) {
bus_space_write_4(iot, ioh, UART_DR, getc(&tp->t_outq));
-
+ fr = bus_space_read_4(iot, ioh, UART_FR);
+ }
out:
splx(s);
}