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

📄 ndis.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 "ndis.h"#include "iw_ndis.h"#include "wrapndis.h"#include "pnp.h"#include "loader.h"#include <linux/kernel_stat.h>#define MAX_ALLOCATED_NDIS_PACKETS 20#define MAX_ALLOCATED_NDIS_BUFFERS 20static workqueue_struct_t *ndis_wq;static void ndis_worker(worker_param_t dummy);static work_struct_t ndis_work;static struct nt_list ndis_work_list;static NT_SPIN_LOCK ndis_work_list_lock;extern struct semaphore loader_mutex;wstdcall void WIN_FUNC(NdisInitializeWrapper,4)	(void **driver_handle, struct driver_object *driver,	 struct unicode_string *reg_path, void *unused){	ENTER1("handle: %p, driver: %p", driver_handle, driver);	*driver_handle = driver;	EXIT1(return);}wstdcall void WIN_FUNC(NdisTerminateWrapper,2)	(struct device_object *dev_obj, void *system_specific){	EXIT1(return);}wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterMiniport,3)	(struct driver_object *drv_obj,	 struct miniport_char *miniport_char, UINT length){	int min_length;	struct wrap_driver *wrap_driver;	struct wrap_ndis_driver *ndis_driver;	min_length = ((char *)&miniport_char->co_create_vc) -		((char *)miniport_char);	ENTER1("%p %p %d", drv_obj, miniport_char, length);	if (miniport_char->major_version < 4) {		ERROR("Driver is using ndis version %d which is too old.",		      miniport_char->major_version);		EXIT1(return NDIS_STATUS_BAD_VERSION);	}	if (length < min_length) {		ERROR("Characteristics length %d is too small", length);		EXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS);	}	TRACE1("%d.%d, %d, %u", miniport_char->major_version,	       miniport_char->minor_version, length,	       (u32)sizeof(struct miniport_char));	wrap_driver = IoGetDriverObjectExtension(drv_obj,						 (void *)WRAP_DRIVER_CLIENT_ID);	if (!wrap_driver) {		ERROR("couldn't get wrap_driver");		EXIT1(return NDIS_STATUS_RESOURCES);	}	if (IoAllocateDriverObjectExtension(		    drv_obj, (void *)NDIS_DRIVER_CLIENT_ID,		    sizeof(*ndis_driver), (void **)&ndis_driver) !=	    STATUS_SUCCESS)		EXIT1(return NDIS_STATUS_RESOURCES);	wrap_driver->ndis_driver = ndis_driver;	TRACE1("driver: %p", ndis_driver);	memcpy(&ndis_driver->miniport, miniport_char,	       length > sizeof(*miniport_char) ?	       sizeof(*miniport_char) : length);	DBG_BLOCK(2) {		int i;		void **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", "shutdown",		};		func = (void **)&ndis_driver->miniport.query;		for (i = 0; i < (sizeof(miniport_funcs) /				 sizeof(miniport_funcs[0])); i++)			TRACE2("function '%s' is at %p",			       miniport_funcs[i], func[i]);	}	EXIT1(return NDIS_STATUS_SUCCESS);}wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterDevice,6)	(struct driver_object *drv_obj, struct unicode_string *dev_name,	 struct unicode_string *link, void **funcs,	 struct device_object **dev_obj, void **dev_obj_handle){	NTSTATUS status;	struct device_object *tmp;	int i;	ENTER1("%p, %p, %p", drv_obj, dev_name, link);	status = IoCreateDevice(drv_obj, 0, dev_name, FILE_DEVICE_NETWORK, 0,				FALSE, &tmp);	if (status != STATUS_SUCCESS)		EXIT1(return NDIS_STATUS_RESOURCES);	if (link)		status = IoCreateSymbolicLink(link, dev_name);	if (status != STATUS_SUCCESS) {		IoDeleteDevice(tmp);		EXIT1(return NDIS_STATUS_RESOURCES);	}	*dev_obj = tmp;	*dev_obj_handle = *dev_obj;	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)		if (funcs[i] && i != IRP_MJ_PNP && i != IRP_MJ_POWER) {			drv_obj->major_func[i] = funcs[i];			TRACE1("mj_fn for 0x%x is at %p", i, funcs[i]);		}	EXIT1(return NDIS_STATUS_SUCCESS);}wstdcall NDIS_STATUS WIN_FUNC(NdisMDeregisterDevice,1)	(struct device_object *dev_obj){	ENTER2("%p", dev_obj);	IoDeleteDevice(dev_obj);	return NDIS_STATUS_SUCCESS;}wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemoryWithTag,3)	(void **dest, UINT length, ULONG tag){	void *addr;	addr = ExAllocatePoolWithTag(NonPagedPool, length, tag);	TRACE4("%p", addr);	if (addr) {		*dest = addr;		EXIT4(return NDIS_STATUS_SUCCESS);	} else		EXIT4(return NDIS_STATUS_FAILURE);}wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemory,4)	(void **dest, UINT length, UINT flags, NDIS_PHY_ADDRESS highest_address){	return NdisAllocateMemoryWithTag(dest, length, 0);}/* length_tag is either length or tag, depending on if * NdisAllocateMemory or NdisAllocateMemoryTag is used to allocate * memory */wstdcall void WIN_FUNC(NdisFreeMemory,3)	(void *addr, UINT length_tag, UINT flags){	TRACE4("%p", addr);	ExFreePool(addr);}noregparm void WIN_FUNC(NdisWriteErrorLogEntry,12)	(struct driver_object *drv_obj, ULONG error, ULONG count, ...){	va_list args;	int i;	ULONG code;	va_start(args, count);	ERROR("log: %08X, count: %d, return_address: %p",	      error, count, __builtin_return_address(0));	for (i = 0; i < count; i++) {		code = va_arg(args, ULONG);		ERROR("code: 0x%x", code);	}	va_end(args);	EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenConfiguration,3)	(NDIS_STATUS *status, struct ndis_miniport_block **conf_handle,	 struct ndis_miniport_block *handle){	ENTER2("%p", conf_handle);	*conf_handle = handle;	*status = NDIS_STATUS_SUCCESS;	EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenProtocolConfiguration,3)	(NDIS_STATUS *status, void **confhandle,	 struct unicode_string *section){	ENTER2("%p", confhandle);	*status = NDIS_STATUS_SUCCESS;	EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByName,4)	(NDIS_STATUS *status, void *handle,	 struct unicode_string *key, void **subkeyhandle){	struct ansi_string ansi;	ENTER2("");	if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE) == STATUS_SUCCESS) {		TRACE2("%s", ansi.buf);		RtlFreeAnsiString(&ansi);	}	*subkeyhandle = handle;	*status = NDIS_STATUS_SUCCESS;	EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByIndex,5)	(NDIS_STATUS *status, void *handle, ULONG index,	 struct unicode_string *key, void **subkeyhandle){	ENTER2("%u", index);//	*subkeyhandle = handle;	*status = NDIS_STATUS_FAILURE;	EXIT2(return);}wstdcall void WIN_FUNC(NdisCloseConfiguration,1)	(void *handle){	/* instead of freeing all configuration parameters as we are	 * supposed to do here, we free them when the device is	 * removed */	ENTER2("%p", handle);	return;}wstdcall void WIN_FUNC(NdisOpenFile,5)	(NDIS_STATUS *status, struct wrap_bin_file **file,	 UINT *filelength, struct unicode_string *filename,	 NDIS_PHY_ADDRESS highest_address){	struct ansi_string ansi;	struct wrap_bin_file *bin_file;	ENTER2("%p, %d, %llx, %p", status, *filelength, highest_address, *file);	if (RtlUnicodeStringToAnsiString(&ansi, filename, TRUE) !=	    STATUS_SUCCESS) {		*status = NDIS_STATUS_RESOURCES;		EXIT2(return);	}	TRACE2("%s", ansi.buf);	bin_file = get_bin_file(ansi.buf);	if (bin_file) {		*file = bin_file;		*filelength = bin_file->size;		*status = NDIS_STATUS_SUCCESS;	} else		*status = NDIS_STATUS_FILE_NOT_FOUND;	RtlFreeAnsiString(&ansi);	EXIT2(return);}wstdcall void WIN_FUNC(NdisMapFile,3)	(NDIS_STATUS *status, void **mappedbuffer, struct wrap_bin_file *file){	ENTER2("%p", file);	if (!file) {		*status = NDIS_STATUS_ALREADY_MAPPED;		EXIT2(return);	}	*status = NDIS_STATUS_SUCCESS;	*mappedbuffer = file->data;	EXIT2(return);}wstdcall void WIN_FUNC(NdisUnmapFile,1)	(struct wrap_bin_file *file){	ENTER2("%p", file);	EXIT2(return);}wstdcall void WIN_FUNC(NdisCloseFile,1)	(struct wrap_bin_file *file){	ENTER2("%p", file);	free_bin_file(file);	EXIT2(return);}wstdcall void WIN_FUNC(NdisGetSystemUpTime,1)	(ULONG *ms){	*ms = 1000 * jiffies / HZ;	EXIT5(return);}wstdcall ULONG WIN_FUNC(NDIS_BUFFER_TO_SPAN_PAGES,1)	(ndis_buffer *buffer){	ULONG n, length;	if (buffer == NULL)		EXIT2(return 0);	if (MmGetMdlByteCount(buffer) == 0)		EXIT2(return 1);	length = MmGetMdlByteCount(buffer);	n = SPAN_PAGES(MmGetMdlVirtualAddress(buffer), length);	TRACE4("%p, %p, %d, %d", buffer->startva, buffer->mappedsystemva,	       length, n);	EXIT3(return n);}wstdcall void WIN_FUNC(NdisGetBufferPhysicalArraySize,2)	(ndis_buffer *buffer, UINT *arraysize){	ENTER3("%p", buffer);	*arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer);	EXIT3(return);}static struct ndis_configuration_parameter *ndis_encode_setting(struct wrap_device_setting *setting,		    enum ndis_parameter_type type){	struct ansi_string ansi;	struct ndis_configuration_parameter *param;	param = setting->encoded;	if (param) {		if (param->type == type)			EXIT2(return param);		if (param->type == NdisParameterString)			RtlFreeUnicodeString(&param->data.string);		setting->encoded = NULL;	} else		param = ExAllocatePoolWithTag(NonPagedPool, sizeof(*param), 0);	if (!param) {		ERROR("couldn't allocate memory");		return NULL;	}	switch(type) {	case NdisParameterInteger:		param->data.integer = simple_strtol(setting->value, NULL, 0);		TRACE2("%u", (ULONG)param->data.integer);		break;	case NdisParameterHexInteger:		param->data.integer = simple_strtol(setting->value, NULL, 16);		TRACE2("%u", (ULONG)param->data.integer);		break;	case NdisParameterString:		RtlInitAnsiString(&ansi, setting->value);		TRACE2("'%s'", ansi.buf);		if (RtlAnsiStringToUnicodeString(&param->data.string,						 &ansi, TRUE)) {			ExFreePool(param);			EXIT2(return NULL);		}		break;	default:		ERROR("unknown type: %d", type);		ExFreePool(param);		return NULL;	}	param->type = type;	setting->encoded = param;	EXIT2(return param);}static int ndis_decode_setting(struct wrap_device_setting *setting,			       struct ndis_configuration_parameter *param){	struct ansi_string ansi;	struct ndis_configuration_parameter *prev;	ENTER2("%p, %p", setting, param);	prev = setting->encoded;	if (prev && prev->type == NdisParameterString) {		RtlFreeUnicodeString(&prev->data.string);		setting->encoded = NULL;	}	switch(param->type) {	case NdisParameterInteger:		snprintf(setting->value, sizeof(u32), "%u", param->data.integer);		setting->value[sizeof(ULONG)] = 0;		break;	case NdisParameterHexInteger:		snprintf(setting->value, sizeof(u32), "%x", param->data.integer);		setting->value[sizeof(ULONG)] = 0;		break;	case NdisParameterString:		ansi.buf = setting->value;		ansi.max_length = MAX_SETTING_VALUE_LEN;		if ((RtlUnicodeStringToAnsiString(&ansi, &param->data.string,						  FALSE) != STATUS_SUCCESS)		    || ansi.length >= MAX_SETTING_VALUE_LEN) {			EXIT1(return -1);		}		if (ansi.length == ansi.max_length)			ansi.length--;		setting->value[ansi.length] = 0;		break;	default:		TRACE2("unknown setting type: %d", param->type);		return -1;	}	TRACE2("setting changed %s='%s', %d", setting->name, setting->value,	       ansi.length);	return 0;}static int read_setting(struct nt_list *setting_list, char *keyname, int length,			struct ndis_configuration_parameter **param,			enum ndis_parameter_type type){	struct wrap_device_setting *setting;	if (down_interruptible(&loader_mutex))		WARNING("couldn't obtain loader_mutex");	nt_list_for_each_entry(setting, setting_list, list) {		if (strnicmp(keyname, setting->name, length) == 0) {			TRACE2("setting %s='%s'", keyname, setting->value);			up(&loader_mutex);			*param = ndis_encode_setting(setting, type);			if (*param)				EXIT2(return 0);			else				EXIT2(return -1);		}	}	up(&loader_mutex);	EXIT2(return -1);}wstdcall void WIN_FUNC(NdisReadConfiguration,5)	(NDIS_STATUS *status, struct ndis_configuration_parameter **param,	 struct ndis_miniport_block *nmb, struct unicode_string *key,	 enum ndis_parameter_type type){	struct ansi_string ansi;	char *keyname;	int ret;	ENTER2("nmb: %p", nmb);	ret = RtlUnicodeStringToAnsiString(&ansi, key, TRUE);	if (ret != STATUS_SUCCESS || ansi.buf == NULL) {

⌨️ 快捷键说明

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