void zskbd_softint(struct zs_chanstate *cs) { struct zskbd_softc *sc = cs->cs_private; struct zskbd_devconfig *dc = sc->sc_dc; int rr0; /* handle pending transmissions */ if (dc->txq_head != dc->txq_tail) { int s; s = splzs(); while (dc->txq_head != dc->txq_tail) { rr0 = zs_read_csr(cs); if ((rr0 & ZSRR0_TX_READY) == 0) break; zs_write_data(cs, dc->txq[dc->txq_head]); dc->txq_head = (dc->txq_head + 1) & ~ZSKBD_TXQ_LEN; } splx(s); } /* handle incoming keystrokes/config */ while (dc->rxq_head != dc->rxq_tail) { zskbd_process(cs, dc->rxq[dc->rxq_head]); dc->rxq_head = (dc->rxq_head + 1) & ~ZSKBD_RXQ_LEN; } }
/* * Polled output char. */ static void zs_putc(int c) { int s, rr0; s = splzs(); /* Wait for transmitter to become ready. */ do { rr0 = zs_read_csr(&zscn_cs); } while ((rr0 & ZSRR0_TX_READY) == 0); zs_write_data(&zscn_cs, c); splx(s); }
/* * Start or restart transmission. */ void zsstart(struct tty *tp) { struct zstty_softc *zst = zs_device_lookup(&zstty_cd, ZSUNIT(tp->t_dev)); struct zs_chanstate *cs = zst->zst_cs; u_char *tba; int tbc, rr0; int s; s = spltty(); if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) goto out; if (zst->zst_tx_stopped) goto out; ttwakeupwr(tp); if (tp->t_outq.c_cc == 0) goto out; /* Grab the first contiguous region of buffer space. */ tba = tp->t_outq.c_cf; tbc = ndqb(&tp->t_outq, 0); #if IPL_ZS != IPL_TTY (void)splzs(); #endif zst->zst_tba = tba; zst->zst_tbc = tbc; SET(tp->t_state, TS_BUSY); zst->zst_tx_busy = 1; do { rr0 = zs_read_csr(cs); if ((rr0 & ZSRR0_TX_READY) == 0) break; zs_write_data(cs, *zst->zst_tba); zst->zst_tbc--; zst->zst_tba++; } while (zst->zst_tbc > 0); out: splx(s); }
/* expects to be in splzs() */ int zskbd_send(struct zs_chanstate *cs, uint8_t *c, u_int len) { struct zskbd_softc *sc = cs->cs_private; struct zskbd_devconfig *dc = sc->sc_dc; u_int i; int rr0; while (len != 0) { rr0 = zs_read_csr(cs); if ((rr0 & ZSRR0_TX_READY) == 0) { /* * poll until whole transmission complete during * autoconf */ if (cold) { for (i = 1000; i != 0; i--) { if ((rr0 & ZSRR0_TX_READY) != 0) break; delay(100); } if (i == 0) return EIO; } else break; } zs_write_data(cs, *c++); len--; } /* * Enqueue any remaining bytes. */ while (len != 0) { dc->txq[dc->txq_tail] = *c++; dc->txq_tail = (dc->txq_tail + 1) & ~ZSKBD_TXQ_LEN; len--; cs->cs_softreq = 1; } return 0; }
/* expects to be in splzs() */ static void ewskbd_zsc_send(struct zs_chanstate *cs, uint8_t *c, u_int len) { struct ewskbd_softc *sc; struct ewskbd_devconfig *dc; int i; sc = cs->cs_private; dc = sc->sc_dc; for (i = 0; i < len; i++) { if (dc->state & TX_READY) { zs_write_data(cs, c[i]); dc->state &= ~TX_READY; } else { dc->txq[dc->txq_tail] = c[i]; dc->txq_tail = EWSKBD_NEXTTXQ(dc->txq_tail); cs->cs_softreq = 1; } } }
static void ewskbd_zsc_softint(struct zs_chanstate *cs) { struct ewskbd_softc *sc; struct ewskbd_devconfig *dc; sc = cs->cs_private; dc = sc->sc_dc; /* handle pending transmissions */ if (dc->txq_head != dc->txq_tail && (dc->state & TX_READY)) { int s; dc->state &= ~TX_READY; s = splzs(); zs_write_data(cs, dc->txq[dc->txq_head]); splx(s); dc->txq_head = EWSKBD_NEXTTXQ(dc->txq_head); } /* don't bother if nobody is listening */ if (!dc->enabled) { dc->rxq_head = dc->rxq_tail; return; } /* handle incoming keystrokes/config */ while (dc->rxq_head != dc->rxq_tail) { uint8_t key = dc->rxq[dc->rxq_head]; /* toss wskbd a bone */ ewskbd_wskbd_input(cs, key); dc->rxq_head = EWSKBD_NEXTRXQ(dc->rxq_head); } }
/* * Transmitter Ready interrupt. * Called at splzs(). */ void zstty_txint(struct zs_chanstate *cs) { struct zstty_softc *zst = cs->cs_private; int rr0; zs_write_csr(cs, ZSWR0_RESET_TXINT); /* * If we've delayed a parameter change, do it now, and restart * output. */ if (cs->cs_heldchange) { zs_loadchannelregs(cs); cs->cs_heldchange = 0; zst->zst_tbc = zst->zst_heldtbc; zst->zst_heldtbc = 0; } while (zst->zst_tbc > 0) { rr0 = zs_read_csr(cs); if ((rr0 & ZSRR0_TX_READY) == 0) break; zs_write_data(cs, *zst->zst_tba); zst->zst_tbc--; zst->zst_tba++; } if (zst->zst_tbc == 0) { if (zst->zst_tx_busy) { zst->zst_tx_busy = 0; zst->zst_tx_done = 1; cs->cs_softreq = 1; } } }