コード例 #1
0
ファイル: hv_net_vsc.c プロジェクト: Hooman3/freebsd
/*
 * Net VSC on receive
 *
 * In the FreeBSD Hyper-V virtual world, this function deals exclusively
 * with virtual addresses.
 */
static void
hv_nv_on_receive(netvsc_dev *net_dev, struct hn_rx_ring *rxr,
    struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr)
{
	const struct vmbus_chanpkt_rxbuf *pkt;
	const nvsp_msg *nvsp_msg_pkt;
	netvsc_packet vsc_pkt;
	netvsc_packet *net_vsc_pkt = &vsc_pkt;
	int count = 0;
	int i = 0;
	int status = nvsp_status_success;

	nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkthdr);

	/* Make sure this is a valid nvsp packet */
	if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) {
		if_printf(rxr->hn_ifp, "packet hdr type %u is invalid!\n",
		    nvsp_msg_pkt->hdr.msg_type);
		return;
	}
	
	pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr;

	if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) {
		if_printf(rxr->hn_ifp, "rxbuf_id %d is invalid!\n",
		    pkt->cp_rxbuf_id);
		return;
	}

	count = pkt->cp_rxbuf_cnt;

	/* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
	for (i = 0; i < count; i++) {
		net_vsc_pkt->status = nvsp_status_success;
		net_vsc_pkt->data = ((uint8_t *)net_dev->rx_buf +
		    pkt->cp_rxbuf[i].rb_ofs);
		net_vsc_pkt->tot_data_buf_len = pkt->cp_rxbuf[i].rb_len;

		hv_rf_on_receive(net_dev, rxr, net_vsc_pkt);
		if (net_vsc_pkt->status != nvsp_status_success) {
			status = nvsp_status_failure;
		}
	}
	
	/*
	 * Moved completion call back here so that all received 
	 * messages (not just data messages) will trigger a response
	 * message back to the host.
	 */
	hv_nv_on_receive_completion(chan, pkt->cp_hdr.cph_xactid, status);
}
コード例 #2
0
/*
 * Net VSC on receive
 *
 * In the FreeBSD Hyper-V virtual world, this function deals exclusively
 * with virtual addresses.
 */
static void
hv_nv_on_receive(netvsc_dev *net_dev, struct hv_device *device,
    struct hv_vmbus_channel *chan, hv_vm_packet_descriptor *pkt)
{
	hv_vm_transfer_page_packet_header *vm_xfer_page_pkt;
	nvsp_msg *nvsp_msg_pkt;
	netvsc_packet vsc_pkt;
	netvsc_packet *net_vsc_pkt = &vsc_pkt;
	device_t dev = device->device;
	int count = 0;
	int i = 0;
	int status = nvsp_status_success;

	/*
	 * All inbound packets other than send completion should be
	 * xfer page packet.
	 */
	if (pkt->type != HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES) {
		device_printf(dev, "packet type %d is invalid!\n", pkt->type);
		return;
	}

	nvsp_msg_pkt = (nvsp_msg *)((unsigned long)pkt
		+ (pkt->data_offset8 << 3));

	/* Make sure this is a valid nvsp packet */
	if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) {
		device_printf(dev, "packet hdr type %d is invalid!\n",
		    pkt->type);
		return;
	}
	
	vm_xfer_page_pkt = (hv_vm_transfer_page_packet_header *)pkt;

	if (vm_xfer_page_pkt->transfer_page_set_id !=
	    NETVSC_RECEIVE_BUFFER_ID) {
		device_printf(dev, "transfer_page_set_id %d is invalid!\n",
		    vm_xfer_page_pkt->transfer_page_set_id);
		return;
	}

	count = vm_xfer_page_pkt->range_count;
	net_vsc_pkt->device = device;

	/* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
	for (i = 0; i < count; i++) {
		net_vsc_pkt->status = nvsp_status_success;
		net_vsc_pkt->data = (void *)((unsigned long)net_dev->rx_buf +
		    vm_xfer_page_pkt->ranges[i].byte_offset);
		net_vsc_pkt->tot_data_buf_len = 
		    vm_xfer_page_pkt->ranges[i].byte_count;

		hv_rf_on_receive(net_dev, device, chan, net_vsc_pkt);
		if (net_vsc_pkt->status != nvsp_status_success) {
			status = nvsp_status_failure;
		}
	}
	
	/*
	 * Moved completion call back here so that all received 
	 * messages (not just data messages) will trigger a response
	 * message back to the host.
	 */
	hv_nv_on_receive_completion(chan, vm_xfer_page_pkt->d.transaction_id,
	    status);
}