static int s3c2410_getc(struct uart_bas *bas, struct mtx *mtx) { while (!sscom_rxrdy(bas->bst, bas->bsh)) continue; return sscom_getc(bas->bst, bas->bsh); }
/* * 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; }
static void sscom_iflush(struct sscom_softc *sc) { bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int timo; timo = 50000; /* flush any pending I/O */ while ( sscom_rxrdy(iot, ioh) && --timo) (void)sscom_getc(iot,ioh); #ifdef DIAGNOSTIC if (!timo) printf("%s: sscom_iflush timeout\n", device_xname(sc->sc_dev)); #endif }
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; }
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; }