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