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