Esempio n. 1
0
/*
 * Software interrupt routine, called at spl[soft]net.
 */
static void
pppintr(netmsg_t msg)
{
    struct mbuf *m;
    struct ppp_softc *sc;
    int i;

    /*
     * Packets are never sent to this netisr so the message must always
     * be replied.  Interlock processing and notification by replying
     * the message first.
     */
    lwkt_replymsg(&msg->lmsg, 0);

    get_mplock();

    sc = ppp_softc;
    for (i = 0; i < NPPP; ++i, ++sc) {
	ifnet_serialize_all(&sc->sc_if);
	if (!(sc->sc_flags & SC_TBUSY)
	    && (!ifq_is_empty(&sc->sc_if.if_snd) || !IF_QEMPTY(&sc->sc_fastq))) {
	    sc->sc_flags |= SC_TBUSY;
	    (*sc->sc_start)(sc);
	} 
	for (;;) {
	    IF_DEQUEUE(&sc->sc_rawq, m);
	    if (m == NULL)
		break;
	    ppp_inproc(sc, m);
	}
	ifnet_deserialize_all(&sc->sc_if);
    }
    rel_mplock();
}
Esempio n. 2
0
/*
 * Watchdog
 */
static void
lgue_watchdog(struct ifnet *ifp)
{
	IFNET_STAT_INC(ifp, oerrors, 1);

	if (!ifq_is_empty(&ifp->if_snd))
		if_devstart_sched(ifp);
}
Esempio n. 3
0
/*
 * Watchdog
 */
static void
lgue_watchdog(struct ifnet *ifp)
{
	ifp->if_oerrors++;

	if (!ifq_is_empty(&ifp->if_snd))
		lgue_start_schedule(ifp);
}
Esempio n. 4
0
void
ep_intr(void *arg)
{
    struct ep_softc *sc = arg;
    struct ifnet *ifp = &sc->arpcom.ac_if;
    int status;

     /*
      * quick fix: Try to detect an interrupt when the card goes away.
      */
    if (sc->gone || inw(BASE + EP_STATUS) == 0xffff) {
	    return;
    }

    outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */

rescan:

    while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) {

	/* first acknowledge all interrupt sources */
	outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK));

	if (status & (S_RX_COMPLETE | S_RX_EARLY))
	    epread(sc);
	if (status & S_TX_AVAIL) {
	    /* we need ACK */
	    ifp->if_timer = 0;
	    ifq_clr_oactive(&ifp->if_snd);
	    GO_WINDOW(1);
	    inw(BASE + EP_W1_FREE_TX);
	    if_devstart(ifp);
	}
	if (status & S_CARD_FAILURE) {
	    ifp->if_timer = 0;
#ifdef EP_LOCAL_STATS
	    kprintf("\n");
	    if_printf(ifp, "\n\tStatus: %x\n", status);
	    GO_WINDOW(4);
	    kprintf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG));
	    kprintf("\tStat: %x\n", sc->stat);
	    kprintf("\tIpackets=%d, Opackets=%d\n",
		ifp->if_ipackets, ifp->if_opackets);
	    kprintf("\tNOF=%d, NOMB=%d, RXOF=%d, RXOL=%d, TXU=%d\n",
		   sc->rx_no_first, sc->rx_no_mbuf, sc->rx_overrunf,
		   sc->rx_overrunl, sc->tx_underrun);
#else

#ifdef DIAGNOSTIC
	    if_printf(ifp, "Status: %x (input buffer overflow)\n", status);
#else
	    IFNET_STAT_INC(ifp, ierrors, 1);
#endif

