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

📄 sdiousb.cpp

📁 <windows驱动开发技术详解>源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "Sdiomain.h"
#include "SdioDev.h"
#include "Ioctls.h"

SDIOGLOBALS SdioGlobals;

NTSTATUS HelloWDMRead(IN PDEVICE_OBJECT fdo,
								 IN PIRP Irp)
{
	KdPrint(("Enter HelloWDMRead\n"));
	PAGED_CODE();

	NTSTATUS status = STATUS_SUCCESS;

	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

	KdPrint(("MDL:%x\n",Irp->MdlAddress));


	status = SdioReadBufferFromDevice(pdx->FunctionalDeviceObject,
		pdx->FunctionNumber,
		Irp->MdlAddress,
		IFDevice_SDIO_DATA_REG,
		pdx->Channel0_Length,
		&Irp->IoStatus.Information);

	Irp->IoStatus.Status = status;

	IoCompleteRequest( Irp, IO_NO_INCREMENT );

	KdPrint(("Leave HelloWDMRead\n"));
	return STATUS_SUCCESS;
}

NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
								 IN PIRP Irp)
{
	PAGED_CODE();
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;	// no bytes xfered
	IoCompleteRequest( Irp, IO_NO_INCREMENT );
	KdPrint(("Leave HelloWDMDispatchRoutine\n"));
	return STATUS_SUCCESS;
}

NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
{
	PAGED_CODE();
	KdPrint(("Enter DefaultPnpHandler\n"));
	IoSkipCurrentIrpStackLocation(Irp);
	KdPrint(("Leave DefaultPnpHandler\n"));
	return IoCallDriver(pdx->TopOfStackDeviceObject, Irp);
}

NTSTATUS OnRequestComplete(PDEVICE_OBJECT junk, PIRP Irp, PKEVENT pev)
{							// OnRequestComplete
	//在完成例程中设置等待事件
	KeSetEvent(pev, 0, FALSE);
	//标志本IRP还需要再次被完成
	return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)
{							// ForwardAndWait
	PAGED_CODE();
	
	KEVENT event;
	//初始化事件
	KeInitializeEvent(&event, NotificationEvent, FALSE);

	//将本层堆栈拷贝到下一层堆栈
	IoCopyCurrentIrpStackLocationToNext(Irp);
	//设置完成例程
	IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
		(PVOID) &event, TRUE, TRUE, TRUE);

	//调用底层驱动,即PDO
	IoCallDriver(pdx->TopOfStackDeviceObject, Irp);
	//等待PDO完成
	KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
	return Irp->IoStatus.Status;
}							// ForwardAndWait

NTSTATUS HandleStartDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
	PAGED_CODE();
	KdPrint(("Enter HandleStartDevice\n"));

	pdx->Channel0_Length = 0;

	//转发IRP并等待返回
	NTSTATUS status = ForwardAndWait(pdx,Irp);
	if (!NT_SUCCESS(status))
	{
		Irp->IoStatus.Status = status;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return status;
	}
	
	UCHAR ucRegVal = 0;
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,0,&ucRegVal,REG_CCCR_IENx,FALSE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("SdioReadWriteByte fail:%x\n",status));
		return status;
	}
	KdPrint(("REG_CCCR_IENx:%x\n",ucRegVal));


	//Set Bus Width to 4 bits
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,0,&ucRegVal,REG_CCCR_BUS_INTERFACE_CTRL,FALSE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Get REG_CCCR_BUS_INTERFACE_CTRL failed:%x\n",status));
		return status;
	}
	KdPrint(("Previous REG_CCCR_BUS_INTERFACE_CTRL:%x\n",ucRegVal));
	ucRegVal = ucRegVal | 0x2;
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,0,&ucRegVal,REG_CCCR_BUS_INTERFACE_CTRL,TRUE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Set Bus Width to 4 bits failed:%x\n",status));
		return status;
	}
	KdPrint(("Set Bus Width to 4 bits successfully!\n"));

	//完成IRP
	Irp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	KdPrint(("Leave HandleStartDevice\n"));
	return status;
}

NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
	PAGED_CODE();
	KdPrint(("Enter HandleRemoveDevice\n"));

    if (pdx->InterfaceStandard.InterfaceDereference) 
    {
        (pdx->InterfaceStandard.InterfaceDereference)(pdx->InterfaceStandard.Context);
        pdx->InterfaceStandard.InterfaceDereference = NULL;
    }

	Irp->IoStatus.Status = STATUS_SUCCESS;
	NTSTATUS status = DefaultPnpHandler(pdx, Irp);
	IoSetDeviceInterfaceState(&pdx->InterfaceName, FALSE);

    //调用IoDetachDevice()把fdo从设备栈中脱开:
    if (pdx->TopOfStackDeviceObject)
        IoDetachDevice(pdx->TopOfStackDeviceObject);
	
    //删除fdo:
    IoDeleteDevice(pdx->FunctionalDeviceObject);
	KdPrint(("Leave HandleRemoveDevice\n"));
	return status;
}

NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
                        IN PIRP Irp)
{
	PAGED_CODE();

	KdPrint(("Enter HelloWDMPnp\n"));
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
	static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) = 
	{
		HandleStartDevice,		// IRP_MN_START_DEVICE
		DefaultPnpHandler,		// IRP_MN_QUERY_REMOVE_DEVICE
		HandleRemoveDevice,		// IRP_MN_REMOVE_DEVICE
		DefaultPnpHandler,		// IRP_MN_CANCEL_REMOVE_DEVICE
		DefaultPnpHandler,		// IRP_MN_STOP_DEVICE
		DefaultPnpHandler,		// IRP_MN_QUERY_STOP_DEVICE
		DefaultPnpHandler,		// IRP_MN_CANCEL_STOP_DEVICE
		DefaultPnpHandler,		// IRP_MN_QUERY_DEVICE_RELATIONS
		DefaultPnpHandler,		// IRP_MN_QUERY_INTERFACE
		DefaultPnpHandler,		// IRP_MN_QUERY_CAPABILITIES
		DefaultPnpHandler,		// IRP_MN_QUERY_RESOURCES
		DefaultPnpHandler,		// IRP_MN_QUERY_RESOURCE_REQUIREMENTS
		DefaultPnpHandler,		// IRP_MN_QUERY_DEVICE_TEXT
		DefaultPnpHandler,		// IRP_MN_FILTER_RESOURCE_REQUIREMENTS
		DefaultPnpHandler,		// 
		DefaultPnpHandler,		// IRP_MN_READ_CONFIG
		DefaultPnpHandler,		// IRP_MN_WRITE_CONFIG
		DefaultPnpHandler,		// IRP_MN_EJECT
		DefaultPnpHandler,		// IRP_MN_SET_LOCK
		DefaultPnpHandler,		// IRP_MN_QUERY_ID
		DefaultPnpHandler,		// IRP_MN_QUERY_PNP_DEVICE_STATE
		DefaultPnpHandler,		// IRP_MN_QUERY_BUS_INFORMATION
		DefaultPnpHandler,		// IRP_MN_DEVICE_USAGE_NOTIFICATION
		DefaultPnpHandler,		// IRP_MN_SURPRISE_REMOVAL
	};

	ULONG fcn = stack->MinorFunction;
	if (fcn >= arraysize(fcntab))
	{						// 未知的子功能代码
		status = DefaultPnpHandler(pdx, Irp); // some function we don't know about
		return status;
	}						

#if DBG
	static char* fcnname[] = 
	{
		"IRP_MN_START_DEVICE",
		"IRP_MN_QUERY_REMOVE_DEVICE",
		"IRP_MN_REMOVE_DEVICE",
		"IRP_MN_CANCEL_REMOVE_DEVICE",
		"IRP_MN_STOP_DEVICE",
		"IRP_MN_QUERY_STOP_DEVICE",
		"IRP_MN_CANCEL_STOP_DEVICE",
		"IRP_MN_QUERY_DEVICE_RELATIONS",
		"IRP_MN_QUERY_INTERFACE",
		"IRP_MN_QUERY_CAPABILITIES",
		"IRP_MN_QUERY_RESOURCES",
		"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
		"IRP_MN_QUERY_DEVICE_TEXT",
		"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
		"",
		"IRP_MN_READ_CONFIG",
		"IRP_MN_WRITE_CONFIG",
		"IRP_MN_EJECT",
		"IRP_MN_SET_LOCK",
		"IRP_MN_QUERY_ID",
		"IRP_MN_QUERY_PNP_DEVICE_STATE",
		"IRP_MN_QUERY_BUS_INFORMATION",
		"IRP_MN_DEVICE_USAGE_NOTIFICATION",
		"IRP_MN_SURPRISE_REMOVAL",
	};

	KdPrint(("PNP Request (%s)\n", fcnname[fcn]));
#endif // DBG

	status = (*fcntab[fcn])(pdx, Irp);
	KdPrint(("Leave HelloWDMPnp\n"));
	return status;
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING UniRegistryPath
)
{

	NTSTATUS ntStatus;
	PUNICODE_STRING pregistryPath = &SdioGlobals.Sdio_RegistryPath;
	
	KdPrint(("Enter DriverEntry\n"));
	
	//
	// Allocate pool to hold a null-terminated copy of the path.
	// Safe in paged pool since all registry routines execute at
	// PASSIVE_LEVEL.
	//
	pregistryPath->MaximumLength = UniRegistryPath->Length + sizeof(UNICODE_NULL);
	pregistryPath->Length = UniRegistryPath->Length;
	pregistryPath->Buffer = (PWSTR )ExAllocatePool(PagedPool,pregistryPath->MaximumLength);
	
	if (!(pregistryPath->Buffer)) 
	{
		KdPrint(("DriverEntry: Failed to allocate memory for registryPath\n"));
		ntStatus = STATUS_INSUFFICIENT_RESOURCES;
		goto DriverEntry_Exit;
	}
	
	RtlZeroMemory (pregistryPath->Buffer,
		pregistryPath->MaximumLength);
		RtlMoveMemory (pregistryPath->Buffer,
		UniRegistryPath->Buffer,
		UniRegistryPath->Length);

	ntStatus = STATUS_SUCCESS;
	
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloWDMDeviceIOControl;
	DriverObject->MajorFunction[IRP_MJ_POWER] = HelloWDMDispatchRoutine;
	DriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
	DriverObject->MajorFunction[IRP_MJ_CREATE] = HelloWDMDispatchRoutine;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloWDMDispatchRoutine;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP] = HelloWDMDispatchRoutine;
	DriverObject->MajorFunction[IRP_MJ_READ] = HelloWDMRead;
	DriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
	DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HelloWDMDispatchRoutine;

	DriverObject->DriverUnload = SdioClientDrv_DriverUnload;
	DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE) SdioClientDrv_AddDevice;
	
	DriverEntry_Exit:
	KdPrint(("Leave DriverEntry\n"));
	return ntStatus;
}

