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

📄 ndis.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}wstdcall BOOLEAN WIN_FUNC(NdisMSynchronizeWithInterrupt,3)	(struct ndis_mp_interrupt *mp_interrupt,	 PKSYNCHRONIZE_ROUTINE sync_func, void *ctx){	BOOLEAN ret;	unsigned long flags;	ENTER6("%p %p", sync_func, ctx);	nt_spin_lock_irqsave(&mp_interrupt->lock, flags);	ret = LIN2WIN1(sync_func, ctx);	nt_spin_unlock_irqrestore(&mp_interrupt->lock, flags);	TRACE6("ret: %d", ret);	EXIT6(return ret);}/* called via function pointer; but 64-bit RNDIS driver calls directly */wstdcall void WIN_FUNC(NdisMIndicateStatus,4)	(struct ndis_miniport_block *nmb, NDIS_STATUS status,	 void *buf, UINT len){	struct wrap_ndis_device *wnd = nmb->wnd;	struct ndis_status_indication *si;	struct ndis_auth_req *auth_req;	struct ndis_radio_status_indication *radio_status;	ENTER2("status=0x%x len=%d", status, len);	switch (status) {	case NDIS_STATUS_MEDIA_DISCONNECT:		if (!netif_carrier_ok(wnd->net_dev))			break;		netif_carrier_off(wnd->net_dev);		set_bit(LINK_STATUS_CHANGED, &wnd->wrap_ndis_pending_work);		schedule_wrap_work(&wnd->wrap_ndis_work);		break;	case NDIS_STATUS_MEDIA_CONNECT:		if (netif_carrier_ok(wnd->net_dev))			break;		netif_carrier_on(wnd->net_dev);		set_bit(LINK_STATUS_CHANGED, &wnd->wrap_ndis_pending_work);		schedule_wrap_work(&wnd->wrap_ndis_work);		break;	case NDIS_STATUS_MEDIA_SPECIFIC_INDICATION:		if (!buf)			break;		si = buf;		TRACE2("status_type=%d", si->status_type);		switch (si->status_type) {		case Ndis802_11StatusType_Authentication:			buf = (char *)buf + sizeof(*si);			len -= sizeof(*si);			while (len > 0) {				auth_req = (struct ndis_auth_req *)buf;				TRACE1(MACSTRSEP, MAC2STR(auth_req->bssid));				if (auth_req->flags & 0x01)					TRACE2("reqauth");				if (auth_req->flags & 0x02)					TRACE2("keyupdate");				if (auth_req->flags & 0x06)					TRACE2("pairwise_error");				if (auth_req->flags & 0x0E)					TRACE2("group_error");				/* TODO: report to wpa_supplicant */				len -= auth_req->length;				buf = (char *)buf + auth_req->length;			}			break;		case Ndis802_11StatusType_MediaStreamMode:			break;#ifdef CONFIG_NET_RADIO		case Ndis802_11StatusType_PMKID_CandidateList:		{			u8 *end;			unsigned long i;			struct ndis_pmkid_candidate_list *cand;			cand = buf + sizeof(struct ndis_status_indication);			if (len < sizeof(struct ndis_status_indication) +			    sizeof(struct ndis_pmkid_candidate_list) ||				cand->version != 1) {				WARNING("Unrecognized PMKID_CANDIDATE_LIST"					" ignored");				EXIT1(return);			}			end = (u8 *)buf + len;			TRACE2("PMKID_CANDIDATE_LIST ver %ld num_cand %ld",			       cand->version, cand->num_candidates);			for (i = 0; i < cand->num_candidates; i++) {#if WIRELESS_EXT > 17				struct iw_pmkid_cand pcand;				union iwreq_data wrqu;#endif				struct ndis_pmkid_candidate *c =					&cand->candidates[i];				if ((u8 *)(c + 1) > end) {					TRACE2("Truncated PMKID_CANDIDATE_LIST");					break;				}				TRACE2("%ld: " MACSTRSEP " 0x%lx",				       i, MAC2STR(c->bssid), c->flags);#if WIRELESS_EXT > 17				memset(&pcand, 0, sizeof(pcand));				if (c->flags & 0x01)					pcand.flags |= IW_PMKID_CAND_PREAUTH;				pcand.index = i;				memcpy(pcand.bssid.sa_data, c->bssid, ETH_ALEN);				memset(&wrqu, 0, sizeof(wrqu));				wrqu.data.length = sizeof(pcand);				wireless_send_event(wnd->net_dev, IWEVPMKIDCAND,						    &wrqu, (u8 *)&pcand);#endif			}			break;		}		case Ndis802_11StatusType_RadioState:			radio_status = buf;			if (radio_status->radio_state ==			    Ndis802_11RadioStatusOn)				INFO("radio is turned on");			else if (radio_status->radio_state ==				 Ndis802_11RadioStatusHardwareOff)				INFO("radio is turned off by hardware");			else if (radio_status->radio_state ==				 Ndis802_11RadioStatusSoftwareOff)				INFO("radio is turned off by software");			break;#endif		default:			/* is this RSSI indication? */			TRACE2("unknown indication: %x", si->status_type);			break;		}		break;	default:		TRACE2("unknown status: %08X", status);		break;	}	EXIT2(return);}/* called via function pointer; but 64-bit RNDIS driver calls directly */wstdcall void WIN_FUNC(NdisMIndicateStatusComplete,1)	(struct ndis_miniport_block *nmb){	struct wrap_ndis_device *wnd = nmb->wnd;	ENTER2("%p", wnd);	schedule_wrap_work(&wnd->wrap_ndis_work);	if (wnd->tx_ok)		schedule_wrap_work(&wnd->tx_work);}/* called via function pointer */wstdcall void NdisMSendComplete(struct ndis_miniport_block *nmb,				struct ndis_packet *packet, NDIS_STATUS status){	struct wrap_ndis_device *wnd = nmb->wnd;	ENTER4("%p, %08X", packet, status);	if (deserialized_driver(wnd))		free_tx_packet(wnd, packet, status);	else {		struct ndis_packet_oob_data *oob_data;		NDIS_STATUS pkt_status;		TRACE3("%p, %08x", packet, status);		oob_data = NDIS_PACKET_OOB_DATA(packet);		switch ((pkt_status = xchg(&oob_data->status, status))) {		case NDIS_STATUS_NOT_RECOGNIZED:			free_tx_packet(wnd, packet, status);			break;		case NDIS_STATUS_PENDING:		case 0:			break;		default:			WARNING("%p: invalid status: %08X", packet, pkt_status);			break;		}		/* In case a serialized driver has earlier requested a		 * pause by returning NDIS_STATUS_RESOURCES during		 * MiniportSend(Packets), wakeup tx worker now.		 */		if (xchg(&wnd->tx_ok, 1) == 0) {			TRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);			schedule_wrap_work(&wnd->tx_work);		}	}	EXIT3(return);}/* called via function pointer */wstdcall void NdisMSendResourcesAvailable(struct ndis_miniport_block *nmb){	struct wrap_ndis_device *wnd = nmb->wnd;	ENTER3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);	wnd->tx_ok = 1;	schedule_wrap_work(&wnd->tx_work);	EXIT3(return);}wstdcall void return_packet(void *arg1, void *arg2){	struct wrap_ndis_device *wnd;	struct ndis_packet *packet;	struct miniport_char *miniport;	KIRQL irql;	wnd = arg1;	packet = arg2;	ENTER4("%p, %p", wnd, packet);	miniport = &wnd->wd->driver->ndis_driver->miniport;	irql = serialize_lock_irql(wnd);	LIN2WIN2(miniport->return_packet, wnd->nmb->adapter_ctx, packet);	serialize_unlock_irql(wnd, irql);	EXIT4(return);}WIN_FUNC_DECL(return_packet,2)/* called via function pointer */wstdcall void NdisMIndicateReceivePacket(struct ndis_miniport_block *nmb,					 struct ndis_packet **packets,					 UINT nr_packets){	struct wrap_ndis_device *wnd;	ndis_buffer *buffer;	struct ndis_packet *packet;	struct sk_buff *skb;	ULONG i, length, total_length;	struct ndis_packet_oob_data *oob_data;	void *virt;	struct ndis_tcp_ip_checksum_packet_info csum;	ENTER3("%p, %d", nmb, nr_packets);	wnd = nmb->wnd;	for (i = 0; i < nr_packets; i++) {		packet = packets[i];		if (!packet) {			WARNING("empty packet ignored");			continue;		}		wnd->net_dev->last_rx = jiffies;		/* get total number of bytes in packet */		NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt,						 &length, &total_length,						 NormalPagePriority);		TRACE3("%d, %d", length, total_length);		oob_data = NDIS_PACKET_OOB_DATA(packet);		TRACE3("0x%x, 0x%x, %Lu", packet->private.flags,		       packet->private.packet_flags, oob_data->time_rxed);		skb = dev_alloc_skb(total_length);		if (skb) {			while (buffer) {				memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),					   MmGetMdlByteCount(buffer));				buffer = buffer->next;			}			skb->dev = wnd->net_dev;			skb->protocol = eth_type_trans(skb, wnd->net_dev);			pre_atomic_add(wnd->net_stats.rx_bytes, total_length);			atomic_inc_var(wnd->net_stats.rx_packets);			csum.value = (typeof(csum.value))(ULONG_PTR)				oob_data->ext.info[TcpIpChecksumPacketInfo];			TRACE3("0x%05x", csum.value);			if (wnd->rx_csum.value &&			    (csum.rx.tcp_succeeded || csum.rx.udp_succeeded ||			     csum.rx.ip_succeeded))				skb->ip_summed = CHECKSUM_UNNECESSARY;			else				skb->ip_summed = CHECKSUM_NONE;			netif_rx(skb);		} else {			WARNING("couldn't allocate skb; packet dropped");			atomic_inc_var(wnd->net_stats.rx_dropped);		}		/* serialized drivers check the status upon return		 * from this function */		if (!deserialized_driver(wnd)) {			oob_data->status = NDIS_STATUS_SUCCESS;			continue;		}		/* if a deserialized driver sets		 * NDIS_STATUS_RESOURCES, then it reclaims the packet		 * upon return from this function */		if (oob_data->status == NDIS_STATUS_RESOURCES)			continue;		assert(oob_data->status == NDIS_STATUS_SUCCESS);		/* deserialized driver doesn't check the status upon		 * return from this function; we need to call		 * MiniportReturnPacket later for this packet. Calling		 * MiniportReturnPacket from here is not correct - the		 * driver doesn't expect it (at least Centrino driver		 * crashes) */		schedule_ntos_work_item(WIN_FUNC_PTR(return_packet,2),					wnd, packet);	}	EXIT3(return);}/* called via function pointer (by NdisMEthIndicateReceive macro); the * first argument is nmb->eth_db */wstdcall void EthRxIndicateHandler(struct ndis_miniport_block *nmb, void *rx_ctx,				   char *header1, char *header, UINT header_size,				   void *look_ahead, UINT look_ahead_size,				   UINT packet_size){	struct sk_buff *skb = NULL;	struct wrap_ndis_device *wnd;	unsigned int skb_size = 0;	KIRQL irql;	struct ndis_packet_oob_data *oob_data;	ENTER3("nmb = %p, rx_ctx = %p, buf = %p, size = %d, buf = %p, "	       "size = %d, packet = %d", nmb, rx_ctx, header, header_size,	       look_ahead, look_ahead_size, packet_size);	wnd = nmb->wnd;	TRACE3("wnd = %p", wnd);	if (!wnd) {		ERROR("nmb is NULL");		EXIT3(return);	}	wnd->net_dev->last_rx = jiffies;	if (look_ahead_size < packet_size) {		struct ndis_packet *packet;		struct miniport_char *miniport;		unsigned int bytes_txed;		NDIS_STATUS res;		NdisAllocatePacket(&res, &packet, wnd->tx_packet_pool);		if (res != NDIS_STATUS_SUCCESS) {			atomic_inc_var(wnd->net_stats.rx_dropped);			EXIT3(return);		}		oob_data = NDIS_PACKET_OOB_DATA(packet);		miniport = &wnd->wd->driver->ndis_driver->miniport;		irql = serialize_lock_irql(wnd);		res = LIN2WIN6(miniport->tx_data, packet, &bytes_txed, nmb,			       rx_ctx, look_ahead_size, packet_size);		serialize_unlock_irql(wnd, irql);		TRACE3("%d, %d, %d", header_size, look_ahead_size, bytes_txed);		if (res == NDIS_STATUS_SUCCESS) {			ndis_buffer *buffer;			struct ndis_tcp_ip_checksum_packet_info csum;			skb = dev_alloc_skb(header_size + look_ahead_size +					    bytes_txed);			if (!skb) {				ERROR("couldn't allocate skb; packet dropped");				atomic_inc_var(wnd->net_stats.rx_dropped);				NdisFreePacket(packet);				return;			}			memcpy_skb(skb, header, header_size);			memcpy_skb(skb, look_ahead, look_ahead_size);			buffer = packet->private.buffer_head;			while (buffer) {				memcpy_skb(skb,					   MmGetSystemAddressForMdl(buffer),					   MmGetMdlByteCount(buffer));				buffer = buffer->next;			}			skb_size = header_size + look_ahead_size + bytes_txed;			csum.value = (typeof(csum.value))(ULONG_PTR)				oob_data->ext.info[TcpIpChecksumPacketInfo];			TRACE3("0x%05x", csum.value);			if (wnd->rx_csum.value &&			    (csum.rx.tcp_succeeded || csum.rx.udp_succeeded))				skb->ip_summed = CHECKSUM_UNNECESSARY;			else				skb->ip_summed = CHECKSUM_NONE;			NdisFreePacket(packet);		} else if (res == NDIS_STATUS_PENDING) {			/* driver will call td_complete */			oob_data->look_ahead = kmalloc(look_ahead_size,						       GFP_ATOMIC);			if (!oob_data->look_ahead) {				NdisFreePacket(packet);				ERROR("packet dropped");				atomic_inc_var(wnd->net_stats.rx_dropped);				EXIT3(return);			}			assert(sizeof(oob_data->header) == header_size);			memcpy(oob_data->header, header,			       sizeof(oob_data->header));			memcpy(oob_data->look_ahead, look_ahead,			       look_ahead_size);			oob_data->look_ahead_size = look_ahead_size;			EXIT3(return);		} else {			WARNING("packet dropped: %08X", res);			atomic_inc_var(wnd->net_stats.rx_dropped);			NdisFreePacket(packet);			EXIT3(return);		}	} else {		skb_size = header_size + packet_size;		skb = dev_alloc_skb(skb_size);		if (skb) {			memcpy_skb(skb, header, header_size);			memcpy_skb(skb, look_ahead, packet_size);		}	}	if (skb) {		skb->dev = wnd->net_dev;		skb->protocol = eth_type_trans(skb, wnd->net_dev);		pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);		atomic_inc_var(wnd->net_stats.rx_packets);		netif_rx(skb);	}	EXIT3(return);}/* called via function pointer */wstdcall void NdisMTransferDataComplete(struct ndis_miniport_block *nmb,					struct ndis_packet *packet,					NDIS_STATUS status, UINT bytes_txed){	struct wrap_ndis_device *wnd = nmb->wnd;	struct sk_buff *skb;	unsigned int skb_size;	struct ndis_packet_oob_data *oob_data;	ndis_buffer *buffer;	struct ndis_tcp_ip_checksum_packet_info csum;	ENTER3("wnd = %p, packet = %p, bytes_txed = %d",	       wnd, packet, bytes_txed);	if (!packet) {		WARNING("illegal packet");		EXIT3(return);	}	wnd->net_dev->last_rx = jiffies;	oob_data = NDIS_PACKET_OOB_DATA(packet);	skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size +		bytes_txed;	skb = dev_alloc_skb(skb_size);	if (!skb) {		kfree(oob_data->look_ahead);		NdisFreePacket(packet);		ERROR("couldn't allocate skb; packet dropped");		atomic_inc_var(wnd->net_stats.rx_dropped);		EXIT3(return);	}	memcpy_skb(skb, oob_data->header, sizeof(oob_data->header));	memcpy_skb(skb, oob_data->look_ahead, oob_data->look_ahead_size);	buffer = packet->private.buffer_head;	while (buffer) {		memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),			   MmGetMdlByteCount(buffer));		buffer = buffer->next;	}	kfree(oob_data->look_ahead);	NdisFreePacket(packet);	skb->dev = wnd->net_dev;	skb->protocol = eth_type_trans(skb, wnd->net_dev);	pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);	atomic_inc_var(wnd->net_stats

⌨️ 快捷键说明

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