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

📄 ndis.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	DBG_BLOCK(2) {		if (pool->num_used_descr >= pool->max_descr)			WARNING("pool %p is full: %d(%d)", pool,				pool->num_used_descr, pool->max_descr);	}	/* packet has space for 1 byte in protocol_reserved field */	packet_length = sizeof(*packet) - 1 + pool->proto_rsvd_length +		sizeof(struct ndis_packet_oob_data);	irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL);	if (pool->free_descr) {		packet = pool->free_descr;		pool->free_descr = (void *)(ULONG_PTR)packet->reserved[0];		nt_spin_unlock_irql(&pool->lock, irql);	} else {		nt_spin_unlock_irql(&pool->lock, irql);		packet = kmalloc(packet_length, gfp_irql());		if (!packet) {			WARNING("couldn't allocate packet");			*status = NDIS_STATUS_RESOURCES;			return;		}		atomic_inc_var(pool->num_allocated_descr);	}	TRACE3("packet: %p", packet);	atomic_inc_var(pool->num_used_descr);	memset(packet, 0, packet_length);	packet->private.oob_offset =		packet_length - sizeof(struct ndis_packet_oob_data);	packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS;	packet->private.pool = pool;	*ndis_packet = packet;	*status = NDIS_STATUS_SUCCESS;	TRACE4("packet: %p, pool: %p", packet, pool);	EXIT4(return);}wstdcall void WIN_FUNC(NdisDprAllocatePacket,3)	(NDIS_STATUS *status, struct ndis_packet **packet,	 struct ndis_packet_pool *pool){	NdisAllocatePacket(status, packet, pool);}wstdcall void WIN_FUNC(NdisFreePacket,1)	(struct ndis_packet *packet){	struct ndis_packet_pool *pool;	KIRQL irql;	ENTER3("packet: %p, pool: %p", packet, packet->private.pool);	pool = packet->private.pool;	if (!pool) {		ERROR("pool for descriptor %p is invalid", packet);		EXIT4(return);	}	atomic_dec_var(pool->num_used_descr);	irql = nt_spin_lock_irql(&pool->lock, DISPATCH_LEVEL);	if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) {		nt_spin_unlock_irql(&pool->lock, irql);		atomic_dec_var(pool->num_allocated_descr);		kfree(packet);	} else {		packet->reserved[0] = (ULONG_PTR)pool->free_descr;		pool->free_descr = packet;		nt_spin_unlock_irql(&pool->lock, irql);	}	EXIT4(return);}wstdcall void WIN_FUNC(NdisCopyFromPacketToPacketSafe,7)	(struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,	 struct ndis_packet *src, UINT src_offset, UINT *num_copied,	 enum mm_page_priority priority){	UINT dst_n, src_n, n, left;	ndis_buffer *dst_buf;	ndis_buffer *src_buf;	ENTER4("");	if (!dst || !src) {		*num_copied = 0;		EXIT4(return);	}	dst_buf = dst->private.buffer_head;	src_buf = src->private.buffer_head;	if (!dst_buf || !src_buf) {		*num_copied = 0;		EXIT4(return);	}	dst_n = MmGetMdlByteCount(dst_buf) - dst_offset;	src_n = MmGetMdlByteCount(src_buf) - src_offset;	n = min(src_n, dst_n);	n = min(n, num_to_copy);	memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,	       MmGetSystemAddressForMdl(src_buf) + src_offset, n);	left = num_to_copy - n;	while (left > 0) {		src_offset += n;		dst_offset += n;		dst_n -= n;		src_n -= n;		if (dst_n == 0) {			dst_buf = dst_buf->next;			if (!dst_buf)				break;			dst_n = MmGetMdlByteCount(dst_buf);			dst_offset = 0;		}		if (src_n == 0) {			src_buf = src_buf->next;			if (!src_buf)				break;			src_n = MmGetMdlByteCount(src_buf);			src_offset = 0;		}		n = min(src_n, dst_n);		n = min(n, left);		memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,		       MmGetSystemAddressForMdl(src_buf) + src_offset, n);		left -= n;	}	*num_copied = num_to_copy - left;	EXIT4(return);}wstdcall void WIN_FUNC(NdisCopyFromPacketToPacket,6)	(struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,	 struct ndis_packet *src, UINT src_offset, UINT *num_copied){	NdisCopyFromPacketToPacketSafe(dst, dst_offset, num_to_copy,				       src, src_offset, num_copied,				       NormalPagePriority);	return;}wstdcall void WIN_FUNC(NdisIMCopySendPerPacketInfo,2)	(struct ndis_packet *dst, struct ndis_packet *src){	struct ndis_packet_oob_data *dst_oob, *src_oob;	dst_oob = NDIS_PACKET_OOB_DATA(dst);	src_oob = NDIS_PACKET_OOB_DATA(src);	memcpy(&dst_oob->ext, &src_oob->ext, sizeof(dst_oob->ext));	return;}wstdcall void WIN_FUNC(NdisSend,3)	(NDIS_STATUS *status, struct ndis_miniport_block *nmb,	 struct ndis_packet *packet){	struct wrap_ndis_device *wnd = nmb->wnd;	struct miniport_char *miniport;	KIRQL irql;	miniport = &wnd->wd->driver->ndis_driver->miniport;	if (miniport->send_packets) {		irql = serialize_lock_irql(wnd);		LIN2WIN3(miniport->send_packets, wnd->nmb->adapter_ctx,			 &packet, 1);		serialize_unlock_irql(wnd, irql);		if (deserialized_driver(wnd))			*status = NDIS_STATUS_PENDING;		else {			struct ndis_packet_oob_data *oob_data;			oob_data = NDIS_PACKET_OOB_DATA(packet);			*status = oob_data->status;			switch (*status) {			case NDIS_STATUS_SUCCESS:				free_tx_packet(wnd, packet, *status);				break;			case NDIS_STATUS_PENDING:				break;			case NDIS_STATUS_RESOURCES:				wnd->tx_ok = 0;				break;			case NDIS_STATUS_FAILURE:			default:				free_tx_packet(wnd, packet, *status);				break;			}		}	} else {		irql = serialize_lock_irql(wnd);		*status = LIN2WIN3(miniport->send, wnd->nmb->adapter_ctx,				   packet, 0);		serialize_unlock_irql(wnd, irql);		switch (*status) {		case NDIS_STATUS_SUCCESS:			free_tx_packet(wnd, packet, *status);			break;		case NDIS_STATUS_PENDING:			break;		case NDIS_STATUS_RESOURCES:			wnd->tx_ok = 0;			break;		case NDIS_STATUS_FAILURE:		default:			free_tx_packet(wnd, packet, *status);			break;		}	}	EXIT3(return);}wstdcall void wrap_miniport_timer(struct kdpc *kdpc, void *ctx, void *arg1,				  void *arg2){	struct ndis_miniport_timer *timer;	struct ndis_miniport_block *nmb;	timer = ctx;	TIMERENTER("timer: %p, func: %p, ctx: %p, nmb: %p",		   timer, timer->func, timer->ctx, timer->nmb);	nmb = timer->nmb;	/* already called at DISPATCH_LEVEL */	if (!deserialized_driver(nmb->wnd))		serialize_lock(nmb->wnd);	LIN2WIN4(timer->func, &timer->kdpc, timer->ctx, NULL, NULL);	if (!deserialized_driver(nmb->wnd))		serialize_unlock(nmb->wnd);	TIMEREXIT(return);}WIN_FUNC_DECL(wrap_miniport_timer,4)wstdcall void WIN_FUNC(NdisMInitializeTimer,4)	(struct ndis_miniport_timer *timer, struct ndis_miniport_block *nmb,	 DPC func, void *ctx){	TIMERENTER("timer: %p, func: %p, ctx: %p, nmb: %p",		   timer, func, ctx, nmb);	timer->func = func;	timer->ctx = ctx;	timer->nmb = nmb;//	KeInitializeDpc(&timer->kdpc, func, ctx);	KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(wrap_miniport_timer,4),			timer);	wrap_init_timer(&timer->nt_timer, NotificationTimer, &timer->kdpc, nmb);	TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2)	(struct ndis_miniport_timer *timer, UINT period_ms){	unsigned long expires = MSEC_TO_HZ(period_ms) + 1;	TIMERENTER("%p, %u, %ld", timer, period_ms, expires);	wrap_set_timer(&timer->nt_timer, expires, expires, NULL);	TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisMCancelTimer,2)	(struct ndis_miniport_timer *timer, BOOLEAN *canceled){	TIMERENTER("%p", timer);	*canceled = KeCancelTimer(&timer->nt_timer);	TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisInitializeTimer,3)	(struct ndis_timer *timer, void *func, void *ctx){	TIMERENTER("%p, %p, %p", timer, func, ctx);	KeInitializeDpc(&timer->kdpc, func, ctx);	wrap_init_timer(&timer->nt_timer, NotificationTimer, &timer->kdpc, NULL);	TIMEREXIT(return);}/* NdisMSetTimer is a macro that calls NdisSetTimer with * ndis_miniport_timer typecast to ndis_timer */wstdcall void WIN_FUNC(NdisSetTimer,2)	(struct ndis_timer *timer, UINT duetime_ms){	unsigned long expires = MSEC_TO_HZ(duetime_ms) + 1;	TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer,		   duetime_ms, expires);	wrap_set_timer(&timer->nt_timer, expires, 0, NULL);	TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisCancelTimer,2)	(struct ndis_timer *timer, BOOLEAN *canceled){	TIMERENTER("%p", timer);	*canceled = KeCancelTimer(&timer->nt_timer);	TIMEREXIT(return);}wstdcall void WIN_FUNC(NdisReadNetworkAddress,4)	(NDIS_STATUS *status, void **addr, UINT *len,	 struct ndis_miniport_block *nmb){	struct wrap_ndis_device *wnd = nmb->wnd;	struct ndis_configuration_parameter *param;	struct unicode_string key;	struct ansi_string ansi;	int ret;	ENTER1("");	RtlInitAnsiString(&ansi, "mac_address");	*len = 0;	*status = NDIS_STATUS_FAILURE;	if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS)		EXIT1(return);	NdisReadConfiguration(status, &param, nmb, &key, NdisParameterString);	RtlFreeUnicodeString(&key);	if (*status == NDIS_STATUS_SUCCESS) {		int int_mac[ETH_ALEN];		ret = RtlUnicodeStringToAnsiString(&ansi, &param->data.string,						   TRUE);		if (ret != NDIS_STATUS_SUCCESS)			EXIT1(return);		ret = sscanf(ansi.buf, MACSTRSEP, MACINTADR(int_mac));		if (ret != ETH_ALEN)			ret = sscanf(ansi.buf, MACSTR, MACINTADR(int_mac));		RtlFreeAnsiString(&ansi);		if (ret == ETH_ALEN) {			int i;			for (i = 0; i < ETH_ALEN; i++)				wnd->mac[i] = int_mac[i];			printk(KERN_INFO "%s: %s ethernet device " MACSTRSEP			       "\n", wnd->net_dev->name, DRIVER_NAME,			       MAC2STR(wnd->mac));			*len = ETH_ALEN;			*addr = wnd->mac;			*status = NDIS_STATUS_SUCCESS;		}	}	EXIT1(return);}wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3)	(struct ndis_miniport_block *nmb, void *ctx, void *func){	struct wrap_ndis_device *wnd = nmb->wnd;	ENTER1("%p", func);	wnd->wd->driver->ndis_driver->miniport.shutdown = func;	wnd->shutdown_ctx = ctx;}wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1)	(struct ndis_miniport_block *nmb){	struct wrap_ndis_device *wnd = nmb->wnd;	wnd->wd->driver->ndis_driver->miniport.shutdown = NULL;	wnd->shutdown_ctx = NULL;}/* TODO: rt61 (serialized) driver doesn't want MiniportEnableInterrupt * to be called in irq handler, but mrv800c (deserialized) driver * wants. NDIS is confusing about when to call MiniportEnableInterrupt * For now, handle these cases with two separate irq handlers based on * observation of these two drivers. However, it is likely not * correct. */static void deserialized_irq_handler(unsigned long data){	struct ndis_mp_interrupt *mp_interrupt = (typeof(mp_interrupt))data;	struct wrap_ndis_device *wnd = mp_interrupt->nmb->wnd;	LIN2WIN1(mp_interrupt->mp_dpc, wnd->nmb->adapter_ctx);	if (mp_interrupt->enable) {		struct miniport_char *miniport;		miniport = &wnd->wd->driver->ndis_driver->miniport;		LIN2WIN1(miniport->enable_interrupt, wnd->nmb->adapter_ctx);	}}static void serialized_irq_handler(unsigned long data){	struct ndis_mp_interrupt *mp_interrupt = (typeof(mp_interrupt))data;	struct wrap_ndis_device *wnd = mp_interrupt->nmb->wnd;	serialize_lock(wnd);	LIN2WIN1(mp_interrupt->mp_dpc, wnd->nmb->adapter_ctx);	serialize_unlock(wnd);}irqreturn_t ndis_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL){	struct ndis_mp_interrupt *mp_interrupt = data;	struct wrap_ndis_device *wnd = mp_interrupt->nmb->wnd;	BOOLEAN recognized, queue_handler;	/* this spinlock should be shared with NdisMSynchronizeWithInterrupt	 */	nt_spin_lock(&mp_interrupt->lock);	if (mp_interrupt->shared)		LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler,			 wnd->nmb->adapter_ctx);	else {		struct miniport_char *miniport;		miniport = &wnd->wd->driver->ndis_driver->miniport;		LIN2WIN1(miniport->disable_interrupt, wnd->nmb->adapter_ctx);		/* it is not shared interrupt, so handler must be called */		recognized = queue_handler = TRUE;	}	nt_spin_unlock(&mp_interrupt->lock);	if (recognized) {		if (queue_handler)			tasklet_schedule(&wnd->irq_tasklet);		EXIT6(return IRQ_HANDLED);	}	EXIT6(return IRQ_NONE);}wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7)	(struct ndis_mp_interrupt *mp_interrupt,	 struct ndis_miniport_block *nmb, UINT vector, UINT level,	 BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode){	struct wrap_ndis_device *wnd = nmb->wnd;	struct miniport_char *miniport;	ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d",	       mp_interrupt, vector, level, req_isr, shared, mode);	mp_interrupt->irq = vector;	mp_interrupt->nmb = nmb;	mp_interrupt->req_isr = req_isr;	if (shared && !req_isr)		WARNING("shared but dynamic interrupt!");	mp_interrupt->shared = shared;	nt_spin_lock_init(&mp_interrupt->lock);	wnd->mp_interrupt = mp_interrupt;	miniport = &wnd->wd->driver->ndis_driver->miniport;	mp_interrupt->isr = miniport->isr;	mp_interrupt->mp_dpc = miniport->handle_interrupt;	if (miniport->enable_interrupt)		mp_interrupt->enable = TRUE;	else		mp_interrupt->enable = FALSE;	tasklet_init(&wnd->irq_tasklet, deserialized_driver(wnd) ?		     deserialized_irq_handler : serialized_irq_handler,		     (unsigned long)mp_interrupt);	if (request_irq(vector, ndis_isr, req_isr ? IRQF_SHARED : 0,			wnd->net_dev->name, mp_interrupt)) {		printk(KERN_WARNING "%s: request for IRQ %d failed\n",		       DRIVER_NAME, vector);		EXIT1(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_miniport_block *nmb;	ENTER1("%p", mp_interrupt);	nmb = mp_interrupt->nmb;	free_irq(mp_interrupt->irq, mp_interrupt);	tasklet_kill(&nmb->wnd->irq_tasklet);	mp_interrupt->nmb = NULL;	nmb->wnd->mp_interrupt = NULL;	EXIT1(return);

⌨️ 快捷键说明

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