Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

//-------------------------------------------------------------------------
// WINNT driver for PCIVME interface from ARW Elektronik, Germany ---------
// all around recognition and basic services of VMEMM
//
// (c) 1999-2004 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
//
// $Log: pcivme_v.c,v $
// Revision 1.3  2004/07/24 07:07:26  klaus
// Update copyright to 2004
//
// Revision 1.2  2003/11/15 19:12:51  klaus
// Update copyright to 2003
//
// Revision 1.1.1.1  2003/11/14 23:16:33  klaus
// First put into repository
//
// Revision 1.3  2002/10/27 16:17:48  klaus
// Typing bug fixed caused at log addition
//
// Revision 1.2  2002/10/27 16:11:02  klaus
// Added CVS log into header
//
// what                                            who          when
// started                                         AR           02.07.1999
// first release 1.0                                                       AR                   17.10.1999
// changed resource allocation caused by WIN2000   AR           08.06.2002
//

//-------------------------------------------------------------------------
// INCLUDES
//
#include <ntddk.h>
#include <pcivme_drv.h>
#include <pcivme_v.h>
#include <pciif.h>                      // all around the pci interface

#ifndef WORD                            // don't touch include files of WIN95 driver
#define WORD USHORT
#endif

#ifndef DWORD
#define DWORD ULONG
#endif

//------------------------------------------------------------------------
// PROTOTYPES
//

//------------------------------------------------------------------------
// GLOBALS
//

//------------------------------------------------------------------------
// FUNCTIONS
//

//------------------------------------------------------------------------
// test connection to VMEMM devices without disturbing anything
//
NTSTATUS TestConnection(PCIADA *pciada)
{
        USHORT *pwADRH = (USHORT *)((ULONG)(pciada->pvVirtIfr) + (ULONG)ADRH);
        USHORT *pwADRL = (USHORT *)((ULONG)(pciada->pvVirtIfr) + (ULONG)ADRL);
        int i;
        USHORT wRet;
    USHORT wADRHContent;
    USHORT wADRLContent;

       
        KdPrint(("TestConnection()\n"));
       
        wADRHContent = READ_REGISTER_USHORT(pwADRH);    // save previous content
        wADRLContent = READ_REGISTER_USHORT(pwADRL);

        for (i = 0; i < 10000; i++)
        {
                WRITE_REGISTER_USHORT(pwADRH, 0x5555);
                WRITE_REGISTER_USHORT(pwADRL, 0xAAAA);
                wRet = READ_REGISTER_USHORT(pwADRH);
                if (wRet != 0x5555) return STATUS_UNSUCCESSFUL;
   
                WRITE_REGISTER_USHORT(pwADRH, 0xAAAA);
                WRITE_REGISTER_USHORT(pwADRL, 0x5555);
                wRet = READ_REGISTER_USHORT(pwADRH);
                if (wRet != 0xAAAA) return STATUS_UNSUCCESSFUL;

                WRITE_REGISTER_USHORT(pwADRH, 0x0000);
                WRITE_REGISTER_USHORT(pwADRL, 0xFFFF);
                wRet = READ_REGISTER_USHORT(pwADRH);
                if (wRet != 0x0000) return STATUS_UNSUCCESSFUL;

                WRITE_REGISTER_USHORT(pwADRH, 0xFFFF);
                WRITE_REGISTER_USHORT(pwADRL, 0x0000);
                wRet = READ_REGISTER_USHORT(pwADRH);
                if (wRet != 0xFFFF) return STATUS_UNSUCCESSFUL;
        }

        WRITE_REGISTER_USHORT(pwADRH, wADRHContent);    // restore previous content
        WRITE_REGISTER_USHORT(pwADRL, wADRLContent);

        KdPrint(("TestConnection() OK.\n"));

        return STATUS_SUCCESS;
}
 
