void tslot_slot_intr(struct tslot_data *td, int intreg) { struct tslot_softc *sc = td->td_parent; int status, sockstat; status = TSLOT_READ(td, TS102_REG_CARD_A_STS); #ifdef TSLOT_DEBUG printf("%s: interrupt on socket %d ir %x sts %x\n", sc->sc_dev.dv_xname, td->td_slot, intreg, status); #endif sockstat = td->td_status; /* * The TS102 queues interrupt requests, and may trigger an interrupt * for a condition the driver does not want to receive anymore (for * example, after a card gets removed). * Thus, only proceed if the driver is currently allowing a particular * condition. */ if ((intreg & TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED) != 0 && (intreg & TS102_CARD_INT_MASK_CARDDETECT_STATUS) != 0) { tslot_queue_event(sc, td->td_slot); #ifdef TSLOT_DEBUG printf("%s: slot %d status changed from %d to %d\n", sc->sc_dev.dv_xname, td->td_slot, sockstat, td->td_status); #endif /* * Ignore extra interrupt bits, they are part of the change. */ return; } if ((intreg & TS102_CARD_INT_STATUS_IRQ) != 0 && (intreg & TS102_CARD_INT_MASK_IRQ) != 0) { /* ignore interrupts if we have a pending state change */ if (sc->sc_events & (1 << td->td_slot)) return; if ((sockstat & TS_CARD) == 0) { printf("%s: spurious interrupt on slot %d isr %x\n", sc->sc_dev.dv_xname, td->td_slot, intreg); return; } if (td->td_softintr != NULL) { /* * Disable this sbus interrupt, until the * softintr handler had a chance to run. */ TSLOT_WRITE(td, TS102_REG_CARD_A_INT, TSLOT_READ(td, TS102_REG_CARD_A_INT) & ~TS102_CARD_INT_MASK_IRQ); softintr_schedule(td->td_softintr); } } }
int vcons_intr(void *arg) { struct vcons_softc *sc = arg; if (sc->sc_tty) softintr_schedule(sc->sc_si); return (1); }
void vsaudio_hwintr(void *v) { struct vsaudio_softc *sc = v; uint8_t *d, *e; int k; mtx_enter(&audio_lock); /* clear interrupt */ k = vsaudio_codec_dread(sc, AM7930_DREG_IR); #if 0 /* interrupt is not shared, this shouldn't happen */ if ((k & (AM7930_IR_DTTHRSH | AM7930_IR_DRTHRSH | AM7930_IR_DSRI | AM7930_IR_DERI | AM7930_IR_BBUFF)) == 0) { mtx_leave(&audio_lock); return 0; } #endif /* receive incoming data */ d = sc->sc_rdata; e = sc->sc_rend; if (d != NULL && d <= e) { *d = vsaudio_codec_dread(sc, AM7930_DREG_BBRB); sc->sc_rdata++; if (d == e) { DPRINTFN(1, ("vsaudio_hwintr: swintr(r) requested")); softintr_schedule(sc->sc_swintr); } } /* send outgoing data */ d = sc->sc_pdata; e = sc->sc_pend; if (d != NULL && d <= e) { vsaudio_codec_dwrite(sc, AM7930_DREG_BBTB, *d); sc->sc_pdata++; if (d == e) { DPRINTFN(1, ("vsaudio_hwintr: swintr(p) requested")); softintr_schedule(sc->sc_swintr); } } mtx_leave(&audio_lock); }
int viocon_rx_intr(struct virtqueue *vq) { struct virtio_softc *vsc = vq->vq_owner; struct viocon_softc *sc = (struct viocon_softc *)vsc->sc_child; int portidx = (vq->vq_index - 1) / 2; struct viocon_port *vp = sc->sc_ports[portidx]; softintr_schedule(vp->vp_si); return 1; }
/* * The real-time timer, interrupting hz times per second. */ void hardclock(struct clockframe *frame) { struct proc *p; struct cpu_info *ci = curcpu(); p = curproc; if (p && ((p->p_flag & (P_SYSTEM | P_WEXIT)) == 0)) { struct process *pr = p->p_p; /* * Run current process's virtual and profile time, as needed. */ if (CLKF_USERMODE(frame) && timerisset(&pr->ps_timer[ITIMER_VIRTUAL].it_value) && itimerdecr(&pr->ps_timer[ITIMER_VIRTUAL], tick) == 0) { atomic_setbits_int(&p->p_flag, P_ALRMPEND); need_proftick(p); } if (timerisset(&pr->ps_timer[ITIMER_PROF].it_value) && itimerdecr(&pr->ps_timer[ITIMER_PROF], tick) == 0) { atomic_setbits_int(&p->p_flag, P_PROFPEND); need_proftick(p); } } /* * If no separate statistics clock is available, run it from here. */ if (stathz == 0) statclock(frame); if (--ci->ci_schedstate.spc_rrticks <= 0) roundrobin(ci); /* * If we are not the primary CPU, we're not allowed to do * any more work. */ if (CPU_IS_PRIMARY(ci) == 0) return; tc_ticktock(); ticks++; /* * Update real-time timeout queue. * Process callouts at a very low cpu priority, so we don't keep the * relatively high clock interrupt priority any longer than necessary. */ if (timeout_hardclock_update()) softintr_schedule(softclock_si); }
int imxuart_intr(void *arg) { struct imxuart_softc *sc = 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 sr1; u_int16_t *p; u_int16_t c; sr1 = bus_space_read_2(iot, ioh, IMXUART_USR1); if (ISSET(sr1, IMXUART_SR1_TRDY) && 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 (sc->sc_tty == NULL) return(0); if(!ISSET(bus_space_read_2(iot, ioh, IMXUART_USR2), IMXUART_SR2_RDR)) return 0; p = sc->sc_ibufp; while(ISSET(bus_space_read_2(iot, ioh, IMXUART_USR2), IMXUART_SR2_RDR)) { c = bus_space_read_1(iot, ioh, IMXUART_URXD); if (p >= sc->sc_ibufend) { sc->sc_floods++; if (sc->sc_errors++ == 0) timeout_add(&sc->sc_diag_tmo, 60 * hz); } else { *p++ = c; if (p == sc->sc_ibufhigh && ISSET(tp->t_cflag, CRTSCTS)) { /* XXX */ CLR(sc->sc_ucr3, IMXUART_CR3_DSR); bus_space_write_2(iot, ioh, IMXUART_UCR3, sc->sc_ucr3); } } /* XXX - msr stuff ? */ } sc->sc_ibufp = p; softintr_schedule(sc->sc_si); return 1; }
void sbbc_intr_cons(struct sbbc_softc *sc, uint32_t reason) { #ifdef DDB if ((reason & SBBC_SRAM_CONS_BRK) && sc == sbbc_cons_input) { if (db_console) Debugger(); } #endif if ((reason & SBBC_SRAM_CONS_IN) && sc->sc_tty) softintr_schedule(sc->sc_cons_si); }
int dt_intr(void *cookie) { struct dt_softc *sc; struct dt_msg *msg, *pend; sc = cookie; switch (dt_msg_get(&sc->sc_msg, 1)) { case DT_GET_ERROR: /* * Ugh! The most common occurrence of a data overrun is upon * a key press and the result is a software generated "stuck * key". All I can think to do is fake an "all keys up" * whenever a data overrun occurs. */ sc->sc_msg.src = dt_kbd_addr; sc->sc_msg.ctl = DT_CTL(1, 0, 0); sc->sc_msg.body[0] = DT_KBD_EMPTY; #ifdef DIAGNOSTIC printf("%s: data overrun or stray interrupt\n", sc->sc_dv.dv_xname); #endif break; case DT_GET_DONE: break; case DT_GET_NOTYET: return (1); } if ((msg = SLIST_FIRST(&sc->sc_free)) == NULL) { printf("%s: input overflow\n", sc->sc_dv.dv_xname); return (1); } SLIST_REMOVE_HEAD(&sc->sc_free, chain.slist); memcpy(msg, &sc->sc_msg, sizeof(*msg)); pend = SIMPLEQ_FIRST(&sc->sc_queue); SIMPLEQ_INSERT_TAIL(&sc->sc_queue, msg, chain.simpleq); if (pend == NULL) softintr_schedule(sc->sc_sih); return (1); }
int vioconhwiflow(struct tty *tp, int stop) { struct viocon_port *vp = dev2port(tp->t_dev); int s; s = spltty(); vp->vp_iflow = stop; if (stop) { virtio_stop_vq_intr(vp->vp_sc->sc_virtio, vp->vp_rx); } else { virtio_start_vq_intr(vp->vp_sc->sc_virtio, vp->vp_rx); softintr_schedule(vp->vp_si); } splx(s); return 1; }
int j720kbd_intr(void *arg) { struct j720ssp_softc *sc = arg; bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1); /* * Schedule a soft interrupt to process at lower priority, * as reading keycodes takes time. * * Interrupts are generated every 25-33ms as long as there * are unprocessed key events. So it is not a good idea to * use callout to call j720kbdsoft after some delay in hope * of reducing interrupts. */ softintr_schedule(sc->sc_si); return (1); }
/* * Our ZS chips all share a common, autovectored interrupt, * so we have to look at all of them on each interrupt. */ int zshard(void *arg) { struct zsc_softc *zsc; int unit, rval; rval = 0; for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { zsc = zsc_cd.cd_devs[unit]; if (zsc == NULL) continue; rval |= zsc_intr_hard(zsc); if (zsc->zsc_cs[0]->cs_softreq) { /* zsc_req_softint(zsc); */ /* We are at splzs here, so no need to lock. */ if (zssoftpending == 0) { zssoftpending = 1; softintr_schedule(zsc->zsc_softintr); } } } return (rval); }
/* * hard interrupt routine * * returns 1 if it handled it, otherwise 0 * * runs at interrupt priority */ int magma_hard(void *arg) { struct magma_softc *sc = arg; struct cd1400 *cd; int chip, status = 0; int serviced = 0; int needsoftint = 0; /* * check status of all the CD1400 chips */ for (chip = 0 ; chip < sc->ms_ncd1400 ; chip++) status |= CD1400_READ_REG(&sc->ms_cd1400[chip], CD1400_SVRR); if (ISSET(status, CD1400_SVRR_RXRDY)) { /* enter rx service context */ u_int8_t rivr = bus_space_read_1(sc->sc_bustag, sc->sc_svcackrh, 0); int port = rivr >> 4; if (rivr & (1<<3)) { /* parallel port */ struct mbpp_port *mbpp; int n_chars; mbpp = &sc->ms_mbpp->ms_port[port]; cd = mbpp->mp_cd1400; /* don't think we have to handle exceptions */ n_chars = CD1400_READ_REG(cd, CD1400_RDCR); while (n_chars--) { if (mbpp->mp_cnt == 0) { SET(mbpp->mp_flags, MBPPF_WAKEUP); needsoftint = 1; break; } *mbpp->mp_ptr = CD1400_READ_REG(cd, CD1400_RDSR); mbpp->mp_ptr++; mbpp->mp_cnt--; } } else { /* serial port */ struct mtty_port *mtty; u_char *ptr, n_chars, line_stat; mtty = &sc->ms_mtty->ms_port[port]; cd = mtty->mp_cd1400; if (ISSET(rivr, CD1400_RIVR_EXCEPTION)) { line_stat = CD1400_READ_REG(cd, CD1400_RDSR); n_chars = 1; } else { /* no exception, received data OK */ line_stat = 0; n_chars = CD1400_READ_REG(cd, CD1400_RDCR); } ptr = mtty->mp_rput; while (n_chars--) { *ptr++ = line_stat; *ptr++ = CD1400_READ_REG(cd, CD1400_RDSR); if (ptr == mtty->mp_rend) ptr = mtty->mp_rbuf; if (ptr == mtty->mp_rget) { if (ptr == mtty->mp_rbuf) ptr = mtty->mp_rend; ptr -= 2; SET(mtty->mp_flags, MTTYF_RING_OVERFLOW); break; } } mtty->mp_rput = ptr; needsoftint = 1; } CD1400_WRITE_REG(cd, CD1400_EOSRR, 0); /* end service context */ serviced = 1; } /* if(rx_service...) */ if (ISSET(status, CD1400_SVRR_MDMCH)) { u_int8_t mivr = bus_space_read_1(sc->sc_bustag, sc->sc_svcackmh, 0); int port = mivr >> 4; struct mtty_port *mtty; int carrier; u_char msvr; /* * Handle CD (LC2+1Sp = DSR) changes. */ mtty = &sc->ms_mtty->ms_port[port]; cd = mtty->mp_cd1400; msvr = CD1400_READ_REG(cd, CD1400_MSVR2); carrier = ISSET(msvr, cd->cd_parmode ? CD1400_MSVR2_DSR : CD1400_MSVR2_CD); if (mtty->mp_carrier != carrier) { SET(mtty->mp_flags, MTTYF_CARRIER_CHANGED); mtty->mp_carrier = carrier; needsoftint = 1; } CD1400_WRITE_REG(cd, CD1400_EOSRR, 0); /* end service context */ serviced = 1; } /* if(mdm_service...) */ if (ISSET(status, CD1400_SVRR_TXRDY)) { /* enter tx service context */ u_int8_t tivr = bus_space_read_1(sc->sc_bustag, sc->sc_svcackth, 0); int port = tivr >> 4; if (tivr & (1<<3)) { /* parallel port */ struct mbpp_port *mbpp; mbpp = &sc->ms_mbpp->ms_port[port]; cd = mbpp->mp_cd1400; if (mbpp->mp_cnt) { int count = 0; /* fill the fifo */ while (mbpp->mp_cnt && count++ < CD1400_PAR_FIFO_SIZE) { CD1400_WRITE_REG(cd, CD1400_TDR, *mbpp->mp_ptr); mbpp->mp_ptr++; mbpp->mp_cnt--; } } else { /* fifo is empty and we got no more data to send, so shut * off interrupts and signal for a wakeup, which can't be * done here in case we beat mbpp_send to the tsleep call * (we are running at >spltty) */ CD1400_WRITE_REG(cd, CD1400_SRER, 0); SET(mbpp->mp_flags, MBPPF_WAKEUP); needsoftint = 1; } } else { /* serial port */ struct mtty_port *mtty; struct tty *tp; mtty = &sc->ms_mtty->ms_port[port]; cd = mtty->mp_cd1400; tp = mtty->mp_tty; if (!ISSET(mtty->mp_flags, MTTYF_STOP)) { int count = 0; /* check if we should start/stop a break */ if (ISSET(mtty->mp_flags, MTTYF_SET_BREAK)) { CD1400_WRITE_REG(cd, CD1400_TDR, 0); CD1400_WRITE_REG(cd, CD1400_TDR, 0x81); /* should we delay too? */ CLR(mtty->mp_flags, MTTYF_SET_BREAK); count += 2; } if (ISSET(mtty->mp_flags, MTTYF_CLR_BREAK)) { CD1400_WRITE_REG(cd, CD1400_TDR, 0); CD1400_WRITE_REG(cd, CD1400_TDR, 0x83); CLR(mtty->mp_flags, MTTYF_CLR_BREAK); count += 2; } /* I don't quite fill the fifo in case the last one is a * NULL which I have to double up because its the escape * code for embedded transmit characters. */ while (mtty->mp_txc > 0 && count < CD1400_TX_FIFO_SIZE - 1) { u_char ch; ch = *mtty->mp_txp; mtty->mp_txc--; mtty->mp_txp++; if (ch == 0) { CD1400_WRITE_REG(cd, CD1400_TDR, ch); count++; } CD1400_WRITE_REG(cd, CD1400_TDR, ch); count++; } } /* if we ran out of work or are requested to STOP then * shut off the txrdy interrupts and signal DONE to flush * out the chars we have sent. */ if (mtty->mp_txc == 0 || ISSET(mtty->mp_flags, MTTYF_STOP)) { int srer; srer = CD1400_READ_REG(cd, CD1400_SRER); CLR(srer, CD1400_SRER_TXRDY); CD1400_WRITE_REG(cd, CD1400_SRER, srer); CLR(mtty->mp_flags, MTTYF_STOP); SET(mtty->mp_flags, MTTYF_DONE); needsoftint = 1; } } CD1400_WRITE_REG(cd, CD1400_EOSRR, 0); /* end service context */ serviced = 1; } /* if(tx_service...) */ /* XXX service CD1190 interrupts too for (chip = 0 ; chip < sc->ms_ncd1190 ; chip++) { } */ if (needsoftint) softintr_schedule(sc->sc_sih); return (serviced); }
int sxiuart_intr(void *arg) { struct sxiuart_softc *sc = arg; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; struct tty *tp; uint32_t cnt; uint8_t c, iir, lsr, msr, delta; uint8_t *p; iir = bus_space_read_1(iot, ioh, SXIUART_IIR); if ((iir & IIR_IMASK) == IIR_BUSY) { (void)bus_space_read_1(iot, ioh, SXIUART_USR); return (0); } if (ISSET(iir, IIR_NOPEND)) return (0); if (sc->sc_tty == NULL) return (0); tp = sc->sc_tty; cnt = 0; loop: lsr = bus_space_read_1(iot, ioh, SXIUART_LSR); if (ISSET(lsr, LSR_RXRDY)) { if (cnt == 0) { p = sc->sc_ibufp; softintr_schedule(sc->sc_si); } cnt++; c = bus_space_read_1(iot, ioh, SXIUART_RBR); if (ISSET(lsr, LSR_BI)) { #if defined(DDB) if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { if (db_console) Debugger(); goto loop; } #endif c = 0; } if (p >= sc->sc_ibufend) { sc->sc_floods++; if (sc->sc_errors++ == 0) timeout_add_sec(&sc->sc_diag_tmo, 60); } else { *p++ = c; *p++ = lsr; if (p == sc->sc_ibufhigh && ISSET(tp->t_cflag, CRTSCTS)) { /* XXX */ CLR(sc->sc_mcr, MCR_RTS); bus_space_write_1(iot, ioh, SXIUART_MCR, sc->sc_mcr); } } goto loop; } else if (cnt > 0) sc->sc_ibufp = p; msr = bus_space_read_1(iot, ioh, SXIUART_MSR); if (msr != sc->sc_msr) { delta = msr ^ sc->sc_msr; ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS, sc->sc_msr & MSR_DCD, msr & MSR_DCD); sc->sc_msr = msr; if (ISSET(delta, MSR_DCD)) { if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) { CLR(sc->sc_mcr, sc->sc_dtr); bus_space_write_1(iot, ioh, SXIUART_MCR, sc->sc_mcr); } } if (ISSET(delta & msr, MSR_CTS) && ISSET(tp->t_cflag, CRTSCTS)) (*linesw[tp->t_line].l_start)(tp); } if (ISSET(tp->t_state, TS_BUSY) && ISSET(lsr, LSR_TXRDY)) { CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (sc->sc_halt > 0) wakeup(&tp->t_outq); (*linesw[tp->t_line].l_start)(tp); } iir = bus_space_read_1(iot, ioh, SXIUART_IIR); if (ISSET(iir, IIR_NOPEND)) goto done; cnt = 0; goto loop; done: return (1); }