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

📄 ndis.c

📁 linux下安装无线网卡启动的程式
💻 C
📖 第 1 页 / 共 5 页
字号:
wstdcall BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx){	struct ndis_mp_interrupt *mp_interrupt = ctx;	struct wrap_ndis_device *wnd = mp_interrupt->nmb->wnd;	BOOLEAN recognized, queue_handler;	TRACE6("%p", wnd);	/* kernel may call ISR when registering interrupt, in	 * the same context if DEBUG_SHIRQ is enabled */	assert_irql(_irql_ == DIRQL || _irql_ == PASSIVE_LEVEL);	if (mp_interrupt->shared)		LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler,			 wnd->nmb->mp_ctx);	else {		struct miniport *mp;		mp = &wnd->wd->driver->ndis_driver->mp;		LIN2WIN1(mp->disable_interrupt, wnd->nmb->mp_ctx);		/* it is not shared interrupt, so handler must be called */		recognized = queue_handler = TRUE;	}	if (recognized) {		if (queue_handler) {			TRACE5("%p", &wnd->irq_kdpc);			queue_kdpc(&wnd->irq_kdpc);		}		EXIT6(return TRUE);	}	EXIT6(return FALSE);}WIN_FUNC_DECL(ndis_isr,2)wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7)	(struct ndis_mp_interrupt *mp_interrupt,	 struct ndis_mp_block *nmb, UINT vector, UINT level,	 BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode){	struct wrap_ndis_device *wnd = nmb->wnd;	struct miniport *mp;	ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d",	       mp_interrupt, vector, level, req_isr, shared, mode);	mp = &wnd->wd->driver->ndis_driver->mp;	nt_spin_lock_init(&mp_interrupt->lock);	mp_interrupt->irq = vector;	mp_interrupt->isr = mp->isr;	mp_interrupt->mp_dpc = mp->handle_interrupt;	mp_interrupt->nmb = nmb;	mp_interrupt->req_isr = req_isr;	if (shared && !req_isr)		WARNING("shared but dynamic interrupt!");	mp_interrupt->shared = shared;	wnd->mp_interrupt = mp_interrupt;	if (mp->enable_interrupt)		mp_interrupt->enable = TRUE;	else		mp_interrupt->enable = FALSE;	if (deserialized_driver(wnd)) {		KeInitializeDpc(&wnd->irq_kdpc,				WIN_FUNC_PTR(deserialized_irq_handler,4),				nmb->wnd);		wnd->irq_kdpc.arg1 = mp->handle_interrupt;		wnd->irq_kdpc.arg2 = mp;		TRACE2("%p, %p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,		       nmb->wnd, nmb->mp_ctx);	} else {		KeInitializeDpc(&wnd->irq_kdpc,				WIN_FUNC_PTR(serialized_irq_handler,4),				nmb->wnd);		wnd->irq_kdpc.arg1 = mp->handle_interrupt;		wnd->irq_kdpc.arg2 = nmb->mp_ctx;		TRACE2("%p, %p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,		       nmb->wnd, nmb->mp_ctx);	}	if (IoConnectInterrupt(&mp_interrupt->kinterrupt,			       WIN_FUNC_PTR(ndis_isr,2), mp_interrupt, NULL,			       vector, DIRQL, DIRQL, mode, shared, 0, FALSE) !=	    STATUS_SUCCESS) {		printk(KERN_WARNING "%s: request for IRQ %d failed\n",		       DRIVER_NAME, vector);		return NDIS_STATUS_RESOURCES;	}	printk(KERN_INFO "%s: using IRQ %d\n", DRIVER_NAME, vector);	EXIT1(return NDIS_STATUS_SUCCESS);}wstdcall void WIN_FUNC(NdisMDeregisterInterrupt,1)	(struct ndis_mp_interrupt *mp_interrupt){	struct ndis_mp_block *nmb;	ENTER1("%p", mp_interrupt);	nmb = xchg(&mp_interrupt->nmb, NULL);	TRACE1("%p", nmb);	if (!nmb) {		WARNING("interrupt already freed?");		return;	}	nmb->wnd->mp_interrupt = NULL;	if (dequeue_kdpc(&nmb->wnd->irq_kdpc))		TRACE2("interrupt kdpc was pending");	IoDisconnectInterrupt(mp_interrupt->kinterrupt);	EXIT1(return);}wstdcall BOOLEAN WIN_FUNC(NdisMSynchronizeWithInterrupt,3)	(struct ndis_mp_interrupt *mp_interrupt,	 PKSYNCHRONIZE_ROUTINE sync_func, void *ctx){	return KeSynchronizeExecution(mp_interrupt->kinterrupt, sync_func, ctx);}/* called via function pointer; but 64-bit RNDIS driver calls directly */wstdcall void WIN_FUNC(NdisMIndicateStatus,4)	(struct ndis_mp_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_CONNECT:		netif_carrier_on(wnd->net_dev);		wnd->tx_ok = 1;		if (netif_queue_stopped(wnd->net_dev))			netif_wake_queue(wnd->net_dev);		if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {			set_bit(LINK_STATUS_ON, &wnd->wrap_ndis_pending_work);			schedule_wrapndis_work(&wnd->wrap_ndis_work);		}		break;	case NDIS_STATUS_MEDIA_DISCONNECT:		netif_carrier_off(wnd->net_dev);		netif_stop_queue(wnd->net_dev);		wnd->tx_ok = 0;		if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {			memset(&wnd->essid, 0, sizeof(wnd->essid));			set_bit(LINK_STATUS_OFF, &wnd->wrap_ndis_pending_work);			schedule_wrapndis_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_MediaStreamMode:			break;#ifdef CONFIG_WIRELESS_EXT		case Ndis802_11StatusType_Authentication:			buf = (char *)buf + sizeof(*si);			len -= sizeof(*si);			while (len > 0) {				int pairwise_error = 0, group_error = 0;				auth_req = (struct ndis_auth_req *)buf;				TRACE1(MACSTRSEP, MAC2STR(auth_req->bssid));				if (auth_req->flags & 0x01)					TRACE2("reauth request");				if (auth_req->flags & 0x02)					TRACE2("key update request");				if (auth_req->flags & 0x06) {					pairwise_error = 1;					TRACE2("pairwise_error");				}				if (auth_req->flags & 0x0E) {					group_error = 1;					TRACE2("group_error");				}#if WIRELESS_EXT > 17				if (pairwise_error || group_error) {					union iwreq_data wrqu;					struct iw_michaelmicfailure micfailure;					memset(&micfailure, 0, sizeof(micfailure));					if (pairwise_error)						micfailure.flags |=							IW_MICFAILURE_PAIRWISE;					if (group_error)						micfailure.flags |=							IW_MICFAILURE_GROUP;					memcpy(micfailure.src_addr.sa_data,					       auth_req->bssid, ETH_ALEN);					memset(&wrqu, 0, sizeof(wrqu));					wrqu.data.length = sizeof(micfailure);					wireless_send_event(wnd->net_dev,							    IWEVMICHAELMICFAILURE,							    &wrqu, (u8 *)&micfailure);				}#endif				len -= auth_req->length;				buf = (char *)buf + auth_req->length;			}			break;		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 ignored");				EXIT1(return);			}			end = (u8 *)buf + len;			TRACE2("PMKID ver %d num_cand %d",			       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");					break;				}				TRACE2("%ld: " MACSTRSEP " 0x%x",				       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_mp_block *nmb){	struct wrap_ndis_device *wnd = nmb->wnd;	ENTER2("%p", wnd);	if (wnd->tx_ok)		schedule_wrapndis_work(&wnd->tx_work);}/* called via function pointer */wstdcall void NdisMSendComplete(struct ndis_mp_block *nmb,				struct ndis_packet *packet, NDIS_STATUS status){	struct wrap_ndis_device *wnd = nmb->wnd;	ENTER4("%p, %08X", packet, status);	assert_irql(_irql_ <= DISPATCH_LEVEL);	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_wrapndis_work(&wnd->tx_work);		}	}	EXIT3(return);}/* called via function pointer */wstdcall void NdisMSendResourcesAvailable(struct ndis_mp_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_wrapndis_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 *mp;	KIRQL irql;	wnd = arg1;	packet = arg2;	ENTER4("%p, %p", wnd, packet);	mp = &wnd->wd->driver->ndis_driver->mp;	irql = serialize_lock_irql(wnd);	assert_irql(_irql_ == DISPATCH_LEVEL);	LIN2WIN2(mp->return_packet, wnd->nmb->mp_ctx, packet);	serialize_unlock_irql(wnd, irql);	EXIT4(return);}WIN_FUNC_DECL(return_packet,2)/* called via function pointer */wstdcall void NdisMIndicateReceivePacket(struct ndis_mp_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);	assert_irql(_irql_ <= DISPATCH_LEVEL);	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;			if (in_interrupt())				netif_rx(skb);			else				netif_rx_ni(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_mp_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 *mp;		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

⌨️ 快捷键说明

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