Exemple #1
0
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);
		}
	}
}
Exemple #2
0
int
vcons_intr(void *arg)
{
	struct vcons_softc *sc = arg;

	if (sc->sc_tty)
		softintr_schedule(sc->sc_si);
	return (1);
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
0
/*
 * 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);
}
Exemple #6
0
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;
}
Exemple #7
0
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);
}
Exemple #8
0
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);
}
Exemple #9
0
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;
}
Exemple #10
0
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);
}
Exemple #11
0
/*
 * 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);
}
Exemple #12
0
/*
 * 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);
}
Exemple #13
0
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);
}