Parent Directory
|
Revision Log
|
Revision Graph
minor modifications
// $Id: vme_rcc_lib.cpp,v 1.14 2004/03/09 08:09:34 joos Exp $
/********************************************************************************/
/* */
/* File: vme_rcc_lib.c */
/* */
/* This is the RCC VMEbus library */
/* */
/* 24. Oct. 01 MAJO created */
/* 01. Nov. 01 JOP interrupts */
/* 26. Nov. 01 JOP bus errors */
/* 09. Jan. 02 JOP replace parameters by structure pointer in wait/getinfo */
/* */
/************ C 2001 - The software with that certain something *****************/
#include <iostream>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <asm/page.h>
#include <linux/pci.h>
#include "rcc_error/rcc_error.h"
#include "vme_rcc.h"
#include "vme_rcc_lib.h"
#include "cmem_rcc/cmem_rcc.h"
#include "io_rcc/io_rcc.h"
#include "DFDebug/DFDebug.h"
//globals
static u_int is_open = 0;
static int gahandle,dev_handle;
static VME_MasterMap_t ga_master_map;
static VME_MasterMapInt_t mastermap_table[VME_MAX_MASTERMAP];
static VME_SlaveMapInt_t slavemap_table[VME_MAX_SLAVEMAP];
static int shandle;
static unsigned int crcsrok, shandle_size, shandle_paddr, shandle_uaddr;
static u_int universe_handle, chains[VME_MAXCHAIN];
static VME_IntHandle_t int_handle[VME_MAX_INTHANDLE]; // the interrupt handles
/********************************************/
int VME_ErrorPrint(VME_ErrorCode_t error_code)
/********************************************/
{
unsigned int ret;
ret = rcc_error_print(stdout, error_code);
return(ret);
}
/*****************************************************************/
int VME_ErrorString(VME_ErrorCode_t error_code, char *error_string)
/*****************************************************************/
{
unsigned int ret;
ret = rcc_error_string(error_string, error_code);
return(ret);
}
/****************************************************************/
int VME_ErrorNumber(VME_ErrorCode_t error_code, int *error_number)
/****************************************************************/
{
*error_number = RCC_ERROR_MINOR(error_code);
return(0);
}
/****************************/
VME_ErrorCode_t VME_Open(void)
/****************************/
{
int loop,ret;
u_int *ptr;
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Open: Start of function");
//we need to open the driver only once
if (is_open)
{
is_open++; //keep track of multiple open calls
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
is_open = 1;
//open the error package
ret = rcc_error_init(P_ID_VMERCC,vmercc_err_get);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Open: Failed to open error package");
is_open = 0;
return(RCC_ERROR_RETURN(0, VME_ERROR_FAIL));
}
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Open: error package opened");
dev_handle = open(DEVICE, O_RDWR, 0);
if (dev_handle < 0)
{
is_open = 0;
return(RCC_ERROR_RETURN(0, VME_FILE));
}
//initialize the master map table
for (loop = 0; loop < VME_MAX_MASTERMAP; loop++)
mastermap_table[loop].used = 0;
//initialize the slave map table
for (loop = 0; loop < VME_MAX_SLAVEMAP; loop++)
slavemap_table[loop].used = 0;
//Open the IO package
ret = IO_Open();
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Open: Error from IO_Open");
is_open = 0;
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
//allocate memory for chain descriptors
ret = CMEM_Open();
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Open: Error from CMEM_Open");
is_open = 0;
return(RCC_ERROR_RETURN(ret, VME_CMEM_FAIL));
}
shandle_size = DMA_DESC_SIZE;
ret = CMEM_SegmentAllocate(shandle_size, "VME_RCC_DMA_INTERNAL", &shandle);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Open: Error from CMEM_SegmentAllocate");
is_open = 0;
return(RCC_ERROR_RETURN(ret, VME_CMEM_FAIL));
}
ret = CMEM_SegmentPhysicalAddress(shandle, &shandle_paddr);
ret = CMEM_SegmentVirtualAddress(shandle, &shandle_uaddr);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_Open: shandle_uaddr=0x" << std::hex << (u_int)shandle_uaddr << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_Open: shandle_paddr=0x" << std::hex << (u_int)shandle_paddr << std::dec);
//initialize the DMA chain descriptors
ptr = (u_int *)shandle_uaddr;
for (loop = 0; loop < ((VME_MAXCHAINEL * VME_MAXCHAIN * sizeof(VME_DmaChain_t)) >> 2); loop++)
*ptr ++= 0;
//initialize the DMA chain descriptor handles
for (loop = 0; loop < VME_MAXCHAIN; loop++)
chains[loop] = 0;
//Get a permanent mapping for CR/CSR space access
//An error here should not kill us as we have to be able to open the library
//in vmeconfig
crcsrok = 1;
ga_master_map.vmebus_address = CRCSR_BASE;
ga_master_map.window_size = CRCSR_SIZE;
ga_master_map.address_modifier= VME_CRCSR;
ga_master_map.options = CRCSR_OPT;
ret = VME_MasterMap(&ga_master_map, &gahandle);
if (ret != VME_SUCCESS)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Open: Error received from VME_MasterMap for CR/CSR window");
crcsrok = 0;
}
else
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Open: Mapping created for CR/CSR space access");
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Open: End of function");
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*****************************/
VME_ErrorCode_t VME_Close(void)
/*****************************/
{
int ret;
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Close: Start of function");
ISOPEN;
if (is_open > 1)
{
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_Close: is_open = " << is_open);
is_open--;
}
else
{
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Close: Now closing the library");
//Close master mapping for CR/CSR space access
if (crcsrok)
{
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_Close: gahandle = " << gahandle);
ret = VME_MasterUnmap(gahandle);
if (ret != VME_SUCCESS)
return(RCC_ERROR_RETURN(0, ret));
}
ret = CMEM_SegmentFree(shandle);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Close: Error from CMEM_SegmentFree");
return(RCC_ERROR_RETURN(ret, VME_CMEM_FAIL));
}
ret = CMEM_Close();
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Close: Error from CMEM_Close");
return(RCC_ERROR_RETURN(ret, VME_CMEM_FAIL));
}
ret = IO_Close();
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Close: Error from IO_Close");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
ret = close(dev_handle);
if (ret < 0)
return(RCC_ERROR_RETURN(0, VME_FILE));
is_open = 0;
}
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Close: End of function");
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**********************************************************************************/
VME_ErrorCode_t VME_ReadCRCSR(int slot_number, u_int crcsr_identifier, u_int *value)
/**********************************************************************************/
{
u_int offset, nbytes, ret;
u_char bdata1, bdata2, bdata3, bdata4;
ISOPEN;
if (!crcsrok)
return(RCC_ERROR_RETURN(0, VME_NOCRCSRMAP));
if (slot_number < 1 && slot_number > 21)
return(RCC_ERROR_RETURN(0, VME_RANGE));
nbytes = crcsr_identifier >> 28;
offset = crcsr_identifier & 0x0fffffff;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_ReadCRCSR: nbytes = " << nbytes);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_ReadCRCSR: offset = 0x" << std::hex << offset << std::dec);
//Add the board offset
offset += CRCSR_OFF * slot_number;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_ReadCRCSR: VMEbus address = 0x" << std::hex << offset << std::dec);
bdata1 = 0;
bdata2 = 0;
bdata3 = 0;
bdata4 = 0;
ret = VME_ReadSafeUChar(gahandle, offset, &bdata1);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_ReadCRCSR: bdata1 = 0x" << std::hex << bdata1 << std::dec);
if (nbytes > 1)
{
ret = VME_ReadSafeUChar(gahandle, offset + 0x4, &bdata2);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_ReadCRCSR: bdata2 = 0x" << std::hex << bdata2 << std::dec);
}
if (nbytes > 2)
{
ret = VME_ReadSafeUChar(gahandle, offset + 0x8, &bdata3);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_ReadCRCSR: bdata3 = 0x" << std::hex << bdata3 << std::dec);
}
if (nbytes > 3)
{
ret = VME_ReadSafeUChar(gahandle, offset + 0xc, &bdata4);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_ReadCRCSR: bdata4 = 0x" << std::hex << bdata4 << std::dec);
}
if (nbytes == 1)
*value = bdata1;
if (nbytes == 2)
*value = (bdata1 << 8) | bdata2;
if (nbytes == 3)
*value = (bdata1 << 16) | (bdata2 << 8) | bdata3;
if (nbytes == 4)
*value = (bdata1 << 24) | (bdata2 << 16) | (bdata3 << 8) | bdata4;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**********************************************************************************/
VME_ErrorCode_t VME_WriteCRCSR(int slot_number, u_int crcsr_identifier, u_int value)
/**********************************************************************************/
{
u_int offset,nbytes,ret;
u_char bdata1,bdata2,bdata3,bdata4;
ISOPEN;
if (!crcsrok)
return(RCC_ERROR_RETURN(0, VME_NOCRCSRMAP));
if (slot_number < 1 && slot_number > 21)
return(RCC_ERROR_RETURN(0, VME_RANGE));
nbytes = crcsr_identifier >> 28;
offset = crcsr_identifier & 0x0fffffff;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_WriteCRCSR: nbytes = " << nbytes);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_WriteCRCSR: offset = 0x" << std::hex << offset << std::dec);
//Add the board offset
offset += CRCSR_OFF * slot_number;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_WriteCRCSR: VMEbus address = 0x" << std::hex << offset << std::dec);
if (nbytes == 1)
bdata1 = value & 0xff;
if (nbytes == 2)
{
bdata1 = (value >> 8) & 0xff;
bdata2 = value & 0xff;
}
if (nbytes == 3)
{
bdata1 = (value >> 16) & 0xff;
bdata2 = (value >> 8) & 0xff;
bdata3 = value & 0xff;
}
if (nbytes == 4)
{
bdata1 = (value >> 24) & 0xff;
bdata2 = (value >> 16) & 0xff;
bdata3 = (value >> 8) & 0xff;
bdata4 = value & 0xff;
}
ret = VME_WriteSafeUChar(gahandle, offset, bdata1);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
if (nbytes > 1)
{
ret = VME_WriteSafeUChar(gahandle, offset + 0x4, bdata2);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
}
if (nbytes > 2)
{
ret = VME_WriteSafeUChar(gahandle, offset + 0x8, bdata3);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
}
if (nbytes > 3)
{
ret = VME_WriteSafeUChar(gahandle, offset + 0xc, bdata4);
if (ret)
return(RCC_ERROR_RETURN(0, ret));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*****************************************************************************/
VME_ErrorCode_t VME_MasterMap(VME_MasterMap_t *master_map, int *master_mapping)
/*****************************************************************************/
{
int loop, ret, ok, paddr;
u_int size, rest;
ISOPEN;
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_MasterMap: Start of function");
//check the input in master_map for consistency
//MJ: to be done
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: vmebus_address = 0x" << std::hex << master_map->vmebus_address << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: window_size = 0x" << std::hex << master_map->window_size << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: address_modifier = 0x" << std::hex << master_map->address_modifier << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: options = " << master_map->options);
//look for a free slot in the master map table
ok = 0;
for (loop = 0; loop < VME_MAX_MASTERMAP; loop++)
{
if (mastermap_table[loop].used == 0)
{
mastermap_table[loop].used = 1;
mastermap_table[loop].in.vmebus_address = master_map->vmebus_address;
mastermap_table[loop].in.window_size = master_map->window_size;
mastermap_table[loop].in.address_modifier = master_map->address_modifier;
mastermap_table[loop].in.options = master_map->options;
ok=1;
break;
}
}
if (!ok)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_MasterMap: No entry found in master map table");
return(RCC_ERROR_RETURN(0, VME_NOMAP));
}
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: Using entry " << loop << " in master map table");
*master_mapping = loop;
ret = ioctl(dev_handle, VMEMASTERMAP, &mastermap_table[loop]);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_MasterMap: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
mastermap_table[loop].used = 0;
return(RCC_ERROR_RETURN(0, errno));
}
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: PCI address=0x" << std::hex << mastermap_table[loop].pci_address << std::dec);
//get virtual address
//PCI address must be page aligned
paddr = mastermap_table[loop].pci_address & ~(PAGE_SIZE - 1);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: aligned PCI address=0x" << std::hex << paddr << std::dec);
rest = mastermap_table[loop].pci_address - paddr;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: rest=0x" << std::hex << rest << std::dec);
//size must be page aligned
size = master_map->window_size + rest;
if (size % PAGE_SIZE)
size = (size + PAGE_SIZE) & ~(PAGE_SIZE - 1);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: aligned size=0x" << std::hex << size << std::dec);
mastermap_table[loop].virt_address = (u_int)mmap(0, size, (PROT_READ|PROT_WRITE), MAP_SHARED, dev_handle, paddr);
if ((int)mastermap_table[loop].virt_address <= 0)
{
mastermap_table[loop].virt_address = 0;
return(RCC_ERROR_RETURN(0, VME_VIRT));
}
//add offset
mastermap_table[loop].virt_address += rest;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterMap: virtual address = 0x" << std::hex << mastermap_table[loop].virt_address << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_MasterMap: End of function");
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*************************************************************************************/
VME_ErrorCode_t VME_MasterMapVirtualAddress(int master_mapping, u_int *virtual_address)
/*************************************************************************************/
{
ISOPEN;
if (mastermap_table[master_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
*virtual_address = mastermap_table[master_mapping].virt_address;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**************************************************************************************/
VME_ErrorCode_t VME_ReadSafeUInt(int master_mapping, u_int address_offset, u_int *value)
/**************************************************************************************/
{
int ret;
VME_SingleCycle_t sc;
ISOPEN;
if (mastermap_table[master_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (address_offset & 0x3)
return(RCC_ERROR_RETURN(0, VME_ALIGN));
if (address_offset >= mastermap_table[master_mapping].in.window_size)
return(RCC_ERROR_RETURN(0, VME_RANGE));
sc.kvirt_address = mastermap_table[master_mapping].kvirt_address;
sc.offset = address_offset;
sc.nbytes = 4; //transfer 32 bits
sc.rw = 1; //read
DEBUG_TEXT(DFDB_VMERCC, 20, "VME_ReadSafeUInt: master_mapping = " << master_mapping << " address_offset = 0x" << std::hex << address_offset << std::dec);
ret = ioctl(dev_handle, VMESCSAFE, &sc);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_ReadSafeUInt: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
*value = sc.data;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/******************************************************************************************/
VME_ErrorCode_t VME_ReadSafeUShort(int master_mapping, u_int address_offset, u_short *value)
/******************************************************************************************/
{
int ret;
VME_SingleCycle_t sc;
ISOPEN;
if (mastermap_table[master_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (address_offset & 0x1)
return(RCC_ERROR_RETURN(0, VME_ALIGN));
if (address_offset >= mastermap_table[master_mapping].in.window_size)
return(RCC_ERROR_RETURN(0, VME_RANGE));
sc.kvirt_address = mastermap_table[master_mapping].kvirt_address;
sc.offset = address_offset;
sc.nbytes = 2; //transfer 16 bits
sc.rw = 1; //read
DEBUG_TEXT(DFDB_VMERCC, 20, "VME_ReadSafeUShort: master_mapping = " << master_mapping << " address_offset = 0x" << std::hex << address_offset << std::dec);
ret = ioctl(dev_handle, VMESCSAFE, &sc);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_ReadSafeUShort: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
*value = sc.data & 0xffff;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/****************************************************************************************/
VME_ErrorCode_t VME_ReadSafeUChar(int master_mapping, u_int address_offset, u_char *value)
/****************************************************************************************/
{
int ret;
VME_SingleCycle_t sc;
ISOPEN;
if (mastermap_table[master_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (address_offset >= mastermap_table[master_mapping].in.window_size)
return(RCC_ERROR_RETURN(0, VME_RANGE));
sc.kvirt_address = mastermap_table[master_mapping].kvirt_address;
sc.offset = address_offset;
sc.nbytes = 1; //transfer 8 bits
sc.rw = 1; //read
DEBUG_TEXT(DFDB_VMERCC, 20, "VME_ReadSafeUChar: master_mapping = " << master_mapping << " address_offset = 0x" << std::hex << address_offset << std::dec);
ret = ioctl(dev_handle, VMESCSAFE, &sc);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_ReadSafeUChar: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
*value = sc.data & 0xff;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**************************************************************************************/
VME_ErrorCode_t VME_WriteSafeUInt(int master_mapping, u_int address_offset, u_int value)
/**************************************************************************************/
{
int ret;
VME_SingleCycle_t sc;
ISOPEN;
if (mastermap_table[master_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (address_offset & 0x3)
return(RCC_ERROR_RETURN(0, VME_ALIGN));
if (address_offset >= mastermap_table[master_mapping].in.window_size)
return(RCC_ERROR_RETURN(0, VME_RANGE));
sc.kvirt_address = mastermap_table[master_mapping].kvirt_address;
sc.offset = address_offset;
sc.nbytes = 4; //transfer 32 bits
sc.rw = 0; //write
sc.data = value;
DEBUG_TEXT(DFDB_VMERCC, 20, "VME_WriteSafeUInt: master_mapping = " << master_mapping << " address_offset = 0x" << std::hex << address_offset << std::dec);
ret = ioctl(dev_handle, VMESCSAFE, &sc);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_WriteSafeUInt: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/******************************************************************************************/
VME_ErrorCode_t VME_WriteSafeUShort(int master_mapping, u_int address_offset, u_short value)
/******************************************************************************************/
{
int ret;
VME_SingleCycle_t sc;
ISOPEN;
if (mastermap_table[master_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (address_offset & 0x1)
return(RCC_ERROR_RETURN(0, VME_ALIGN));
if (address_offset >= mastermap_table[master_mapping].in.window_size)
return(RCC_ERROR_RETURN(0, VME_RANGE));
sc.kvirt_address = mastermap_table[master_mapping].kvirt_address;
sc.offset = address_offset;
sc.nbytes = 2; //transfer 16 bits
sc.rw = 0; //write
sc.data = (u_int)value;
DEBUG_TEXT(DFDB_VMERCC, 20, "VME_WriteSafeUShort: master_mapping = " << master_mapping << " address_offset = 0x" << std::hex << address_offset << std::dec);
ret = ioctl(dev_handle, VMESCSAFE, &sc);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_WriteSafeUShort: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/****************************************************************************************/
VME_ErrorCode_t VME_WriteSafeUChar(int master_mapping, u_int address_offset, u_char value)
/****************************************************************************************/
{
int ret;
VME_SingleCycle_t sc;
ISOPEN;
if (mastermap_table[master_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (address_offset >= mastermap_table[master_mapping].in.window_size)
return(RCC_ERROR_RETURN(0, VME_RANGE));
sc.kvirt_address = mastermap_table[master_mapping].kvirt_address;
sc.offset = address_offset;
sc.nbytes = 1; //transfer 8 bits
sc.rw = 0; //write
sc.data = (u_int)value;
DEBUG_TEXT(DFDB_VMERCC, 20, "VME_WriteSafeUChar: master_mapping = " << master_mapping << " address_offset = 0x" << std::hex << address_offset << std::dec);
ret = ioctl(dev_handle, VMESCSAFE, &sc);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_WriteSafeUChar: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/***************************************************************************/
void VME_ReadFastUInt(int master_mapping, u_int address_offset, u_int *value)
/***************************************************************************/
{
u_int ret, virtual_address;
ret = VME_MasterMapVirtualAddress(master_mapping, &virtual_address);
if (!ret)
*value = *(u_int *)(virtual_address + address_offset);
else
*value = 0xffffffff;
}
/*******************************************************************************/
void VME_ReadFastUShort(int master_mapping, u_int address_offset, u_short *value)
/*******************************************************************************/
{
u_int ret, virtual_address;
ret = VME_MasterMapVirtualAddress(master_mapping, &virtual_address);
if (!ret)
*value = *(u_short *)(virtual_address + address_offset);
else
*value = 0xffff;
}
/*****************************************************************************/
void VME_ReadFastUChar(int master_mapping, u_int address_offset, u_char *value)
/*****************************************************************************/
{
u_int ret, virtual_address;
ret = VME_MasterMapVirtualAddress(master_mapping, &virtual_address);
if (!ret)
*value = *(u_char *)(virtual_address + address_offset);
else
*value = 0xff;
}
/***************************************************************************/
void VME_WriteFastUInt(int master_mapping, u_int address_offset, u_int value)
/***************************************************************************/
{
u_int ret, virtual_address;
ret = VME_MasterMapVirtualAddress(master_mapping, &virtual_address);
if (!ret)
*(u_int *)(virtual_address + address_offset) = value;
}
/*******************************************************************************/
void VME_WriteFastUShort(int master_mapping, u_int address_offset, u_short value)
/*******************************************************************************/
{
u_int ret, virtual_address;
ret = VME_MasterMapVirtualAddress(master_mapping, &virtual_address);
if (!ret)
*(u_short *)(virtual_address + address_offset) = value;
}
/*****************************************************************************/
void VME_WriteFastUChar(int master_mapping, u_int address_offset, u_char value)
/*****************************************************************************/
{
u_int ret, virtual_address;
ret = VME_MasterMapVirtualAddress(master_mapping, &virtual_address);
if (!ret)
*(u_char *)(virtual_address + address_offset) = value;
}
/*************************************************/
VME_ErrorCode_t VME_MasterUnmap(int master_mapping)
/*************************************************/
{
int ret;
u_int vaddr, size;
ISOPEN;
if (!mastermap_table[master_mapping].used)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
mastermap_table[master_mapping].used = 0;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterUnmap: mastermap_table[" << master_mapping << "].kvirt_address = 0x" << std::hex << mastermap_table[master_mapping].kvirt_address << std::dec);
ret = ioctl(dev_handle, VMEMASTERUNMAP, &mastermap_table[master_mapping].kvirt_address);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_MasterUnmap: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
//compute values for munmap
vaddr = mastermap_table[master_mapping].virt_address - (mastermap_table[master_mapping].pci_address & (PAGE_SIZE - 1));
size = mastermap_table[master_mapping].in.window_size + (mastermap_table[master_mapping].pci_address & (PAGE_SIZE - 1));
if (size % PAGE_SIZE)
size = (size + PAGE_SIZE) & ~(PAGE_SIZE - 1);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterUnmap: size = 0x" << std::hex << size << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_MasterUnmap: virt. address = 0x" << std::hex << vaddr << std::dec);
ret = munmap((char *)vaddr, size);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_MasterUnmap: Error from munmap, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, VME_MUNMAP));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*************************************/
VME_ErrorCode_t VME_MasterMapDump(void)
/*************************************/
{
int ret;
char mytext[TEXT_SIZE1];
ISOPEN;
ret = ioctl(dev_handle, VMEMASTERMAPDUMP, mytext);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_MasterMapDump: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
printf("%s", mytext);
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/***********************************************************/
VME_ErrorCode_t VME_BusErrorRegisterSignal(int signal_number)
/***********************************************************/
{
int ret;
VME_RegSig_t reg_sig_arg;
ISOPEN;
reg_sig_arg.signum = signal_number;
ret = ioctl(dev_handle, VMEBERRREGISTERSIGNAL, ®_sig_arg);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BerrRegisterSignal: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*********************************************************************/
VME_ErrorCode_t VME_BusErrorInfoGet(VME_BusErrorInfo_t *bus_error_info)
/*********************************************************************/
{
int ret;
ISOPEN;
// pass the structure unchanged ..
ret = ioctl(dev_handle, VMEBERRINFO, bus_error_info);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BusErrorInfoGet: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*************************************************************************/
VME_ErrorCode_t VME_SlaveMap(VME_SlaveMap_t *slave_map, int *slave_mapping)
/*************************************************************************/
{
int loop, ret, ok;
ISOPEN;
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_SlaveMap: Start of function");
//check the input in slave_map for consistency
//MJ: to be done
//look for a free slot in the slave map table
ok = 0;
for (loop = 0; loop < VME_MAX_SLAVEMAP; loop++)
{
if (slavemap_table[loop].used == 0)
{
slavemap_table[loop].used = 1;
slavemap_table[loop].in.system_iobus_address = slave_map->system_iobus_address;
slavemap_table[loop].in.window_size = slave_map->window_size;
slavemap_table[loop].in.address_width = slave_map->address_width;
slavemap_table[loop].in.options = slave_map->options;
ok = 1;
break;
}
}
if (!ok)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SlaveMap: No entry found in slave map table");
return(RCC_ERROR_RETURN(0, VME_NOMAP));
}
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_SlaveMap: Using entry " << loop << " in slave map table");
*slave_mapping = loop;
ret = ioctl(dev_handle, VMESLAVEMAP, &slavemap_table[loop]);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SlaveMap: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
slavemap_table[loop].used = 0;
return(RCC_ERROR_RETURN(0, errno));
}
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_SlaveMap: VME address=0x" << std::hex << slavemap_table[loop].vme_address << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_SlaveMap: End of function");
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*********************************************************************************/
VME_ErrorCode_t VME_SlaveMapVmebusAddress(int slave_mapping, u_int *vmebus_address)
/*********************************************************************************/
{
ISOPEN;
if (!slavemap_table[slave_mapping].used)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_SlaveMapVmebusAddress: VME address=0x" << std::hex << slavemap_table[slave_mapping].vme_address << std::dec);
*vmebus_address = slavemap_table[slave_mapping].vme_address;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/***********************************************/
VME_ErrorCode_t VME_SlaveUnmap(int slave_mapping)
/***********************************************/
{
ISOPEN;
if (slavemap_table[slave_mapping].used == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
slavemap_table[slave_mapping].used = 0;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/************************************/
VME_ErrorCode_t VME_SlaveMapDump(void)
/************************************/
{
int ret;
char mytext[TEXT_SIZE1];
ISOPEN;
ret = ioctl(dev_handle, VMESLAVEMAPDUMP, mytext);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SlaveMapDump: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
printf("%s", mytext);
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/******************************************************************************************************/
VME_ErrorCode_t VME_BlockTransferInit(VME_BlockTransferList_t *block_transfer_list, int *block_transfer)
/******************************************************************************************************/
{
int loop, ok, celem, cnum;
u_int offset, vaddr, paddr, size, msize, ctrl, fcap, next;
VME_DmaChain_t *chain;
ISOPEN;
//look for a free dma chain
ok = 0;
for (cnum = 0; cnum < VME_MAXCHAIN; cnum++)
{
if(chains[cnum] == 0)
{
chains[cnum] = 1;
ok = 1;
break;
}
}
if (!ok)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: No free chain found");
return(RCC_ERROR_RETURN(0, VME_NOCHAINMEM));
}
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: Using chain " << cnum);
*block_transfer = cnum;
//fill the chain with information from block_transfer_list
celem = 0;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: List contains " << block_transfer_list->number_of_items << " elements");
for (loop = 0; loop < block_transfer_list->number_of_items; loop++)
{
vaddr = block_transfer_list->list_of_items[loop].vmebus_address;
paddr = block_transfer_list->list_of_items[loop].system_iobus_address;
size = block_transfer_list->list_of_items[loop].size_requested;
ctrl = block_transfer_list->list_of_items[loop].control_word;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: vaddr = 0x" << std::hex << vaddr << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: paddr = 0x" << std::hex << paddr << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: size = 0x" << std::hex << size << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: ctrl = 0x" << std::hex << ctrl << std::dec);
if (!size)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: Size=0 in item " << loop);
return(RCC_ERROR_RETURN(0, VME_NOSIZE));
}
if (size & 0x7)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: Size not 8 byte aligned in item " << loop);
return(RCC_ERROR_RETURN(0, VME_ALIGN));
}
if ((vaddr & 0x7) != (paddr & 0x7))
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: VME/PCI addresses not 8 byte aligned in item " << loop);
return(RCC_ERROR_RETURN(0, VME_ALIGN));
}
if ((ctrl & VME_DMA_D64) && (vaddr & 0x7))
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: VMEbus address not 8 byte aligned in item " << loop);
return(RCC_ERROR_RETURN(0, VME_ALIGN));
}
if ((ctrl & VME_DMA_D64) && (paddr & 0x7))
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: PCI address not 8 byte aligned in item " << loop);
return(RCC_ERROR_RETURN(0, VME_ALIGN));
}
else if (size & 0x3) //Check size alignment for D32 transfers
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: Size address not 4 byte aligned in item " << loop);
return(RCC_ERROR_RETURN(0, VME_ALIGN));
}
while (size)
{
if (celem > VME_MAXCHAINEL)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferInit: Chain overflow");
return(RCC_ERROR_RETURN(0, VME_TOOLONG));
}
msize = size;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: msize = 0x" << std::hex << msize << std::dec);
//check for size overflow
if (msize > VME_DMA_MAX_BLOCK_SIZE)
msize = VME_DMA_MAX_BLOCK_SIZE;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: msize(2) = 0x" << std::hex << msize << std::dec);
//reduce remaining size
size -= msize;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: Current chain = " << cnum);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: Current element = " << celem);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: sizeof(VME_DmaChain_t) = 0x" << std::hex << sizeof(VME_DmaChain_t) << std::dec);
//calculate the offset of the current chain element
offset = cnum * VME_MAXCHAINEL * sizeof(VME_DmaChain_t) + celem * sizeof(VME_DmaChain_t);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: offset of chain element = 0x" << std::hex << offset << std::dec);
//get the user address of the current chain element
chain = (VME_DmaChain_t *)(shandle_uaddr + offset);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: Virtual address of first chain descriptor = 0x" << std::hex << (u_int)chain << std::dec);
//calculate the PCI address of the next chain element
next = shandle_paddr + offset + sizeof(VME_DmaChain_t);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: PCI address of next element = 0x" << std::hex << next << std::dec);
if (size == 0 && (loop + 1) == block_transfer_list->number_of_items) //last element in the chain
fcap = DMA_CHAIN_END;
else
fcap = next; //address of next cap
//MJ: Use the line below on 64bit PCI busses
//ctrl |= 0x80;
chain->dtbc = BSWAP(msize);
chain->dctl = BSWAP(ctrl);
chain->dla = BSWAP(paddr);
chain->dva = BSWAP(vaddr);
chain->dcpp = BSWAP(fcap);
chain->ref = loop;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: dctl=0x" << std::hex << BSWAP(chain->dctl) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: dtbc=0x" << std::hex << BSWAP(chain->dtbc) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: dla =0x" << std::hex << BSWAP(chain->dla) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: dva =0x" << std::hex << BSWAP(chain->dva) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: dcpp=0x" << std::hex << BSWAP(chain->dcpp) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: ref =0x" << std::hex << BSWAP(chain->ref) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferInit: blocklet = 0x" << std::hex << msize << " rest = 0x" << size << " Address of chain = 0x" << (u_int)chain << std::dec);
//update addresses
paddr += msize;
vaddr += msize;
celem++;
}
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/********************************************************/
VME_ErrorCode_t VME_BlockTransferStart(int block_transfer)
/********************************************************/
{
int ret;
u_int paddr;
VME_DMAstart_t params;
ISOPEN;
//does this list exist?
if (chains[block_transfer] != 1)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
//calculate the PCI address of the first chain element
paddr = shandle_paddr + block_transfer * VME_MAXCHAINEL * sizeof(VME_DmaChain_t);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferStart: PCI address of first chain element = 0x" << std::hex << paddr << std::dec);
params.paddr = paddr;
params.handle = block_transfer;
ret = ioctl(dev_handle, VMEDMASTART, ¶ms);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferStart: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*******************************************************************************************************************/
VME_ErrorCode_t VME_BlockTransferWait(int block_transfer, int time_out, VME_BlockTransferList_t *block_transfer_list)
/*******************************************************************************************************************/
{
u_int celem, offset, ok, ret;
int tics;
VME_DmaChain_t *chain;
VME_DMAhandle_t poll;
ISOPEN;
//does this list exist?
if (chains[block_transfer] != 1)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (time_out > 0)
tics = (time_out + 9) / 10;
else if (time_out == 0)
tics = 0;
else if (time_out == -1)
tics = -1;
else
return(RCC_ERROR_RETURN(0, VME_ILL_TO));
poll.handle = block_transfer;
poll.timeoutval = tics;
ret = ioctl(dev_handle, VMEDMAPOLL, &poll);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferWait: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: After poll/wait poll.ctrl =0x" << std::hex << poll.ctrl << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: After poll/wait poll.counter =0x" << std::hex << poll.counter << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: After poll/wait poll.timeout =0x" << std::hex << poll.timeout << std::dec);
//are we still busy
if (poll.ctrl == 0 && time_out == 0)
return(RCC_ERROR_RETURN(0, VME_DMABUSY));
//was there a time-out
//if (poll.ctrl == 0 && time_out > 0)
//return(RCC_ERROR_RETURN(0, VME_TIMEOUT));
//DMA has ended. Analyze result
ok = 1;
for (celem = 0; celem < VME_MAXCHAINEL; celem++)
{
//calculate the offset of the current chain element
offset = block_transfer * VME_MAXCHAINEL * sizeof(VME_DmaChain_t) + celem * sizeof(VME_DmaChain_t);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: offset of chain element = 0x" << std::hex << offset << std::dec);
//get the user address of the current chain element
chain = (VME_DmaChain_t *)(shandle_uaddr + offset);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: Virtual address of first chain descriptor = 0x" << std::hex << (u_int)chain << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: Dumping chain element " << celem);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: dctl = 0x" << std::hex << BSWAP(chain->dctl) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: dtbc = 0x" << std::hex << BSWAP(chain->dtbc) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: dla = 0x" << std::hex << BSWAP(chain->dla) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: dva = 0x" << std::hex << BSWAP(chain->dva) << std::dec);
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: dcpp = 0x" << std::hex << BSWAP(chain->dcpp) << std::dec);
if (!ok) //there was already an error in a previous block
{
block_transfer_list->list_of_items[chain->ref].status_word= VME_NOT_EXECUTED;
block_transfer_list->list_of_items[chain->ref].size_remaining = block_transfer_list->list_of_items[chain->ref].size_requested;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: Element not executed");
}
else if (BSWAP(chain->dcpp) & 0x2) //element successfully completed
{
block_transfer_list->list_of_items[chain->ref].status_word = VME_SUCCESS;
block_transfer_list->list_of_items[chain->ref].size_remaining = 0;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_BlockTransferWait: Element OK");
}
else
{
if (poll.ctrl & 0x400)
{
block_transfer_list->list_of_items[chain->ref].status_word = VME_PCI_ERR;
block_transfer_list->list_of_items[chain->ref].size_remaining = poll.counter;
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferWait: Element has PCI error");
}
else if (poll.ctrl & 0x200)
{
block_transfer_list->list_of_items[chain->ref].status_word = VME_VME_ERR;
block_transfer_list->list_of_items[chain->ref].size_remaining = poll.counter;
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferWait: Element has VMEbus error");
}
else if (poll.ctrl & 0x100)
{
block_transfer_list->list_of_items[chain->ref].status_word = VME_PROTOCOL_ERR;
block_transfer_list->list_of_items[chain->ref].size_remaining = poll.counter;
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferWait: Element has protocol error");
}
ok = 0;
}
if (BSWAP(chain->dcpp) & 0x1) //end of chain
break;
}
if (poll.ctrl != 0x800)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferWait: Transfer had an error. poll.ctrl is 0x" << std::hex << poll.ctrl << std::dec);
return(RCC_ERROR_RETURN(0, VME_DMAERR));
}
if (!poll.timeout)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_BlockTransferWait: transfer timed out");
return(RCC_ERROR_RETURN(0, VME_TIMEOUT));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/******************************************************/
VME_ErrorCode_t VME_BlockTransferEnd(int block_transfer)
/******************************************************/
{
ISOPEN;
//does this list exist?
if (chains[block_transfer] != 1)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
chains[block_transfer] = 0;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*******************************************************************************************/
VME_ErrorCode_t VME_BlockTransfer(VME_BlockTransferList_t *block_transfer_list, int time_out)
/*******************************************************************************************/
{
u_int ret;
int handle, errnum;
ISOPEN;
if (time_out == 0)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
ret = VME_BlockTransferInit(block_transfer_list, &handle);
if (ret != VME_SUCCESS)
return(RCC_ERROR_RETURN(0, ret));
else
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_BlockTransfer: VME_BlockTransferInit OK");
// We do not want VME_BlockTransfer to fail because VME_BlockTransferStart return
// VME_DMABUSY. Therefore we wait for the DMA controller to become available.
// This is aceptable because VME_BlockTransfer is a blocking function anyway.
// The while() loop could only be endless if the DMA semaphore gets lost. This is
// a fatal error anyway. One could discuss putting a yield() into the loop to preserve
// some CPU time.
while(1)
{
ret = VME_BlockTransferStart(handle);
VME_ErrorNumber(ret, &errnum);
if (errnum != VME_SUCCESS && errnum != VME_DMABUSY)
{
VME_BlockTransferEnd(handle);
return(RCC_ERROR_RETURN(0, ret));
}
if (errnum == VME_SUCCESS)
{
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_BlockTransfer: VME_BlockTransferStart OK");
break;
}
}
ret = VME_BlockTransferWait(handle, time_out, block_transfer_list);
if (ret != VME_SUCCESS)
{
VME_BlockTransferEnd(handle);
return(RCC_ERROR_RETURN(0, ret));
}
else
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_BlockTransfer: VME_BlockTransferWait OK");
ret = VME_BlockTransferEnd(handle);
if (ret != VME_SUCCESS)
return(RCC_ERROR_RETURN(0, ret));
else
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_BlockTransfer: VME_BlockTransferEnd OK");
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**************************************************************************************/
VME_ErrorCode_t VME_BlockTransferStatus(VME_BlockTransferList_t *block_transfer_list,
int position_of_block, VME_ErrorCode_t *status)
/**************************************************************************************/
{
ISOPEN;
if (position_of_block > block_transfer_list->number_of_items)
return(RCC_ERROR_RETURN(0, VME_RANGE));
*status = block_transfer_list->list_of_items[position_of_block].status_word;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**************************************************************************************/
VME_ErrorCode_t VME_BlockTransferRemaining(VME_BlockTransferList_t *block_transfer_list,
int position_of_block, int *remaining)
/**************************************************************************************/
{
ISOPEN;
if (position_of_block > block_transfer_list->number_of_items)
return(RCC_ERROR_RETURN(0, VME_RANGE));
*remaining = block_transfer_list->list_of_items[position_of_block].size_remaining;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*****************************************/
VME_ErrorCode_t VME_BlockTransferDump(void)
/*****************************************/
{
int ret;
char mytext[TEXT_SIZE2];
ISOPEN;
ret = ioctl(dev_handle, VMEDMADUMP, mytext);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_MasterMapDump: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
printf("%s", mytext);
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/********************************************/
VME_ErrorCode_t VME_SysfailInterruptLink(void)
/********************************************/
{
int ret, dummy;
ISOPEN;
ret = ioctl(dev_handle, VMESYSFAILLINK, &dummy);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailInterruptLink: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/***********************************************************************/
VME_ErrorCode_t VME_SysfailInterruptRegisterSignal(int signal_number)
/***********************************************************************/
{
int ret;
VME_RegSig_t reg_sig_arg;
ISOPEN;
reg_sig_arg.signum = signal_number;
ret = ioctl(dev_handle, VMESYSFAILREGISTERSIGNAL, ®_sig_arg);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailInterruptRegisterSignal: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/****************************************************/
VME_ErrorCode_t VME_SysfailInterruptWait(int time_out)
/****************************************************/
{
int ret;
VME_WaitInt_t wait_arg;
ISOPEN;
if (time_out > 0)
wait_arg.timeout = (time_out + 9) / 10; // ms to ticks;
else
wait_arg.timeout = time_out;
ret = ioctl(dev_handle, VMESYSFAILWAIT, &wait_arg);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailInterruptWait: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
if (wait_arg.multiple == 0) // no pending vector found
return(RCC_ERROR_RETURN(0, VME_NOINTERRUPT));
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**********************************************/
VME_ErrorCode_t VME_SysfailInterruptUnlink(void)
/**********************************************/
{
int ret, dummy;
ISOPEN;
ret = ioctl(dev_handle, VMESYSFAILUNLINK, &dummy);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailInterruptUnlink: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/************************************************/
VME_ErrorCode_t VME_SysfailInterruptReenable(void)
/************************************************/
{
int ret, dummy;
ISOPEN;
ret = ioctl(dev_handle, VMESYSFAILREENABLE, &dummy);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailInterruptReenable: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/****************************************/
VME_ErrorCode_t VME_SysfailPoll(int *flag)
/****************************************/
{
int ret;
ISOPEN;
ret = ioctl(dev_handle, VMESYSFAILPOLL, flag);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailPoll: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**********************************/
VME_ErrorCode_t VME_SysfailSet(void)
/**********************************/
{
int ret, dummy;
ISOPEN;
ret = ioctl(dev_handle, VMESYSFAILSET, &dummy);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailSet: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/************************************/
VME_ErrorCode_t VME_SysfailReset(void)
/************************************/
{
int ret, dummy;
ISOPEN;
ret = ioctl(dev_handle, VMESYSFAILRESET, &dummy);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_SysfailRest: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**********************************************************************************/
VME_ErrorCode_t VME_InterruptLink(VME_InterruptList_t* vme_irq_list, int *interrupt)
/**********************************************************************************/
{
int i, ret;
int index;
int first_level, first_type;
ISOPEN;
if ( vme_irq_list->number_of_items > VME_MAXINTERRUPT)
return(RCC_ERROR_RETURN(0, VME_TOOMANYINT));
// find a free slot
index = -1;
for (i = 0; i < VME_MAX_INTHANDLE; i++)
{
if (int_handle[i].nvectors == 0)
{
index = i;
break;
}
}
if (index == -1)
return(RCC_ERROR_RETURN(0, VME_TOOMANYHDL));
int_handle[index].nvectors = vme_irq_list->number_of_items;
for (i = 0; i < vme_irq_list->number_of_items; i++)
{
int_handle[index].vector[i] = (int)vme_irq_list->list_of_items[i].vector; // no check
if (vme_irq_list->list_of_items[i].level < 1 || vme_irq_list->list_of_items[i].level > 7)
return(RCC_ERROR_RETURN(0, VME_ILLINTLEVEL));
if (vme_irq_list->list_of_items[i].type != VME_INT_ROAK &&
vme_irq_list->list_of_items[i].type != VME_INT_RORA)
return(RCC_ERROR_RETURN(0, VME_ILLINTTYPE));
if ( i == 0)
{
first_level = vme_irq_list->list_of_items[i].level;
first_type = vme_irq_list->list_of_items[i].type;
}
else
{
if (vme_irq_list->list_of_items[i].level != first_level)
return(RCC_ERROR_RETURN(0, VME_ILLINTLEVEL));
if (vme_irq_list->list_of_items[i].type != first_type)
return(RCC_ERROR_RETURN(0, VME_ILLINTTYPE));
}
}
int_handle[index].level = first_level;
int_handle[index].type = first_type;
ret = ioctl(dev_handle, VMELINK, &int_handle[index]);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_InterruptLink: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
*interrupt = index;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**************************************************/
VME_ErrorCode_t VME_InterruptReenable(int interrupt)
/**************************************************/
{
int ret;
VME_IntEnable_t level_arg;
ISOPEN;
if (interrupt < 0 || interrupt > VME_MAX_INTHANDLE)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
level_arg.level = int_handle[interrupt].level;
level_arg.type = 0; //dummy
ret = ioctl(dev_handle, VMEINTENABLE, &level_arg);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_InterruptEnable: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/******************************************************************************************/
VME_ErrorCode_t VME_InterruptWait(int interrupt, int time_out, VME_InterruptInfo_t* ir_info)
/******************************************************************************************/
{
int ret;
VME_WaitInt_t wait_arg;
ISOPEN;
if (interrupt < 0 || interrupt > VME_MAX_INTHANDLE)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
wait_arg.int_handle = int_handle[interrupt];
if (time_out > 0)
wait_arg.timeout = (time_out + 9)/10; // ms to ticks;
else
wait_arg.timeout = time_out;
wait_arg.vector = 0;
ret = ioctl(dev_handle, VMEWAIT, &wait_arg);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_InterruptWait: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
ir_info->vector = (u_char)wait_arg.vector;
ir_info->level = wait_arg.level;
ir_info->type = wait_arg.type;
ir_info->multiple = wait_arg.multiple;
if (wait_arg.multiple == 0) // no pending vector found
return(RCC_ERROR_RETURN(0, VME_NOINTERRUPT));
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/***************************************************************************/
VME_ErrorCode_t VME_InterruptRegisterSignal(int interrupt, int signal_number)
/***************************************************************************/
{
int ret;
VME_RegSig_t reg_sig_arg;
ISOPEN;
if (interrupt < 0 || interrupt > VME_MAX_INTHANDLE)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
reg_sig_arg.int_handle = int_handle[interrupt];
reg_sig_arg.signum = signal_number;
ret = ioctl(dev_handle, VMEREGISTERSIGNAL, ®_sig_arg);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_InterruptRegisterSignal: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/********************************************************************************/
VME_ErrorCode_t VME_InterruptInfoGet(int interrupt, VME_InterruptInfo_t* ir_info)
/********************************************************************************/
{
int ret;
VME_WaitInt_t wait_arg;
ISOPEN;
if (interrupt < 0 || interrupt > VME_MAX_INTHANDLE)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
wait_arg.int_handle = int_handle[interrupt];
wait_arg.timeout = 0; // dummy
wait_arg.vector = 0;
ret = ioctl(dev_handle, VMEINTERRUPTINFOGET, &wait_arg);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_InterruptInfoGet: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
ir_info->vector = (u_char)wait_arg.vector;
ir_info->level = wait_arg.level;
ir_info->type = wait_arg.type;
ir_info->multiple = wait_arg.multiple;
if (wait_arg.multiple == 0) // no pending vector found
return(RCC_ERROR_RETURN(0, VME_NOINTERRUPT));
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/************************************************/
VME_ErrorCode_t VME_InterruptUnlink(int interrupt)
/************************************************/
{
int i, ret;
ISOPEN;
if (interrupt < 0 || interrupt > VME_MAX_INTHANDLE)
return(RCC_ERROR_RETURN(0, VME_NOTKNOWN));
if (int_handle[interrupt].nvectors == 0)
return(RCC_ERROR_RETURN(0, VME_ILLINTHANDLE));
ret = ioctl(dev_handle, VMEUNLINK, &int_handle[interrupt]);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_InterruptUnlink: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
// clean the entry in the handle array
int_handle[interrupt].nvectors = 0;
for (i = 0; i < VME_MAX_INTHANDLE; i++)
{
int_handle[interrupt].vector[i] = 0;
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*************************************************************/
VME_ErrorCode_t VME_InterruptGenerate(int level, u_char vector)
/*************************************************************/
{
ISOPEN;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*************************************/
VME_ErrorCode_t VME_InterruptDump(void)
/*************************************/
{
ISOPEN;
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*******************/
/*Service functions*/
/*******************/
/*****************************************************/
VME_ErrorCode_t VME_UniverseMap(u_int *virtual_address)
/*****************************************************/
{
int ret;
u_int idata, vaddr;
ret = IO_PCIDeviceLink(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, 1, &universe_handle);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_UniverseUnmap: Error from IO_PCIDeviceLink");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
ret = IO_PCIConfigReadUInt(universe_handle, 0x10, &idata);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_UniverseUnmap: Error from IO_PCIConfigReadUInt");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
ret = IO_PCIMemMap(idata, 0x1000, &vaddr);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_UniverseUnmap: Error from IO_PCIMemMap");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
*virtual_address = vaddr;
DEBUG_TEXT(DFDB_VMERCC, 20 ,"VME_UniverseMap: virtual address = 0x" << std::hex << *virtual_address << std::dec);
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/******************************************************/
VME_ErrorCode_t VME_UniverseUnmap(u_int virtual_address)
/******************************************************/
{
int ret;
ret = IO_PCIMemUnmap(virtual_address, 0x1000);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_UniverseUnmap: Error from IO_PCIMemUnmap");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
ret = IO_PCIDeviceUnlink(universe_handle);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_UniverseUnmap: Error from IO_PCIDeviceUnlink");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*****************************************/
VME_ErrorCode_t VME_CCTSetSwap(u_char swap)
/*****************************************/
{
int ret;
u_char data;
ret = IO_IOPeekUChar(0x210, &data);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_CCTSetSwap: Error from IO_IOPeekUChar");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
data &= 0xc7;
data |= swap;
ret = IO_IOPokeUChar(0x210, data);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_CCTSetSwap: Error from IO_IOPokeUChar");
return(RCC_ERROR_RETURN(ret, VME_IO_FAIL));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/********************************************/
VME_ErrorCode_t VME_Update(unsigned int *data)
/********************************************/
{
int ret, i;
VME_Update_t idata;
for(i = 0; i < 9; i++)
idata.irq_mode[i] = data[i];
DEBUG_TEXT(DFDB_VMERCC, 15 ,"VME_Update: Function called");
ret = ioctl(dev_handle, VMEUPDATE, &idata);
if (ret)
{
DEBUG_TEXT(DFDB_VMERCC, 5 ,"VME_Update: Error from ioctl, errno = 0x" << std::hex << errno << std::dec);
return(RCC_ERROR_RETURN(0, errno));
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/*********************************************************************/
VME_ErrorCode_t vmercc_err_get(err_pack err, err_str pid, err_str code)
/*********************************************************************/
{
strcpy(pid, P_ID_VMERCC_STR);
switch (RCC_ERROR_MINOR(err))
{
case VME_SUCCESS: strcpy(code, VME_SUCCESS_STR); break;
case VME_NOTKNOWN: strcpy(code, VME_NOTKNOWN_STR); break;
case VME_UNKNOWN: strcpy(code, VME_UNKNOWN_STR); break;
case VME_NOTOPEN: strcpy(code, VME_NOTOPEN_STR); break;
case VME_RANGE: strcpy(code, VME_RANGE_STR); break;
case VME_BUSERROR: strcpy(code, VME_BUSERROR_STR); break;
case VME_ALIGN: strcpy(code, VME_ALIGN_STR); break;
case VME_NOCHAINMEM: strcpy(code, VME_NOCHAINMEM_STR); break;
case VME_NOBUSERROR: strcpy(code, VME_NOBUSERROR_STR); break;
case VME_TOOLONG: strcpy(code, VME_TOOLONG_STR); break;
case VME_DMABUSY: strcpy(code, VME_DMABUSY_STR); break;
case VME_TIMEOUT: strcpy(code, VME_TIMEOUT_STR); break;
case VME_FILE: strcpy(code, VME_FILE_STR); break;
case VME_NOMAP: strcpy(code, VME_NOMAP_STR); break;
case VME_NOSTATMAP: strcpy(code, VME_NOSTATMAP_STR); break;
case VME_IRGBUSY: strcpy(code, VME_IRGBUSY_STR); break;
case VME_EIO: strcpy(code, VME_EIO_STR); break;
case VME_EFAULT: strcpy(code, VME_EFAULT_STR); break;
case VME_VIRT: strcpy(code, VME_VIRT_STR); break;
case VME_REMAP: strcpy(code, VME_REMAP_STR); break;
case VME_ENOSYS: strcpy(code, VME_ENOSYS_STR); break;
case VME_NOSIZE: strcpy(code, VME_NOSIZE_STR); break;
case VME_CMEM_FAIL: strcpy(code, VME_CMEM_FAIL_STR); break;
case VME_ERESTARTSYS: strcpy(code, VME_ERESTARTSYS_STR); break;
case VME_DMAERR: strcpy(code, VME_DMAERR_STR); break;
case VME_PCI_ERR: strcpy(code, VME_PCI_ERR_STR); break;
case VME_VME_ERR: strcpy(code, VME_VME_ERR_STR); break;
case VME_PROTOCOL_ERR: strcpy(code, VME_PROTOCOL_ERR_STR); break;
case VME_NOT_EXECUTED: strcpy(code, VME_NOT_EXECUTED_STR); break;
case VME_MUNMAP: strcpy(code, VME_MUNMAP_STR); break;
case VME_ILLREV: strcpy(code, VME_ILLREV_STR); break;
case VME_IOREMAP: strcpy(code, VME_IOREMAP_STR); break;
case VME_REQIRQ: strcpy(code, VME_REQIRQ_STR); break;
case VME_TOOMANYINT: strcpy(code, VME_TOOMANYINT_STR); break;
case VME_TOOMANYHDL: strcpy(code, VME_TOOMANYHDL_STR); break;
case VME_INTUSED: strcpy(code, VME_INTUSED_STR); break;
case VME_ILLINTLEVEL: strcpy(code, VME_ILLINTLEVEL_STR); break;
case VME_ILLINTTYPE: strcpy(code, VME_ILLINTTYPE_STR); break;
case VME_INTCONF: strcpy(code, VME_INTCONF_STR); break;
case VME_LVLDISABLED: strcpy(code, VME_LVLDISABLED_STR); break;
case VME_LVLISNOTRORA: strcpy(code, VME_LVLISNOTRORA_STR); break;
case VME_ILLINTHANDLE: strcpy(code, VME_ILLINTHANDLE_STR); break;
case VME_INTBYSIGNAL: strcpy(code, VME_INTBYSIGNAL_STR); break;
case VME_NOINTERRUPT: strcpy(code, VME_NOINTERRUPT_STR); break;
case VME_ENOMEM: strcpy(code, VME_ENOMEM_STR); break;
case VME_KMALLOC: strcpy(code, VME_KMALLOC_STR); break;
case VME_BERRTBLFULL: strcpy(code, VME_BERRTBLFULL_STR); break;
case VME_BERRNOTFOUND: strcpy(code, VME_BERRNOTFOUND_STR); break;
case VME_ILL_TO: strcpy(code, VME_ILL_TO_STR); break;
case VME_NODOMEMEM: strcpy(code, VME_NODOMEMEM_STR); break;
case VME_UNKNOWN_BOARD: strcpy(code, VME_UNKNOWN_BOARD_STR); break;
case VME_NOCRCSRMAP: strcpy(code, VME_NOCRCSRMAP_STR); break;
case VME_IO_FAIL: strcpy(code, VME_IO_FAIL_STR); break;
case VME_SYSFAILTBLFULL: strcpy(code, VME_SYSFAILTBLFULL_STR); break;
case VME_SYSFAILTBLNOTLINKED: strcpy(code, VME_SYSFAILTBLNOTLINKED_STR); break;
case VME_SYSFAILNOTLINKED: strcpy(code, VME_SYSFAILNOTLINKED_STR); break;
case VME_NOSTATMAP2: strcpy(code, VME_NOSTATMAP2_STR); break;
case VME_IOUNMAP: strcpy(code, VME_IOUNMAP_STR); break;
default: strcpy(code, VME_NO_CODE_STR); return(RCC_ERROR_RETURN(0,VME_NO_CODE)); break;
}
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
/**********************************/
/*Additional (temporary) functions*/
/**********************************/
/****************************/
VME_ErrorCode_t VME_test(void)
/****************************/
{
int ret,en;
static int count = 0;
ISOPEN;
ret = ioctl(dev_handle, VMETEST, &count);
en=errno;
if (en != VME_ENOSYS)
printf("Error from VME_test. Return code = %d\n", en);
return(RCC_ERROR_RETURN(0, VME_SUCCESS));
}
| CERN Central CVS service | ViewVC Help |
| Powered by ViewVC 1.0.4 |