Subversion Repositories f9daq

Rev

Rev 17 | Blame | Compare with Previous | Last modification | View Log | RSS feed

//-------------------------------------------------------------------------------------------
// 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;
}