
Добавил:
kasak9595
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:8 СЕМЕСТР / АСУ ЭТО / Wago-IO-PRO CAA 2.3.8.5 (5.10.2007) / Setup_CoDeSys_SP_RTE / IODriver ToolKit / RTIOdrv
.c/*
Copyright by 3S Smart Software Solutions GmbH, 87439 Kempten, Germany
Author: A. Fauter
*/
/*
This file is ready to use, but does nothing.
The most important points in the code, that must be changed to create an own RTIOdriver are
marked with //TODO:
*/
#include "ntddk.h"
#include "IOdrvInterface.h"
#include "CardFunctions.h"
#include "RTIOdrv.h"
#include "IODrvFunctions.h"
#include "Utils.h"
#define MAXIMUM_STRING_BUFFER 80
//globals to export
void* g_pDefaultDispatch = NULL;
RtsApiInterface g_rtsapi;
unsigned long g_ulShmLength = 0x1000;
PHYSICAL_ADDRESS g_paShmBuffer;
char* g_pcBufferAddrInAppl = NULL;
char* g_pcShmBuffer = NULL;
//forward decls
NTSTATUS ntDeviceControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp);
NTSTATUS ntCreateFile(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp);
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS ntShutdown(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp);
// This is the definition for the routine, that will be called by the RT-PLC as a callback.
unsigned long ntCallback(CallbackInfo* pcbi, void* pPar)
{
if(pcbi->ulSecurityId1 != 0x436F4465 || pcbi->ulSecurityId2 != 0x53797320)
return STATUS_SUCCESS; /*This is not a CoDeSys-related programm, that calls the function.*/
switch(pcbi->ulCommand)
{
case DRV_CMD_GET_FUNCTION_POINTER_LIST:
{ //fill the functionpointerlist by using the defined indexes from enum FctIndices.
void** ppfFctTable = pcbi->pAdditionalCmdData;
void** ppfApiFctTable = (void*)pcbi->ulCmdParam;
//fill the rtsapi-structure, believing that ulCmdParam points to an initialized list of functions.
//doing this everytime the function is called is not necessary, but doing it once is too less,
//because the PLC may be unloaded, while the IOdriver keeps running.....
g_rtsapi.ulVersion = (unsigned long)ppfApiFctTable[API_FCT_ULVERSION];
g_rtsapi.pfRtsStopAllTasks = ppfApiFctTable[API_FCT_STOP_ALL_TASKS];
g_rtsapi.pfRtsStartAllTasks = ppfApiFctTable[API_FCT_START_ALL_TASKS];
g_rtsapi.pfRtsGetPlcState = ppfApiFctTable[API_FCT_GET_PLC_STATE];
g_rtsapi.pfRtsProgramLoaded = ppfApiFctTable[API_FCT_PROGRAM_LOADED];
g_rtsapi.pfRtsGetInputMemory = ppfApiFctTable[API_FCT_GET_INPUT_MEMORY];
g_rtsapi.pfRtsGetOutputMemory = ppfApiFctTable[API_FCT_GET_OUTPUT_MEMORY];
g_rtsapi.pfRtsGetInputSize = ppfApiFctTable[API_FCT_GET_INPUTSIZE];
g_rtsapi.pfRtsGetOutputSize = ppfApiFctTable[API_FCT_GET_OUTPUTSIZE];
if((g_rtsapi.ulVersion & 0xffff) >= 1000)
{
g_rtsapi.pfRtsCreateTask = ppfApiFctTable[API_FCT_CREATE_TASK];
g_rtsapi.pfRtsDeleteTask = ppfApiFctTable[API_FCT_DELETE_TASK];
g_rtsapi.pfRtsWaitForObject = ppfApiFctTable[API_FCT_WAIT_FOR_OBJECT];
g_rtsapi.pfRtsSetObject = ppfApiFctTable[API_FCT_SET_OBJECT];
g_rtsapi.pfRtsSleep = ppfApiFctTable[API_FCT_SLEEP];
g_rtsapi.pfAsynchFileOpen = ppfApiFctTable[API_FCT_OPENFILE];
g_rtsapi.pfAsynchFileClose = ppfApiFctTable[API_FCT_CLOSEFILE];
g_rtsapi.pfAsynchFileRead = ppfApiFctTable[API_FCT_READFILE];
g_rtsapi.pfAsynchFileWrite = ppfApiFctTable[API_FCT_WRITEFILE];
g_rtsapi.pfRtsResume = ppfApiFctTable[API_FCT_RESUME];
g_rtsapi.pfRtsSuspend = ppfApiFctTable[API_FCT_SUSPEND];
g_rtsapi.pfRtsProgramReset = ppfApiFctTable[API_FCT_PRGRESET];
g_rtsapi.pfRtsDataManipulation = ppfApiFctTable[API_FCT_DATAMANIPULATION];
g_rtsapi.pfRtsGetProjectInfo = ppfApiFctTable[API_FCT_GETPROJECTINFO];
g_rtsapi.pfSrvComputeService = ppfApiFctTable[API_FCT_PFSRVCOMPUTESERVICE];
g_rtsapi.pfSrvAddClient = ppfApiFctTable[API_FCT_PFSRVADDCLIENT];
g_rtsapi.pfSrvDeleteClient = ppfApiFctTable[API_FCT_PFSRVDELETECLIENT];
g_rtsapi.pfCsEnter = ppfApiFctTable[API_FCT_PFCSENTER];
g_rtsapi.pfCsLeave = ppfApiFctTable[API_FCT_PFCSLEAVE];
g_rtsapi.pfCsCreate = ppfApiFctTable[API_FCT_PFCSCREATE];
g_rtsapi.pfCsDelete = ppfApiFctTable[API_FCT_PFCSDELETE];
}
//TODO: Insert the functions that should be called from the PLC instead of NULL.
//Insert functions beginning with IODrv....
//This is the layer that does the driver-specific work and calls the device-specific functions (IODev...)
ppfFctTable[DRV_FCT_INIT] = IODrvInitIO;
ppfFctTable[DRV_FCT_EXIT] = NULL;
ppfFctTable[DRV_FCT_GET_ID] = IODrvGetId; //TODO:remember to change this function or minimum look at it!
ppfFctTable[DRV_FCT_GET_FLAGS] = NULL;
ppfFctTable[DRV_FCT_GET_IORANGE] = NULL;
ppfFctTable[DRV_FCT_CONFIGURE_IONET] = NULL;
ppfFctTable[DRV_FCT_CONFIGURE_MODULE] = NULL;
ppfFctTable[DRV_FCT_CONFIGURE_DEVICE] = NULL;
ppfFctTable[DRV_FCT_START_WRITE_OUTPUTS] = NULL;
ppfFctTable[DRV_FCT_WRITE_OUTPUTS] = NULL;
ppfFctTable[DRV_FCT_DONE_WRITE_OUTPUTS] = NULL;
ppfFctTable[DRV_FCT_START_READ_INPUTS] = NULL;
ppfFctTable[DRV_FCT_READ_INPUTS] = NULL;
ppfFctTable[DRV_FCT_DONE_READ_INPUTS] = NULL;
ppfFctTable[DRV_FCT_PLC_STATUS_CHANGES] = NULL;
ppfFctTable[DRV_FCT_START_CONFIGURE_IONET] = NULL;
ppfFctTable[DRV_FCT_DONE_CONFIGURE_IONET] = NULL;
ppfFctTable[DRV_FCT_CYCLIC_CALL] = NULL;
ppfFctTable[DRV_GET_EXTREFTABLE] = NULL;
ppfFctTable[DRV_FCT_BUSDIAG_GETBUSSTATE] = NULL;
ppfFctTable[DRV_FCT_BUSDIAG_GETSTATE] = NULL;
ppfFctTable[DRV_FCT_BUSDIAG_SETBUSSTATE] = NULL;
ppfFctTable[DRV_FCT_BUSDIAG_SETSTATE] = NULL;
ppfFctTable[DRV_FCT_AFTERDOWNLOAD] = NULL;
ppfFctTable[DRV_FCT_PLCRESETHOOK] = NULL; //Unused, just backward-compatibility, now use: CST_PROCESSHOOK
ppfFctTable[DRV_FCT_PRECOMPUTE_SERVICE] = NULL;
ppfFctTable[DRV_FCT_POSTCOMPUTE_SERVICE] = NULL;
ppfFctTable[DRV_FCT_SRV_BROWSERCMD] = IODrvSrvBrowserCmds;
ppfFctTable[DRV_FCT_ADD_BROWSERHELP] = IODrvAddBrowserhelp;
ppfFctTable[DRV_FCT_CST_PROCESSHOOK] = NULL;
ppfFctTable[DRV_FCT_GETTARGETIDS] = NULL; //IODrvGetTargetIds if you want to overwrite targetID.
//In this case, you must provide your own .trg-file!!
break;
}
case DRV_CMD_VERSIONCHECK:
{
unsigned short us = (unsigned short)DRV_FCT_MAXINDEX;
*(unsigned long*)pcbi->pAdditionalCmdData = (us << 16) | 2000; //pAdditionalCmdData points to a dword where the driver inserts its version.
//The HIWORD is the number of functionpointers, the driver will insert.
break;
}
case DRV_CMD_INVALID_CMD:
default:
return STATUS_SUCCESS; //what's that for a call?
}
return 1;
}
NTSTATUS ntCreateDevice( IN PDRIVER_OBJECT pDriverObject,
OUT PDEVICE_OBJECT* ppDeviceObject,
OUT void** ppsExtension )
// PURPOSE
// creates the device object for the driver
// ADDITIONAL INFORMATION
// As I don't know what NTSTATUS values "IoCreateSymbolicLink" can return, I also don't know what
// NTSTATUS values can be returned by this function.
// PARAMETERS
// pDriverObject: the driver's object
// ppDeviceObject: pointer to driver's device object - returned by this function, if successfull
// ppsExtension: the driver's device extension - returned by this function, if successfull
// RETURN VALUE
// STATUS_SUCCESS: device object was successfully created
// If the routine wasn't successfull then another NTSTATUS value is returned. Probably one of these:
// STATUS_INSUFFICIENT_RESOURCES
// STATUS_OBJECT_NAME_EXISTS
// STATUS_OBJECT_NAME_COLLISION
{
WCHAR deviceNameBuffer[] = L"\\Device\\RTIOdrv"; //TODO: change to own drivername
//TODO: change #define MY_IODRV_NAME XXXXXX in IOdrvInterface.h also!
UNICODE_STRING deviceNameUnicodeString;
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\RTIOdrv"; //TODO: change to own drivername
UNICODE_STRING deviceLinkUnicodeString;
NTSTATUS ntStatus; // return value / error code
BOOLEAN bHalRes = FALSE;
unsigned long zero = 0;
unsigned long ulBaseAddress = 0x0;
unsigned long ulLength = 0;
NTSTATUS ntsQueryRegRes = -1;
// create device name and win32 device name strings
RtlInitUnicodeString(&deviceNameUnicodeString, deviceNameBuffer);
RtlInitUnicodeString(&deviceLinkUnicodeString, deviceLinkBuffer);
// Create the device object:
ntStatus = IoCreateDevice(
pDriverObject, // DriverObject created by IO Manager when driver was loaded
20, // DeviceExtensionSize //TODO: change to your own device-extension-size
&deviceNameUnicodeString, // DeviceName
FILE_DEVICE_RTIODRIVERthis, // DeviceType
0, // DeviceCharacteristics
FALSE, // Exclusive
ppDeviceObject ); // DeviceObject returned by the function
if (!NT_SUCCESS(ntStatus))
{
// Creating device object failed.
KdPrint(("IoCreateDevice failed."));
return ntStatus;
}
// Create a link from our device name to a name in the Win32 namespace.
ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
&deviceNameUnicodeString);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("IoCreateSymLink failed."));
// Creating a symbolic link failed.
IoDeleteDevice(*ppDeviceObject);
*ppDeviceObject = NULL;
return ntStatus;
}
// Fill in the device extension.
*ppsExtension = (void*)((*ppDeviceObject)->DeviceExtension);
return ntStatus;
} // ntCreateDevice
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING ustrRegistryPath)
// PURPOSE
// This routine is called, when the driver is loaded by the system.
// PARAMETERS
// pDriverObject: Pointer to the driver's object, that was created by the system.
// ustrRegistryPath: Path to the driver's registry entry.
// RETURN VALUE
// STATUS_SUCCESS: Everything upon driver initialization went fine and the driver is ready for IO.
{
NTSTATUS ntStatus; // return value, also gets return values of calls to other functions
PDEVICE_OBJECT pDeviceObject = NULL; // pointer to device object
void* psExtension = NULL; // pointer to device extension
KdPrint(("Entering DriverEntry.\r\n"));
// initialize dispatch routines
g_pDefaultDispatch = (void*)pDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL];
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ntDeviceControl;
pDriverObject->MajorFunction[IRP_MJ_CREATE ] = ntCreateFile;
pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN ] = ntShutdown;
#pragma warning(disable : 4028)
pDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ntCallback;
#pragma warning(default : 4028)
pDriverObject->DriverUnload = DriverUnload;
//initialize the functionpointers to the PLC with NULL, so it's sure, they're not called.
memset((char*)&g_rtsapi,0,sizeof(g_rtsapi));
// create device
ntStatus = ntCreateDevice(pDriverObject, &pDeviceObject, &psExtension);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("Creating a symbolic link failed"));
// Creating a symbolic link failed.
return ntStatus;
}
g_paShmBuffer.u.HighPart = 0;
g_paShmBuffer.u.LowPart = 0xffffffff;
g_pcShmBuffer = MmAllocateContiguousMemory(g_ulShmLength,g_paShmBuffer);
g_paShmBuffer = MmGetPhysicalAddress(g_pcShmBuffer);
return STATUS_SUCCESS;
} // DriverEntry
NTSTATUS ntCreateFile(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
// PURPOSE
// This routine is called, when a user mode app opens a handle to the driver by calling CreateFile.
// It does all specific initializations for this opening process.
// PARAMETERS
// pDriverObject: pointer to the driver's object
// pIrp: pointer to the IRP for the IO call
// RETURN VALUE
// STATUS_SUCCESS: at the current state of development this is the only return value
{
return STATUS_SUCCESS;
}
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
// PURPOSE
// This routine is called when the driver is unloaded (e.g. at system shutdown). It frees all
// resources that the driver has locked.
// PARAMETERS
// pDriverObject: pointer to the driver's object, that was created by the system
{
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\RTIOdrv"; //TODO: change to own driver name.
UNICODE_STRING deviceLinkUnicodeString;
BOOLEAN bConflictDetected; // needed for IoReportResourceUsage, set to true, if
// resources have already been claimed by another device
if(g_pcShmBuffer != NULL)
MmFreeContiguousMemory(g_pcShmBuffer);
// We don't need our resources anymore (ports and interrupt).
IoReportResourceUsage(NULL, pDriverObject, NULL, 0, NULL, NULL, 0, FALSE, &bConflictDetected);
// Delete the link from our device name to a name in the Win32 namespace.
RtlInitUnicodeString(&deviceLinkUnicodeString, deviceLinkBuffer);
IoDeleteSymbolicLink(&deviceLinkUnicodeString);
// Finally delete our device object
IoDeleteDevice(pDriverObject->DeviceObject);
} // DriverUnload
NTSTATUS ntDeviceControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
// PURPOSE
// This routine is called, if a user mode app makes a call to DeviceIoControl.
// PARAMETERS
// pDriverObject: pointer to the driver's object
// pIrp: pointer to the IRP for the IO call
// RETURN VALUE
// Returns a NTSTATUS value.
{
NTSTATUS ntStatus = STATUS_SUCCESS; // return value / get's return values from function calls
void* psExtension = (void*)pDeviceObject->DeviceExtension; // pointer to driver's device extension
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); // pointer to IRP's stack
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
//process a direct command, send by a call to DeviceIOControl from an application.
case IOCTL_DIRECT_COMMAND:
switch(((DirectCommand*)(pIrp->AssociatedIrp.SystemBuffer))->Cmd)
{
case RTS_CUSTOM_SERVICES:
{
switch(((DirectCommand*)(pIrp->AssociatedIrp.SystemBuffer))->SubCmd)
{
case SUBCMD_GETSHMPOINTER:
{
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING physicalMemoryUnicodeString;
HANDLE physicalMemoryHandle;
NTSTATUS ntStatus;
PVOID virtualAddress = NULL;
LARGE_INTEGER laOffset;
unsigned long ulLength = g_ulShmLength;
if(ulLength)
{
laOffset.u.LowPart = g_paShmBuffer.u.LowPart;
laOffset.u.HighPart = 0;
RtlInitUnicodeString (&physicalMemoryUnicodeString,
L"\\Device\\PhysicalMemory");
InitializeObjectAttributes (&objectAttributes,
&physicalMemoryUnicodeString,
OBJ_CASE_INSENSITIVE,
(HANDLE) NULL,
(PSECURITY_DESCRIPTOR) NULL);
ntStatus = ZwOpenSection (&physicalMemoryHandle,
SECTION_MAP_WRITE | SECTION_MAP_READ,
&objectAttributes);
if(NT_SUCCESS(ntStatus))
{
ntStatus = ZwMapViewOfSection (physicalMemoryHandle,
(HANDLE)-1,
&virtualAddress,
0L,
ulLength,
&laOffset,
&ulLength,
ViewShare,
0,
PAGE_READWRITE | PAGE_NOCACHE);
ZwClose(physicalMemoryHandle);
}
}
((DirectCommand*)(pIrp->UserBuffer))->adpar.ulPar1 = (unsigned long)virtualAddress;
((DirectCommand*)(pIrp->UserBuffer))->adpar.ulPar2 = g_ulShmLength = ulLength;
g_pcBufferAddrInAppl = virtualAddress;
pIrp->IoStatus.Information = 1;
break;
}
case SUBCMD_RELEASESHMPOINTER:
{
if(g_pcBufferAddrInAppl != NULL)
ZwUnmapViewOfSection((HANDLE)-1,g_pcBufferAddrInAppl);
pIrp->IoStatus.Information = 1;
break;
}
default:
pIrp->IoStatus.Information = 0;
break;
}
break;
}
default:
pIrp->IoStatus.Information = 0;
break;
}
break;
// unknown IOCTL code
default:
{
ntStatus = STATUS_INVALID_PARAMETER;
pIrp->IoStatus.Information = 0;
}
}
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return ntStatus;
} // ntDeviceControl
NTSTATUS ntShutdown(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
// PURPOSE
// Handles shutdown. Is called by the system before going down.
// but only if a shutdownnotification has been registered.
// PARAMETERS
// pDriverObject: pointer to the driver's object
// pIrp: pointer to the IRP for the IO call
// RETURN VALUE
// Returns a NTSTATUS value.
{
return STATUS_SUCCESS;
}
Соседние файлы в папке IODriver ToolKit