Beispiel #1
0
/*
 * Put user bytes into a free packet buffer, forward this packet to the TX
 * queue, and return OK.  If there are no free packet buffers, return SUSPEND.
 */
static int
virtio_net_send(struct netdriver_data * data, size_t len)
{
	struct vumap_phys phys[2];
	struct packet *p;

	if (STAILQ_EMPTY(&free_list))
		return SUSPEND;

	p = STAILQ_FIRST(&free_list);
	STAILQ_REMOVE_HEAD(&free_list, next);

	if (len > MAX_PACK_SIZE)
		panic("%s: packet too large to send: %zu", name, len);

	netdriver_copyin(data, 0, p->vdata, len);

	phys[0].vp_addr = p->phdr;
	assert(!(phys[0].vp_addr & 1));
	phys[0].vp_size = sizeof(struct virtio_net_hdr);
	phys[1].vp_addr = p->pdata;
	assert(!(phys[1].vp_addr & 1));
	phys[1].vp_size = len;
	virtio_to_queue(net_dev, TX_Q, phys, 2, p);

	return OK;
}
/*============================================================================*
 *				lan8710a_send				      *
 *============================================================================*/
static int
lan8710a_send(struct netdriver_data * data, size_t size)
{
	lan8710a_t *e = &lan8710a_state;
	lan8710a_desc_t *p_tx_desc;
	u8_t *buf;

	/* setup descriptors */
	p_tx_desc = &(e->tx_desc[e->tx_desc_idx]);

	/*
	 * Check if descriptor is available for host and suspend if not.
	 */
	if (LAN8710A_DESC_FLAG_OWN & p_tx_desc->pkt_len_flags)
		return SUSPEND;

	/* Drop packets that exceed the size of our transmission buffer. */
	if (size > LAN8710A_IOBUF_SIZE) {
		printf("%s: dropping large packet (%zu)\n",
		    netdriver_name(), size);

		return OK;
	}

	/* virtual address of buffer */
	buf = e->p_tx_buf + e->tx_desc_idx * LAN8710A_IOBUF_SIZE;

	netdriver_copyin(data, 0, buf, size);

	/* set descriptor length */
	p_tx_desc->buffer_length_off = size;
	/* set flags */
	p_tx_desc->pkt_len_flags = (LAN8710A_DESC_FLAG_OWN |
					LAN8710A_DESC_FLAG_SOP |
					LAN8710A_DESC_FLAG_EOP |
					TX_DESC_TO_PORT1 |
					TX_DESC_TO_PORT_EN);
	p_tx_desc->pkt_len_flags |= size;

	/* setup DMA transfer */
	lan8710a_dma_config_tx(e->tx_desc_idx);

	e->tx_desc_idx++;
	if (LAN8710A_NUM_TX_DESC == e->tx_desc_idx)
		e->tx_desc_idx = 0;

	return OK;
}
Beispiel #3
0
/*
 * Try to send a packet.
 */
static int
e1000_send(struct netdriver_data * data, size_t size)
{
	e1000_t *e;
	e1000_tx_desc_t *desc;
	unsigned int head, tail, next;
	char *ptr;

	e = &e1000_state;

	if (size > E1000_IOBUF_SIZE)
		panic("packet too large to send");

	/*
	 * The queue tail must not advance to the point that it is equal to the
	 * queue head, since this condition indicates that the queue is empty.
	 */
	head = e1000_reg_read(e, E1000_REG_TDH);
	tail = e1000_reg_read(e, E1000_REG_TDT);
	next = (tail + 1) % e->tx_desc_count;

	if (next == head)
		return SUSPEND;

	/* The descriptor to use is the one pointed to by the current tail. */
	desc = &e->tx_desc[tail];

	/* Copy the packet from the caller. */
	ptr = e->tx_buffer + tail * E1000_IOBUF_SIZE;

	netdriver_copyin(data, 0, ptr, size);

	/* Mark this descriptor ready. */
	desc->status = 0;
	desc->length = size;
	desc->command = E1000_TX_CMD_EOP | E1000_TX_CMD_FCS | E1000_TX_CMD_RS;

	/* Increment tail.  Start transmission. */
	e1000_reg_write(e, E1000_REG_TDT, next);

	return OK;
}