/*
cc32lib.c -- a simple access library for the PCICC32 PCI to CAMAC Interface from ARW Elektronik
(c) 2000 ARW Elektronik
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
first steps derived from the LINUX pcicc32 library AR 16.03.2000
added buffer, UNTIL_NOT_Q and AUTOREAD functionality AR 17.03.2001
corrected fault in setAccessParameter() AR 21.05.2002
added framework only fro future interrupt handling AR 08.06.2002
*/
/*--- INCLUDES -----------------------------------------------------------------------------------*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "Vpcic32D.h" /* PCI common ioctl commands and structures between driver and library */
#include "libcc32_95.h" /* shared header bewteen applictaion and library */
/*--- DEFINES ------------------------------------------------------------------------------------*/
#define pwCC32_ADR(adr, N, A, F) (unsigned short *)((N << 10) + (A << 6) + ((F & 0xF) << 2) + adr)
#define plCC32_ADR(adr, N, A, F) (unsigned long *)((N << 10) + (A << 6) + ((F & 0xF) << 2) + adr)
#define WINDOW_SIZE 32768
/*--- EXTERNALS ----------------------------------------------------------------------------------*/
/*--- TYPEDEFS -----------------------------------------------------------------------------------*/
typedef struct
{
HANDLE nHandle; /* the handle of this device */
int nModuleNumber; /* the number of the module */
char *base; /* base of range */
unsigned short wLastAttributes; /* switched attributes like UNTIL_NOT_Q or AUTOREAD */
} CC32_DEVICE;
/*--- FUNCTIONS -----------------------------------------------------------------------*/
//--------------------------------------------------------------------------------------
// a function to get the base address of the CAMAC range
//
static int attachWindow(HANDLE nHandle, DWORD dwInterface, void **base)
{
VPCIC32D_WINDOW window;
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
DWORD result;
*base = NULL;
if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE;
// attach a window into the CC32 space ----------------
result = DeviceIoControl(nHandle, VPCIC32_ATTACH_CC32,
&dwInterface, sizeof(dwInterface),
&window, sizeof(window),
&DIOC_count, NULL);
if (!result)
return GetLastError();
else
{
*base = window.pvWindowBase;
return 0;
}
}
//--------------------------------------------------------------------------------------
// a function to release a attached range
//
static int detachWindow(HANDLE nHandle, DWORD dwInterface)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
DWORD result;
if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE;
// attach a window into the CC32 space ----------------
result = DeviceIoControl(nHandle, VPCIC32_DETACH_CC32,
&dwInterface, sizeof(dwInterface),
NULL, 0, &DIOC_count, NULL);
if (!result)
return GetLastError();
else
return 0;
}
//--------------------------------------------------------------------------------------
// get the PCIADA status from the PCI side of the interface
//
static int getStatus(HANDLE nHandle, DWORD dwInterface, char *nTimeout, char *nLAM)
{
VPCIC32D_STATUS status;
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
DWORD result;
if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE;
*nTimeout = *nLAM = 0;
// attach a window into the CC32 space ----------------
result = DeviceIoControl(nHandle, VPCIC32_GET_STATUS,
&dwInterface, sizeof(dwInterface),
&status, sizeof(status), &DIOC_count, NULL);
if (!result)
return GetLastError();
else
{
*nTimeout = (char)status.bTimeout;
*nLAM = (char)status.bInterrupt;
return 0;
}
}
//--------------------------------------------------------------------------------------
// clear the PCIADA status
//
static int clearStatus(HANDLE nHandle, DWORD dwInterface)
{
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
DWORD result;
if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE;
// attach a window into the CC32 space ----------------
result = DeviceIoControl(nHandle, VPCIC32_CLEAR_STATUS,
&dwInterface, sizeof(dwInterface),
NULL, 0, &DIOC_count, NULL);
if (!result)
return GetLastError();
else
return 0;
}
//-------------------------------------------------------------------------
// set the future access parameters - override the current
//
static int setAccessParameter(HANDLE hHandle, DWORD dwInterface, USHORT wBlockTransfer)
{
DWORD result;
DWORD DIOC_count; // count of returned bytes of DeviceIoControl
VPCIC32D_ACCESS_COMMAND access_parameter;
if (hHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE;
access_parameter.dwInterface = dwInterface;
access_parameter.wBlockTransfer = wBlockTransfer;
result = DeviceIoControl(hHandle, VPCIC32_SET_ACCESS_PARA,
&access_parameter, (DWORD)sizeof(access_parameter), NULL,
0, &DIOC_count, NULL);
if (!result)
return GetLastError();
else
return 0;
}
//--------------------------------------------------------------------------------------
// open the device
//
int cc32_open_95(char *cszPath, int nModuleNumber, void **handle)
{
CC32_DEVICE *dev;
int error;
*handle = (void *)-1;
dev
= (CC32_DEVICE
*)malloc(sizeof(CC32_DEVICE
));
if (!dev) return errno;
dev->base = (char *)0;
dev->nModuleNumber = nModuleNumber;
dev->wLastAttributes = 0;
dev->nHandle = CreateFile(cszPath,
0,
0,
NULL,
0,
FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (dev->nHandle != INVALID_HANDLE_VALUE)
error = attachWindow(dev->nHandle, nModuleNumber, &dev->base);
else
error = GetLastError();
if (error)
{
return error;
}
*handle = (void *)dev;
return NO_ERROR;
}
//--------------------------------------------------------------------------------------
// close the device
//
int cc32_close_95(void *handle)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
int error = NO_ERROR;
if (dev)
{
if (dev->nHandle != INVALID_HANDLE_VALUE)
{
detachWindow(dev->nHandle, dev->nModuleNumber);
CloseHandle(dev->nHandle);
}
}
else
error = ERROR_INVALID_FUNCTION;
return error;
}
//--------------------------------------------------------------------------------------
// read a word
//
unsigned short cc32_read_word_95(void *handle, unsigned int N, unsigned int A, unsigned int F)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
return *pwCC32_ADR(dev->base, N, A, F);
}
//--------------------------------------------------------------------------------------
// read a long
//
unsigned long cc32_read_long_all_95(void *handle, unsigned int N, unsigned int A, unsigned int F)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
return *plCC32_ADR(dev->base, N, A, F);
}
//--------------------------------------------------------------------------------------
// read a long and get Q and X
//
unsigned long cc32_read_long_95(void *handle, unsigned int N, unsigned int A, unsigned int F, char *Q, char *X)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
unsigned long erg = *plCC32_ADR(dev->base, N, A, F);
*Q = (erg & 0x80000000) ? 1 : 0;
*X = (erg & 0x40000000) ? 1 : 0;
return erg & 0x00FFFFFF;
}
//--------------------------------------------------------------------------------------
// write a word
//
void cc32_write_word_95(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned short uwData)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
dev->wLastAttributes = 0;
*pwCC32_ADR(dev->base, N, A, F) = uwData;
}
//--------------------------------------------------------------------------------------
// write a long
//
void cc32_write_long_95(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned long ulData)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
dev->wLastAttributes = 0;
*plCC32_ADR(dev->base, N, A, F) = ulData;
}
//--------------------------------------------------------------------------------------
// clear the PCIADA status
//
int cc32_poll_error_95(void *handle, char *nTimeout, char *nLam)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
int error;
if ((error = getStatus(dev->nHandle, dev->nModuleNumber, nTimeout, nLam)))
return error;
if (*nTimeout) /* clear error */
{
if ((error = clearStatus(dev->nHandle, dev->nModuleNumber)))
return error;
}
return NO_ERROR;
}
//--------------------------------------------------------------------------------------
// read 'len' words or 'UNTIL_NOT_Q' from a address made out of N,A,F
//
int cc32_read_word_buffer_95(void * handle, unsigned int N, unsigned int A, unsigned int F,
unsigned short *pwBuffer, unsigned long *pdwLen)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
register unsigned long i = 0;
unsigned long dwLen = *pdwLen;
unsigned long *pdwAddress = plCC32_ADR(dev->base, N, A, F);
register unsigned long dwTempBuffer;
if (dev->wLastAttributes & UNTIL_NOT_Q)
{
do
{
dwTempBuffer = *pdwAddress;
*pwBuffer++ = (unsigned short)dwTempBuffer;
} while ((dwTempBuffer & 0x80000000) && (i++ < dwLen));
}
else
{
while (i++ < dwLen)
*pwBuffer++ = (unsigned short)*pdwAddress;
}
*pdwLen = --i;
return 0;
}
//--------------------------------------------------------------------------------------
// read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, mask 24 bits out
//
int cc32_read_long_buffer_95(void * handle, unsigned int N, unsigned int A, unsigned int F,
unsigned long *pdwBuffer, unsigned long *pdwLen)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
register unsigned long i = 0;
unsigned long dwLen = *pdwLen;
unsigned long *pdwAddress = plCC32_ADR(dev->base, N, A, F);
register unsigned long dwTempBuffer;
if (dev->wLastAttributes & UNTIL_NOT_Q)
{
do
{
dwTempBuffer = *pdwAddress;
*pdwBuffer++ = dwTempBuffer & 0x00FFFFFF;
} while ((dwTempBuffer & 0x80000000) && (i++ < dwLen));
}
else
{
while (i++ < dwLen)
*pdwBuffer++ = *pdwAddress & 0x00FFFFFF;
}
*pdwLen = --i;
return 0;
}
//--------------------------------------------------------------------------------------
// read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, without interpretation
//
int cc32_read_long_all_buffer_95(void * handle, unsigned int N, unsigned int A, unsigned int F,
unsigned long *pdwBuffer, unsigned long *pdwLen)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
register unsigned long i = 0;
unsigned long dwLen = *pdwLen;
unsigned long *pdwAddress = plCC32_ADR(dev->base, N, A, F);
register unsigned long dwTempBuffer;
if (dev->wLastAttributes & UNTIL_NOT_Q)
{
do
{
dwTempBuffer = *pdwAddress;
*pdwBuffer++ = dwTempBuffer;
} while ((dwTempBuffer & 0x80000000) && (i++ < dwLen));
}
else
{
while (i++ < dwLen)
*pdwBuffer++ = *pdwAddress;
}
*pdwLen = --i;
return 0;
}
//--------------------------------------------------------------------------------------
// switch UNTIL_NOT_Q or AUTOREAD on or off
//
int cc32_access_switch_95(void *handle, unsigned short uwSwitch)
{
CC32_DEVICE *dev = (CC32_DEVICE *)handle;
dev->wLastAttributes = uwSwitch;
return setAccessParameter(dev->nHandle, dev->nModuleNumber, dev->wLastAttributes);
}
//--------------------------------------------------------------------------------------
// switch interrupts on
//
int cc32_enable_interrupt_95(void *handle)
{
return ERROR_INVALID_FUNCTION;
}
//--------------------------------------------------------------------------------------
// switch interrupts off
//
int cc32_disable_interrupt_95(void *handle)
{
return ERROR_INVALID_FUNCTION;
}
//--------------------------------------------------------------------------------------
// wait blocking for the next interrupt
//
int cc32_get_interrupt_95(void *handle, unsigned long *dwStatus)
{
return ERROR_INVALID_FUNCTION;
}