コード例 #1
0
ファイル: if_ntb.c プロジェクト: ele7enxxh/dtrace-pf
static void
ntb_start(struct ifnet *ifp)
{
	struct mbuf *m_head;
	struct ntb_netdev *nt = ifp->if_softc;
	int rc;

	mtx_lock(&nt->tx_lock);
	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
	CTR0(KTR_NTB, "TX: ntb_start");
	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
		CTR1(KTR_NTB, "TX: start mbuf %p", m_head);
		rc = ntb_transport_tx_enqueue(nt->qp, m_head, m_head,
			     m_length(m_head, NULL));
		if (rc != 0) {
			CTR1(KTR_NTB,
			    "TX: could not tx mbuf %p. Returning to snd q",
			    m_head);
			if (rc == EAGAIN) {
				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
				IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
				callout_reset(&nt->qp->queue_full, hz / 1000,
				    ntb_qp_full, ifp);
			}
			break;
		}

	}
	mtx_unlock(&nt->tx_lock);
}
コード例 #2
0
ファイル: if_ffec.c プロジェクト: Digital-Chaos/freebsd
static void
ffec_txstart_locked(struct ffec_softc *sc)
{
	struct ifnet *ifp;
	struct mbuf *m;
	int enqueued;

	FFEC_ASSERT_LOCKED(sc);

	if (!sc->link_is_up)
		return;

	ifp = sc->ifp;

	if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
		return;

	enqueued = 0;

	for (;;) {
		if (sc->txcount == (TX_DESC_COUNT-1)) {
			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
			break;
		}
		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
		if (m == NULL)
			break;
		if (ffec_setup_txbuf(sc, sc->tx_idx_head, &m) != 0) {
			IFQ_DRV_PREPEND(&ifp->if_snd, m);
			break;
		}
		BPF_MTAP(ifp, m);
		sc->tx_idx_head = next_txidx(sc, sc->tx_idx_head);
		++enqueued;
	}

	if (enqueued != 0) {
		bus_dmamap_sync(sc->txdesc_tag, sc->txdesc_map, BUS_DMASYNC_PREWRITE);
		WR4(sc, FEC_TDAR_REG, FEC_TDAR_TDAR);
		bus_dmamap_sync(sc->txdesc_tag, sc->txdesc_map, BUS_DMASYNC_POSTWRITE);
		sc->tx_watchdog_count = WATCHDOG_TIMEOUT_SECS;
	}
}
コード例 #3
0
ファイル: if_kr.c プロジェクト: edgar-pek/PerspicuOS
static void
kr_start_locked(struct ifnet *ifp)
{
	struct kr_softc		*sc;
	struct mbuf		*m_head;
	int			enq;

	sc = ifp->if_softc;

	KR_LOCK_ASSERT(sc);

	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
	    IFF_DRV_RUNNING || sc->kr_link_status == 0 )
		return;

	for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
	    sc->kr_cdata.kr_tx_cnt < KR_TX_RING_CNT - 2; ) {
		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
		if (m_head == NULL)
			break;
		/*
		 * Pack the data into the transmit ring. If we
		 * don't have room, set the OACTIVE flag and wait
		 * for the NIC to drain the ring.
		 */
		if (kr_encap(sc, &m_head)) {
			if (m_head == NULL)
				break;
			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
			break;
		}

		enq++;
		/*
		 * If there's a BPF listener, bounce a copy of this frame
		 * to him.
		 */
		ETHER_BPF_MTAP(ifp, m_head);
	}
}
コード例 #4
0
ファイル: if_smc.c プロジェクト: dcui/FreeBSD-9.3_kernel
static void
smc_task_tx(void *context, int pending)
{
	struct ifnet		*ifp;
	struct smc_softc	*sc;
	struct mbuf		*m, *m0;
	u_int			packet, len;
	int			last_len;
	uint8_t			*data;

	(void)pending;
	ifp = (struct ifnet *)context;
	sc = ifp->if_softc;

	SMC_LOCK(sc);
	
	if (sc->smc_pending == NULL) {
		SMC_UNLOCK(sc);
		goto next_packet;
	}

	m = m0 = sc->smc_pending;
	sc->smc_pending = NULL;
	smc_select_bank(sc, 2);

	/*
	 * Check the allocation result.
	 */
	packet = smc_read_1(sc, ARR);

	/*
	 * If the allocation failed, requeue the packet and retry.
	 */
	if (packet & ARR_FAILED) {
		IFQ_DRV_PREPEND(&ifp->if_snd, m);
		++ifp->if_oerrors;
		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
		smc_start_locked(ifp);
		SMC_UNLOCK(sc);
		return;
	}

	/*
	 * Tell the device to write to our packet number.
	 */
	smc_write_1(sc, PNR, packet);
	smc_write_2(sc, PTR, 0 | PTR_AUTO_INCR);

	/*
	 * Tell the device how long the packet is (including control data).
	 */
	len = m_length(m, 0);
	len += PKT_CTRL_DATA_LEN;
	smc_write_2(sc, DATA0, 0);
	smc_write_2(sc, DATA0, len);

	/*
	 * Push the data out to the device.
	 */
	data = NULL;
	last_len = 0;
	for (; m != NULL; m = m->m_next) {
		data = mtod(m, uint8_t *);
		smc_write_multi_2(sc, DATA0, (uint16_t *)data, m->m_len / 2);
		last_len = m->m_len;
	}

	/*
	 * Push out the control byte and and the odd byte if needed.
	 */
	if ((len & 1) != 0 && data != NULL)
		smc_write_2(sc, DATA0, (CTRL_ODD << 8) | data[last_len - 1]);
	else
		smc_write_2(sc, DATA0, 0);

	/*
	 * Unmask the TX empty interrupt.
	 */
	sc->smc_mask |= TX_EMPTY_INT;
	if ((ifp->if_capenable & IFCAP_POLLING) == 0)
		smc_write_1(sc, MSK, sc->smc_mask);

	/*
	 * Enqueue the packet.
	 */
	smc_mmu_wait(sc);
	smc_write_2(sc, MMUCR, MMUCR_CMD_ENQUEUE);
	callout_reset(&sc->smc_watchdog, hz * 2, smc_watchdog, sc);

	/*
	 * Finish up.
	 */
	ifp->if_opackets++;
	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
	SMC_UNLOCK(sc);
	BPF_MTAP(ifp, m0);
	m_freem(m0);

next_packet:
	/*
	 * See if there's anything else to do.
	 */
	smc_start(ifp);
}
コード例 #5
0
ファイル: if_cdce.c プロジェクト: Gwenio/DragonFlyBSD
static uint8_t
cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uint8_t index)
{
	struct cdce_softc *sc = usbd_xfer_softc(xfer);
	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
	struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, index);
	struct mbuf *m;
	uint32_t rem;
	uint32_t offset;
	uint32_t last_offset;
	uint16_t n;
	uint8_t retval;

	usbd_xfer_set_frame_offset(xfer, index * CDCE_NCM_TX_MAXLEN, index);

	offset = sizeof(sc->sc_ncm.hdr) +
	    sizeof(sc->sc_ncm.dpt) + sizeof(sc->sc_ncm.dp);

	/* Store last valid offset before alignment */
	last_offset = offset;

	/* Align offset */
	offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder,
	    offset, sc->sc_ncm.tx_modulus);

	/* Zero pad */
	cdce_ncm_tx_zero(pc, last_offset, offset);

	/* buffer full */
	retval = 2;

	for (n = 0; n != sc->sc_ncm.tx_nframe; n++) {

		/* check if end of transmit buffer is reached */

		if (offset >= sc->sc_ncm.tx_max)
			break;

		/* compute maximum buffer size */

		rem = sc->sc_ncm.tx_max - offset;

		IFQ_DRV_DEQUEUE(&(ifp->if_snd), m);

		if (m == NULL) {
			/* buffer not full */
			retval = 1;
			break;
		}

		if (m->m_pkthdr.len > rem) {
			if (n == 0) {
				/* The frame won't fit in our buffer */
				DPRINTFN(1, "Frame too big to be transmitted!\n");
				m_freem(m);
				ifp->if_oerrors++;
				n--;
				continue;
			}
			/* Wait till next buffer becomes ready */
			IFQ_DRV_PREPEND(&(ifp->if_snd), m);
			break;
		}
		usbd_m_copy_in(pc, offset, m, 0, m->m_pkthdr.len);

		USETW(sc->sc_ncm.dp[n].wFrameLength, m->m_pkthdr.len);
		USETW(sc->sc_ncm.dp[n].wFrameIndex, offset);

		/* Update offset */
		offset += m->m_pkthdr.len;

		/* Store last valid offset before alignment */
		last_offset = offset;

		/* Align offset */
		offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder,
		    offset, sc->sc_ncm.tx_modulus);

		/* Zero pad */
		cdce_ncm_tx_zero(pc, last_offset, offset);

		/*
		 * If there's a BPF listener, bounce a copy
		 * of this frame to him:
		 */
		BPF_MTAP(ifp, m);

		/* Free mbuf */

		m_freem(m);

		/* Pre-increment interface counter */

		ifp->if_opackets++;
	}

	if (n == 0)
		return (0);

	rem = (sizeof(sc->sc_ncm.dpt) + (4 * n) + 4);

	USETW(sc->sc_ncm.dpt.wLength, rem);

	/* zero the rest of the data pointer entries */
	for (; n != CDCE_NCM_SUBFRAMES_MAX; n++) {
		USETW(sc->sc_ncm.dp[n].wFrameLength, 0);
		USETW(sc->sc_ncm.dp[n].wFrameIndex, 0);
	}

	offset = last_offset;

	/* Align offset */
	offset = CDCE_NCM_ALIGN(0, offset, CDCE_NCM_TX_MINLEN);

	/* Optimise, save bandwidth and force short termination */
	if (offset >= sc->sc_ncm.tx_max)
		offset = sc->sc_ncm.tx_max;
	else
		offset ++;

	/* Zero pad */
	cdce_ncm_tx_zero(pc, last_offset, offset);

	/* set frame length */
	usbd_xfer_set_frame_len(xfer, index, offset);

	/* Fill out 16-bit header */
	sc->sc_ncm.hdr.dwSignature[0] = 'N';
	sc->sc_ncm.hdr.dwSignature[1] = 'C';
	sc->sc_ncm.hdr.dwSignature[2] = 'M';
	sc->sc_ncm.hdr.dwSignature[3] = 'H';
	USETW(sc->sc_ncm.hdr.wHeaderLength, sizeof(sc->sc_ncm.hdr));
	USETW(sc->sc_ncm.hdr.wBlockLength, offset);
	USETW(sc->sc_ncm.hdr.wSequence, sc->sc_ncm.tx_seq);
	USETW(sc->sc_ncm.hdr.wDptIndex, sizeof(sc->sc_ncm.hdr));

	sc->sc_ncm.tx_seq++;

	/* Fill out 16-bit frame table header */
	sc->sc_ncm.dpt.dwSignature[0] = 'N';
	sc->sc_ncm.dpt.dwSignature[1] = 'C';
	sc->sc_ncm.dpt.dwSignature[2] = 'M';
	sc->sc_ncm.dpt.dwSignature[3] = '0';
	USETW(sc->sc_ncm.dpt.wNextNdpIndex, 0);		/* reserved */

	usbd_copy_in(pc, 0, &(sc->sc_ncm.hdr), sizeof(sc->sc_ncm.hdr));
	usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr), &(sc->sc_ncm.dpt),
	    sizeof(sc->sc_ncm.dpt));
	usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr) + sizeof(sc->sc_ncm.dpt),
	    &(sc->sc_ncm.dp), sizeof(sc->sc_ncm.dp));
	return (retval);
}