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

📄 ntoskernel.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *  GNU General Public License for more details. * */#include "ntoskernel.h"#include "ndis.h"#include "usb.h"#include "pnp.h"#include "loader.h"/* MDLs describe a range of virtual address with an array of physical * pages right after the header. For different ranges of virtual * addresses, the number of entries of physical pages may be different * (depending on number of entries required). If we want to allocate * MDLs from a pool, the size has to be constant. So we assume that * maximum range used by a driver is MDL_CACHE_PAGES; if a driver * requests an MDL for a bigger region, we allocate it with kmalloc; * otherwise, we allocate from the pool */#define MDL_CACHE_PAGES 3#define MDL_CACHE_SIZE (sizeof(struct mdl) + \			(sizeof(PFN_NUMBER) * MDL_CACHE_PAGES))struct wrap_mdl {	struct nt_list list;	struct mdl mdl[0];};struct thread_event {	struct task_struct *task;	BOOLEAN done;};/* everything here is for all drivers/devices - not per driver/device */static NT_SPIN_LOCK dispatcher_lock;NT_SPIN_LOCK ntoskernel_lock;static void *mdl_cache;static struct nt_list wrap_mdl_list;static work_struct_t kdpc_work;static void kdpc_worker(worker_param_t dummy);static struct nt_list kdpc_list;static NT_SPIN_LOCK kdpc_list_lock;static struct nt_list callback_objects;struct nt_list object_list;struct bus_driver {	struct nt_list list;	char name[MAX_DRIVER_NAME_LEN];	struct driver_object drv_obj;};static struct nt_list bus_driver_list;static work_struct_t ntos_work;static struct nt_list ntos_work_list;static NT_SPIN_LOCK ntos_work_lock;static void ntos_work_worker(worker_param_t dummy);NT_SPIN_LOCK irp_cancel_lock;extern struct nt_list wrap_drivers;static struct nt_list wrap_timer_list;NT_SPIN_LOCK timer_lock;/* compute ticks (100ns) since 1601 until when system booted into * wrap_ticks_to_boot */u64 wrap_ticks_to_boot;#if defined(CONFIG_X86_64)static struct timer_list shared_data_timer;struct kuser_shared_data kuser_shared_data;static void update_user_shared_data_proc(unsigned long data);#endifWIN_SYMBOL_MAP("KeTickCount", &jiffies)WIN_SYMBOL_MAP("NlsMbCodePageTag", FALSE)#ifdef USE_OWN_NTOS_WORKQUEUEworkqueue_struct_t *ntos_wq;#endif#if defined(CONFIG_X86_64)static void update_user_shared_data_proc(unsigned long data){	/* timer is supposed to be scheduled every 10ms, but bigger	 * intervals seem to work (tried upto 50ms) */	*((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();	*((ULONG64 *)&kuser_shared_data.interrupt_time) =		jiffies * TICKSPERSEC / HZ;	*((ULONG64 *)&kuser_shared_data.tick) = jiffies;	mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30));}#endifvoid *allocate_object(ULONG size, enum common_object_type type,		      struct unicode_string *name){	struct common_object_header *hdr;	void *body;	KIRQL irql;	/* we pad header as prefix to body */	hdr = ExAllocatePoolWithTag(NonPagedPool, OBJECT_SIZE(size), 0);	if (!hdr) {		WARNING("couldn't allocate memory");		return NULL;	}	memset(hdr, 0, OBJECT_SIZE(size));	if (name) {		hdr->name.buf = ExAllocatePoolWithTag(NonPagedPool,						      name->max_length, 0);		if (!hdr->name.buf) {			ExFreePool(hdr);			return NULL;		}		memcpy(hdr->name.buf, name->buf, name->max_length);		hdr->name.length = name->length;		hdr->name.max_length = name->max_length;	}	hdr->type = type;	hdr->ref_count = 1;	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	/* threads are looked up often (in KeWaitForXXX), so optimize	 * for fast lookups of threads */	if (type == OBJECT_TYPE_NT_THREAD)		InsertHeadList(&object_list, &hdr->list);	else		InsertTailList(&object_list, &hdr->list);	nt_spin_unlock_irql(&ntoskernel_lock, irql);	body = HEADER_TO_OBJECT(hdr);	TRACE3("allocated hdr: %p, body: %p", hdr, body);	return body;}void free_object(void *object){	struct common_object_header *hdr;	KIRQL irql;	hdr = OBJECT_TO_HEADER(object);	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	RemoveEntryList(&hdr->list);	nt_spin_unlock_irql(&ntoskernel_lock, irql);	TRACE3("freed hdr: %p, body: %p", hdr, object);	if (hdr->name.buf)		ExFreePool(hdr->name.buf);	ExFreePool(hdr);}static int add_bus_driver(const char *name){	struct bus_driver *bus_driver;	KIRQL irql;	bus_driver = kmalloc(sizeof(*bus_driver), GFP_KERNEL);	if (!bus_driver) {		ERROR("couldn't allocate memory");		return -ENOMEM;	}	memset(bus_driver, 0, sizeof(*bus_driver));	strncpy(bus_driver->name, name, sizeof(bus_driver->name));	bus_driver->name[sizeof(bus_driver->name)-1] = 0;	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	InsertTailList(&bus_driver_list, &bus_driver->list);	nt_spin_unlock_irql(&ntoskernel_lock, irql);	TRACE1("bus driver %s is at %p", name, &bus_driver->drv_obj);	return STATUS_SUCCESS;}struct driver_object *find_bus_driver(const char *name){	struct bus_driver *bus_driver;	struct driver_object *drv_obj;	KIRQL irql;	irql = nt_spin_lock_irql(&ntoskernel_lock, DISPATCH_LEVEL);	drv_obj = NULL;	nt_list_for_each_entry(bus_driver, &bus_driver_list, list) {		if (strcmp(bus_driver->name, name) == 0)			drv_obj = &bus_driver->drv_obj;	}	nt_spin_unlock_irql(&ntoskernel_lock, irql);	return drv_obj;}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertHeadList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	struct nt_list *first;	unsigned long flags;	ENTER5("head = %p, entry = %p", head, entry);	nt_spin_lock_irqsave(lock, flags);	first = InsertHeadList(head, entry);	nt_spin_unlock_irqrestore(lock, flags);	TRACE5("head = %p, old = %p", head, first);	return first;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertHeadList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	ENTER5("%p", head);	return ExfInterlockedInsertHeadList(head, entry, lock);}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertTailList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	struct nt_list *last;	unsigned long flags;	ENTER5("head = %p, entry = %p", head, entry);	nt_spin_lock_irqsave(lock, flags);	last = InsertTailList(head, entry);	nt_spin_unlock_irqrestore(lock, flags);	TRACE5("head = %p, old = %p", head, last);	return last;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertTailList,3)	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock){	ENTER5("%p", head);	return ExfInterlockedInsertTailList(head, entry, lock);}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveHeadList,2)	(struct nt_list *head, NT_SPIN_LOCK *lock){	struct nt_list *ret;	unsigned long flags;	ENTER5("head = %p", head);	nt_spin_lock_irqsave(lock, flags);	ret = RemoveHeadList(head);	nt_spin_unlock_irqrestore(lock, flags);	TRACE5("head = %p, ret = %p", head, ret);	return ret;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveHeadList,2)	(struct nt_list *head, NT_SPIN_LOCK *lock){	ENTER5("%p", head);	return ExfInterlockedRemoveHeadList(head, lock);}wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveTailList,2)	(struct nt_list *head, NT_SPIN_LOCK *lock){	struct nt_list *ret;	unsigned long flags;	ENTER5("head = %p", head);	nt_spin_lock_irqsave(lock, flags);	ret = RemoveTailList(head);	nt_spin_unlock_irqrestore(lock, flags);	TRACE5("head = %p, ret = %p", head, ret);	return ret;}wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveTailList,2)	(struct nt_list *head, NT_SPIN_LOCK *lock){	ENTER5("%p", head);	return ExfInterlockedRemoveTailList(head, lock);}wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPushEntrySList,3)	(nt_slist_header *head, struct nt_slist *entry, NT_SPIN_LOCK *lock){	struct nt_slist *ret;	ret = PushEntrySList(head, entry, lock);	return ret;}wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPushEntrySList,2)	(nt_slist_header *head, struct nt_slist *entry){	struct nt_slist *ret;	ret = PushEntrySList(head, entry, &ntoskernel_lock);	return ret;}wfastcall struct nt_slist *WIN_FUNC(InterlockedPushEntrySList,2)	(nt_slist_header *head, struct nt_slist *entry){	struct nt_slist *ret;	ret = PushEntrySList(head, entry, &ntoskernel_lock);	return ret;}wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPopEntrySList,2)	(nt_slist_header *head, NT_SPIN_LOCK *lock){	struct nt_slist *ret;	ret = PopEntrySList(head, lock);	return ret;}wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPopEntrySList,1)	(nt_slist_header *head){	struct nt_slist *ret;	ret = PopEntrySList(head, &ntoskernel_lock);	return ret;}wfastcall struct nt_slist *WIN_FUNC(InterlockedPopEntrySList,1)	(nt_slist_header *head){	struct nt_slist *ret;	ret = PopEntrySList(head, &ntoskernel_lock);	return ret;}wstdcall USHORT WIN_FUNC(ExQueryDepthSList,1)	(nt_slist_header *head){	USHORT depth;	ENTER5("%p", head);	depth = head->depth;	TRACE5("%d, %p", depth, head->next);	return depth;}wfastcall LONG WIN_FUNC(InterlockedIncrement,1)	(LONG volatile *val){	return post_atomic_add(*val, 1);}wfastcall LONG WIN_FUNC(InterlockedDecrement,1)	(LONG volatile *val){	return post_atomic_add(*val, -1);}wfastcall LONG WIN_FUNC(InterlockedExchange,2)	(LONG volatile *target, LONG val){	return xchg(target, val);}wfastcall LONG WIN_FUNC(InterlockedCompareExchange,3)	(LONG volatile *dest, LONG new, LONG old){	return cmpxchg(dest, old, new);}wfastcall void WIN_FUNC(ExInterlockedAddLargeStatistic,2)	(LARGE_INTEGER volatile *plint, ULONG n){	unsigned long flags;	save_local_irq(flags);#ifdef CONFIG_X86_64	__asm__ __volatile__(		"\n"		LOCK_PREFIX "add %1, %0\n\t"		: "+m" (*plint)		: "r" (n));#else	__asm__ __volatile__(		"\n"		"1:\t"		"   movl %1, %%ebx\n\t"		"   movl %%edx, %%ecx\n\t"		"   addl %%eax, %%ebx\n\t"		"   adcl $0, %%ecx\n\t"		    LOCK_PREFIX "cmpxchg8b %0\n\t"		"   jnz 1b\n\t"		: "+m" (*plint)		: "m" (n), "A" (*plint)		: "ebx", "ecx");#endif	restore_local_irq(flags);}static void initialize_object(struct dispatcher_header *dh, enum dh_type type,			      int state){	memset(dh, 0, sizeof(*dh));	set_object_type(dh, type);	dh->signal_state = state;	InitializeListHead(&dh->wait_blocks);}static void timer_proc(unsigned long data){	struct wrap_timer *wrap_timer = (struct wrap_timer *)data;	struct nt_timer *nt_timer;	struct kdpc *kdpc;	nt_timer = wrap_timer->nt_timer;	TIMERENTER("%p(%p), %lu", wrap_timer, nt_timer, jiffies);#ifdef TIMER_DEBUG	BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);	BUG_ON(nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);#endif	if (wrap_timer->repeat)		mod_timer(&wrap_timer->timer, jiffies + wrap_timer->repeat);	KeSetEvent((struct nt_event *)nt_timer, 0, FALSE);	kdpc = nt_timer->kdpc;	if (kdpc && kdpc->func) {#if 1		LIN2WIN4(kdpc->func, kdpc, kdpc->ctx, kdpc->arg1, kdpc->arg2);#else		queue_kdpc(kdpc);#endif	}	TIMEREXIT(return);}void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type,		     struct kdpc *kdpc, struct ndis_miniport_block *nmb){	struct wrap_timer *wrap_timer;	KIRQL irql;	/* TODO: if a timer is initialized more than once, we allocate	 * memory for wrap_timer more than once for the same nt_timer,	 * wasting memory. We can check if nt_timer->wrap_timer_magic is	 * set and not allocate, but it is not guaranteed always to be	 * safe */	TIMERENTER("%p", nt_timer);	/* we allocate memory for wrap_timer behind driver's back and	 * there is no NDIS/DDK function where this memory can be	 * freed, so we use slack_kmalloc so it gets freed when driver	 * is unloaded */	if (nmb)		wrap_timer = kmalloc(sizeof(*wrap_timer), gfp_irql());	else		wrap_timer = slack_kmalloc(sizeof(*wrap_timer));	if (!wrap_timer) {		ERROR("couldn't allocate memory for timer");		return;	}	memset(wrap_timer, 0, sizeof(*wrap_timer));	init_timer(&wrap_timer->timer);	wrap_timer->timer.data = (unsigned long)wrap_timer;	wrap_timer->timer.function = timer_proc;	wrap_timer->nt_timer = nt_timer;#ifdef TIMER_DEBUG	wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;#endif	nt_timer->wrap_timer = wrap_timer;	nt_timer->kdpc = kdpc;	initialize_object(&nt_timer->dh, type, 0);	nt_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;	irql = nt_spin_lock_irql(&timer_lock, DISPATCH_LEVEL);	if (nmb)		InsertTailList(&nmb->wnd->wrap_timer_list, &wrap_timer->list);	else		InsertTailList(&wrap_timer_list, &wrap_timer->list);	nt_spin_unlock_irql(&timer_lock, irql);	TIMERTRACE("timer %p (%p)", wrap_timer, nt_timer);	TIMEREXIT(return);}

⌨️ 快捷键说明

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