⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wrapndis.c

📁 ndiswrapper工具
💻 C
📖 第 1 页 / 共 4 页
字号:
					   skb->len, PCI_DMA_TODEVICE);		oob_data->ndis_sg_element.length = skb->len;		oob_data->ndis_sg_list.nent = 1;		oob_data->ndis_sg_list.elements = &oob_data->ndis_sg_element;		oob_data->extension.info[ScatterGatherListPacketInfo] =			&oob_data->ndis_sg_list;	}#if 0	if (wnd->tx_csum_info.value)		oob_data->extension.info[TcpIpChecksumPacketInfo] =			&wnd->tx_csum_info;#endif	DBG_BLOCK(4) {		dump_bytes(__FUNCTION__, skb->data, skb->len);	}	DBGTRACE3("packet: %p, buffer: %p, skb: %p", packet, buffer, skb);	return packet;}void free_tx_packet(struct wrap_ndis_device *wnd, struct ndis_packet *packet,		    NDIS_STATUS status){	ndis_buffer *buffer;	struct ndis_packet_oob_data *oob_data;	TRACEENTER3("%p, %08X", packet, status);	if (status == NDIS_STATUS_SUCCESS) {		pre_atomic_add(wnd->stats.tx_bytes, packet->private.len);		atomic_inc_var(wnd->stats.tx_packets);	} else {		DBGTRACE1("packet dropped: %08X", status);		atomic_inc_var(wnd->stats.tx_dropped);	}	oob_data = NDIS_PACKET_OOB_DATA(packet);	if (wnd->use_sg_dma)		PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev,				     oob_data->ndis_sg_element.address,				     oob_data->ndis_sg_element.length,				     PCI_DMA_TODEVICE);	buffer = packet->private.buffer_head;	DBGTRACE3("freeing buffer %p", buffer);	NdisFreeBuffer(buffer);	dev_kfree_skb_any(oob_data->skb);	DBGTRACE3("freeing packet %p", packet);	NdisFreePacket(packet);	TRACEEXIT3(return);}/* MiniportSend and MiniportSendPackets *//* this function is called holding tx_ring_mutex. start and n are such * that start + n < TX_RING_SIZE; i.e., packets don't wrap around * ring */static int miniport_tx_packets(struct wrap_ndis_device *wnd, int start, int n){	NDIS_STATUS res;	struct miniport_char *miniport;	struct ndis_packet *packet;	int sent;	KIRQL irql;	DBGTRACE3("%d, %d", start, n);	miniport = &wnd->wd->driver->ndis_driver->miniport;	if (miniport->send_packets) {		if (deserialized_driver(wnd)) {			LIN2WIN3(miniport->send_packets, wnd->nmb->adapter_ctx,				 &wnd->tx_ring[start], n);			sent = n;		} else {			struct ndis_packet_oob_data *oob_data;			irql = raise_irql(DISPATCH_LEVEL);			serialize_lock(wnd);			LIN2WIN3(miniport->send_packets, wnd->nmb->adapter_ctx,				 &wnd->tx_ring[start], n);			serialize_unlock(wnd);			lower_irql(irql);			for (sent = 0; sent < n && wnd->tx_ok; sent++) {				NDIS_STATUS pkt_status;				packet = wnd->tx_ring[start + sent];				oob_data = NDIS_PACKET_OOB_DATA(packet);				switch ((pkt_status =					 xchg(&oob_data->status,					      NDIS_STATUS_NOT_RECOGNIZED))) {				case NDIS_STATUS_SUCCESS:					free_tx_packet(wnd, packet,						       NDIS_STATUS_SUCCESS);					break;				case NDIS_STATUS_PENDING:					break;				case NDIS_STATUS_RESOURCES:					atomic_dec_var(wnd->tx_ok);					/* resubmit this packet and					 * the rest when resources					 * become available */					sent--;					break;				case NDIS_STATUS_FAILURE:					free_tx_packet(wnd, packet,						       NDIS_STATUS_FAILURE);					break;				default:					ERROR("%p: invalid status: %08X",					      packet, pkt_status);					free_tx_packet(wnd, packet,						       oob_data->status);					break;				}				DBGTRACE3("%p, %d", packet, pkt_status);			}		}		DBGTRACE3("sent: %d(%d)", sent, n);	} else {		irql = PASSIVE_LEVEL;		for (sent = 0; sent < n && wnd->tx_ok; sent++) {			struct ndis_packet_oob_data *oob_data;			packet = wnd->tx_ring[start + sent];			oob_data = NDIS_PACKET_OOB_DATA(packet);			oob_data->status = NDIS_STATUS_NOT_RECOGNIZED;			irql = serialize_lock_irql(wnd);			res = LIN2WIN3(miniport->send, wnd->nmb->adapter_ctx,				       packet, packet->private.flags);			serialize_unlock_irql(wnd, irql);			switch (res) {			case NDIS_STATUS_SUCCESS:				free_tx_packet(wnd, packet, res);				break;			case NDIS_STATUS_PENDING:				break;			case NDIS_STATUS_RESOURCES:				atomic_dec_var(wnd->tx_ok);				/* resend this packet when resources				 * become available */				sent--;				break;			case NDIS_STATUS_FAILURE:				free_tx_packet(wnd, packet, res);				break;			default:				ERROR("packet %p: invalid status: %08X",				      packet, res);				break;			}		}	}	TRACEEXIT3(return sent);}static void tx_worker(void *param){	struct wrap_ndis_device *wnd = param;	int n;	TRACEENTER3("tx_ok %d", wnd->tx_ok);	while (wnd->tx_ok) {		if (down_interruptible(&wnd->tx_ring_mutex))			break;		/* end == start if either ring is empty or full; in		 * the latter case is_tx_ring_full is set */		n = wnd->tx_ring_end - wnd->tx_ring_start;		DBGTRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n);		if (n == 0) {			if (wnd->is_tx_ring_full)				n = TX_RING_SIZE - wnd->tx_ring_start;			else {				up(&wnd->tx_ring_mutex);				break;			}		} else if (n < 0)			n = TX_RING_SIZE - wnd->tx_ring_start;		if (unlikely(n > wnd->max_tx_packets))			n = wnd->max_tx_packets;		n = miniport_tx_packets(wnd, wnd->tx_ring_start, n);		if (n > 0) {			wnd->net_dev->trans_start = jiffies;			wnd->tx_ring_start =				(wnd->tx_ring_start + n) % TX_RING_SIZE;			wnd->is_tx_ring_full = 0;			if (netif_queue_stopped(wnd->net_dev))				netif_wake_queue(wnd->net_dev);		}		up(&wnd->tx_ring_mutex);		DBGTRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n);	}	TRACEEXIT3(return);}static int tx_skbuff(struct sk_buff *skb, struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	struct ndis_packet *packet;	packet = alloc_tx_packet(wnd, skb);	if (!packet) {		WARNING("couldn't allocate packet");		return NETDEV_TX_BUSY;	}	/* no need for lock here - already called holding	 * net_dev->xmit_lock and tx_ring_end is not updated	 * elsewhere */	wnd->tx_ring[wnd->tx_ring_end++] = packet;	if (wnd->tx_ring_end == TX_RING_SIZE)		wnd->tx_ring_end = 0;	if (wnd->tx_ring_end == wnd->tx_ring_start) {		wnd->is_tx_ring_full = 1;		netif_stop_queue(wnd->net_dev);	}	DBGTRACE3("ring: %d, %d", wnd->tx_ring_start, wnd->tx_ring_end);	schedule_wrap_work(&wnd->tx_work);	return NETDEV_TX_OK;}static int set_packet_filter(struct wrap_ndis_device *wnd, ULONG packet_filter){	NDIS_STATUS res;	while (1) {		res = miniport_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER,				       packet_filter);		if (res == NDIS_STATUS_SUCCESS)			break;		DBGTRACE2("couldn't set filter 0x%08x", packet_filter);		/* NDIS_PACKET_TYPE_PROMISCUOUS may not work with 802.11 */		if (packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS) {			packet_filter &= ~NDIS_PACKET_TYPE_PROMISCUOUS;			continue;		}		if (packet_filter & NDIS_PACKET_TYPE_ALL_LOCAL) {			packet_filter &= ~NDIS_PACKET_TYPE_ALL_LOCAL;			continue;		}		if (packet_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) {			packet_filter &= ~NDIS_PACKET_TYPE_ALL_FUNCTIONAL;			continue;		}		if (packet_filter & NDIS_PACKET_TYPE_MULTICAST) {			packet_filter &= ~NDIS_PACKET_TYPE_MULTICAST;			packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;			continue;		}		if (packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) {			packet_filter &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;			continue;		}		break;	}	wnd->packet_filter = packet_filter;	res = miniport_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER,				 &packet_filter);	if (packet_filter != wnd->packet_filter) {		WARNING("filter not set: 0x%08x, 0x%08x",			packet_filter, wnd->packet_filter);		wnd->packet_filter = packet_filter;	}	if (wnd->packet_filter)		TRACEEXIT3(return 0);	else		TRACEEXIT3(return -1);}static int ndis_net_dev_open(struct net_device *net_dev){	struct wrap_ndis_device *wnd = netdev_priv(net_dev);	TRACEENTER1("%p", wnd);	if (set_packet_filter(wnd, wnd->packet_filter)) {		WARNING("couldn't set packet filter");		return -ENODEV;	}	netif_wake_queue(net_dev);	netif_poll_enable(net_dev);	return 0;}static int ndis_net_dev_close(struct net_device *net_dev){	netif_poll_disable(net_dev);	netif_tx_disable(net_dev);	return 0;}#ifdef CONFIG_NET_POLL_CONTROLLERstatic void ndis_poll_controller(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	disable_irq(dev->irq);	ndis_isr(dev->irq, wnd, NULL);	enable_irq(dev->irq);}#endif/* called from BH context */static struct net_device_stats *ndis_get_stats(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	return &wnd->stats;}/* called from BH context */static void ndis_set_multicast_list(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	set_bit(SET_MULTICAST_LIST, &wnd->wrap_ndis_pending_work);	schedule_wrap_work(&wnd->wrap_ndis_work);}/* called from BH context */struct iw_statistics *get_wireless_stats(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	return &wnd->wireless_stats;}#if defined(HAVE_ETHTOOL)static void ndis_get_drvinfo(struct net_device *dev,			     struct ethtool_drvinfo *info){	struct wrap_ndis_device *wnd = netdev_priv(dev);	strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);	strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);	strncpy(info->fw_version, wnd->wd->driver->version,		sizeof(info->fw_version) - 1);	if (wrap_is_pci_bus(wnd->wd->dev_bus))		strncpy(info->bus_info, pci_name(wnd->wd->pci.pdev),			sizeof(info->bus_info) - 1);#ifdef CONFIG_USB	else		usb_make_path(wnd->wd->usb.udev, info->bus_info,			      sizeof(info->bus_info) - 1);#endif	return;}static u32 ndis_get_link(struct net_device *dev){	struct wrap_ndis_device *wnd = netdev_priv(dev);	return netif_carrier_ok(wnd->net_dev);}static void ndis_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (wnd->ndis_wolopts & NDIS_PNP_WAKE_UP_MAGIC_PACKET)		wol->wolopts |= WAKE_MAGIC;	/* no other options supported */	return;}static int ndis_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct wrap_ndis_device *wnd = netdev_priv(dev);	struct ndis_pnp_capabilities pnp_capa;	NDIS_STATUS status;	if (!(wol->wolopts & WAKE_MAGIC))		return -EINVAL;	if (!wnd->pm_capa)		return -EOPNOTSUPP;	status = miniport_query_info(wnd, OID_PNP_CAPABILITIES,				     &pnp_capa, sizeof(pnp_capa));	if (status != NDIS_STATUS_SUCCESS)		return -EOPNOTSUPP;	/* we always suspend to D3 */	DBGTRACE1("%d, %d", pnp_capa.wakeup_capa.min_magic_packet_wakeup,		  pnp_capa.wakeup_capa.min_pattern_wakeup);	if (pnp_capa.wakeup_capa.min_magic_packet_wakeup != NdisDeviceStateD3)		return -EOPNOTSUPP;	/* no other options supported */	wnd->ndis_wolopts = NDIS_PNP_WAKE_UP_MAGIC_PACKET;	return 0;}static struct ethtool_ops ndis_ethtool_ops = {	.get_drvinfo	= ndis_get_drvinfo,	.get_link	= ndis_get_link,	.get_wol	= ndis_get_wol,	.set_wol	= ndis_set_wol,};#endifstatic int notifier_event(struct notifier_block *notifier, unsigned long event,			  void *ptr){	struct net_device *net_dev = (struct net_device *)ptr;	struct wrap_ndis_device *wnd = netdev_priv(net_dev);	/* called with rtnl lock held, so no need to lock */	switch (event) {	case NETDEV_CHANGENAME:		wrap_procfs_remove_ndis_device(wnd);		printk(KERN_INFO "%s: changing interface name from '%s' to "		       "'%s'\n", DRIVER_NAME, wnd->netdev_name, net_dev->name);		memcpy(wnd->netdev_name, net_dev->name,		       sizeof(wnd->netdev_name));		wrap_procfs_add_ndis_device(wnd);		break;	}	return NOTIFY_DONE;}static struct notifier_block netdev_notifier = {	.notifier_call = notifier_event,};static void update_wireless_stats(struct wrap_ndis_device *wnd){	struct iw_statistics *iw_stats = &wnd->wireless_stats;	struct ndis_wireless_stats ndis_stats;	NDIS_STATUS res;	ndis_rssi rssi;	unsigned long frag;	TRACEENTER2("%p", wnd);	if (wnd->stats_enabled == FALSE || !netif_carrier_ok(wnd->net_dev)) {		memset(iw_stats, 0, sizeof(*iw_stats));		TRACEEXIT2(return);	}	res = miniport_query_info(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi));	if (res == NDIS_STATUS_SUCCESS)		iw_stats->qual.level = rssi;	memset(&ndis_stats, 0, sizeof(ndis_stats));	res = miniport_query_info(wnd, OID_802_11_STATISTICS,				  &ndis_stats, sizeof(ndis_stats));	if (res != NDIS_STATUS_SUCCESS)		TRACEEXIT2(return);	iw_stats->discard.retries = (unsigned long)ndis_stats.retry +		(unsigned long)ndis_stats.multi_retry;	iw_stats->discard.misc = (unsigned long)ndis_stats.fcs_err +		(unsigned long)ndis_stats.rtss_fail +		(unsigned long)ndis_stats.ack_fail +		(unsigned long)ndis_stats.frame_dup;	frag = 6 * (unsigned long)ndis_stats.tx_frag;	if (frag)		iw_stats->qual.qual =			100 - 100 * (((unsigned long)ndis_stats.retry +				      2*(unsigned long)ndis_stats.multi_retry +				      3*(unsigned long)ndis_stats.failed) /				     frag);	else		iw_stats->qual.qual = 100;	TRACEEXIT2(return);}static void set_multicast_list(struct wrap_ndis_device *wnd){	struct net_device *net_dev;	ULONG packet_filter;	NDIS_STATUS res;	net_dev = wnd->net_dev;	packet_filter = wnd->packet_filter;	DBGTRACE2("0x%08x", packet_filter);	if (net_dev->flags & IFF_PROMISC) {		packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS |			NDIS_PACKET_TYPE_ALL_LOCAL;	} else if (net_dev->flags & IFF_ALLMULTI ||		   net_dev->mc_count > wnd->multicast_size) {		packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;		DBGTRACE2("0x%08x", packet_filter);	} else if (net_dev->mc_count > 0) {		int i, size;		char *buf;		struct dev_mc_list *mclist;		size = min(wnd->multicast_size, net_dev->mc_count);		DBGTRACE2("%d, %d", wnd->multicast_size, net_dev->mc_count);		buf = kmalloc(size * ETH_ALEN, GFP_KERNEL);		if (!buf) {			WARNING("couldn't allocate memory");			TRACEEXIT2(return);		}		mclist = net_dev->mc_list;		for (i = 0; i < size && mclist; mclist = mclist->next) {			if (mclist->dmi_addrlen != ETH_ALEN)				continue;			memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN);			DBGTRACE2(MACSTRSEP, MAC2STR(mclist->dmi_addr));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -