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

📄 ndis.c

📁 改文件可以安装无线网卡在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 <linux/module.h>#include <linux/pci.h>#include <linux/spinlock.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/types.h>#include <linux/string.h>#include <linux/ctype.h>#include "ndis.h"#include "iw_ndis.h"#include "wrapper.h"extern struct list_head ndis_drivers;extern KSPIN_LOCK ntoskernel_lock;static struct list_head handle_ctx_list;static struct work_struct ndis_work;static struct list_head ndis_work_list;static KSPIN_LOCK ndis_work_list_lock;static void ndis_worker(void *data);static void free_handle_ctx(struct ndis_handle *handle);/* Some drivers allocate all NDIS_PACKETs they need at the beginning * and others allocate them quite often - every time a packet is * sent/received. We use cache pool for this to avoid memory * fragmentation, just like MDLs */static kmem_cache_t *packet_cache;/* ndis_init is called once when module is loaded */int ndis_init(void){	/* only one worker is used for all drivers */	INIT_WORK(&ndis_work, &ndis_worker, NULL);	INIT_LIST_HEAD(&ndis_work_list);	INIT_LIST_HEAD(&handle_ctx_list);	kspin_lock_init(&ndis_work_list_lock);	packet_cache = kmem_cache_create("ndis_packet",					 sizeof(struct ndis_packet), 0, 0,					 NULL, NULL);	if (!packet_cache) {		ERROR("couldn't allocate packet cache");		return -ENOMEM;	}	return 0;}/* ndis_exit is called once when module is removed */void ndis_exit(void){	if (packet_cache && kmem_cache_destroy(packet_cache))		ERROR("A Windows driver didn't free all packet(s);"		      "memory is leaking");	return;}/* ndis_exit_handle is called for each handle */void ndis_exit_handle(struct ndis_handle *handle){	/* TI driver doesn't call NdisMDeregisterInterrupt during halt! */	if (handle->ndis_irq)		NdisMDeregisterInterrupt(handle->ndis_irq);	free_handle_ctx(handle);	if (handle->pci_resources)		vfree(handle->pci_resources);}/* remove all 'handle X ctx' pairs for the given handle */static void free_handle_ctx(struct ndis_handle *handle){	struct list_head *cur, *tmp;	kspin_lock(&ntoskernel_lock);	list_for_each_safe(cur, tmp, &handle_ctx_list) {		struct handle_ctx_entry *handle_ctx =			list_entry(cur, struct handle_ctx_entry, list);		if (handle_ctx->handle == handle) {			list_del(&handle_ctx->list);			kfree(handle_ctx);		}	}	kspin_unlock(&ntoskernel_lock);	return;}/* Called from the driver entry. */STDCALL void WRAP_EXPORT(NdisInitializeWrapper)	(struct ndis_handle **ndis_handle, void *SystemSpecific1,	 void *SystemSpecific2, void *SystemSpecific3){	TRACEENTER1("handle=%p, SS1=%p, SS2=%p", ndis_handle,		    SystemSpecific1, SystemSpecific2);	*ndis_handle = (struct ndis_handle *)SystemSpecific1;	TRACEEXIT1(return);}STDCALL void WRAP_EXPORT(NdisTerminateWrapper)	(struct ndis_handle *handle, void *SystemSpecific1){	TRACEEXIT1(return);}/* Register a miniport with NDIS. Called from driver entry */STDCALL NDIS_STATUS WRAP_EXPORT(NdisMRegisterMiniport)	(struct ndis_driver *ndis_driver,	 struct miniport_char *miniport_char, UINT char_len){	int i, min_length;	int *func;	char *miniport_funcs[] = {		"query",		"reconfig",		"reset",		"send",		"setinfo",		"tx_data",		"return_packet",		"send_packets",		"alloc_complete",		"co_create_vc",		"co_delete_vc",		"co_activate_vc",		"co_deactivate_vc",		"co_send_packets",		"co_request",		"cancel_send_packets",		"pnp_event_notify",		"adapter_shutdown",	};	min_length = ((char *) &miniport_char->co_create_vc) -		((char *) miniport_char);	TRACEENTER1("driver: %p %p %d", ndis_driver, miniport_char, char_len);	if (miniport_char->majorVersion < 4) {		ERROR("Driver %s using ndis version %d which is too old.",		      ndis_driver->name, miniport_char->majorVersion);		TRACEEXIT1(return NDIS_STATUS_BAD_VERSION);	}	if (char_len < min_length) {		ERROR("Characteristics length %d is too small for driver %s",		      char_len, ndis_driver->name);		TRACEEXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS);	}	DBGTRACE1("Version %d.%d", miniport_char->majorVersion,		  miniport_char->minorVersion);	DBGTRACE1("Len: %08x:%u", char_len, (u32)sizeof(struct miniport_char));	memcpy(&ndis_driver->miniport_char, miniport_char,	       sizeof(struct miniport_char));	i = 0;	func = (int *)&ndis_driver->miniport_char.query;	while (i < sizeof(miniport_funcs) / sizeof(miniport_funcs[0])) {		DBGTRACE2("miniport function '%s' is at %lx",			  miniport_funcs[i], (unsigned long)func[i]);		i++;	}	TRACEEXIT1(return NDIS_STATUS_SUCCESS);}STDCALL NDIS_STATUS WRAP_EXPORT(NdisAllocateMemory)	(void **dest, UINT length, UINT flags,	 NDIS_PHY_ADDRESS highest_address){	TRACEENTER3("length = %u, flags = %08X", length, flags);	if (length <= KMALLOC_THRESHOLD) {		if (current_irql() < DISPATCH_LEVEL)			*dest = kmalloc(length, GFP_KERNEL);		else			*dest = kmalloc(length, GFP_ATOMIC);	} else if (flags & NDIS_MEMORY_CONTIGUOUS) {		WARNING("Allocating %u bytes of physically "		       "contiguous memory may fail", length);		*dest = kmalloc(length, GFP_KERNEL);	} else {		if (current_irql() == DISPATCH_LEVEL)			ERROR("Windows driver allocating too big a block"			      " at DISPATCH_LEVEL: %d", length);		*dest = vmalloc(length);	}	if (*dest)		TRACEEXIT3(return NDIS_STATUS_SUCCESS);	DBGTRACE3("Allocatemem failed size=%d", length);	TRACEEXIT3(return NDIS_STATUS_FAILURE);}STDCALL NDIS_STATUS WRAP_EXPORT(NdisAllocateMemoryWithTag)	(void **dest, UINT length, ULONG tag){	TRACEEXIT3(return NdisAllocateMemory(dest, length, 0, 0));}STDCALL void WRAP_EXPORT(NdisFreeMemory)	(void *addr, UINT length, UINT flags){	struct ndis_work_entry *ndis_work_entry;	struct ndis_free_mem_work_item *free_mem;	KIRQL irql;	TRACEENTER3("addr = %p, flags = %08X", addr, flags);	if (!addr)		TRACEEXIT3(return);	if (length <= KMALLOC_THRESHOLD)		kfree(addr);	else if (flags & NDIS_MEMORY_CONTIGUOUS)		kfree(addr);	else {		if (!in_interrupt()) {			vfree(addr);			TRACEEXIT3(return);		}		/* Centrino 2200 driver calls this function when in		 * ad-hoc mode in interrupt context when length >		 * KMALLOC_THRESHOLD, which implies that vfree is		 * called in interrupt context, which is not		 * correct. So we use worker for it */		ndis_work_entry = kmalloc(sizeof(*ndis_work_entry),					  GFP_ATOMIC);		BUG_ON(!ndis_work_entry);		ndis_work_entry->type = NDIS_FREE_MEM_WORK_ITEM;		free_mem = &ndis_work_entry->entry.free_mem_work_item;		free_mem->addr = addr;		free_mem->length = length;		free_mem->flags = flags;		irql = kspin_lock_irql(&ndis_work_list_lock, DISPATCH_LEVEL);		list_add_tail(&ndis_work_entry->list, &ndis_work_list);		kspin_unlock_irql(&ndis_work_list_lock, irql);		schedule_work(&ndis_work);	}	TRACEEXIT3(return);}/* * This function should not be STDCALL because it's a variable args function. */NOREGPARM void WRAP_EXPORT(NdisWriteErrorLogEntry)	(struct ndis_handle *handle, unsigned int error, ULONG count,	 unsigned int p1){	ERROR("log: %08X, count: %d (%08x), return address: %p, entry: %p"	      " offset: %lu", error, count, p1, __builtin_return_address(0),	      handle->driver->entry,	      (unsigned long)addr_offset(handle->driver));	return;}STDCALL void WRAP_EXPORT(NdisOpenConfiguration)	(NDIS_STATUS *status, struct ndis_handle **confhandle,	 struct ndis_handle *handle){	TRACEENTER2("confHandle: %p, handle->dev_name: %s",			confhandle, handle->net_dev->name);	*confhandle = handle;	*status = NDIS_STATUS_SUCCESS;	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisOpenProtocolConfiguration)	(NDIS_STATUS *status, struct ndis_handle **confhandle,	 struct unicode_string *section){	TRACEENTER2("confHandle: %p", confhandle);	*confhandle = (struct ndis_handle *)section;	*status = NDIS_STATUS_SUCCESS;	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisOpenConfigurationKeyByName)	(NDIS_STATUS *status, struct ndis_handle *handle,	 struct unicode_string *key, struct ndis_handle **subkeyhandle){	TRACEENTER2("%s", "");	*subkeyhandle = handle;	*status = NDIS_STATUS_SUCCESS;	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisOpenConfigurationKeyByIndex)	(NDIS_STATUS *status, struct ndis_handle *handle, ULONG index,	 struct unicode_string *key, struct ndis_handle **subkeyhandle){	TRACEENTER2("%s", "");	*subkeyhandle = handle;	*status = NDIS_STATUS_SUCCESS;	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisCloseConfiguration)	(struct ndis_handle *handle){	TRACEENTER2("handle: %p", handle);	return;}STDCALL void WRAP_EXPORT(NdisOpenFile)	(NDIS_STATUS *status, struct ndis_bin_file **filehandle,	 UINT *filelength, struct unicode_string *filename,	 NDIS_PHY_ADDRESS highest_address){	struct ansi_string ansi;	struct list_head *cur, *tmp;	struct ndis_bin_file *file;	TRACEENTER2("status = %p, filelength = %p, *filelength = %d, "		    "high = %llx, filehandle = %p, *filehandle = %p",		    status, filelength, *filelength,		    highest_address, filehandle, *filehandle);	ansi.buf = kmalloc(MAX_STR_LEN, GFP_KERNEL);	if (!ansi.buf) {		*status = NDIS_STATUS_RESOURCES;		return;	}	ansi.buf[MAX_STR_LEN-1] = 0;	ansi.buflen = MAX_STR_LEN;	if (RtlUnicodeStringToAnsiString(&ansi, filename, 0)) {		*status = NDIS_STATUS_RESOURCES;		RtlFreeAnsiString(&ansi);		TRACEEXIT2(return);	}	DBGTRACE2("Filename: %s", ansi.buf);	/* Loop through all drivers and all files to find the requested file */	list_for_each_safe(cur, tmp, &ndis_drivers) {		struct ndis_driver *driver;		int i;		driver = list_entry(cur, struct ndis_driver, list);		for (i = 0; i < driver->num_bin_files; i++) {			int n;			file = &driver->bin_files[i];			DBGTRACE2("considering %s", file->name);			n = min(strlen(file->name), strlen(ansi.buf));			if (strnicmp(file->name, ansi.buf, n) == 0) {				*filehandle = file;				*filelength = file->size;				*status = NDIS_STATUS_SUCCESS;				RtlFreeAnsiString(&ansi);				TRACEEXIT2(return);			}		}	}	*status = NDIS_STATUS_FILE_NOT_FOUND;	RtlFreeAnsiString(&ansi);	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisMapFile)	(NDIS_STATUS *status, void **mappedbuffer,	 struct ndis_bin_file *filehandle){	TRACEENTER2("handle: %p", filehandle);	if (!filehandle) {		*status = NDIS_STATUS_ALREADY_MAPPED;		TRACEEXIT2(return);	}	*status = NDIS_STATUS_SUCCESS;	*mappedbuffer = filehandle->data;	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisUnmapFile)	(struct ndis_bin_file *filehandle){	TRACEENTER2("handle: %p", filehandle);	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisCloseFile)	(struct ndis_bin_file *filehandle){	TRACEENTER2("handle: %p", filehandle);	TRACEEXIT2(return);}STDCALL void WRAP_EXPORT(NdisGetSystemUpTime)	(ULONG *systemuptime){	TRACEENTER4("%s", "");	*systemuptime = 10 * jiffies / HZ;	TRACEEXIT4(return);}/* called as macro */STDCALL ULONG WRAP_EXPORT(NDIS_BUFFER_TO_SPAN_PAGES)	(ndis_buffer *buffer){	ULONG_PTR start;	ULONG n;	TRACEENTER4("%s", "");	if (buffer == NULL)		return 0;	if (MmGetMdlByteCount(buffer) == 0)		return 1;	start = (ULONG_PTR)(MmGetMdlVirtualAddress(buffer));	n = SPAN_PAGES(start, MmGetMdlByteCount(buffer));	DBGTRACE4("pages = %u", n);	TRACEEXIT3(return n);}STDCALL void WRAP_EXPORT(NdisGetBufferPhysicalArraySize)	(ndis_buffer *buffer, UINT *arraysize){	TRACEENTER3("Buffer: %p", buffer);	*arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer);	TRACEEXIT3(return);}static int ndis_encode_setting(struct device_setting *setting,			       int device_setting_type){	struct ansi_string ansi;	struct ndis_config_param *param;	TRACEENTER2("type = %d", device_setting_type);	if (setting->config_param.type == device_setting_type)		return NDIS_STATUS_SUCCESS;	switch(device_setting_type) {	case NDIS_CONFIG_PARAM_INT:		setting->config_param.data.intval =			simple_strtol(setting->value, NULL, 0);		DBGTRACE1("value = %u",			  (ULONG)setting->config_param.data.intval);		break;	case NDIS_CONFIG_PARAM_HEXINT:		setting->config_param.data.intval =			simple_strtol(setting->value, NULL, 16);		DBGTRACE2("value = %u",			  (ULONG)setting->config_param.data.intval);		break;	case NDIS_CONFIG_PARAM_STRING:		ansi.buflen = ansi.len = strlen(setting->value);		ansi.buf = setting->value;		DBGTRACE2("setting value = %s", ansi.buf);		param = &setting->config_param;		if (param->data.ustring.buf)			RtlFreeUnicodeString(&param->data.ustring);		if (RtlAnsiStringToUnicodeString(&param->data.ustring,						 &ansi, 1))			TRACEEXIT1(return NDIS_STATUS_FAILURE);		break;	default:		return NDIS_STATUS_FAILURE;	}	setting->config_param.type = device_setting_type;	return NDIS_STATUS_SUCCESS;}static int ndis_decode_setting(struct device_setting *setting,			       struct ndis_config_param *val){	struct ansi_string ansi;	if (setting->config_param.type == NDIS_CONFIG_PARAM_STRING &&

⌨️ 快捷键说明

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