📄 pciop.c
字号:
/*++
Copyright (c) 1990-98 Microsoft Corporation All Rights Reserved
Module Name:
sioctl.c
Abstract:
Purpose of this driver is to demonstrate how the four different types
of IOCTLs can be used, and how the I/O manager handles the user I/O
buffers in each case. This sample also helps to understand the usage of
some of the memory manager functions.
Author:
Eliyas Yakub - July 1997.
Environment:
Kernel mode only.
Notes:
Revision History:
--*/
//
// Include files.
//
#include <ntddk.h> // various NT definitions
#include <string.h>
#include "pciop.h"
#define NT_DEVICE_NAME L"\\Device\\PCIOP"
#define DOS_DEVICE_NAME L"\\DosDevices\\PCIOP"
#if DBG
#define SIOCTL_KDPRINT(_x_) \
DbgPrint("PCIOP.SYS: ");\
DbgPrint _x_;
#else
#define SIOCTL_KDPRINT(_x_)
#endif
//
// Device driver routine declarations.
//
NTSTATUS
DriverEntry(
IN OUT PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
PciopCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
PciopDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
PciopUnloadDriver(
IN PDRIVER_OBJECT DriverObject
);
VOID
PrintIrpInfo(PIRP Irp);
VOID
PrintHex(
IN PCHAR BufferAddress,
IN ULONG CountChars
);
BOOLEAN
PciopScanIteratePCI
( IN BOOLEAN First,
IN unsigned int pciVendorId,
IN unsigned int pciDeviceId,
IN OUT PCI_SLOT_NUMBER *returnSlotData,
IN OUT PCI_COMMON_CONFIG *returnPciData,
IN OUT unsigned int *returnBusNumber );
BOOLEAN PciopScanAllPCI(ULONG* pcidevices_found);
NTSTATUS
FindPciDevice(
IN USHORT VendorId,
IN USHORT DeviceId
);
ULONG
IOReadWrite(
IN PCHAR inBuf,
OUT PCHAR outBuf
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, DriverEntry )
#pragma alloc_text( PAGE, PciopCreateClose)
#pragma alloc_text( PAGE, PciopDeviceControl)
#pragma alloc_text( PAGE, PciopUnloadDriver)
#pragma alloc_text( PAGE, PrintIrpInfo)
#pragma alloc_text( PAGE, PrintHex)
#pragma alloc_text( PAGE, PciopScanIteratePCI)
#pragma alloc_text( PAGE, PciopScanAllPCI)
#pragma alloc_text( PAGE, FindPciDevice)
#pragma alloc_text( PAGE, IOReadWrite)
#endif // ALLOC_PRAGMA
NTSTATUS
DriverEntry(
IN OUT PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine is called by the Operating System to initialize the driver.
It creates the device object, fills in the dispatch entry points and
completes the initialization.
Arguments:
DriverObject - a pointer to the object that represents this device
driver.
RegistryPath - a pointer to our Services key in the registry.
Return Value:
STATUS_SUCCESS if initialized; an error otherwise.
--*/
{
NTSTATUS ntStatus;
UNICODE_STRING ntUnicodeString; // NT Device Name "\Device\SIOCTL"
UNICODE_STRING ntWin32NameString; // Win32 Name "\DosDevices\IoctlTest"
PDEVICE_OBJECT deviceObject = NULL; // ptr to device object
RtlInitUnicodeString( &ntUnicodeString, NT_DEVICE_NAME );
ntStatus = IoCreateDevice(
DriverObject, // Our Driver Object
0, // We don't use a device extension
&ntUnicodeString, // Device name "\Device\SIOCTL"
FILE_DEVICE_UNKNOWN, // Device type
FILE_DEVICE_SECURE_OPEN, // Device characteristics
FALSE, // Not an exclusive device
&deviceObject ); // Returned ptr to Device Object
if ( !NT_SUCCESS( ntStatus ) )
{
SIOCTL_KDPRINT(("Couldn't create the device object\n"));
return ntStatus;
}
//
// Initialize the driver object with this driver's entry points.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = PciopCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PciopCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciopDeviceControl;
DriverObject->DriverUnload = PciopUnloadDriver;
//
// Initialize a Unicode String containing the Win32 name
// for our device.
//
RtlInitUnicodeString( &ntWin32NameString, DOS_DEVICE_NAME );
//
// Create a symbolic link between our device name and the Win32 name
//
ntStatus = IoCreateSymbolicLink(
&ntWin32NameString, &ntUnicodeString );
if ( !NT_SUCCESS( ntStatus ) )
{
//
// Delete everything that this routine has allocated.
//
SIOCTL_KDPRINT(("Couldn't create symbolic link\n"));
IoDeleteDevice( deviceObject );
}
return ntStatus;
}
NTSTATUS
PciopCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O system when the SIOCTL is opened or
closed.
No action is performed other than completing the request successfully.
Arguments:
DeviceObject - a pointer to the object that represents the device
that I/O is to be done on.
Irp - a pointer to the I/O Request Packet for this request.
Return Value:
NT status code
--*/
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
VOID
PciopUnloadDriver(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This routine is called by the I/O system to unload the driver.
Any resources previously allocated must be freed.
Arguments:
DriverObject - a pointer to the object that represents our driver.
Return Value:
None
--*/
{
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
UNICODE_STRING uniWin32NameString;
//
// Create counted string version of our Win32 device name.
//
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
//
// Delete the link from our device name to a name in the Win32 namespace.
//
IoDeleteSymbolicLink( &uniWin32NameString );
if ( deviceObject != NULL )
{
IoDeleteDevice( deviceObject );
}
}
NTSTATUS
PciopDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called by the I/O system to perform a device I/O
control function.
Arguments:
DeviceObject - a pointer to the object that represents the device
that I/O is to be done on.
Irp - a pointer to the I/O Request Packet for this request.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpSp;// Pointer to current stack location
NTSTATUS ntStatus = STATUS_SUCCESS;// Assume success
ULONG inBufLength; // Input buffer length
ULONG outBufLength; // Output buffer length
PCHAR inBuf, outBuf; // pointer to Input and output buffer
PCHAR data = "This String is from Device Driver !!!";
ULONG datalen = strlen(data)+1;//Length of data including null
PMDL mdl = NULL;
PCHAR buffer = NULL;
PCI_SLOT_NUMBER pci_slot_number;
unsigned int dev_number;
PCI_COMMON_CONFIG pci_cm_conf;
ULONG pcidev_found = 0;
BOOLEAN ret_pci_found;
PPCIDEVQUERY pPciQuery;
PPCIQUERYRESULT pPciResult;
PMEMORYRP pMemRead;
PHYSICAL_ADDRESS physicalAddress;
PVOID lineAddress;
ULONG ioRwRet = 0;
ULONG count = 0;
irpSp = IoGetCurrentIrpStackLocation( Irp );
inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
//
// Determine which I/O control code was specified.
//
switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
{
case IOCTL_PORT_READ_WRITE:
if(inBufLength != sizeof(IOPORTRWP))
{
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
inBuf = Irp->AssociatedIrp.SystemBuffer;
outBuf = Irp->AssociatedIrp.SystemBuffer;
ioRwRet = IOReadWrite(inBuf, outBuf);
if(ioRwRet == 0)
{
ntStatus = STATUS_INVALID_PARAMETER;
}
else
{
Irp->IoStatus.Information = ioRwRet;
}
break;
case IOCTL_MEMORY_READ_WRITE:
KdPrint (("Try read/write memory data here....\n"));
if(inBufLength != sizeof(MEMORYRP))
{
KdPrint (("Error parameter %x....\n", inBufLength));
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
inBuf = Irp->AssociatedIrp.SystemBuffer;
//Callers of MmMapIoSpace must be running at IRQL <= DISPATCH_LEVEL
pMemRead = (PMEMORYRP)inBuf;
physicalAddress.HighPart = 0;
physicalAddress.LowPart = pMemRead->memoryAddress;
lineAddress = MmMapIoSpace(physicalAddress, pMemRead->rSize, MmNonCached);
KdPrint (("Get line address 0x%x:\n", lineAddress));
//
// To access the output buffer, just get the system address
// for the buffer. For this method,
//this buffer is intended for transfering data
// from the driver to the application when read memory.
//
//this buffer is intended for transfering data
// from the appliction to driver when read memory.
buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
if(!buffer) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if(pMemRead->isRead)
{
//
// Write data to be sent to the user in this buffer
//
READ_REGISTER_BUFFER_UCHAR(lineAddress, buffer,pMemRead->rSize);
for(count=0; count< pMemRead->rSize/32; count++)
{
PrintHex(buffer+32*count, 32);
}
if(pMemRead->rSize %32)
{
PrintHex(buffer+32*count, pMemRead->rSize);
}
}
else
{
//
//Write data to the memory lineAddress
//
for(count=0; count< pMemRead->rSize/32; count++)
{
PrintHex(buffer+32*count, 32);
}
if(pMemRead->rSize %32)
{
PrintHex(buffer+32*count, pMemRead->rSize);
}
WRITE_REGISTER_BUFFER_UCHAR(lineAddress, buffer,pMemRead->rSize);
}
Irp->IoStatus.Information = pMemRead->rSize;
break;
case IOCTL_MEMORY_WRITE:
break;
case IOCTL_PCIOP_BUFFERED_TEST:
inBuf = Irp->AssociatedIrp.SystemBuffer;
outBuf = Irp->AssociatedIrp.SystemBuffer;
memcpy(outBuf, data, strlen(data)+1);
KdPrint (("outBuf is %s\n", outBuf));
Irp->IoStatus.Information = (outBufLength<datalen?outBufLength:datalen);
break;
case IOCTL_PCIOP_GET_PCIDEVICE:
//
// Input buffer and output buffer is same in this case, read the
// content of the buffer before writing to it
//
if(inBufLength != sizeof(PCIDEVQUERY) || outBufLength != sizeof(PCIQUERYRESULT))
{
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
inBuf = Irp->AssociatedIrp.SystemBuffer;
outBuf = Irp->AssociatedIrp.SystemBuffer;
pPciQuery = (PPCIDEVQUERY)inBuf;
pPciResult = (PPCIQUERYRESULT)outBuf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -