//-------------------------------------------------------------------------------------------
// 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>
#include <stdio.h>
FILE
*vmefp
;
//-------------------------------------------------------------------------------------------
// 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_s
(buffer
, 255 , DEFDEVICENAME
);
else
strcpy_s
(buffer
, 255 , 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
= 0;
vmefp
= fopen("pcivme_ni.log","w");
fprintf(vmefp
, "VMEinitNT\n");
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
();
fprintf(vmefp
, "DeviceIoControl result=%d\n", result
);
fclose(vmefp
);
CloseHandle
(open_path
->nHandle
);
removeListElement
(open_path
);
return result
;
}
*pnHandle
= (int)open_path
;
return 0;
}
else
{
result
= GetLastError
();
fprintf(vmefp
, "CreateFile error result=%d %s\n", result
, DeviceName
(cszDeviceName
, nVMEMM
));
fclose(vmefp
);
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;
}