int xenconscn_getc(dev_t dev) { char c; int s = spltty(); XENCONS_RING_IDX cons, prod; if (xencons_console_device && xencons_console_device->polling == 0) { printf("xenconscn_getc() but not polling\n"); splx(s); return 0; } if (xendomain_is_dom0()) { while (HYPERVISOR_console_io(CONSOLEIO_read, 1, &c) == 0) ; cn_check_magic(dev, c, xencons_cnm_state); splx(s); return c; } if (xencons_console_device == NULL) { printf("xenconscn_getc(): not console\n"); while (1) ; /* loop here instead of in ddb */ splx(s); return 0; } if (xencons_console_device->polling == 0) { printf("xenconscn_getc() but not polling\n"); splx(s); return 0; } cons = xencons_interface->in_cons; prod = xencons_interface->in_prod; xen_rmb(); while (cons == prod) { HYPERVISOR_yield(); prod = xencons_interface->in_prod; } xen_rmb(); c = xencons_interface->in[MASK_XENCONS_IDX(xencons_interface->in_cons, xencons_interface->in)]; xen_rmb(); xencons_interface->in_cons = cons + 1; cn_check_magic(dev, c, xencons_cnm_state); splx(s); return c; }
void xencons_tty_input(struct xencons_softc *sc, char* buf, int len) { struct tty *tp; int i; tp = sc->sc_tty; if (tp == NULL) return; for (i = 0; i < len; i++) { cn_check_magic(sc->sc_tty->t_dev, buf[i], xencons_cnm_state); (*tp->t_linesw->l_rint)(buf[i], tp); } }
static void pcons_poll(void *aux) { struct pconssoftc *sc = aux; struct tty *tp = sc->of_tty; int c; char ch; while ((c = prom_peekchar()) >= 0) { ch = c; cn_check_magic(tp->t_dev, ch, pcons_cnm_state); if (tp && (tp->t_state & TS_ISOPEN)) (*tp->t_linesw->l_rint)(ch, tp); } callout_reset(&sc->sc_poll_ch, 1, pcons_poll, sc); }
/* * Console kernel output character routine. */ void sscomcnputc(dev_t dev, int c) { int s = splserial(); int timo; int cin; int __attribute__((__unused__)) stat; if (sscom_readaheadcount < MAX_READAHEAD && sscom_rxrdy(sscomconstag, sscomconsioh)) { int __attribute__((__unused__))cn_trapped = 0; cin = sscom_getc(sscomconstag, sscomconsioh); stat = sscom_geterr(sscomconstag, sscomconsioh); cn_check_magic(dev, cin, sscom_cnm_state); sscom_readahead[sscom_readaheadcount++] = cin; }
int at91usart_cn_getc(dev_t dev) { int c, sr; int s; #if 0 bus_space_tag_t iot = usart_cn_sc.sc_iot; bus_space_handle_t ioh = usart_cn_sc.sc_ioh; #endif s = spltty(); while ((c = USART_PEEKC()) == -1) { splx(s); s = spltty(); } ; sr = USARTREG(USART_SR); if (ISSET(sr, USART_SR_FRAME) && c == 0) { USARTREG(USART_CR) = USART_CR_RSTSTA; // reset status bits c = CNC_BREAK; } #ifdef DDB extern int db_active; if (!db_active) #endif { int cn_trapped = 0; /* unused */ cn_check_magic(dev, c, at91usart_cnm_state); } splx(s); c &= 0xff; return (c); }
int sscomcngetc(dev_t dev) { int s = splserial(); u_char __attribute__((__unused__)) stat; u_char c; /* got a character from reading things earlier */ if (sscom_readaheadcount > 0) { int i; c = sscom_readahead[0]; for (i = 1; i < sscom_readaheadcount; i++) { sscom_readahead[i-1] = sscom_readahead[i]; } sscom_readaheadcount--; splx(s); return c; } /* block until a character becomes available */ while (!sscom_rxrdy(sscomconstag, sscomconsioh)) ; c = sscom_getc(sscomconstag, sscomconsioh); stat = sscom_geterr(sscomconstag, sscomconsioh); { int __attribute__((__unused__))cn_trapped = 0; #ifdef DDB extern int db_active; if (!db_active) #endif cn_check_magic(dev, c, sscom_cnm_state); } splx(s); return c; }
static int dbgu_intr(void* arg) { struct at91dbgu_softc *sc = arg; #if 0 bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; #endif u_char *put, *end; u_int cc; uint32_t imr, sr; int c = 0; imr = DBGUREG(DBGU_IMR); #if 0 if (!imr) return 0; #endif sr = DBGUREG(DBGU_SR); if (!(sr & imr)) { if (sr & DBGU_SR_RXRDY) { // printf("sr=0x%08x imr=0x%08x\n", sr, imr); } return 0; } end = sc->sc_ebuf; put = sc->sc_rbput; cc = sc->sc_rbavail; // ok, we DO have some interrupts to serve! if (sr & DBGU_SR_RXRDY) { int cn_trapped = 0; c = DBGUREG(DBGU_RHR); if (ISSET(sr, (DBGU_SR_OVRE | DBGU_SR_FRAME | DBGU_SR_PARE))) DBGUREG(DBGU_CR) = DBGU_CR_RSTSTA; if (ISSET(sr, DBGU_SR_FRAME) && c == 0) { c = CNC_BREAK; } #ifdef DDB extern int db_active; if (!db_active) #endif cn_check_magic(cn_tab->cn_dev, c, at91dbgu_cnm_state); if (!cn_trapped && cc) { put[0] = c & 0xff; put[1] = sr & 0xff; put += 2; if (put >= end) put = sc->sc_rbuf; cc--; /* * Current string of incoming characters ended because * no more data was available or we ran out of space. * Schedule a receive event if any data was received. * If we're out of space, turn off receive interrupts. */ sc->sc_rbput = put; sc->sc_rbavail = cc; if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) sc->sc_rx_ready = 1; /* * See if we are in danger of overflowing a buffer. If * so, use hardware flow control to ease the pressure. */ /* but at91dbgu cannot (yet). X-( */ /* * If we're out of space, disable receive interrupts * until the queue has drained a bit. */ if (!cc) { SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); } } } /* * Done handling any receive interrupts. See if data can be * transmitted as well. Schedule tx done event if no data left * and tty was marked busy. */ if (ISSET(sr, DBGU_SR_TXRDY) && sc->sc_tbc > 0) { /* Output the next chunk of the contiguous buffer, if any. */ at91dbgu_filltx(sc); } else { /* Disable transmit completion interrupts if necessary. */ DBGUREG(DBGU_IDR) = DBGU_INT_TXRDY; if (sc->sc_tx_busy) { sc->sc_tx_busy = 0; sc->sc_tx_done = 1; } } /* Wake up the poller. */ softint_schedule(sc->sc_si); #if 0 #ifdef RND_COM rnd_add_uint32(&sc->rnd_source, imr ^ sr ^ c); #endif #endif return (1); }
int sabtty_intr(struct sabtty_softc *sc, int *needsoftp) { uint8_t isr0, isr1; int i, len = 0, needsoft = 0, r = 0, clearfifo = 0; isr0 = SAB_READ(sc, SAB_ISR0); isr1 = SAB_READ(sc, SAB_ISR1); if (isr0 || isr1) r = 1; if (isr0 & SAB_ISR0_RPF) { len = 32; clearfifo = 1; } if (isr0 & SAB_ISR0_TCD) { len = (32 - 1) & SAB_READ(sc, SAB_RBCL); clearfifo = 1; } if (isr0 & SAB_ISR0_TIME) { sabtty_cec_wait(sc); SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD); } if (isr0 & SAB_ISR0_RFO) { sc->sc_flags |= SABTTYF_RINGOVERFLOW; clearfifo = 1; } if (len != 0) { uint8_t *ptr, b; ptr = sc->sc_rput; for (i = 0; i < len; i++) { b = SAB_READ(sc, SAB_RFIFO); if (i % 2 == 0) /* skip status byte */ cn_check_magic(sc->sc_tty->t_dev, b, sabtty_cnm_state); *ptr++ = b; if (ptr == sc->sc_rend) ptr = sc->sc_rbuf; if (ptr == sc->sc_rget) { if (ptr == sc->sc_rbuf) ptr = sc->sc_rend; ptr--; sc->sc_flags |= SABTTYF_RINGOVERFLOW; } } sc->sc_rput = ptr; needsoft = 1; } if (clearfifo) { sabtty_cec_wait(sc); SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC); } if (isr0 & SAB_ISR0_CDSC) { sc->sc_flags |= SABTTYF_CDCHG; needsoft = 1; } if (isr1 & SAB_ISR1_BRKT) cn_check_magic(sc->sc_tty->t_dev, CNC_BREAK, sabtty_cnm_state); if (isr1 & (SAB_ISR1_XPR | SAB_ISR1_ALLS)) { if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_XFW) && (sc->sc_flags & SABTTYF_STOP) == 0) { if (sc->sc_txc < 32) len = sc->sc_txc; else len = 32; if (len > 0) { SAB_WRITE_BLOCK(sc, SAB_XFIFO, sc->sc_txp, len); sc->sc_txp += len; sc->sc_txc -= len; sabtty_cec_wait(sc); SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF); /* * Prevent the false end of xmit from * confusing things below. */ isr1 &= ~SAB_ISR1_ALLS; } } if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) { if ((sc->sc_imr1 & SAB_IMR1_XPR) == 0) { sc->sc_imr1 |= SAB_IMR1_XPR; sc->sc_imr1 &= ~SAB_IMR1_ALLS; SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); } } } if ((isr1 & SAB_ISR1_ALLS) && ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP))) { if (sc->sc_flags & SABTTYF_TXDRAIN) wakeup(sc); sc->sc_flags &= ~SABTTYF_STOP; sc->sc_flags |= SABTTYF_DONE; sc->sc_imr1 |= SAB_IMR1_ALLS; SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1); needsoft = 1; } if (needsoft) *needsoftp = needsoft; return (r); }
int sscomrxintr(void *arg) { struct sscom_softc *sc = arg; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; u_char *put, *end; u_int cc; if (SSCOM_ISALIVE(sc) == 0) return 0; SSCOM_LOCK(sc); end = sc->sc_ebuf; put = sc->sc_rbput; cc = sc->sc_rbavail; do { u_char msts, delta; u_char uerstat; uint32_t ufstat; ufstat = bus_space_read_4(iot, ioh, SSCOM_UFSTAT); /* XXX: break interrupt with no character? */ if ( (ufstat & (UFSTAT_RXCOUNT|UFSTAT_RXFULL)) && !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { while (cc > 0) { int cn_trapped = 0; /* get status and received character. read status register first */ uerstat = sscom_geterr(iot, ioh); put[0] = sscom_getc(iot, ioh); if (ISSET(uerstat, UERSTAT_BREAK)) { int con_trapped = 0; cn_check_magic(sc->sc_tty->t_dev, CNC_BREAK, sscom_cnm_state); if (con_trapped) continue; #if defined(KGDB) if (ISSET(sc->sc_hwflags, SSCOM_HW_KGDB)) { kgdb_connect(1); continue; } #endif } put[1] = uerstat; cn_check_magic(sc->sc_tty->t_dev, put[0], sscom_cnm_state); if (!cn_trapped) { put += 2; if (put >= end) put = sc->sc_rbuf; cc--; } ufstat = bus_space_read_4(iot, ioh, SSCOM_UFSTAT); if ( (ufstat & (UFSTAT_RXFULL|UFSTAT_RXCOUNT)) == 0 ) break; } /* * Current string of incoming characters ended because * no more data was available or we ran out of space. * Schedule a receive event if any data was received. * If we're out of space, turn off receive interrupts. */ sc->sc_rbput = put; sc->sc_rbavail = cc; if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) sc->sc_rx_ready = 1; /* * See if we are in danger of overflowing a buffer. If * so, use hardware flow control to ease the pressure. */ if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) && cc < sc->sc_r_hiwat) { SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); sscom_hwiflow(sc); } /* * If we're out of space, disable receive interrupts * until the queue has drained a bit. */ if (!cc) { SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); sscom_disable_rxint(sc); sc->sc_ucon &= ~UCON_ERRINT; bus_space_write_4(iot, ioh, SSCOM_UCON, sc->sc_ucon); } } msts = sc->sc_read_modem_status(sc); delta = msts ^ sc->sc_msts; sc->sc_msts = msts; #ifdef notyet /* * Pulse-per-second (PSS) signals on edge of DCD? * Process these even if line discipline is ignoring DCD. */ if (delta & sc->sc_ppsmask) { struct timeval tv; if ((msr & sc->sc_ppsmask) == sc->sc_ppsassert) { /* XXX nanotime() */ microtime(&tv); TIMEVAL_TO_TIMESPEC(&tv, &sc->ppsinfo.assert_timestamp); if (sc->ppsparam.mode & PPS_OFFSETASSERT) { timespecadd(&sc->ppsinfo.assert_timestamp, &sc->ppsparam.assert_offset, &sc->ppsinfo.assert_timestamp); } #ifdef PPS_SYNC if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) hardpps(&tv, tv.tv_usec); #endif sc->ppsinfo.assert_sequence++; sc->ppsinfo.current_mode = sc->ppsparam.mode; } else if ((msr & sc->sc_ppsmask) == sc->sc_ppsclear) { /* XXX nanotime() */ microtime(&tv); TIMEVAL_TO_TIMESPEC(&tv, &sc->ppsinfo.clear_timestamp); if (sc->ppsparam.mode & PPS_OFFSETCLEAR) { timespecadd(&sc->ppsinfo.clear_timestamp, &sc->ppsparam.clear_offset, &sc->ppsinfo.clear_timestamp); } #ifdef PPS_SYNC if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR) hardpps(&tv, tv.tv_usec); #endif sc->ppsinfo.clear_sequence++; sc->ppsinfo.current_mode = sc->ppsparam.mode; } } #endif /* * Process normal status changes */ if (ISSET(delta, sc->sc_msr_mask)) { SET(sc->sc_msr_delta, delta); /* * Stop output immediately if we lose the output * flow control signal or carrier detect. */ if (ISSET(~msts, sc->sc_msr_mask)) { sc->sc_tbc = 0; sc->sc_heldtbc = 0; #ifdef SSCOM_DEBUG if (sscom_debug) sscomstatus(sc, "sscomintr "); #endif } sc->sc_st_check = 1; } /* * Done handling any receive interrupts. */ /* * If we've delayed a parameter change, do it * now, and restart * output. */ if ((ufstat & UFSTAT_TXCOUNT) == 0) { /* XXX: we should check transmitter empty also */ if (sc->sc_heldchange) { sscom_loadchannelregs(sc); sc->sc_heldchange = 0; sc->sc_tbc = sc->sc_heldtbc; sc->sc_heldtbc = 0; } } } while (0); SSCOM_UNLOCK(sc); /* Wake up the poller. */ softint_schedule(sc->sc_si); #ifdef RND_COM rnd_add_uint32(&sc->rnd_source, iir | rsr); #endif return 1; }
STATIC void gtmpsc_intr_rx(struct gtmpsc_softc *sc) { gtmpsc_pollrx_t *vrxp; uint32_t csr; int kick, ix; kick = 0; /* already handled in gtmpsc_common_getc() */ if (sc->sc_rcvdrx == sc->sc_rcvrx) return; ix = sc->sc_rcvdrx; vrxp = &sc->sc_poll_sdmapage->rx[ix]; bus_dmamap_sync(sc->sc_dmat, sc->sc_txdma_map, ix * sizeof(gtmpsc_pollrx_t), sizeof(sdma_desc_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); csr = vrxp->rxdesc.sdma_csr; while (!(csr & SDMA_CSR_RX_OWN)) { bus_dmamap_sync(sc->sc_dmat, sc->sc_rxdma_map, ix * sizeof(gtmpsc_pollrx_t) + sizeof(sdma_desc_t), sizeof(vrxp->rxbuf), BUS_DMASYNC_POSTREAD); vrxp->rxdesc.sdma_cnt &= SDMA_RX_CNT_BCNT_MASK; if (vrxp->rxdesc.sdma_csr & SDMA_CSR_RX_BR) { int cn_trapped = 0; cn_check_magic(sc->sc_tty->t_dev, CNC_BREAK, gtmpsc_cnm_state); if (cn_trapped) continue; #if defined(KGDB) && !defined(DDB) if (ISSET(sc->sc_flags, GTMPSC_KGDB)) { kgdb_connect(1); continue; } #endif } sc->sc_rcvcnt += vrxp->rxdesc.sdma_cnt; kick = 1; ix = (ix + 1) % GTMPSC_NTXDESC; vrxp = &sc->sc_poll_sdmapage->rx[ix]; bus_dmamap_sync(sc->sc_dmat, sc->sc_txdma_map, ix * sizeof(gtmpsc_pollrx_t), sizeof(sdma_desc_t), BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); csr = vrxp->rxdesc.sdma_csr; } bus_dmamap_sync(sc->sc_dmat, sc->sc_txdma_map, ix * sizeof(gtmpsc_pollrx_t), sizeof(sdma_desc_t), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); if (kick) { sc->sc_rcvdrx = ix; sc->sc_rx_ready = 1; softint_schedule(sc->sc_si); } }