misc_funcs.c

来自「改文件可以安装无线网卡在linux下的驱动,大家可以在网站上查找一下用法」· C语言 代码 · 共 934 行 · 第 1/2 页

C
934
字号
/* *  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 <linux/types.h>#include <linux/module.h>#include <linux/delay.h>#include <asm/io.h>#include <linux/ctype.h>#include <linux/net.h>#include <linux/list.h>#include "ndis.h"static struct list_head wrap_allocs;static KSPIN_LOCK wrap_allocs_lock;int misc_funcs_init(void){	INIT_LIST_HEAD(&wrap_allocs);	kspin_lock_init(&wrap_allocs_lock);	return 0;}/* called when a handle is being removed */void misc_funcs_exit_handle(struct ndis_handle *handle){	char canceled;	KIRQL irql;	/* cancel any timers left by bugyy windows driver	 * Also free the memory for timers	 */	while (1) {		struct wrapper_timer *timer;		irql = kspin_lock_irql(&handle->timers_lock, DISPATCH_LEVEL);		if (list_empty(&handle->timers)) {			kspin_unlock_irql(&handle->timers_lock, irql);			break;		}		timer = list_entry(handle->timers.next,				   struct wrapper_timer, list);		list_del(&timer->list);		kspin_unlock_irql(&handle->timers_lock, irql);		DBGTRACE1("fixing up timer %p, timer->list %p",			  timer, &timer->list);		wrapper_cancel_timer(timer, &canceled);		wrap_kfree(timer);	}}/* called when module is being removed */void misc_funcs_exit(void){	/* free all pointers on the allocated list */	kspin_lock(&wrap_allocs_lock);	while (!list_empty(&wrap_allocs)) {		struct wrap_alloc *alloc;		alloc = list_entry(wrap_allocs.next, struct wrap_alloc, list);		list_del(&alloc->list);		kfree(alloc->ptr);		kfree(alloc);	}	kspin_unlock(&wrap_allocs_lock);	TRACEEXIT4(return);}/* allocate memory with given flags and add it to list of allocated pointers; * if a driver doesn't free this memory for any reason (buggy driver or we * allocate space behind driver's back since we need more space than * corresponding Windows structure provides etc.), this gets freed * automatically during module unloading */void *wrap_kmalloc(size_t size, int flags){	struct wrap_alloc *alloc;	TRACEENTER4("size = %lu, flags = %d", (unsigned long)size, flags);	if ((flags & GFP_ATOMIC) || irqs_disabled())		alloc = kmalloc(sizeof(*alloc), GFP_ATOMIC);	else		alloc = kmalloc(sizeof(*alloc), GFP_KERNEL);	if (!alloc)		return NULL;	alloc->ptr = kmalloc(size, flags);	if (!alloc->ptr) {		kfree(alloc);		return NULL;	}	kspin_lock(&wrap_allocs_lock);	list_add(&alloc->list, &wrap_allocs);	kspin_unlock(&wrap_allocs_lock);	DBGTRACE4("%p, %p", alloc, alloc->ptr);	TRACEEXIT4(return alloc->ptr);}/* free pointer and remove from list of allocated pointers */void wrap_kfree(void *ptr){	struct list_head *cur, *tmp;	TRACEENTER4("%p", ptr);	kspin_lock(&wrap_allocs_lock);	list_for_each_safe(cur, tmp, &wrap_allocs) {		struct wrap_alloc *alloc;		alloc = list_entry(cur, struct wrap_alloc, list);		if (alloc->ptr == ptr) {			list_del(&alloc->list);			kfree(alloc->ptr);			kfree(alloc);			break;		}	}	kspin_unlock(&wrap_allocs_lock);	TRACEEXIT4(return);}void wrapper_timer_handler(unsigned long data){	struct wrapper_timer *timer = (struct wrapper_timer *)data;	struct kdpc *kdpc;	STDCALL void (*miniport_timer)(void *specific1, void *ctx,				       void *specific2, void *specific3);	KIRQL irql;	TRACEENTER5("%p", timer);#ifdef DEBUG_TIMER	BUG_ON(timer == NULL);	BUG_ON(timer->wrapper_timer_magic != WRAPPER_TIMER_MAGIC);	BUG_ON(timer->kdpc == NULL);#endif	/* don't add the timer if aperiodic; see wrapper_cancel_timer	 * protect access to kdpc, repeat, and active via spinlock */	irql = kspin_lock_irql(&timer->lock, DISPATCH_LEVEL);	kdpc = timer->kdpc;	if (timer->repeat) {		timer->timer.expires = jiffies + timer->repeat;		add_timer(&timer->timer);	} else		timer->active = 0;	kspin_unlock_irql(&timer->lock, irql);	miniport_timer = kdpc->func;	/* call the handler after restarting in case it cancels itself */	if (miniport_timer) {		KIRQL irql;		irql = raise_irql(DISPATCH_LEVEL);		LIN2WIN4(miniport_timer, kdpc, kdpc->ctx, kdpc->arg1,			 kdpc->arg2);		lower_irql(irql);	}	TRACEEXIT5(return);}void wrapper_init_timer(struct ktimer *ktimer, void *handle){	struct wrapper_timer *wrapper_timer;	struct ndis_handle *ndis_handle = (struct ndis_handle *)handle;	TRACEENTER5("%s", "");	wrapper_timer = wrap_kmalloc(sizeof(struct wrapper_timer), GFP_ATOMIC);	if (!wrapper_timer) {		ERROR("couldn't allocate memory for timer");		return;	}	memset(wrapper_timer, 27, sizeof(*wrapper_timer));	init_timer(&wrapper_timer->timer);	wrapper_timer->timer.data = (unsigned long)wrapper_timer;	wrapper_timer->timer.function = &wrapper_timer_handler;	wrapper_timer->active = 0;	wrapper_timer->repeat = 0;	wrapper_timer->kdpc = NULL;#ifdef DEBUG_TIMER	wrapper_timer->wrapper_timer_magic = WRAPPER_TIMER_MAGIC;#endif	ktimer->wrapper_timer = wrapper_timer;	kspin_lock_init(&wrapper_timer->lock);	if (handle) {		kspin_lock(&ndis_handle->timers_lock);		list_add(&wrapper_timer->list, &ndis_handle->timers);		kspin_unlock(&ndis_handle->timers_lock);	}	DBGTRACE4("added timer %p, wrapper_timer->list %p\n",		  wrapper_timer, &wrapper_timer->list);	TRACEEXIT5(return);}int wrapper_set_timer(struct wrapper_timer *timer, unsigned long expires,		      unsigned long repeat, struct kdpc *kdpc){	KIRQL irql;	TRACEENTER5("%p", timer);	if (!timer) {		ERROR("invalid timer");		return FALSE;	}#ifdef DEBUG_TIMER	if (timer->wrapper_timer_magic != WRAPPER_TIMER_MAGIC) {		WARNING("timer %p is not initialized (%lu)",			timer, timer->wrapper_timer_magic);		timer->wrapper_timer_magic = WRAPPER_TIMER_MAGIC;	}#endif	/* timer handler also uses timer->repeat, active, and kdpc, so	 * protect in case of SMP */	irql = kspin_lock_irql(&timer->lock, DISPATCH_LEVEL);	if (kdpc)		timer->kdpc = kdpc;	timer->repeat = repeat;	if (timer->active) {		DBGTRACE4("modifying timer %p to %lu, %lu",			  timer, expires, repeat);		mod_timer(&timer->timer, expires);		kspin_unlock_irql(&timer->lock, irql);		TRACEEXIT5(return TRUE);	} else {		DBGTRACE4("setting timer %p to %lu, %lu",			  timer, expires, repeat);		timer->timer.expires = expires;		timer->active = 1;		add_timer(&timer->timer);		kspin_unlock_irql(&timer->lock, irql);		TRACEEXIT5(return FALSE);	}}void wrapper_cancel_timer(struct wrapper_timer *timer, char *canceled){	KIRQL irql;	TRACEENTER4("timer = %p, canceled = %p", timer, canceled);	if (!timer) {		ERROR("%s", "invalid timer");		return;	}#ifdef DEBUG_TIMER	DBGTRACE4("canceling timer %p", timer);	BUG_ON(timer->wrapper_timer_magic != WRAPPER_TIMER_MAGIC);#endif	/* timer handler also uses timer->repeat, so protect it in	 * case of SMP */	/* Oh, and del_timer_sync is not required ('canceled' argument	 * tells the driver if the timer was deleted or not) here; nor	 * is del_timer_sync correct, as this function may be called	 * at DISPATCH_LEVEL */	irql = kspin_lock_irql(&timer->lock, DISPATCH_LEVEL);	if (timer->repeat) {		/* first mark as aperiodic, so timer function doesn't call		 * add_timer after del_timer returned */		timer->repeat = 0;		del_timer(&timer->timer);		/* periodic timers always return TRUE */		*canceled = TRUE;	} else		*canceled = del_timer(&timer->timer);	kspin_unlock_irql(&timer->lock, irql);	TRACEEXIT5(return);}NOREGPARM INT WRAP_EXPORT(_win_sprintf)	(char *buf, const char *format, ...){	va_list args;	int res;	va_start(args, format);	res = vsprintf(buf, format, args);	va_end(args);	return res;}NOREGPARM INT WRAP_EXPORT(_win_vsprintf)	(char *str, const char *format, va_list ap){	return vsprintf(str, format, ap);}NOREGPARM INT WRAP_EXPORT(_win_snprintf)	(char *buf, SIZE_T count, const char *format, ...){	va_list args;	int res;	va_start(args, format);	res = vsnprintf(buf, count, format, args);	va_end(args);	return res;}NOREGPARM INT WRAP_EXPORT(_win__snprintf)	(char *buf, SIZE_T count, const char *format, ...){	va_list args;	int res;	va_start(args, format);	res = vsnprintf(buf, count, format, args);	va_end(args);	return res;}NOREGPARM INT WRAP_EXPORT(_win_vsnprintf)	(char *str, SIZE_T size, const char *format, va_list ap){	return vsnprintf(str, size, format, ap);}NOREGPARM INT WRAP_EXPORT(_win__vsnprintf)	(char *str, SIZE_T size, const char *format, va_list ap){	return vsnprintf(str, size, format, ap);}NOREGPARM char *WRAP_EXPORT(_win_strncpy)	(char *dst, char *src, SIZE_T n){	return strncpy(dst, src, n);}NOREGPARM SIZE_T WRAP_EXPORT(_win_strlen)	(const char *s){       return strlen(s);}NOREGPARM INT WRAP_EXPORT(_win_strncmp)	(const char *s1, const char *s2, SIZE_T n){	return strncmp(s1, s2, n);}NOREGPARM INT WRAP_EXPORT(_win_strcmp)	(const char *s1, const char *s2){	return strcmp(s1, s2);}int stricmp(const char *s1, const char *s2){	while (*s1 && *s2 && tolower(*s1) == tolower(*s2)) {		s1++;		s2++;	}	return (int)*s1 - (int)*s2;}NOREGPARM INT WRAP_EXPORT(_win_tolower)	(INT c){	return tolower(c);}NOREGPARM INT WRAP_EXPORT(_win_toupper)	(INT c){	return toupper(c);}NOREGPARM void *WRAP_EXPORT(_win_memcpy)	(void *to, const void *from, SIZE_T n){	return memcpy(to, from, n);}NOREGPARM void *WRAP_EXPORT(_win_strcpy)	(void *to, const void *from){	return strcpy(to, from);}NOREGPARM char *WRAP_EXPORT(_win_strstr)	(const char *s1, const char *s2){	return strstr(s1, s2);}NOREGPARM char *WRAP_EXPORT(_win_strchr)	(const char *s, int c){	return strchr(s, c);}NOREGPARM void *WRAP_EXPORT(_win_memset)	(void *s, char c, SIZE_T count){	return memset(s, c, count);}NOREGPARM void *WRAP_EXPORT(_win_memmove)	(void *to, void *from, SIZE_T count){	return memmove(to, from, count);}NOREGPARM void *WRAP_EXPORT(_win_memchr)	(const void *s, INT c, SIZE_T n){	return memchr(s, c, n);}NOREGPARM void WRAP_EXPORT(_win_srand)	(UINT seed){	net_srandom(seed);}NOREGPARM int WRAP_EXPORT(_win_atoi)	(const char *ptr){	int i = simple_strtol(ptr, NULL, 10);	return i;}STDCALL s64 WRAP_EXPORT(_alldiv)	(s64 a, s64 b){	return (a / b);}STDCALL u64 WRAP_EXPORT(_aulldiv)	(u64 a, u64 b){	return (a / b);}STDCALL s64 WRAP_EXPORT(_allmul)	(s64 a, s64 b){	return (a * b);}STDCALL u64 WRAP_EXPORT(_aullmul)	(u64 a, u64 b){	return (a * b);}STDCALL s64 WRAP_EXPORT(_allrem)	(s64 a, s64 b){

⌨️ 快捷键说明

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