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

📄 ntoskernel_io.c

📁 ndis在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 "ntoskernel.h"#include "ndis.h"#include "wrapndis.h"#include "usb.h"#include "loader.h"extern NT_SPIN_LOCK ntoskernel_lock;extern NT_SPIN_LOCK irp_cancel_lock;extern struct nt_list object_list;wstdcall void WIN_FUNC(IoAcquireCancelSpinLock,1)	(KIRQL *irql){	*irql = nt_spin_lock_irql(&irp_cancel_lock, DISPATCH_LEVEL);}wstdcall void WIN_FUNC(IoReleaseCancelSpinLock,1)	(KIRQL irql){	nt_spin_unlock_irql(&irp_cancel_lock, irql);}wstdcall int WIN_FUNC(IoIsWdmVersionAvailable,2)	(UCHAR major, UCHAR minor){	IOENTER("%d, %x", major, minor);	if ((major == 6 && minor == 0x00) || // Vista	    (major == 1 &&	     (minor == 0x30 || // Windows 2003	      minor == 0x20 || // Windows XP	      minor == 0x10))) // Windows 2000		IOEXIT(return TRUE);	IOEXIT(return FALSE);}wstdcall BOOLEAN WIN_FUNC(IoIs32bitProcess,1)	(struct irp *irp){#ifdef CONFIG_X86_64	return FALSE;#else	return TRUE;#endif}wstdcall void WIN_FUNC(IoInitializeIrp,3)	(struct irp *irp, USHORT size, CCHAR stack_count){	IOENTER("irp: %p, %d, %d", irp, size, stack_count);	memset(irp, 0, size);	irp->size = size;	irp->stack_count = stack_count;	irp->current_location = stack_count;	IoGetCurrentIrpStackLocation(irp) = IRP_SL(irp, stack_count);	IOEXIT(return);}wstdcall void WIN_FUNC(IoReuseIrp,2)	(struct irp *irp, NTSTATUS status){	IOENTER("%p, %d", irp, status);	if (irp) {		UCHAR alloc_flags;		alloc_flags = irp->alloc_flags;		IoInitializeIrp(irp, irp->size, irp->stack_count);		irp->alloc_flags = alloc_flags;		irp->io_status.status = status;	}	IOEXIT(return);}wstdcall struct irp *WIN_FUNC(IoAllocateIrp,2)	(char stack_count, BOOLEAN charge_quota){	struct irp *irp;	int irp_size;	IOENTER("count: %d", stack_count);	stack_count++;	irp_size = IoSizeOfIrp(stack_count);	irp = kmalloc(irp_size, gfp_irql());	if (irp)		IoInitializeIrp(irp, irp_size, stack_count);	IOTRACE("irp %p", irp);	IOEXIT(return irp);}wstdcall BOOLEAN WIN_FUNC(IoCancelIrp,1)	(struct irp *irp){	typeof(irp->cancel_routine) cancel_routine;	/* NB: this function may be called at DISPATCH_LEVEL */	IOTRACE("irp: %p", irp);	if (!irp)		return FALSE;	DUMP_IRP(irp);	IoAcquireCancelSpinLock(&irp->cancel_irql);	cancel_routine = xchg(&irp->cancel_routine, NULL);	IOTRACE("%p", cancel_routine);	irp->cancel = TRUE;	if (cancel_routine) {		struct io_stack_location *irp_sl;		irp_sl = IoGetCurrentIrpStackLocation(irp);		IOTRACE("%p, %p", irp_sl, irp_sl->dev_obj);		/* cancel_routine will release the spin lock */		LIN2WIN2(cancel_routine, irp_sl->dev_obj, irp);		/* in usb's cancel, irp->cancel is set to indicate		 * status of cancel */		IOEXIT(return xchg(&irp->cancel, TRUE));	} else {		IOTRACE("irp %p already canceled", irp);		IoReleaseCancelSpinLock(irp->cancel_irql);		IOEXIT(return FALSE);	}}wstdcall void IoQueueThreadIrp(struct irp *irp){	struct nt_thread *thread;	KIRQL irql;	thread = get_current_nt_thread();	if (thread) {		IOTRACE("thread: %p, task: %p", thread, thread->task);		irp->flags |= IRP_SYNCHRONOUS_API;		irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);		InsertTailList(&thread->irps, &irp->thread_list);		IoIrpThread(irp) = thread;		nt_spin_unlock_irql(&thread->lock, irql);	} else		IoIrpThread(irp) = NULL;}wstdcall void IoDequeueThreadIrp(struct irp *irp){	struct nt_thread *thread;	KIRQL irql;	thread = IoIrpThread(irp);	if (thread) {		irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);		RemoveEntryList(&irp->thread_list);		nt_spin_unlock_irql(&thread->lock, irql);	}}wstdcall void WIN_FUNC(IoFreeIrp,1)	(struct irp *irp){	IOENTER("irp = %p", irp);	if (irp->flags & IRP_SYNCHRONOUS_API)		IoDequeueThreadIrp(irp);	kfree(irp);	IOEXIT(return);}wstdcall struct irp *WIN_FUNC(IoBuildAsynchronousFsdRequest,6)	(ULONG major_fn, struct device_object *dev_obj, void *buffer,	 ULONG length, LARGE_INTEGER *offset,	 struct io_status_block *user_status){	struct irp *irp;	struct io_stack_location *irp_sl;	IOENTER("%p", dev_obj);	if (!dev_obj)		IOEXIT(return NULL);	irp = IoAllocateIrp(dev_obj->stack_count, FALSE);	if (irp == NULL) {		WARNING("couldn't allocate irp");		IOEXIT(return NULL);	}	irp_sl = IoGetNextIrpStackLocation(irp);	irp_sl->major_fn = major_fn;	IOTRACE("major_fn: %d", major_fn);	irp_sl->minor_fn = 0;	irp_sl->flags = 0;	irp_sl->control = 0;	irp_sl->dev_obj = dev_obj;	irp_sl->file_obj = NULL;	irp_sl->completion_routine = NULL;	if (dev_obj->flags & DO_DIRECT_IO) {		irp->mdl = IoAllocateMdl(buffer, length, FALSE, FALSE, irp);		if (irp->mdl == NULL) {			IoFreeIrp(irp);			return NULL;		}		MmProbeAndLockPages(irp->mdl, KernelMode,				    major_fn == IRP_MJ_WRITE ?				    IoReadAccess : IoWriteAccess);		IOTRACE("mdl: %p", irp->mdl);	} else if (dev_obj->flags & DO_BUFFERED_IO) {		irp->associated_irp.system_buffer = buffer;		irp->flags = IRP_BUFFERED_IO;		irp->mdl = NULL;		IOTRACE("buffer: %p", buffer);	}	if (major_fn == IRP_MJ_READ) {		irp_sl->params.read.length = length;		irp_sl->params.read.byte_offset = *offset;	} else if (major_fn == IRP_MJ_WRITE) {		irp_sl->params.write.length = length;		irp_sl->params.write.byte_offset = *offset;	}	irp->user_status = user_status;	IOTRACE("irp: %p", irp);	return irp;}wstdcall struct irp *WIN_FUNC(IoBuildSynchronousFsdRequest,7)	(ULONG major_fn, struct device_object *dev_obj, void *buf,	 ULONG length, LARGE_INTEGER *offset, struct nt_event *event,	 struct io_status_block *user_status){	struct irp *irp;	irp = IoBuildAsynchronousFsdRequest(major_fn, dev_obj, buf, length,					    offset, user_status);	if (irp == NULL)		return NULL;	irp->user_event = event;	IoQueueThreadIrp(irp);	return irp;}wstdcall struct irp *WIN_FUNC(IoBuildDeviceIoControlRequest,9)	(ULONG ioctl, struct device_object *dev_obj,	 void *input_buf, ULONG input_buf_len, void *output_buf,	 ULONG output_buf_len, BOOLEAN internal_ioctl,	 struct nt_event *event, struct io_status_block *io_status){	struct irp *irp;	struct io_stack_location *irp_sl;	ULONG buf_len;	IOENTER("%p, 0x%08x, %d", dev_obj, ioctl, internal_ioctl);	if (!dev_obj)		IOEXIT(return NULL);	irp = IoAllocateIrp(dev_obj->stack_count, FALSE);	if (irp == NULL) {		WARNING("couldn't allocate irp");		return NULL;	}	irp_sl = IoGetNextIrpStackLocation(irp);	irp_sl->params.dev_ioctl.code = ioctl;	irp_sl->params.dev_ioctl.input_buf_len = input_buf_len;	irp_sl->params.dev_ioctl.output_buf_len = output_buf_len;	irp_sl->major_fn = (internal_ioctl) ?		IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;	IOTRACE("%d", IO_METHOD_FROM_CTL_CODE(ioctl));	switch (IO_METHOD_FROM_CTL_CODE(ioctl)) {	case METHOD_BUFFERED:		buf_len = max(input_buf_len, output_buf_len);		if (buf_len) {			irp->associated_irp.system_buffer =				ExAllocatePoolWithTag(NonPagedPool, buf_len, 0);			if (!irp->associated_irp.system_buffer) {				IoFreeIrp(irp);				IOEXIT(return NULL);			}			irp->associated_irp.system_buffer = input_buf;			if (input_buf)				memcpy(irp->associated_irp.system_buffer,				       input_buf, input_buf_len);			irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;			if (output_buf)				irp->flags = IRP_INPUT_OPERATION;			irp->user_buf = output_buf;		} else			irp->user_buf = NULL;		break;	case METHOD_IN_DIRECT:	case METHOD_OUT_DIRECT:		if (input_buf) {			irp->associated_irp.system_buffer =				ExAllocatePoolWithTag(NonPagedPool,						      input_buf_len, 0);			if (!irp->associated_irp.system_buffer) {				IoFreeIrp(irp);				IOEXIT(return NULL);			}			memcpy(irp->associated_irp.system_buffer,			       input_buf, input_buf_len);			irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;		}		/* TODO: we are supposed to setup MDL, but USB layer		 * doesn't use MDLs. Moreover, USB layer mirrors		 * non-DMAable buffers, so no need to allocate		 * DMAable buffer here */		if (output_buf) {			irp->associated_irp.system_buffer =				ExAllocatePoolWithTag(NonPagedPool,						      output_buf_len, 0);			if (!irp->associated_irp.system_buffer) {				IoFreeIrp(irp);				IOEXIT(return NULL);			}			irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;		}		break;	case METHOD_NEITHER:		irp->user_buf = output_buf;		irp_sl->params.dev_ioctl.type3_input_buf = input_buf;		break;	}	irp->user_status = io_status;	irp->user_event = event;	IoQueueThreadIrp(irp);	IOTRACE("irp: %p", irp);	IOEXIT(return irp);}wfastcall NTSTATUS WIN_FUNC(IofCallDriver,2)	(struct device_object *dev_obj, struct irp *irp){	struct io_stack_location *irp_sl;	NTSTATUS status;	driver_dispatch_t *major_func;	struct driver_object *drv_obj;	IOTRACE("%p, %p, %p, %d, %d, %p", dev_obj, irp, dev_obj->drv_obj,		irp->current_location, irp->stack_count,		IoGetCurrentIrpStackLocation(irp));	if (irp->current_location <= 0) {		ERROR("invalid irp: %p, %d", irp, irp->current_location);		return STATUS_INVALID_PARAMETER;	}	IoSetNextIrpStackLocation(irp);	DUMP_IRP(irp);	irp_sl = IoGetCurrentIrpStackLocation(irp);	drv_obj = dev_obj->drv_obj;	irp_sl->dev_obj = dev_obj;	major_func = drv_obj->major_func[irp_sl->major_fn];	IOTRACE("major_func: %p, dev_obj: %p", major_func, dev_obj);	if (major_func)		status = LIN2WIN2(major_func, dev_obj, irp);	else {		ERROR("major_function %d is not implemented",		      irp_sl->major_fn);		status = STATUS_NOT_SUPPORTED;	}	IOEXIT(return status);}wfastcall void WIN_FUNC(IofCompleteRequest,2)	(struct irp *irp, CHAR prio_boost){#ifdef IO_DEBUG	DUMP_IRP(irp);	if (irp->io_status.status == STATUS_PENDING) {		ERROR("invalid irp: %p, STATUS_PENDING", irp);		return;	}	if (irp->current_location < 0) {		ERROR("invalid irp: %p, %d", irp, irp->current_location);		return;	}#endif	while (irp->current_location < irp->stack_count) {		struct io_stack_location *irp_sl;		struct device_object *dev_obj;		NTSTATUS status;		irp_sl = IoGetCurrentIrpStackLocation(irp);		DUMP_IRP(irp);		if (irp_sl->control & SL_PENDING_RETURNED)			irp->pending_returned = TRUE;		/* current_location and dev_obj must be same as when		 * driver called IoSetCompletionRoutine, which sets		 * completion routine at next (lower) location, which		 * is what we are going to call below; so we set		 * current_location and dev_obj for the previous		 * (higher) location */		IoSkipCurrentIrpStackLocation(irp);		if (irp->current_location < irp->stack_count)			dev_obj = IoGetCurrentIrpStackLocation(irp)->dev_obj;		else			dev_obj = NULL;		IOTRACE("%d, %d, %p", irp->current_location, irp->stack_count,			dev_obj);		if (irp_sl->completion_routine &&		    ((irp->io_status.status == STATUS_SUCCESS &&		      irp_sl->control & SL_INVOKE_ON_SUCCESS) ||		     (irp->io_status.status != STATUS_SUCCESS &&		      irp_sl->control & SL_INVOKE_ON_ERROR) ||		     (irp->cancel == TRUE &&		      irp_sl->control & SL_INVOKE_ON_CANCEL))) {			IOTRACE("calling completion_routine at: %p, %p",				irp_sl->completion_routine, irp_sl->context);			status = LIN2WIN3(irp_sl->completion_routine,					  dev_obj, irp, irp_sl->context);			IOTRACE("status: %08X", status);			if (status == STATUS_MORE_PROCESSING_REQUIRED)				IOEXIT(return);		} else {			/* propagate pending status to next irp_sl */			if (irp->pending_returned &&			    irp->current_location < irp->stack_count)				IoMarkIrpPending(irp);		}	}	if (irp->user_status) {		irp->user_status->status = irp->io_status.status;		irp->user_status->info = irp->io_status.info;	}	if (irp->user_event) {		IOTRACE("setting event %p", irp->user_event);		KeSetEvent(irp->user_event, prio_boost, FALSE);	}	if (irp->associated_irp.system_buffer &&	    (irp->flags & IRP_DEALLOCATE_BUFFER))		ExFreePool(irp->associated_irp.system_buffer);	else {		struct mdl *mdl;		while ((mdl = irp->mdl)) {			irp->mdl = mdl->next;			MmUnlockPages(mdl);			IoFreeMdl(mdl);		}	}	IOTRACE("freeing irp %p", irp);	IoFreeIrp(irp);	IOEXIT(return);}wstdcall NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp){	IoSkipCurrentIrpStackLocation(irp);	IOEXIT(return IoCallDriver(dev_obj, irp));}wstdcall NTSTATUS IoIrpSyncComplete(struct device_object *dev_obj,				    struct irp *irp, void *context){	if (irp->pending_returned == TRUE)		KeSetEvent(context, IO_NO_INCREMENT, FALSE);	IOEXIT(return STATUS_MORE_PROCESSING_REQUIRED);}WIN_FUNC_DECL(IoIrpSyncComplete,3)wstdcall NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj,				   struct irp *irp){	struct nt_event event;	NTSTATUS status;	IoCopyCurrentIrpStackLocationToNext(irp);	KeInitializeEvent(&event, SynchronizationEvent, FALSE);	/* completion function is called as Windows function */	IoSetCompletionRoutine(irp, WIN_FUNC_PTR(IoIrpSyncComplete,3), &event,			       TRUE, TRUE, TRUE);	status = IoCallDriver(dev_obj, irp);	IOTRACE("%08X", status);	if (status == STATUS_PENDING) {		KeWaitForSingleObject(&event, Executive, KernelMode, FALSE,				      NULL);		status = irp->io_status.status;	}	IOTRACE("%08X", status);	IOEXIT(return status);}WIN_FUNC_DECL(IoSyncForwardIrp,2)wstdcall NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj,				    struct irp *irp){	NTSTATUS status;	IoCopyCurrentIrpStackLocationToNext(irp);	status = IoCallDriver(dev_obj, irp);	IOEXIT(return status);}WIN_FUNC_DECL(IoAsyncForwardIrp,2)wstdcall NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj,					 struct irp *irp){	struct io_stack_location *irp_sl;	NTSTATUS status;	irp_sl = IoGetCurrentIrpStackLocation(irp);	WARNING("%d:%d not implemented", irp_sl->major_fn, irp_sl->minor_fn);	irp->io_status.status = STATUS_SUCCESS;	irp->io_status.info = 0;	status = irp->io_status.status;	IoCompleteRequest(irp, IO_NO_INCREMENT);	IOEXIT(return status);}WIN_FUNC_DECL(IoInvalidDeviceRequest,2)static irqreturn_t io_irq_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL){	struct kinterrupt *interrupt = data;	BOOLEAN ret;	nt_spin_lock(&interrupt->lock);	ret = LIN2WIN2(interrupt->service_routine, interrupt,		       interrupt->service_context);	nt_spin_unlock(&interrupt->lock);	if (ret == TRUE)		return IRQ_HANDLED;	else		return IRQ_NONE;}wstdcall NTSTATUS WIN_FUNC(IoConnectInterrupt,11)	(struct kinterrupt **kinterrupt, PKSERVICE_ROUTINE service_routine,	 void *service_context, NT_SPIN_LOCK *lock, ULONG vector,	 KIRQL irql, KIRQL synch_irql, enum kinterrupt_mode interrupt_mode,	 BOOLEAN shareable, KAFFINITY processor_enable_mask,	 BOOLEAN floating_save){	struct kinterrupt *interrupt;	IOENTER("");	interrupt = kmalloc(sizeof(*interrupt), GFP_KERNEL);	if (!interrupt)		IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);	memset(interrupt, 0, sizeof(*interrupt));	interrupt->vector = vector;	interrupt->processor_enable_mask = processor_enable_mask;	nt_spin_lock_init(&interrupt->lock);	if (lock)		interrupt->actual_lock = lock;	else		interrupt->actual_lock = &interrupt->lock;

⌨️ 快捷键说明

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