#endif
	    ep_if_init(sc);
	    return;
	}
	if (status & S_TX_COMPLETE) {
	    ifp->if_timer = 0;
	    /* we  need ACK. we do it at the end */
	    /*
	     * We need to read TX_STATUS until we get a 0 status in order to
	     * turn off the interrupt flag.
	     */
	    while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
		if (status & TXS_SUCCES_INTR_REQ);
		else if (status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION)) {
		    outw(BASE + EP_COMMAND, TX_RESET);
		    if (status & TXS_UNDERRUN) {
#ifdef EP_LOCAL_STATS
			sc->tx_underrun++;
#endif
		    } else {
			if (status & TXS_JABBER);
			else	/* TXS_MAX_COLLISION - we shouldn't get here */
			    IFNET_STAT_INC(ifp, collisions, 1);
		    }
		    IFNET_STAT_INC(ifp, oerrors, 1);
		    outw(BASE + EP_COMMAND, TX_ENABLE);
		    /*
		     * To have a tx_avail_int but giving the chance to the
		     * Reception
		     */
		    if (!ifq_is_empty(&ifp->if_snd))
			outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
		}
		outb(BASE + EP_W1_TX_STATUS, 0x0);	/* pops up the next
							 * status */
	    }			/* while */
	    ifq_clr_oactive(&ifp->if_snd);
	    GO_WINDOW(1);
	    inw(BASE + EP_W1_FREE_TX);
	    if_devstart(ifp);
	}			/* end TX_COMPLETE */
    }

    outw(BASE + EP_COMMAND, C_INTR_LATCH);	/* ACK int Latch */

    if ((status = inw(BASE + EP_STATUS)) & S_5_INTS)
	goto rescan;

    /* re-enable Ints */
    outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
}
Esempio n. 5
0
static void
ep_if_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
{
    struct ep_softc *sc = ifp->if_softc;
    u_int len;
    struct mbuf *m;
    struct mbuf *top;
    int pad;

    ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);

    if (sc->gone) {
	ifq_purge(&ifp->if_snd);
	return;
    }

    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
    if (ifq_is_oactive(&ifp->if_snd)) {
	return;
    }

    crit_enter();

startagain:
    /* Sneak a peek at the next packet */
    m = ifq_dequeue(&ifp->if_snd, NULL);
    if (m == NULL) {
	crit_exit();
	return;
    }

    for (len = 0, top = m; m; m = m->m_next)
	len += m->m_len;
    m = top;

    pad = padmap[len & 3];

    /*
     * The 3c509 automatically pads short packets to minimum ethernet length,
     * but we drop packets that are too large. Perhaps we should truncate
     * them instead?
     */
    if (len + pad > ETHER_MAX_LEN) {
	/* packet is obviously too large: toss it */
	IFNET_STAT_INC(ifp, oerrors, 1);
	m_freem(m);
	goto readcheck;
    }
    if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
	/* no room in FIFO */
	outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
	/* make sure */
	if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
	    ifq_set_oactive(&ifp->if_snd);
	    ifq_prepend(&ifp->if_snd, top);
	    crit_exit();
	    return;
	}
    } else {
	outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
    }

    outw(BASE + EP_W1_TX_PIO_WR_1, len); 
    outw(BASE + EP_W1_TX_PIO_WR_1, 0x0);	/* Second dword meaningless */

    if (EP_FTST(sc, F_ACCESS_32_BITS)) {
        for (top = m; m != NULL; m = m->m_next) {
	    outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
		  m->m_len / 4);
	    if (m->m_len & 3)
		outsb(BASE + EP_W1_TX_PIO_WR_1,
		      mtod(m, caddr_t) + (m->m_len & (~3)),
		      m->m_len & 3);
	}
    } else {
        for (top = m; m != NULL; m = m->m_next) {
	    outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
	    if (m->m_len & 1)
		outb(BASE + EP_W1_TX_PIO_WR_1,
		     *(mtod(m, caddr_t) + m->m_len - 1));
	}
    }

    while (pad--)
	outb(BASE + EP_W1_TX_PIO_WR_1, 0);	/* Padding */

    BPF_MTAP(ifp, top);

    ifp->if_timer = 2;
    IFNET_STAT_INC(ifp, opackets, 1);
    m_freem(top);

    /*
     * Is another packet coming in? We don't want to overflow the tiny RX
     * fifo.
     */
readcheck:
    if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
	/*
	 * we check if we have packets left, in that case we prepare to come
	 * back later
	 */
	if (!ifq_is_empty(&ifp->if_snd))
	    outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);

        crit_exit();
	return;
    }
    goto startagain;
}