NTSTATUS EnableInt(PDEVICE_EXTENSION pdx)
{
	NTSTATUS status;
	UCHAR ucRegVal;
	//Enable CCCR interrupt
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,0,&ucRegVal,REG_CCCR_IENx,FALSE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Get REG_CCCR_IENx failed:%x\n",status));
		return status;
	}
	KdPrint(("Previous REG_CCCR_IENx:%x\n",ucRegVal));

	ucRegVal = ucRegVal | 1;
	ucRegVal = ucRegVal | (1<<pdx->FunctionNumber);

	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,0,&ucRegVal,REG_CCCR_IENx,TRUE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Enable CCCR interrupt failed:%x\n",status));
		return status;
	}
	KdPrint(("Enable CCCR interrupt successfully!\n"));


	//Enable Device interrupt
	ucRegVal = 0x07;
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,pdx->FunctionNumber,&ucRegVal,IFDevice_INT0_ENABLE,TRUE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Enable Device interrupt failed:%x\n",status));
		return status;
	}
	KdPrint(("Enable Device interrupt successfully!\n"));
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,pdx->FunctionNumber,&ucRegVal,IFDevice_INT0_ENABLE,FALSE);
	if (NT_SUCCESS(status))
	{
		KdPrint(("IFDevice_INT0_ENABLE:%x\n",ucRegVal));
	}
	return status;
}

NTSTATUS DisableInt(PDEVICE_EXTENSION pdx)
{
	NTSTATUS status;

	//Disable Device interrupt
	UCHAR ucRegVal = 0x0;
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,pdx->FunctionNumber,&ucRegVal,IFDevice_INT0_ENABLE,TRUE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Disable Device interrupt failed:%x\n",status));
		return status;
	}
	KdPrint(("Disable Device interrupt successfully!\n"));
	status = SdioReadWriteByte(pdx->FunctionalDeviceObject,pdx->FunctionNumber,&ucRegVal,IFDevice_INT0_ENABLE,FALSE);
	if (NT_SUCCESS(status))
	{
		KdPrint(("IFDevice_INT0_ENABLE:%x\n",ucRegVal));
	}
	return status;
}

NTSTATUS
SdioReadBufferFromDevice(IN PDEVICE_OBJECT deviceObject,
                   IN ULONG Function,
                   IN PMDL Mdl,
                   IN ULONG Address,
                   IN ULONG Length,
                   OUT PULONG BytesRead
                   )
{
    PDEVICE_EXTENSION pdx = 
    	(PDEVICE_EXTENSION)deviceObject->DeviceExtension; 

	//disable interrput
	DisableInt(pdx);

    SDBUS_REQUEST_PACKET sdrp;
    SD_RW_EXTENDED_ARGUMENT extendedArgument;
    NTSTATUS                 status;
    const SDCMD_DESCRIPTOR ReadIoExtendedDesc =
    {SDCMD_IO_RW_EXTENDED, SDCC_STANDARD, SDTD_READ, SDTT_SINGLE_BLOCK, SDRT_5};

    //PAGED_CODE();

    RtlZeroMemory(&sdrp, sizeof(SDBUS_REQUEST_PACKET));

    sdrp.RequestFunction = SDRF_DEVICE_COMMAND;
    sdrp.Parameters.DeviceCommand.Mdl = Mdl;

    extendedArgument.u.AsULONG = 0;
    extendedArgument.u.bits.Function = Function;
    extendedArgument.u.bits.OpCode = 0;             // non-increment address
    extendedArgument.u.bits.BlockMode = 0;
    extendedArgument.u.bits.Address = Address;

	sdrp.Parameters.DeviceCommand.CmdDesc  = ReadIoExtendedDesc;

    sdrp.Parameters.DeviceCommand.Argument = extendedArgument.u.AsULONG;
    sdrp.Parameters.DeviceCommand.Length   = Length;

    //
    // Send the IO request down to the bus driver
    //

    status = SdBusSubmitRequest(pdx->InterfaceStandard.Context, &sdrp);
    *BytesRead = (ULONG)sdrp.Information;
	//enable interrput
	EnableInt(pdx);
    return status;

}

NTSTATUS
SdioReadWriteBuffer(IN PDEVICE_OBJECT deviceObject,
                   IN ULONG Function,
                   IN PMDL Mdl,
                   IN ULONG Address,

⌨️ 快捷键说明

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