//-------------------------------------------------------------------------------------------
// pcivme_ni_NT.c - a ni labview dll skeleton for the ARW pcivme interface, winNT
//
// (c) 1999-2004 ARW Elektronik, Germany
//
// this source code is published under GPL (Open Source). You can use, redistrubute and
// modify it unless this header is not modified or deleted. No warranty is given that
// this software will work like expected.
// This product is not authorized for use as critical component in life support systems
// wihout the express written approval of ARW Elektronik Germany.
//
// Please announce changes and hints to ARW Elektronik
//
// $Log: pcivme_ni_NT.c,v $
// Revision 1.2 2004/07/24 07:47:00 klaus
// Update copyright to 2004
//
// Revision 1.1.1.1 2003/11/14 23:17:18 klaus
// First put into repository
//
// Revision 1.4 2002/10/27 21:32:35 klaus
// compatibility improved
//
// Revision 1.3 2002/10/27 19:22:58 klaus
// backward compatibilty problem for 2 Gbyte limit solved
//
// Revision 1.2 2002/10/27 17:05:33 klaus
// CVS log added, file addressing bug > 2 Gbtye circumvent
//
// what who when
// first steps AR 07.11.1999
//
//-------------------------------------------------------------------------------------------
// INCLUDES
//
#include <windows.h>
#include <winioctl.h>
#include <pcivme.h> // header for win-NT
#include <vic.h>
#include <vme.h>
#include <pcivme_ni_NT.h>
#include <Klist.h>
//-------------------------------------------------------------------------------------------
// DEFINES
//
#define DEFDEVICENAME "\\\\.\\PCIVME:\\VMEMMxx"
#define LIMIT_2GBYTE 0x80000000 // 2 GByte addressing limit of WINNT ...
//-------------------------------------------------------------------------------------------
// TYPEDEFS
//
typedef struct // a element associated to a open path (between VMEinit and VMEclose)
{
HANDLE nHandle;
PCIVME_ACCESS_COMMAND access;
} OPEN_PATH;
//-------------------------------------------------------------------------------------------
// LOCALS
//
// user initialisation table for pcivme
static PCIVME_INIT_COMMAND sUserInitStruct = {2, {{STOP, WORD_ACCESS, 0, 0}}};
// user deinitialisation table
static PCIVME_INIT_COMMAND sUserDeInitStruct = {2, {{STOP, WORD_ACCESS, 0, 0}}};
// the list of Path specific data (a element lives between VMEinit and VMEclose)
static LIST liPathList = (LIST)NULL;
//-------------------------------------------------------------------------------------------
// EXTERNALS
//
//-------------------------------------------------------------------------------------------
// GLOBALS
//
//-------------------------------------------------------------------------------------------
// FUNCTIONS
//
// not only delete a element - even remove the whole list if it is empty
static void removeListElement(OPEN_PATH *open_path)
{
List_Delete((LPVOID)open_path);
// remove the list if the last item was deleted ----
if ((liPathList != NULL) && (List_IsEmpty(liPathList) == TRUE))
{
List_Destroy(&liPathList);
liPathList = (LIST)NULL;
}
}
//-------------------------------------------------------------------------
// create a DeviceName out of cszDeviceName and nIfcNum
static char *DeviceName(const char *cszDeviceName, int nIfcNum)
{
static char buffer[255];
char *ptr = buffer;
if (cszDeviceName == NULL)
strcpy(buffer
, DEFDEVICENAME
);
else
strcpy(buffer
, cszDeviceName
);
while (*ptr) ptr++;
do
{
ptr--;
} while (*ptr != 'M');
ptr++;
if (nIfcNum >= 10)
{
*ptr++ = '1';
nIfcNum -= 10;
}
*ptr++ = '0' + nIfcNum;
*ptr = 0;
return buffer;
}
int VMEinitNT(const char *cszDeviceName, unsigned short nVMEMM, unsigned char ubAddressModifier, int *pnHandle)
{
OPEN_PATH *open_path;
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
DWORD result;
if (liPathList == NULL) // create a list to hold the paths and its variables
{
liPathList = List_Create();
if (liPathList == (LIST)NULL)
return GetLastError();
}
open_path = (OPEN_PATH *)List_NewFirst(liPathList, sizeof(OPEN_PATH));
*pnHandle = -1;
if ((open_path->nHandle = CreateFile(
DeviceName(cszDeviceName, nVMEMM),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) != ((HANDLE)-1))
{
// init hardware (only one time after the first init it works OK)
result = DeviceIoControl(open_path->nHandle,
PCIVME_INIT_HARDWARE,
&sUserInitStruct,
(DWORD)sizeof(sUserInitStruct),
NULL,
(DWORD)0,
&DIOC_count,
NULL);
// set the current access parameters ------------------
open_path->access.bAddressModifier = ubAddressModifier;
open_path->access.bAccessType =
open_path->access.bIncrement = BYTE_ACCESS;
open_path->access.dwAccessBase = 0;
result = DeviceIoControl(open_path->nHandle,
PCIVME_SET_ACCESS_PARA,
&open_path->access,
(DWORD)sizeof(open_path->access),
NULL,
0,
&DIOC_count,
NULL);
if (!result)
{
result = GetLastError();
CloseHandle(open_path->nHandle);
removeListElement(open_path);
return result;
}
*pnHandle = (int)open_path;
return 0;
}
else
{
result = GetLastError();
removeListElement(open_path);
return result;
}
}
int VMEreadNT(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
unsigned long ulNumberOfBytes = ulElementCount * ubAccessWidth;
unsigned long bytesRead;
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
// set the current access parameters ------------------
open_path->access.bAccessType =
open_path->access.bIncrement = ubAccessWidth;
// take care of only 2 Gbyte addressing capabilities of WINNT ...
if (ulAddress >= LIMIT_2GBYTE)
{
ulAddress -= LIMIT_2GBYTE;
open_path->access.dwAccessBase = LIMIT_2GBYTE;
}
else
open_path->access.dwAccessBase = 0;
if (!DeviceIoControl(open_path->nHandle,
PCIVME_SET_ACCESS_PARA,
&open_path->access,
(DWORD)sizeof(open_path->access),
NULL,
0,
&DIOC_count,
NULL))
return GetLastError();
SetFilePointer(open_path->nHandle, ulAddress, NULL, FILE_BEGIN);
if (!ReadFile(open_path->nHandle, pvBuffer, ulNumberOfBytes, &bytesRead, NULL))
return GetLastError();
return 0;
}
int VMEwriteNT(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
unsigned long ulNumberOfBytes = ulElementCount * ubAccessWidth;
unsigned long bytesRead;
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
// set the current access parameters ------------------
open_path->access.bAccessType =
open_path->access.bIncrement = ubAccessWidth;
// take care of only 2 Gbyte addressing capabilities of WINNT ...
if (ulAddress >= LIMIT_2GBYTE)
{
ulAddress -= LIMIT_2GBYTE;
open_path->access.dwAccessBase = LIMIT_2GBYTE;
}
else
open_path->access.dwAccessBase = 0;
if (!DeviceIoControl(open_path->nHandle,
PCIVME_SET_ACCESS_PARA,
&open_path->access,
(DWORD)sizeof(open_path->access),
NULL,
0,
&DIOC_count,
NULL))
return GetLastError();
SetFilePointer(open_path->nHandle, ulAddress, NULL, FILE_BEGIN);
if (!WriteFile(open_path->nHandle, pvBuffer, ulNumberOfBytes, &bytesRead, NULL))
return GetLastError();
return 0;
}
int VMEaccessVICNT(int nHandle, unsigned char ubAccessMode, unsigned short uwAddress, unsigned char *ubContent)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
PCIVME_VIC68A_ACTION sAction; // structure to access vic chip
DWORD result;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
sAction.wRegisterAddress = uwAddress;
sAction.wAccessMode = ubAccessMode;
sAction.bContent = *ubContent;
result = DeviceIoControl(open_path->nHandle, PCIVME_ACCESS_VIC68A,
&sAction, sizeof(sAction), &sAction,
sizeof(sAction), &DIOC_count, NULL);
*ubContent = sAction.bContent;
if (!result)
return GetLastError();
else
return 0;
}
int VMEresetNT(int nHandle)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
DWORD result;
PCIVME_RESET_COMMAND reset_command;
PCIVME_RESET_RESULT reset_result;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
reset_command.wCommand = VME_RESET_CMD;
reset_result.wResult = 0;
result = DeviceIoControl(open_path->nHandle, PCIVME_RESET,
&reset_command, sizeof(reset_command),
&reset_result, sizeof(reset_result),
&DIOC_count, NULL);
if (!result)
return GetLastError();
else
{
result = 1;
while (reset_result.wResult && result)
{
reset_command.wCommand = POLL_RESET_CMD;
result = DeviceIoControl(open_path->nHandle, PCIVME_RESET,
&reset_command, sizeof(reset_command),
&reset_result, sizeof(reset_result),
&DIOC_count, NULL);
Sleep(10);
}
}
if (!result)
return GetLastError();
else
return 0;
}
int VMETASNT(int nHandle, unsigned long ulAddress, unsigned char *ubResult)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
PCIVME_TAS_STRUCT sTAS; // structure to do a Test and Set
DWORD result;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
sTAS.wModifier = open_path->access.bAddressModifier;
sTAS.dwAddress = ulAddress;
sTAS.bContent = 0x80;
result = DeviceIoControl(open_path->nHandle, PCIVME_TAS,
&sTAS, (DWORD)sizeof(sTAS), &sTAS,
(DWORD)sizeof(sTAS), &DIOC_count, NULL);
*ubResult = sTAS.bContent;
if (!result)
return GetLastError();
else
return 0;
}
int VMEinterruptNT(int nHandle, unsigned char *ubVector)
{
// DWORD DIOC_count; // count of returned bytes of DeviceIoControl
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
return 0;
}
int VMEsysfailGetNT(int nHandle, BOOLEAN *bResult)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
PCIVME_VIC68A_ACTION sAction; // structure to access vic chip
DWORD result;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
sAction.wRegisterAddress = EGICR;
sAction.wAccessMode = VIC68A_READ;
sAction.bContent = 0;
result = DeviceIoControl(open_path->nHandle, PCIVME_ACCESS_VIC68A,
&sAction, sizeof(sAction), &sAction,
sizeof(sAction), &DIOC_count, NULL);
*bResult = (sAction.bContent & 0x08) ? FALSE : TRUE;
if (!result)
return GetLastError();
else
return 0;
}
int VMEsysfailSetNT(int nHandle, BOOLEAN bForce)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
PCIVME_VIC68A_ACTION sAction; // structure to access vic chip
DWORD result;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
sAction.wRegisterAddress = ICR7;
sAction.wAccessMode = (bForce == TRUE) ? VIC68A_AND : VIC68A_OR;
sAction.bContent = (bForce == TRUE) ? 0x3F : 0x80;
result = DeviceIoControl(open_path->nHandle, PCIVME_ACCESS_VIC68A,
&sAction, (DWORD)sizeof(sAction), &sAction,
(DWORD)sizeof(sAction), &DIOC_count, NULL);
if (!result)
return GetLastError();
else
return 0;
}
int VMEcloseNT(int nHandle)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
OPEN_PATH *open_path = (OPEN_PATH *)nHandle;
if (nHandle == -1) return ERROR_PATH_NOT_FOUND;
DeviceIoControl(open_path->nHandle,
PCIVME_DEINIT_HARDWARE,
&sUserDeInitStruct,
(DWORD)sizeof(sUserDeInitStruct),
NULL,
0,
&DIOC_count,
NULL);
CloseHandle(open_path->nHandle);
removeListElement(open_path);
return 0;
}