#include <iostream>
#include <cstdio>
#include "VMEmanager.h"
using namespace std;
#if defined(HAS_VME) && defined(HAS_NIVXI)
static void __attribute__ ((constructor)) __init__lib__()
{
printf("### Loading NI-VXI module...\n");
}
static void __attribute__ ((destructor)) __close__lib__()
{
printf("### Unloading NI-VXI module...\n");
}
#define VXILINUX 1
#include <nivxi.h>
typedef NIVXI_HQUAL void NIVXI_HSPEC (*NIInterruptFunc)(int16 , uint16 , uint32);
typedef struct _modules_
{
short memSpace;
short LA;
int used;
char *name;
unsigned long Vadd, Vme;
}
MODULES, *LPMODULES;
class VXImanager : public VMEmanager
{
private:
int nModules;
unsigned long Window24, Window32;
LPMODULES modules;
void CloseMyVXI();
public:
VXImanager();
~VXImanager();
bool connected() const
{
return true;
}
int InitMyVXI(char *mList[]);
LPMODULES Module(int x);
int NModules() const
{
return nModules;
}
unsigned long map_address(unsigned long add, int size, int type);
unsigned long read32(unsigned long add );
void write32(unsigned long add, unsigned long val);
unsigned short read16(unsigned long add );
void write16(unsigned long add, unsigned short val);
void enable_interrupts(InterruptFunc, unsigned short);
void disable_interrupts();
};
VXImanager::VXImanager()
: nModules(0), Window24(0), Window32(0)
{
if (InitVXIlibrary() != 0)
{
std::cout << "Unable to initialize VXI library!" << std::endl;
exit(1);
}
}
VXImanager::~VXImanager()
{
CloseMyVXI();
}
void VXImanager::CloseMyVXI()
{
std::cout << "Closing VxI" << std::endl;
if ( Window24 ) UnMapVXIAddress(Window24);
if ( Window32 ) UnMapVXIAddress(Window32);
CloseVXIlibrary();
std::cout << "...OK" << std::endl;
}
MODULES *VXImanager::Module(int x)
{
return &modules[x];
}
int VXImanager::InitMyVXI(char *mList[])
{
int i;
int16 ret;
uint32 *uptr;
int16 Smallest24, Smallest32;
unsigned long SmAddr24 = 0xffffffff, SmAddr32 = 0xffffffff;
Window24 = 0;
Window32 = 0;
// savebushandler = GetBusErrorHandler();
// ret = SetBusErrorHandler(MyBusErrorHandler);
// if (InitVXIlibrary() != 0) {
// printf("Unable to initialize VXI library!\n");
// exit(1);
// }
// ret = MapVXIAddressSize(0x40000);
// if ( ret<0 ) {
// printf("NO way of increasing the window size\n");
// exit(1);
// }
//---------------------------------------------------------------------
// Get number of modules in the list
//---------------------------------------------------------------------
for (i = 0;mList[i];i++) nModules++;
// Allocate space
modules = (MODULES *)malloc(nModules * sizeof(MODULES));
for ( i = 0;i < nModules;i++)
{
modules[i].name = strdup(mList[i]);
modules[i].used = 1;
}
//---------------------------------------------------------------------
// Search the modules in the VXI data base
//---------------------------------------------------------------------
for (i = 0;i < nModules;i++)
{
ret = FindDevLA(modules[i].name, -1, -1, -1, -1, -1, -1, &modules[i].LA);
if ( ret < 0 )
{
std::cout << "Could not find module " << modules[i].name << std::endl;
CloseVXIlibrary();
exit(1);
}
ret = GetDevInfo(modules[i].LA, DI_MEMSPACE, &modules[i].memSpace);
ret = GetDevInfo(modules[i].LA, DI_MEMBASE, &modules[i].Vadd);
if ( modules[i].memSpace == 0 )
{
if ( modules[i].Vadd < SmAddr24 )
{
SmAddr24 = modules[i].Vadd;
Smallest24 = i;
}
}
else if ( modules[i].memSpace == 1 )
{
if ( modules[i].Vadd < SmAddr32 )
{
SmAddr32 = modules[i].Vadd;
Smallest32 = i;
}
}
else
{
std::cout << "Module " << modules[i].name << " is A16" << std::endl;
}
}
//---------------------------------------------------------------------
// Map memory for A24
//---------------------------------------------------------------------
if ( SmAddr24 != 0xffffffff )
{
uptr = (uint32 *)MapVXIAddress(AccessP_Space(A24_SPACE) |
AccessP_Priv(NonPriv_DATA) |
AccessP_BO(MOTOROLA_ORDER),
SmAddr24, 1000L, &Window24, &ret);
if ( ret < 0 || uptr == 0 )
{
std::cout << "Could not get pointer to Window\n"
<< "MapVXIAddress rc = " << ret << std::endl;
CloseVXIlibrary();
exit(1);
}
for (i = 0;i < nModules; i++)
if ( modules[i].memSpace == 0 )
modules[i].Vadd =
(unsigned long)uptr + ( modules[i].Vadd - SmAddr24 );
}
//---------------------------------------------------------------------
// Map memory for A32
//---------------------------------------------------------------------
if ( SmAddr32 != 0xffffffff )
{
uptr = (uint32 *)MapVXIAddress(AccessP_Space(A32_SPACE) |
AccessP_Priv(NonPriv_DATA) |
AccessP_BO(MOTOROLA_ORDER),
SmAddr32, 1000L, &Window32, &ret);
if ( ret < 0 || uptr == 0 )
{
std::cout << "Could not get pointer to Window\n"
<< "MapVXIAddress rc = " << ret << std::endl;
CloseVXIlibrary();
exit(1);
}
for (i = 0;i < nModules; i++)
if ( modules[i].memSpace == 1 )
modules[i].Vadd =
(unsigned long)uptr + ( modules[i].Vadd - SmAddr32 );
}
return 0;
}
unsigned long VXImanager::map_address(unsigned long add, int __s, int __type)
{
int16 ret;
int8 dname[14];
unsigned long Window32;
// Find the module in the NI database
short la;
unsigned long base, size, addr;
bool found = false;
for (la = 0x100;la < 0x200;la++)
{
ret = GetDevInfo(la, DI_MEMSPACE, &addr);
if (!ret)
{ // found it
std::cout << "Address space " << std::hex << addr << std::dec << std::endl;
ret = GetDevInfo(la, DI_MEMBASE, &base);
if ( base != add)
continue;
found = true;
ret = GetDevInfo(la, DI_MEMSIZE, &size);
ret = GetDevInfo(la, DI_DEVNAME, dname);
std::cout << "Found module " << (char *)dname
<< " LA " << std::hex << la << std::dec
<< " Addr. " << std::hex << base << std::dec
<< " size " << std::hex << size << std::dec
<< " Mem. space " << addr
<< std::endl;
switch (addr)
{
case 0:
addr = A24_SPACE;
break;
case 1:
addr = A32_SPACE;
break;
default:
addr = A24_SPACE;
break;
}
break;
}
}
if (!found)
{
std::cout << "No module registered whith address "
<< std::hex << add << std::dec << std::endl;
return 0;
}
unsigned long *uptr =
(uint32 *)MapVXIAddress(AccessP_Space(addr) |
AccessP_Priv(NonPriv_DATA) |
AccessP_BO(MOTOROLA_ORDER),
base, size, &Window24, &ret);
if ( ret < 0 || uptr == 0 )
{
std::cout << "Could not map VME address "
<< std::hex << base << std::dec
<< std::endl;
CloseVXIlibrary();
exit(1);
}
return (unsigned long )uptr;
}
void VXImanager::enable_interrupts(InterruptFunc func, unsigned short mask)
{
mask = 0x7f;
uint16 controler = 0xffff;
RouteVXIint(controler, 0);
SetVXIintHandler(mask, (NIInterruptFunc)func);
VXIintAcknowledgeMode(controler, 0);
EnableVXIint(controler, mask);
}
void VXImanager::disable_interrupts()
{
uint16 controler = 0xffff;
RouteVXIint(controler, 0);
SetVXIintHandler(0x7f, 0);
VXIintAcknowledgeMode(controler, 0);
EnableVXIint(controler, 0);
}
unsigned long VXImanager::read32(unsigned long add )
{
volatile unsigned long *p = (unsigned long *)add;
return *p;
}
void VXImanager::write32(unsigned long add, unsigned long val)
{
volatile unsigned long *p = (unsigned long *)add;
*p = val;
}
unsigned short VXImanager::read16(unsigned long add )
{
volatile unsigned short *p = (unsigned short *)add;
return *p;
}
void VXImanager::write16(unsigned long add, unsigned short val)
{
volatile unsigned short *p = (unsigned short *)add;
*p = val;
}
extern "C"
{
VMEmanager *create_nivxi_manager()
{
static VXImanager vxi;
return &vxi;
}
}
#endif