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

📄 pnp.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2005 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 "usb.h"#include "pnp.h"#include "wrapndis.h"#include "loader.h"extern struct semaphore loader_mutex;static NTSTATUS start_pdo(struct device_object *pdo){	int i, ret, count, resources_size;	struct wrap_device *wd;	struct pci_dev *pdev;	struct cm_partial_resource_descriptor *entry;	struct cm_partial_resource_list *partial_resource_list;	ENTER1("%p, %p", pdo, pdo->reserved);	wd = pdo->reserved;	if (ntoskernel_init_device(wd))		EXIT1(return STATUS_FAILURE);	if (wrap_is_usb_bus(wd->dev_bus)) {#ifdef CONFIG_USB		if (usb_init_device(wd)) {			ntoskernel_exit_device(wd);			EXIT1(return STATUS_FAILURE);		}#endif		EXIT1(return STATUS_SUCCESS);	}	if (!wrap_is_pci_bus(wd->dev_bus))		EXIT1(return STATUS_SUCCESS);	pdev = wd->pci.pdev;	ret = pci_enable_device(pdev);	if (ret) {		ERROR("couldn't enable PCI device: %x", ret);		return STATUS_FAILURE;	}	ret = pci_request_regions(pdev, DRIVER_NAME);	if (ret) {		ERROR("couldn't request PCI regions: %x", ret);		goto err_enable;	}	pci_set_power_state(pdev, PCI_D0);#ifdef CONFIG_X86_64	/* 64-bit broadcom driver doesn't work if DMA is allocated	 * from over 1GB */	if (wd->vendor == 0x14e4) {		if (pci_set_dma_mask(pdev, 0x3fffffff) ||		    pci_set_consistent_dma_mask(pdev, 0x3fffffff))			WARNING("couldn't set DMA mask; this driver "				"may not work with more than 1GB RAM");	}#endif	/* IRQ resource entry is filled in from pdev, instead of	 * pci_resource macros */	for (i = count = 0; pci_resource_start(pdev, i); i++)		if ((pci_resource_flags(pdev, i) & IORESOURCE_MEM) ||		    (pci_resource_flags(pdev, i) & IORESOURCE_IO))			count++;	/* space for entry for IRQ is already in	 * cm_partial_resource_list */	resources_size = sizeof(struct cm_resource_list) +		sizeof(struct cm_partial_resource_descriptor) * count;	TRACE2("resources: %d, %d", count, resources_size);	wd->resource_list = kmalloc(resources_size, GFP_KERNEL);	if (!wd->resource_list) {		WARNING("couldn't allocate memory");		goto err_regions;	}	memset(wd->resource_list, 0, resources_size);	wd->resource_list->count = 1;	wd->resource_list->list[0].interface_type = PCIBus;	/* bus_number is not used by WDM drivers */	wd->resource_list->list[0].bus_number = pdev->bus->number;	partial_resource_list =		&wd->resource_list->list->partial_resource_list;	partial_resource_list->version = 1;	partial_resource_list->revision = 1;	partial_resource_list->count = count + 1;	for (i = count = 0; pci_resource_start(pdev, i); i++) {		entry = &partial_resource_list->partial_descriptors[count];		TRACE2("%d", count);		if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {			entry->type = CmResourceTypeMemory;			entry->flags = CM_RESOURCE_MEMORY_READ_WRITE;			entry->share = CmResourceShareDeviceExclusive;		} else if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {			entry->type = CmResourceTypePort;			entry->flags = CM_RESOURCE_PORT_IO;			entry->share = CmResourceShareDeviceExclusive;#if 0		} else if (pci_resource_flags(pdev, i) & IORESOURCE_DMA) {			/* it looks like no driver uses this resource */			typeof(pci_resource_flags(pdev, 0)) flags;			entry->type = CmResourceTypeDma;			flags = pci_resource_flags(pdev, i);			if (flags & IORESOURCE_DMA_TYPEA)				entry->flags |= CM_RESOURCE_DMA_TYPE_A;			else if (flags & IORESOURCE_DMA_TYPEB)				entry->flags |= CM_RESOURCE_DMA_TYPE_B;			else if (flags & IORESOURCE_DMA_TYPEF)				entry->flags |= CM_RESOURCE_DMA_TYPE_F;			if (flags & IORESOURCE_DMA_8BIT)				entry->flags |= CM_RESOURCE_DMA_8;			else if (flags & IORESOURCE_DMA_16BIT)				entry->flags |= CM_RESOURCE_DMA_16;			/* what about 32bit DMA? */			else if (flags & IORESOURCE_DMA_8AND16BIT)				entry->flags |= CM_RESOURCE_DMA_8_AND_16;			if (flags & IORESOURCE_DMA_MASTER)				entry->flags |= CM_RESOURCE_DMA_BUS_MASTER;			entry->u.dma.channel = pci_resource_start(pdev, i);			/* what should this be? */			entry->u.dma.port = 1;#endif		} else			continue;		/* TODO: Add other resource types? */		entry->u.generic.start =			(ULONG_PTR)pci_resource_start(pdev, i);		entry->u.generic.length = pci_resource_len(pdev, i);		count++;	}	/* put IRQ resource at the end */	entry = &partial_resource_list->partial_descriptors[count++];	entry->type = CmResourceTypeInterrupt;	entry->flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;	/* we assume all devices use shared IRQ */	entry->share = CmResourceShareShared;	/* as per documentation, interrupt level should be DIRQL, but	 * examples from DDK as well some drivers, such as AR5211,	 * RT8180L use interrupt level as interrupt vector also in	 * NdisMRegisterInterrupt */	entry->u.interrupt.level = pdev->irq;	entry->u.interrupt.vector = pdev->irq;	entry->u.interrupt.affinity = -1;	TRACE2("resource list count %d, irq: %d",	       partial_resource_list->count, pdev->irq);	pci_set_drvdata(pdev, wd);	EXIT1(return STATUS_SUCCESS);err_regions:	pci_release_regions(pdev);err_enable:	pci_disable_device(pdev);	wd->pci.pdev = NULL;	wd->pdo = NULL;	EXIT1(return STATUS_FAILURE);}static void remove_pdo(struct device_object *pdo){	struct wrap_device *wd = pdo->reserved;	ntoskernel_exit_device(wd);	if (wrap_is_pci_bus(wd->dev_bus)) {		struct pci_dev *pdev = wd->pci.pdev;		pci_release_regions(pdev);		pci_disable_device(pdev);		wd->pci.pdev = NULL;		pci_set_drvdata(pdev, NULL);	} else if (wrap_is_usb_bus(wd->dev_bus)) {#ifdef CONFIG_USB		usb_exit_device(wd);#endif	}	if (wd->resource_list)		kfree(wd->resource_list);	wd->resource_list = NULL;	return;}wstdcall NTSTATUS IoSendIrpTopDev(struct device_object *dev_obj, ULONG major_fn,				 ULONG minor_fn, struct io_stack_location *sl){	NTSTATUS status;	struct nt_event event;	struct irp *irp;	struct io_stack_location *irp_sl;	struct device_object *top_dev = IoGetAttachedDeviceReference(dev_obj);	KeInitializeEvent(&event, NotificationEvent, FALSE);	irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, top_dev, NULL, 0, NULL,					   &event, NULL);	irp->io_status.status = STATUS_NOT_IMPLEMENTED;	irp->io_status.info = 0;	irp_sl = IoGetNextIrpStackLocation(irp);	if (sl)		memcpy(irp_sl, sl, sizeof(*irp_sl));	irp_sl->major_fn = major_fn;	irp_sl->minor_fn = minor_fn;	status = IoCallDriver(top_dev, irp);	if (status == STATUS_PENDING) {		KeWaitForSingleObject(&event, Executive, KernelMode,				      FALSE, NULL);		status = irp->io_status.status;	}	ObDereferenceObject(top_dev);	return status;}wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo,					  struct  irp *irp){	struct io_stack_location *irp_sl;	NTSTATUS status;	DUMP_IRP(irp);	irp_sl = IoGetCurrentIrpStackLocation(irp);#ifdef CONFIG_USB	status = wrap_submit_irp(pdo, irp);	IOTRACE("status: %08X", status);	if (status != STATUS_PENDING)		IoCompleteRequest(irp, IO_NO_INCREMENT);#else	status = irp->io_status.status = STATUS_NOT_IMPLEMENTED;	IoCompleteRequest(irp, IO_NO_INCREMENT);#endif	IOEXIT(return status);}WIN_FUNC_DECL(pdoDispatchDeviceControl,2)wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp){	struct io_stack_location *irp_sl;	struct wrap_device *wd;	NTSTATUS status;#ifdef CONFIG_USB	struct usbd_bus_interface_usbdi *usb_intf;#endif	irp_sl = IoGetCurrentIrpStackLocation(irp);	TRACE2("%p %d:%d", pdo, irp_sl->major_fn, irp_sl->minor_fn);	wd = pdo->reserved;	switch (irp_sl->minor_fn) {	case IRP_MN_START_DEVICE:		status = start_pdo(pdo);		break;	case IRP_MN_QUERY_STOP_DEVICE:	case IRP_MN_STOP_DEVICE:	case IRP_MN_QUERY_REMOVE_DEVICE:		status = STATUS_SUCCESS;		break;	case IRP_MN_REMOVE_DEVICE:		remove_pdo(pdo);		status = STATUS_SUCCESS;		break;	case IRP_MN_QUERY_INTERFACE:#ifdef CONFIG_USB		if (!wrap_is_usb_bus(wd->dev_bus)) {			status = STATUS_NOT_IMPLEMENTED;			break;		}		TRACE2("type: %x, size: %d, version: %d",		       irp_sl->params.query_intf.type->data1,		       irp_sl->params.query_intf.size,		       irp_sl->params.query_intf.version);		usb_intf = (struct usbd_bus_interface_usbdi *)			irp_sl->params.query_intf.intf;		usb_intf->Context = wd;		usb_intf->InterfaceReference = USBD_InterfaceReference;		usb_intf->InterfaceDereference = USBD_InterfaceDereference;		usb_intf->GetUSBDIVersion = USBD_InterfaceGetUSBDIVersion;		usb_intf->QueryBusTime = USBD_InterfaceQueryBusTime;		usb_intf->SubmitIsoOutUrb = USBD_InterfaceSubmitIsoOutUrb;		usb_intf->QueryBusInformation =			USBD_InterfaceQueryBusInformation;		if (irp_sl->params.query_intf.version >=		    USB_BUSIF_USBDI_VERSION_1)			usb_intf->IsDeviceHighSpeed =				USBD_InterfaceIsDeviceHighSpeed;		if (irp_sl->params.query_intf.version >=		    USB_BUSIF_USBDI_VERSION_2)			usb_intf->LogEntry = USBD_InterfaceLogEntry;		status = STATUS_SUCCESS;#else		status = STATUS_NOT_IMPLEMENTED;#endif		break;	default:		TRACE2("fn %d not implemented", irp_sl->minor_fn);		status = STATUS_SUCCESS;		break;	}	irp->io_status.status = status;	TRACE2("status: %08X", status);	IoCompleteRequest(irp, IO_NO_INCREMENT);	IOEXIT(return status);}WIN_FUNC_DECL(pdoDispatchPnp,2)wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp){	struct io_stack_location *irp_sl;	struct wrap_device *wd;	union power_state power_state;	struct pci_dev *pdev;	NTSTATUS status;	irp_sl = IoGetCurrentIrpStackLocation(irp);	wd = pdo->reserved;	TRACE2("pdo: %p, fn: %d:%d, wd: %p",	       pdo, irp_sl->major_fn, irp_sl->minor_fn, wd);	switch (irp_sl->minor_fn) {	case IRP_MN_WAIT_WAKE:		/* TODO: this is not complete/correct */		TRACE2("state: %d, completion: %p",			  irp_sl->params.power.state.system_state,			  irp_sl->completion_routine);		IoMarkIrpPending(irp);		status = STATUS_PENDING;		break;	case IRP_MN_SET_POWER:		power_state = irp_sl->params.power.state;		if (power_state.device_state == PowerDeviceD0) {			TRACE2("resuming device %p", wd);			if (wrap_is_pci_bus(wd->dev_bus)) {				pdev = wd->pci.pdev;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)				pci_restore_state(pdev);#else				pci_restore_state(pdev, wd->pci.pci_state);#endif			} else { // usb device#ifdef CONFIG_USB				wrap_resume_urbs(wd);#endif			}		} else {			TRACE2("suspending device %p", wd);			if (wrap_is_pci_bus(wd->dev_bus)) {				pdev = wd->pci.pdev;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)				pci_save_state(pdev);#else				pci_save_state(pdev, wd->pci.pci_state);#endif			} else { // usb device#ifdef CONFIG_USB				wrap_suspend_urbs(wd);#endif			}		}		status = STATUS_SUCCESS;		break;	case IRP_MN_QUERY_POWER:		status = STATUS_SUCCESS;		break;	default:		TRACE2("fn %d not implemented", irp_sl->minor_fn);		status = STATUS_SUCCESS;		break;	}	irp->io_status.status = status;	IoCompleteRequest(irp, IO_NO_INCREMENT);	return status;}WIN_FUNC_DECL(pdoDispatchPower,2)NTSTATUS pnp_set_device_power_state(struct wrap_device *wd,				    enum device_power_state state){	NTSTATUS status;	struct device_object *pdo;	struct io_stack_location irp_sl;

⌨️ 快捷键说明

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