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

📄 loader.c

📁 改文件可以安装无线网卡在linux下的驱动,大家可以在网站上查找一下用法
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  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/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/vmalloc.h>#include <linux/kmod.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/miscdevice.h>#include <linux/pci.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/ethtool.h>#include <linux/if_arp.h>#include <net/iw_handler.h>#include <linux/rtnetlink.h>#include <asm/uaccess.h>#include "ndis.h"#include "loader.h"#include "wrapper.h"static KSPIN_LOCK loader_lock;static struct ndis_device *ndis_devices;static unsigned int num_ndis_devices;struct list_head ndis_drivers;static struct pci_device_id *ndiswrapper_pci_devices;static struct usb_device_id *ndiswrapper_usb_devices;static struct pci_driver ndiswrapper_pci_driver;static struct usb_driver ndiswrapper_usb_driver;/* load driver for given device, if not already loaded */static struct ndis_driver *ndiswrapper_load_driver(struct ndis_device *device){	int err, found;	struct ndis_driver *ndis_driver;	TRACEENTER1("device: %04X:%04X:%04X:%04X", device->vendor,		    device->device, device->subvendor, device->subdevice);	found = 0;	kspin_lock(&loader_lock);	list_for_each_entry(ndis_driver, &ndis_drivers, list) {		if (strcmp(ndis_driver->name, device->driver_name) == 0) {			DBGTRACE1("driver %s already loaded",				  ndis_driver->name);			found = 1;			break;		}	}	kspin_unlock(&loader_lock);	if (found)		TRACEEXIT1(return ndis_driver);	else {		char *argv[] = {"loadndisdriver", #if defined DEBUG && DEBUG >= 1				"1",#else				"0",#endif				NDISWRAPPER_VERSION, device->driver_name,				device->conf_file_name, NULL};		char *env[] = {NULL};		DBGTRACE1("loading driver %s", device->driver_name);		err = call_usermodehelper("/sbin/loadndisdriver", argv, env#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)					  , 1#endif			);		if (err) {			ERROR("loadndiswrapper failed (%d); check system log "			      "for messages from 'loadndisdriver'", err);			TRACEEXIT1(return NULL);		}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)		/* wait for the driver to load and initialize */		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(HZ);#endif		found = 0;		kspin_lock(&loader_lock);		list_for_each_entry(ndis_driver, &ndis_drivers, list) {			if (strcmp(ndis_driver->name,				   device->driver_name) == 0) {				found = 1;				break;			}		}		kspin_unlock(&loader_lock);		if (!found) {			ERROR("couldn't load driver '%s'",			      device->driver_name);			TRACEEXIT1(return NULL);		}		DBGTRACE1("driver %s is loaded", ndis_driver->name);	}	TRACEEXIT1(return ndis_driver);}/* * Called by PCI-subsystem for each PCI-card found. * * This function should not be marked __devinit because ndiswrapper * adds PCI_id's dynamically. */static int ndiswrapper_add_one_pci_dev(struct pci_dev *pdev,				       const struct pci_device_id *ent){	int res;	struct ndis_device *device;	struct ndis_driver *driver;	struct ndis_handle *handle;	struct net_device *dev;	struct miniport_char *miniport;	TRACEENTER1("ent: %p", ent);	DBGTRACE1("called for %04x:%04x:%04x:%04x", pdev->vendor, pdev->device,		  pdev->subsystem_vendor, pdev->subsystem_device);	device = &ndis_devices[ent->driver_data];	driver = ndiswrapper_load_driver(device);	if (!driver) {		res = -ENODEV;		goto out_nodev;	}	dev = ndis_init_netdev(&handle, device, driver);	if (!dev) {		ERROR("couldn't initialize network device");		res = -ENOMEM;		goto out_nodev;	}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)	SET_NETDEV_DEV(dev, &pdev->dev);#endif	handle->dev.pci = pdev;	handle->device = device;	pci_set_drvdata(pdev, handle);	device->handle = handle;	res = pci_enable_device(pdev);	if (res) {		ERROR("couldn't enable PCI device: %08x", res);		goto out_enable;	}	res = pci_request_regions(pdev, DRIVER_NAME);	if (res) {		ERROR("couldn't request PCI regions: %08x", res);		goto out_regions;	}	pci_set_power_state(pdev, 0);#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)	pci_restore_state(pdev, NULL);#endif	DBGTRACE1("%s", "calling ndis init routine");	if ((res = miniport_init(handle))) {		ERROR("Windows driver couldn't initialize the device (%08X)",			res);		res = -EINVAL;		goto out_start;	}	handle->hw_status = 0;	handle->wrapper_work = 0;	/* do we need to power up the card explicitly? */	miniport_set_int(handle, OID_PNP_SET_POWER, NdisDeviceStateD0);	miniport = &handle->driver->miniport_char;	/* According NDIS, pnp_event_notify should be called whenever power	 * is set to D0	 * Only NDIS 5.1 drivers are required to supply this function; some	 * drivers don't seem to support it (at least Orinoco)	 */	/*	if (miniport->pnp_event_notify) {		DBGTRACE3("%s", "calling pnp_event_notify");		miniport->pnp_event_notify(handle, NDIS_PNP_PROFILE_CHANGED,					 &profile_inf, sizeof(profile_inf));	}	*/	/* IPW2200 devices turn off radio if reset is called */	if (pdev->vendor != 0x8086)		miniport_reset(handle);	/* Wait a little to let card power up otherwise ifup might fail after	   boot */	set_current_state(TASK_INTERRUPTIBLE);	schedule_timeout(HZ/2);	if (setup_dev(handle->net_dev)) {		ERROR("couldn't setup network device");		res = -EINVAL;		goto out_setup;	}	atomic_inc(&driver->users);	TRACEEXIT1(return 0);out_setup:	miniport_halt(handle);out_start:	pci_release_regions(pdev);out_regions:	pci_disable_device(pdev);out_enable:	free_netdev(dev);out_nodev:	TRACEEXIT1(return res);}/* * Remove one PCI-card. */static void __devexit ndiswrapper_remove_one_pci_dev(struct pci_dev *pdev){	struct ndis_handle *handle;	TRACEENTER1("%p", pdev);	handle = (struct ndis_handle *)pci_get_drvdata(pdev);	TRACEENTER1("%p", handle);	if (!handle)		TRACEEXIT1(return);	atomic_dec(&handle->driver->users);	ndiswrapper_remove_one_dev(handle);	pci_release_regions(pdev);	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);}#ifdef CONFIG_USB#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)static int ndiswrapper_add_one_usb_dev(struct usb_interface *intf,				       const struct usb_device_id *usb_id)#elsestatic void *ndiswrapper_add_one_usb_dev(struct usb_device *udev,					 unsigned int ifnum,					 const struct usb_device_id *usb_id)#endif{	int res;	struct ndis_device *device;	struct ndis_driver *driver;	struct ndis_handle *handle;	struct net_device *dev;	struct miniport_char *miniport;//	unsigned long profile_inf = NDIS_POWER_PROFILE_AC;	TRACEENTER1("vendor: %04x, product: %04x",		    usb_id->idVendor, usb_id->idProduct);	device = &ndis_devices[usb_id->driver_info];	driver = ndiswrapper_load_driver(device);	if (!driver) {		res = -ENODEV;		goto out_nodev;	}	dev = ndis_init_netdev(&handle, device, driver);	if (!dev) {		ERROR("couldn't initialize network device");		res = -ENOMEM;		goto out_nodev;	}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)	SET_NETDEV_DEV(dev, &intf->dev);	handle->dev.usb = interface_to_usbdev(intf);	handle->intf    = intf;	usb_set_intfdata(intf, handle);#else	handle->dev.usb = udev;#endif	TRACEENTER1("calling ndis init routine");	if ((res = miniport_init(handle))) {		ERROR("Windows driver couldn't initialize the device (%08X)",			res);		res = -EINVAL;		goto out_start;	}	handle->hw_status = 0;	handle->wrapper_work = 0;	/* do we need to power up the card explicitly? */	miniport_set_int(handle, OID_PNP_SET_POWER, NdisDeviceStateD0);	miniport = &handle->driver->miniport_char;	/*	if (miniport->pnp_event_notify) {		DBGTRACE3("%s", "calling pnp_event_notify");		miniport->pnp_event_notify(handle->adapter_ctx,					   NDIS_PNP_PROFILE_CHANGED,					   &profile_inf, sizeof(profile_inf));		DBGTRACE3("%s", "done");	}	*/	miniport_reset(handle);	/* wait here seems crucial; without this delay, at least	 * prism54 driver crashes (why?) */	set_current_state(TASK_INTERRUPTIBLE);	schedule_timeout(3*HZ);	if (setup_dev(handle->net_dev)) {		ERROR("couldn't setup network device");		res = -EINVAL;		goto out_setup;	}	atomic_inc(&driver->users);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)	TRACEEXIT1(return 0);#else	TRACEEXIT1(return handle);#endifout_setup:	miniport_halt(handle);out_start:	free_netdev(dev);out_nodev:#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)	TRACEEXIT1(return res);#else	TRACEEXIT1(return NULL);#endif}#endif // CONFIG_USB#ifdef CONFIG_USB#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)static voidndiswrapper_remove_one_usb_dev(struct usb_interface *intf){	struct ndis_handle *handle;	TRACEENTER1("");	handle = (struct ndis_handle *)usb_get_intfdata(intf);	if (!handle)		TRACEEXIT1(return);	usb_set_intfdata(intf, NULL);	atomic_dec(&handle->driver->users);	ndiswrapper_remove_one_dev(handle);}#elsestatic voidndiswrapper_remove_one_usb_dev(struct usb_device *udev, void *ptr){	struct ndis_handle *handle = (struct ndis_handle *)ptr;	TRACEENTER1("");	if (!handle || !handle->dev.usb)		TRACEEXIT1(return);	handle->dev.usb = NULL;	atomic_dec(&handle->driver->users);	ndiswrapper_remove_one_dev(handle);}#endif#endif /* CONFIG_USB *//* load the driver files from userspace. */static int load_sys_files(struct ndis_driver *driver,			  struct load_driver *load_driver){	int i, err;	TRACEENTER1("");	DBGTRACE1("num_pe_images = %d", load_driver->nr_sys_files);	DBGTRACE1("loading driver: %s", load_driver->name);	memcpy(driver->name, load_driver->name, MAX_DRIVER_NAME_LEN);	DBGTRACE1("driver: %s", driver->name);	err = 0;	driver->num_pe_images = 0;	for (i = 0; i < load_driver->nr_sys_files; i++) {		struct pe_image *pe_image;		pe_image = &driver->pe_images[driver->num_pe_images];		pe_image->name[MAX_DRIVER_NAME_LEN-1] = 0;		memcpy(pe_image->name, load_driver->sys_files[i].name,		       MAX_DRIVER_NAME_LEN);		DBGTRACE1("image size: %lu bytes",			  (unsigned long)load_driver->sys_files[i].size);#ifdef CONFIG_X86_64#ifdef PAGE_KERNEL_EXECUTABLE		pe_image->image = __vmalloc(load_driver->sys_files[i].size,					    GFP_KERNEL | __GFP_HIGHMEM,					    PAGE_KERNEL_EXECUTABLE);#elif defined PAGE_KERNEL_EXEC		pe_image->image = __vmalloc(load_driver->sys_files[i].size,					    GFP_KERNEL | __GFP_HIGHMEM,					    PAGE_KERNEL_EXEC);#else#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC#endif#else		pe_image->image = vmalloc(load_driver->sys_files[i].size);#endif		if (!pe_image->image) {			ERROR("couldn't allocate memory");			break;		}		DBGTRACE1("image is at %p", pe_image->image);		if (copy_from_user(pe_image->image,				   load_driver->sys_files[i].data,				   load_driver->sys_files[i].size)) {			ERROR("couldn't load file %s",			      load_driver->sys_files[i].name);			break;		}		pe_image->size = load_driver->sys_files[i].size;		driver->num_pe_images++;	}	if (load_pe_images(driver->pe_images, driver->num_pe_images)) {		ERROR("unable to prepare driver '%s'", load_driver->name);		err = -EINVAL;	}	if (driver->num_pe_images < load_driver->nr_sys_files || err) {		for (i = 0; i < driver->num_pe_images; i++)			if (driver->pe_images[i].image)				vfree(driver->pe_images[i].image);		driver->num_pe_images = 0;		TRACEEXIT1(return -EINVAL);	} else {		TRACEEXIT1(return 0);	}}/* load firmware files from userspace */static int load_bin_files(struct ndis_driver *driver,			  struct load_driver *load_driver){	struct ndis_bin_file *bin_files;	int i;	TRACEENTER1("loading bin files for driver %s", load_driver->name);	bin_files = kmalloc(load_driver->nr_bin_files * sizeof(*bin_files),			    GFP_KERNEL);	if (!bin_files) {		ERROR("couldn't allocate memory");		TRACEEXIT1(return -ENOMEM);	}	memset(bin_files, 0, load_driver->nr_bin_files * sizeof(*bin_files));	driver->num_bin_files = 0;	for (i = 0; i < load_driver->nr_bin_files; i++) {		struct ndis_bin_file *bin_file = &bin_files[i];		struct load_driver_file *load_bin_file =			&load_driver->bin_files[i];		memcpy(bin_file->name, load_bin_file->name,		       MAX_DRIVER_NAME_LEN);		bin_file->size = load_bin_file->size;		bin_file->data = vmalloc(load_bin_file->size);		if (!bin_file->data) {			ERROR("cound't allocate memory");			break;		}		if (copy_from_user(bin_file->data, load_bin_file->data,				   load_bin_file->size)) {			ERROR("couldn't load file %s", load_bin_file->name);			break;		}		DBGTRACE2("loaded bin file %s", bin_file->name);		driver->num_bin_files++;	}

⌨️ 快捷键说明

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