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

📄 wrapndis.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct wrap_ndis_device *wnd = netdev_priv(dev);	if (wnd->sg_dma_size)		return ethtool_op_set_sg(dev, data);	else		return -EOPNOTSUPP;} 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,	.get_tx_csum	= ndis_get_tx_csum,	.get_rx_csum	= ndis_get_rx_csum,	.set_tx_csum	= ndis_set_tx_csum,	.set_rx_csum	= ndis_set_rx_csum,	.get_sg		= ndis_get_sg,	.set_sg		= ndis_set_sg,};#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;	if (net_dev->open != ndis_net_dev_open)		return NOTIFY_DONE;	wnd = netdev_priv(net_dev);	/* called with rtnl lock held, so no need to lock */	if (event == 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);		return NOTIFY_OK;	}	TRACE2("%s: %lx", wnd->netdev_name, event);	return NOTIFY_DONE;}static struct notifier_block netdev_notifier = {	.notifier_call = notifier_event,};static NDIS_STATUS wrap_ndis_start_device(struct wrap_ndis_device *wnd){	struct wrap_device *wd;	struct net_device *net_dev;	NDIS_STATUS status;	char *buf;	const int buf_len = 256;	mac_address mac;	struct transport_header_offset *tx_header_offset;	int n;	status = miniport_init(wnd);	if (status == NDIS_STATUS_NOT_RECOGNIZED)		EXIT1(return NDIS_STATUS_SUCCESS);	if (status != NDIS_STATUS_SUCCESS)		EXIT1(return status);	wd = wnd->wd;	net_dev = wnd->net_dev;	status = miniport_query_info(wnd, OID_802_3_CURRENT_ADDRESS,				     mac, sizeof(mac));	if (status) {		ERROR("couldn't get mac address: %08X", status);		goto err_start;	}	TRACE1("mac:" MACSTRSEP, MAC2STR(mac));	status = miniport_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM,				    &wnd->physical_medium);	if (status != NDIS_STATUS_SUCCESS)		wnd->physical_medium = NdisPhysicalMediumUnspecified;	get_supported_oids(wnd);	strncpy(net_dev->name, if_name, IFNAMSIZ - 1);	net_dev->name[IFNAMSIZ - 1] = '\0';	memcpy(&net_dev->dev_addr, mac, ETH_ALEN);	wnd->packet_filter = NDIS_PACKET_TYPE_DIRECTED |		NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_MULTICAST;	net_dev->open = ndis_net_dev_open;	net_dev->hard_start_xmit = tx_skbuff;	net_dev->stop = ndis_net_dev_close;	net_dev->get_stats = ndis_get_stats;	net_dev->change_mtu = ndis_change_mtu;	net_dev->do_ioctl = NULL;	if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {#if WIRELESS_EXT < 19		net_dev->get_wireless_stats = get_iw_stats;#endif		net_dev->wireless_handlers = &ndis_handler_def;	}	net_dev->set_multicast_list = ndis_set_multicast_list;	net_dev->set_mac_address = ndis_set_mac_address;#if defined(HAVE_ETHTOOL)	net_dev->ethtool_ops = &ndis_ethtool_ops;#endif	if (wnd->mp_interrupt)		net_dev->irq = wnd->mp_interrupt->irq;	net_dev->mem_start = wnd->mem_start;	net_dev->mem_end = wnd->mem_end;	status = miniport_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE,					 &wnd->multicast_size);	if (status != NDIS_STATUS_SUCCESS || wnd->multicast_size < 0)		wnd->multicast_size = 0;	if (wnd->multicast_size > 0)		net_dev->flags |= IFF_MULTICAST;	else		net_dev->flags &= ~IFF_MULTICAST;#ifdef CONFIG_NET_POLL_CONTROLLER	net_dev->poll_controller = ndis_poll_controller;#endif	buf = kmalloc(buf_len, GFP_KERNEL);	if (!buf) {		WARNING("couldn't allocate memory");		goto err_start;	}	set_task_offload(wnd, buf, buf_len);#ifdef NETIF_F_LLTX	net_dev->features |= NETIF_F_LLTX;#endif	if (register_netdev(net_dev)) {		ERROR("cannot register net device %s", net_dev->name);		goto err_register;	}	memcpy(wnd->netdev_name, net_dev->name, sizeof(wnd->netdev_name));	memset(buf, 0, buf_len);	status = miniport_query_info(wnd, OID_GEN_VENDOR_DESCRIPTION,				     buf, buf_len);	if (status != NDIS_STATUS_SUCCESS) {		WARNING("couldn't get vendor information: 0x%x", status);		buf[0] = 0;	}	wnd->drv_ndis_version = n = 0;	miniport_query_int(wnd, OID_GEN_DRIVER_VERSION,			   &wnd->drv_ndis_version);	miniport_query_int(wnd, OID_GEN_VENDOR_DRIVER_VERSION, &n);	printk(KERN_INFO "%s: ethernet device " MACSTRSEP " using %sNDIS "	       "driver: %s, version: 0x%x, NDIS version: 0x%x, vendor: '%s', "	       "%s\n", net_dev->name, MAC2STR(net_dev->dev_addr),	       deserialized_driver(wnd) ? "" : "serialized ",	       wnd->wd->driver->name, n, wnd->drv_ndis_version, buf,	       wnd->wd->conf_file_name);	if (deserialized_driver(wnd)) {		/* deserialized drivers don't have a limit, but we		 * keep max at TX_RING_SIZE */		wnd->max_tx_packets = TX_RING_SIZE;	} else {		status = miniport_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS,					    &wnd->max_tx_packets);		if (status != NDIS_STATUS_SUCCESS)			wnd->max_tx_packets = 1;		if (wnd->max_tx_packets > TX_RING_SIZE)			wnd->max_tx_packets = TX_RING_SIZE;	}	TRACE2("maximum send packets: %d", wnd->max_tx_packets);	NdisAllocatePacketPoolEx(&status, &wnd->tx_packet_pool,				 wnd->max_tx_packets, 0,				 PROTOCOL_RESERVED_SIZE_IN_PACKET);	if (status != NDIS_STATUS_SUCCESS) {		ERROR("couldn't allocate packet pool");		goto packet_pool_err;	}	NdisAllocateBufferPool(&status, &wnd->tx_buffer_pool,			       wnd->max_tx_packets + 4);	if (status != NDIS_STATUS_SUCCESS) {		ERROR("couldn't allocate buffer pool");		goto buffer_pool_err;	}	TRACE1("pool: %p", wnd->tx_buffer_pool);	if (miniport_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &n) ==	    NDIS_STATUS_SUCCESS && n > ETH_HLEN)		ndis_change_mtu(wnd->net_dev, n - ETH_HLEN);	if (miniport_query_int(wnd, OID_GEN_MAC_OPTIONS, &n) ==	    NDIS_STATUS_SUCCESS && n > 0)		TRACE2("mac options supported: 0x%x", n);	tx_header_offset = (typeof(tx_header_offset))buf;	tx_header_offset->protocol_type = NDIS_PROTOCOL_ID_TCP_IP;	tx_header_offset->header_offset = sizeof(ETH_HLEN);	status = miniport_set_info(wnd, OID_GEN_TRANSPORT_HEADER_OFFSET,				   tx_header_offset, sizeof(*tx_header_offset));	TRACE2("%08X", status);	wnd->tx_ok = 1;	if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {		miniport_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF);		get_encryption_capa(wnd, buf, buf_len);		TRACE1("capbilities = %ld", wnd->capa.encr);		printk(KERN_INFO "%s: encryption modes supported: "		       "%s%s%s%s%s%s%s\n", net_dev->name,		       test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ?		       "WEP" : "none",		       test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ?		       "; TKIP with WPA" : "",		       test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?		       ", WPA2" : "",		       test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?		       ", WPA2PSK" : "",		       test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ?		       "; AES/CCMP with WPA" : "",		       test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?		       ", WPA2" : "",		       test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?		       ", WPA2PSK" : "");		set_infra_mode(wnd, Ndis802_11Infrastructure);		set_scan(wnd);		set_priv_filter(wnd, Ndis802_11PrivFilterAcceptAll);		set_auth_mode(wnd, Ndis802_11AuthModeOpen);		set_encr_mode(wnd, Ndis802_11EncryptionDisabled);		set_essid(wnd, "", 0);	}	kfree(buf);	wrap_procfs_add_ndis_device(wnd);	hangcheck_add(wnd);	add_iw_stats_timer(wnd);	EXIT1(return NDIS_STATUS_SUCCESS);buffer_pool_err:	wnd->tx_buffer_pool = NULL;	if (wnd->tx_packet_pool) {		NdisFreePacketPool(wnd->tx_packet_pool);		wnd->tx_packet_pool = NULL;	}packet_pool_err:err_register:	kfree(buf);err_start:	wrap_ndis_remove_device(wnd);	EXIT1(return NDIS_STATUS_FAILURE);}static int wrap_ndis_remove_device(struct wrap_ndis_device *wnd){	s8 tx_pending;	KIRQL irql;	/* prevent setting essid during disassociation */	memset(&wnd->essid, 0, sizeof(wnd->essid));	if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {		up(&wnd->ndis_comm_mutex);		disassociate(wnd, 0);		down_interruptible(&wnd->ndis_comm_mutex);	}	set_bit(SHUTDOWN, &wnd->wrap_ndis_pending_work);	wnd->tx_ok = 0;	unregister_netdev(wnd->net_dev);	netif_carrier_off(wnd->net_dev);	/* if device is suspended, but resume failed, tx_ring_mutex	 * may already be locked */	down_trylock(&wnd->tx_ring_mutex);	irql = nt_spin_lock_irql(&wnd->tx_ring_lock, DISPATCH_LEVEL);	tx_pending = wnd->tx_ring_end - wnd->tx_ring_start;	if (tx_pending < 0)		tx_pending += TX_RING_SIZE;	else if (tx_pending == 0 && wnd->is_tx_ring_full)		tx_pending = TX_RING_SIZE - 1;	wnd->is_tx_ring_full = 0;	/* throw away pending packets */	while (tx_pending > 0) {		struct ndis_packet *packet;		packet = wnd->tx_ring[wnd->tx_ring_start];		free_tx_packet(wnd, packet, NDIS_STATUS_CLOSING);		wnd->tx_ring_start = (wnd->tx_ring_start + 1) % TX_RING_SIZE;		tx_pending--;	}	nt_spin_unlock_irql(&wnd->tx_ring_lock, irql);	up(&wnd->tx_ring_mutex);	wrap_procfs_remove_ndis_device(wnd);	miniport_halt(wnd);	ndis_exit_device(wnd);	if (wnd->tx_packet_pool) {		NdisFreePacketPool(wnd->tx_packet_pool);		wnd->tx_packet_pool = NULL;	}	if (wnd->tx_buffer_pool) {		NdisFreeBufferPool(wnd->tx_buffer_pool);		wnd->tx_buffer_pool = NULL;	}	printk(KERN_INFO "%s: device %s removed\n", DRIVER_NAME,	       wnd->net_dev->name);	free_netdev(wnd->net_dev);	EXIT2(return 0);}static wstdcall NTSTATUS NdisAddDevice(struct driver_object *drv_obj,				       struct device_object *pdo){	struct device_object *fdo;	struct ndis_miniport_block *nmb;	NTSTATUS status;	struct wrap_ndis_device *wnd;	struct net_device *net_dev;	struct wrap_device *wd;	unsigned long i;	ENTER2("%p, %p", drv_obj, pdo);	if (strlen(if_name) >= IFNAMSIZ) {		ERROR("interface name '%s' is too long", if_name);		return STATUS_INVALID_PARAMETER;	}	net_dev = alloc_etherdev(sizeof(*wnd) + sizeof(*nmb));	if (!net_dev) {		ERROR("couldn't allocate device");		return STATUS_RESOURCES;	}	wd = pdo->reserved;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)	SET_MODULE_OWNER(net_dev);	if (wrap_is_pci_bus(wd->dev_bus))		SET_NETDEV_DEV(net_dev, &wd->pci.pdev->dev);	if (wrap_is_usb_bus(wd->dev_bus))		SET_NETDEV_DEV(net_dev, &wd->usb.intf->dev);#endif	status = IoCreateDevice(drv_obj, 0, NULL,				FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);	if (status != STATUS_SUCCESS) {		free_netdev(net_dev);		EXIT2(return status);	}	wnd = netdev_priv(net_dev);	TRACE1("wnd: %p", wnd);	nmb = ((void *)wnd) + sizeof(*wnd);#if defined(DEBUG) && DEBUG >= 6	/* poison nmb so if a driver accesses uninitialized pointers, we	 * know what it is */	for (i = 0; i < sizeof(*nmb) / sizeof(unsigned long); i++)		((unsigned long *)nmb)[i] = i + 0x8a3fc1;#endif	wnd->nmb = nmb;	nmb->wnd = wnd;	nmb->pdo = pdo;	wd->wnd = wnd;	wnd->wd = wd;	wnd->net_dev = net_dev;	fdo->reserved = wnd;	nmb->fdo = fdo;	if (ndis_init_device(wnd)) {		IoDeleteDevice(fdo);		free_netdev(net_dev);		EXIT1(return STATUS_RESOURCES);	}	nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo);	nt_spin_lock_init(&wnd->tx_ring_lock);	init_MUTEX(&wnd->tx_ring_mutex);	init_MUTEX(&wnd->ndis_comm_mutex);	wnd->ndis_comm_done = 0;	initialize_work(&wnd->tx_work, tx_worker, wnd);	wnd->tx_ring_start = 0;	wnd->tx_ring_end = 0;	wnd->is_tx_ring_full = 0;	wnd->encr_mode = Ndis802_11EncryptionDisabled;	wnd->auth_mode = Ndis802_11AuthModeOpen;	wnd->capa.encr = 0;	wnd->capa.auth = 0;	wnd->attributes = 0;	wnd->dma_map_count = 0;	wnd->dma_map_addr = NULL;	wnd->nick[0] = 0;	init_timer(&wnd->hangcheck_timer);	wnd->scan_timestamp = 0;	init_timer(&wnd->iw_stats_timer);	wnd->iw_stats_interval = 10 * HZ;	wnd->wrap_ndis_pending_work = 0;	memset(&wnd->essid, 0, sizeof(wnd->essid));	memset(&wnd->encr_info, 0, sizeof(wnd->encr_info));	wnd->infrastructure_mode = Ndis802_11Infrastructure;	initialize_work(&wnd->wrap_ndis_work, wrap_ndis_worker, wnd);	wnd->iw_stats_enabled = TRUE;	TRACE1("nmb: %p, pdo: %p, fdo: %p, attached: %p, next: %p",	       nmb, pdo, fdo, fdo->attached, nmb->next_device);	/* dispatch routines are called as Windows functions */	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)		drv_obj->major_func[i] = WIN_FUNC_PTR(IoPassIrpDown,2);	drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(NdisDispatchPnp,2);	drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(NdisDispatchPower,2);	drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] =		WIN_FUNC_PTR(NdisDispatchDeviceControl,2);//	drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] =//		WIN_FUNC_PTR(NdisDispatchDeviceControl,2);	EXIT2(return STATUS_SUCCESS);}int init_ndis_driver(struct driver_object *drv_obj){	ENTER1("%p", drv_obj);	drv_obj->drv_ext->add_device = NdisAddDevice;	return 0;}int wrapndis_init(void){	register_netdevice_notifier(&netdev_notifier);	return 0;}void wrapndis_exit(void){	unregister_netdevice_notifier(&netdev_notifier);}

⌨️ 快捷键说明

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