//-------------------------------------------------------------------------
 
// WINNT driver for PCICC32 interface from ARW Elektronik, Germany --------
 
// all around recognition and basic services of VMEMM
 
//
 
// (c) 2000-2002 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
 
//
 
// what                                            who          when
 
// started from pcivme_v.c                         AR           02.07.2000
 
// changed making procedure (only VCC > 6.0)       AR           30.05.2002
 
//
 
 
 
//-------------------------------------------------------------------------
 
// INCLUDES
 
//
 
#include <ntddk.h>
 
#include <pcicc32_drv.h>
 
#include <pcicc32_v.h>
 
#include <pcicc32_local.h>  // all around the pciada 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 
 
//
 
//---------------------------------------------------------------------
 
// checks a connection with a small test pattern
 
//
 
NTSTATUS TestConnection(PCIADA *pciada)
 
{
 
        USHORT *pwADRH = (USHORT *)_WORD_NAF(pciada->pvVirtIfr, 30, 1, 0);
 
        USHORT *pwADRL = (USHORT *)_WORD_NAF(pciada->pvVirtIfr, 30, 0, 0);
 
        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 PCICC32ScanCC32(PDEVICE_OBJECT deviceObj)
 
{
 
        int i;
 
        int nPCIADAs = ((DEVICE_EXT*)(deviceObj->DeviceExtension))->nPCIADAs;
 
        PCIADA           *pciada;
 
        USHORT           wCntrl;
 
        USHORT                   wIntCSR;
 
        USHORT                   wModuleStatus;
 
 
 
        KdPrint(("PCICC32ScanCC32(nPCIADAs = %d)\n", nPCIADAs));
 
 
 
    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);
 
 
 
                KdPrint(("wCntrl = 0x%04x, wIntCSR = 0x%04x\n", wCntrl, wIntCSR));
 
 
 
                WRITE_REGISTER_USHORT(pciada->pwCntrl, INHIBIT_CC32);  // switch off before open
 
                WRITE_REGISTER_USHORT(pciada->pwIntCSR, DISABLE_PCIADA_IRQS);
 
                WRITE_REGISTER_USHORT(pciada->pwCntrl, RELEASE_CC32);  // open it for test
 
 
 
                if (wCntrl & 0x0800)
 
                {
 
                        if (TestConnection(pciada) == STATUS_SUCCESS)
 
                        {      
 
                                wModuleStatus  = READ_REGISTER_USHORT(pciada->pvVirtIfr);
 
 
 
                                pciada->bConnected              = TRUE;
 
 
 
                                // interpret the content
 
                                pciada->wModuleNumber   = (wModuleStatus & MASK_MODNR)   >> 4;
 
                                pciada->wFPGAVersion    = (wModuleStatus & MASK_FPGA)    >> 8;
 
                                pciada->wModuleType             = (wModuleStatus & MASK_MODTYPE) >> 12;
 
 
 
                                KdPrint(("PCIADA %d <-> CC32 %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_CC32);   
 
 
 
                WRITE_REGISTER_USHORT(pciada->pwIntCSR, wIntCSR);    // restore interrupt masks
 
    }
 
 
 
        return STATUS_SUCCESS;
 
}
 
 
 
 
 
//------------------------------------------------------------------------
 
// deinit all PCIADAs in a passive state 
 
//
 
NTSTATUS PCICC32DeInitPCIADAs(PDEVICE_OBJECT deviceObj)
 
{
 
        int              i;
 
        DEVICE_EXT       *pDevExt = (DEVICE_EXT*)deviceObj->DeviceExtension;
 
        int                              nPCIADAs = pDevExt->nPCIADAs;
 
        PCIADA           *pciada;
 
 
 
        KdPrint(("PCICC32DeInitPCIADAs()\n"));
 
 
 
        // dis connect the interrupts to service routines
 
        for (i = 0; i < nPCIADAs; i++)
 
        {
 
                pciada = &pDevExt->pciada[i];
 
 
 
                WRITE_REGISTER_USHORT(pciada->pwCntrl,  INHIBIT_CC32);
 
                // this is the same as globalInterruptDisable(pciada);
 
                WRITE_REGISTER_USHORT(pciada->pwIntCSR, DISABLE_PCIADA_IRQS);
 
        }
 
 
 
        return STATUS_SUCCESS;
 
}
 
 
 
//------------------------------------------------------------------------
 
// switches pciada on or off 
 
//
 
void enableCC32(PCIADA *pciada)
 
{
 
        WRITE_REGISTER_USHORT(pciada->pwCntrl,  RELEASE_CC32);
 
}
 
 
 
void disableCC32(PCIADA *pciada)
 
{
 
        WRITE_REGISTER_USHORT(pciada->pwCntrl,  INHIBIT_CC32);
 
}