//------------------------------------------------------------------------
// scan VMEMM devices without disturbing anything
//
NTSTATUS PCIVMEScanVMEMM(PDEVICE_OBJECT deviceObj)
{
        int i;
        int nPCIADAs = ((DEVICE_EXT*)(deviceObj->DeviceExtension))->nPCIADAs;
        PCIADA           *pciada;
        USHORT           wCntrl;
        USHORT                   wIntCSR;
        USHORT                   wVMEMMStatus;

        KdPrint(("PCIVMEScanVMEMM()\n"));

    for (i = 0; i < nPCIADAs; i++)
    {
                pciada = &((DEVICE_EXT*)(deviceObj->DeviceExtension))->pciada[i];
               
                wCntrl  = READ_REGISTER_USHORT(pciada->pwCntrl);   // save it for later use
        wIntCSR = READ_REGISTER_USHORT(pciada->pwIntCSR);

                WRITE_REGISTER_USHORT(pciada->pwIntCSR, DISABLE_PCIADA_IRQS);
                WRITE_REGISTER_USHORT(pciada->pwCntrl, RELEASE_VMEMM);  // open it for test

                if (wCntrl & 0x0800)
                {
                        if (TestConnection(pciada) == STATUS_SUCCESS)
                        {      
                                wVMEMMStatus  = READ_REGISTER_USHORT(pciada->pvVirtIfr);

                                pciada->bConnected              = TRUE;

                                // interpret the content
                                pciada->bWordMode               = (wVMEMMStatus & FLAG_WORD)   ? TRUE : FALSE;
                                pciada->bSysControl             = (wVMEMMStatus & FLAG_SYSCTL) ? TRUE : FALSE;
                                pciada->wModuleNumber   = (wVMEMMStatus & MASK_MODNR)   >> 4;
                                pciada->wFPGAVersion    = (wVMEMMStatus & MASK_FPGA)    >> 8;
                                pciada->wModuleType             = (wVMEMMStatus & MASK_MODTYPE) >> 12;

                                // calculate some heavy used addresses
                                pciada->pwCSR                   = (PUSHORT)((ULONG)(pciada->pvVirtIfr) + CSR);
                                pciada->pbModifier              = (PUCHAR) ((ULONG)(pciada->pvVirtIfr) + VICBASE + AMSR);
                                pciada->pdwVMEAdr               = (PULONG) ((ULONG)(pciada->pvVirtIfr) + ADRHL);
                                pciada->pwIRQStat               = (PUSHORT)((ULONG)(pciada->pvVirtIfr) + VICRES);
                                pciada->pbVector                = (PUCHAR) ((ULONG)(pciada->pvVirtIfr) + VECBASE);
                                pciada->pvVME                   = (PVOID)  ((ULONG)(pciada->pvVirtIfr) + VMEBASE);

                                KdPrint(("PCIADA %d <-> VMEMM %d\n", i, pciada->wModuleNumber));
                        }
                        else  
                                pciada->wModuleNumber = 0xFFFF;  // not recognized, take it out
                }
                else
                        pciada->wModuleNumber = 0xFFFF;  // not recognized, take it out

                if (pciada->wModuleNumber != 0xFFFF)
                  WRITE_REGISTER_USHORT(pciada->pwCntrl,  wCntrl);   // restore state
                else
                  WRITE_REGISTER_USHORT(pciada->pwCntrl,  INHIBIT_VMEMM);  

                WRITE_REGISTER_USHORT(pciada->pwIntCSR, wIntCSR);    // restore interrupt masks
    }

        return STATUS_SUCCESS;
}

 
//------------------------------------------------------------------------
// deinit all PCIADAs in a passive state
//
NTSTATUS PCIVMEDeInitPCIADAs(PDEVICE_OBJECT deviceObj)
{
        int              i;
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)deviceObj->DeviceExtension;
        int                              nPCIADAs = pDevExt->nPCIADAs;
        PCIADA           *pciada;

        KdPrint(("PCIVMEDeInitPCIADAs()\n"));

        // dis connect the interrupts to service routines
        for (i = 0; i < nPCIADAs; i++)
        {
                pciada = &pDevExt->pciada[i];

                WRITE_REGISTER_USHORT(pciada->pwIntCSR, DISABLE_PCIADA_IRQS);
                WRITE_REGISTER_USHORT(pciada->pwCntrl,  INHIBIT_VMEMM);
        }
 
        return STATUS_SUCCESS;
}