Example #1
0
/*
 * Start transfer
 */
static void
lgue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
{
	struct lgue_softc *sc;
	struct mbuf *m_head;

	ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);

	sc = ifp->if_softc;
	if (sc->lgue_dying)
		return;

	if (ifq_is_oactive(&ifp->if_snd)) {
		return;
	}

	/* To internal queue */
	while ((m_head = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) {
		if (lgue_encap(sc, m_head)) {
			m_freem(m_head);
			break;
		}
		/* Filter */
		BPF_MTAP(ifp, m_head);
	}

	lgue_start_transfer(sc);
}
Example #2
0
static void
sbsh_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
{
	struct sbsh_softc  *sc = ifp->if_softc;

	ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);

	if (sc->state == ACTIVE)
		start_xmit_frames(ifp->if_softc);
}
Example #3
0
static void
ue_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
{
	struct usb_ether *ue = ifp->if_softc;

	ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);

	if ((ifp->if_flags & IFF_RUNNING) == 0 ||
	    ifq_is_oactive(&ifp->if_snd))
		return;

	UE_LOCK(ue);
	ue->ue_methods->ue_start(ue);
	UE_UNLOCK(ue);
}
Example #4
0
static void
usie_if_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
{
	struct usie_softc *sc = ifp->if_softc;

	ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);

	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
		DPRINTF("Not running\n");
		return;
	}
	mtx_lock(&sc->sc_mtx);
	usbd_transfer_start(sc->sc_if_xfer[USIE_IF_TX]);
	mtx_unlock(&sc->sc_mtx);

	DPRINTFN(3, "interface started\n");
}
Example #5
0
void
snstart(struct ifnet *ifp, struct ifaltq_subque *ifsq)
{
	struct sn_softc *sc = ifp->if_softc;
	u_int  len;
	struct mbuf *m;
	struct mbuf    *top;
	int             pad;
	int             mask;
	u_short         length;
	u_short         numPages;
	u_char          packet_no;
	int             time_out;

	ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);

	if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd))
		return;

	if (sc->pages_wanted != -1) {
		/* XXX should never happen */
		kprintf("%s: snstart() while memory allocation pending\n",
		       ifp->if_xname);
		ifq_set_oactive(&ifp->if_snd);
		return;
	}
startagain:

	/*
	 * Sneak a peek at the next packet
	 */
	m = ifq_dequeue(&ifp->if_snd);
	if (m == NULL)
		return;

	/*
	 * Compute the frame length and set pad to give an overall even
	 * number of bytes.  Below we assume that the packet length is even.
	 */
	for (len = 0, top = m; m; m = m->m_next)
		len += m->m_len;

	pad = (len & 1);

	/*
	 * We drop packets that are too large. Perhaps we should truncate
	 * them instead?
	 */
	if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) {
		kprintf("%s: large packet discarded (A)\n", ifp->if_xname);
		IFNET_STAT_INC(&sc->arpcom.ac_if, oerrors, 1);
		m_freem(top);
		goto readcheck;
	}
#ifdef SW_PAD

	/*
	 * If HW padding is not turned on, then pad to ETHER_MIN_LEN.
	 */
	if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
		pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;

#endif	/* SW_PAD */

	length = pad + len;

	/*
	 * The MMU wants the number of pages to be the number of 256 byte
	 * 'pages', minus 1 (A packet can't ever have 0 pages. We also
	 * include space for the status word, byte count and control bytes in
	 * the allocation request.
	 */
	numPages = (length + 6) >> 8;


	/*
	 * Now, try to allocate the memory
	 */
	SMC_SELECT_BANK(2);
	outw(BASE + MMU_CMD_REG_W, MMUCR_ALLOC | numPages);

	/*
	 * Wait a short amount of time to see if the allocation request
	 * completes.  Otherwise, I enable the interrupt and wait for
	 * completion asyncronously.
	 */

	time_out = MEMORY_WAIT_TIME;
	do {
		if (inb(BASE + INTR_STAT_REG_B) & IM_ALLOC_INT)
			break;
	} while (--time_out);

	if (!time_out) {

		/*
		 * No memory now.  Oh well, wait until the chip finds memory
		 * later.   Remember how many pages we were asking for and
		 * enable the allocation completion interrupt. Also set a
		 * watchdog in case  we miss the interrupt. We mark the
		 * interface active since there is no point in attempting an
		 * snstart() until after the memory is available.
		 */
		mask = inb(BASE + INTR_MASK_REG_B) | IM_ALLOC_INT;
		outb(BASE + INTR_MASK_REG_B, mask);
		sc->intr_mask = mask;

		ifp->if_timer = 1;
		ifq_set_oactive(&ifp->if_snd);
		sc->pages_wanted = numPages;
		ifq_prepend(&ifp->if_snd, top);

		return;
	}
	/*
	 * The memory allocation completed.  Check the results.
	 */
	packet_no = inb(BASE + ALLOC_RESULT_REG_B);
	if (packet_no & ARR_FAILED) {
		kprintf("%s: Memory allocation failed\n", ifp->if_xname);
		ifq_prepend(&ifp->if_snd, top);
		goto startagain;
	}
	/*
	 * We have a packet number, so tell the card to use it.
	 */
	outb(BASE + PACKET_NUM_REG_B, packet_no);

	/*
	 * Point to the beginning of the packet
	 */
	outw(BASE + POINTER_REG_W, PTR_AUTOINC | 0x0000);

	/*
	 * Send the packet length (+6 for status, length and control byte)
	 * and the status word (set to zeros)
	 */
	outw(BASE + DATA_REG_W, 0);
	outb(BASE + DATA_REG_B, (length + 6) & 0xFF);
	outb(BASE + DATA_REG_B, (length + 6) >> 8);

	/*
	 * Push out the data to the card.
	 */
	for (m = top; m != NULL; m = m->m_next) {

		/*
		 * Push out words.
		 */
		outsw(BASE + DATA_REG_W, mtod(m, caddr_t), m->m_len / 2);

		/*
		 * Push out remaining byte.
		 */
		if (m->m_len & 1)
			outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
	}

	/*
	 * Push out padding.
	 */
	while (pad > 1) {
		outw(BASE + DATA_REG_W, 0);
		pad -= 2;
	}
	if (pad)
		outb(BASE + DATA_REG_B, 0);

	/*
	 * Push out control byte and unused packet byte The control byte is 0
	 * meaning the packet is even lengthed and no special CRC handling is
	 * desired.
	 */
	outw(BASE + DATA_REG_W, 0);

	/*
	 * Enable the interrupts and let the chipset deal with it Also set a
	 * watchdog in case we miss the interrupt.
	 */
	mask = inb(BASE + INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
	outb(BASE + INTR_MASK_REG_B, mask);
	sc->intr_mask = mask;

	outw(BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE);

	ifq_set_oactive(&ifp->if_snd);
	ifp->if_timer = 1;

	BPF_MTAP(ifp, top);

	IFNET_STAT_INC(ifp, opackets, 1);
	m_freem(top);

readcheck:

	/*
	 * Is another packet coming in?  We don't want to overflow the tiny
	 * RX FIFO.  If nothing has arrived then attempt to queue another
	 * transmit packet.
	 */
	if (inw(BASE + FIFO_PORTS_REG_W) & FIFO_REMPTY)
		goto startagain;
}
Example #6
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;
}