Files
Jungfraujoch/fpga/host_library/JungfraujochDevice.cpp

212 lines
7.8 KiB
C++

// Copyright (2019-2023) Paul Scherrer Institute
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "../../common/Definitions.h"
#include "JungfraujochDevice.h"
#include "../../common/JFJochException.h"
#include "../pcie_driver/jfjoch_ioctl.h"
JungfraujochDevice::JungfraujochDevice(const std::string &device_name, bool write_access) {
fd = open(device_name.c_str(), write_access ? O_RDWR : O_RDONLY);
if (fd == -1)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Cannot open device");
auto action_type = GetDataCollectionStatus().action_type;
if (action_type != ACTION_TYPE)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Wrong device type");
}
JungfraujochDevice::~JungfraujochDevice() {
close(fd);
}
void JungfraujochDevice::Start() {
if (ioctl(fd, IOCTL_JFJOCH_START) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed starting action", errno);
}
void JungfraujochDevice::Cancel() {
if (ioctl(fd, IOCTL_JFJOCH_CANCEL) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed setting cancel bit", errno);
}
void JungfraujochDevice::End() {
if (ioctl(fd, IOCTL_JFJOCH_END) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed ending action", errno);
}
bool JungfraujochDevice::IsIdle() const {
uint32_t tmp;
if (ioctl(fd, IOCTL_JFJOCH_ISIDLE, &tmp) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed checking if idle", errno);
return tmp;
}
DataCollectionStatus JungfraujochDevice::GetDataCollectionStatus() const {
DataCollectionStatus ret{};
if (ioctl(fd, IOCTL_JFJOCH_STATUS, &ret) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed reading status", errno);
return ret;
}
DataCollectionConfig JungfraujochDevice::GetConfig() const {
DataCollectionConfig ret{};
if (ioctl(fd, IOCTL_JFJOCH_READ_CONFIG, &ret) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed reading config", errno);
return ret;
}
DeviceStatus JungfraujochDevice::GetDeviceStatus() const {
DeviceStatus ret{};
if (ioctl(fd, IOCTL_JFJOCH_GET_DEV_STATUS, &ret) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed reading env. data", errno);
return ret;
}
void JungfraujochDevice::ClearNetworkCounters() {
if (ioctl(fd, IOCTL_JFJOCH_CLR_CNTRS) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed clearing network counters", errno);
}
void JungfraujochDevice::Reset() {
}
uint32_t JungfraujochDevice::GetNumaNode() const {
int32_t tmp;
if (ioctl(fd, IOCTL_JFJOCH_NUMA, &tmp) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed reading NUMA node", errno);
return tmp;
}
uint32_t JungfraujochDevice::GetCompletedDescriptors() const {
uint32_t ret = 0;
if (ioctl(fd, IOCTL_JFJOCH_C2H_DMA_DESC, &ret) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed geting C2H completed descriptor count", errno);
return ret;
}
void JungfraujochDevice::SetConfig(const DataCollectionConfig &config) {
if (ioctl(fd, IOCTL_JFJOCH_SET_CONFIG, &config) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed writing config", errno);
}
bool JungfraujochDevice::ReadWorkCompletion(uint32_t output[16]) {
int tmp = ioctl(fd, IOCTL_JFJOCH_READ_WC_MBOX, output);
if (tmp != 0) {
if (errno == EAGAIN)
return false;
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed receiving work completion", errno);
}
return true;
}
bool JungfraujochDevice::SendWorkRequest(uint32_t id) {
int tmp = ioctl(fd, IOCTL_JFJOCH_SEND_WR, &id);
if (tmp != 0) {
if (errno == EAGAIN)
return false;
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed sending work request", errno);
}
return true;
}
uint32_t JungfraujochDevice::GetBufferCount() const {
uint32_t tmp;
if (ioctl(fd, IOCTL_JFJOCH_BUF_COUNT, &tmp) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed getting buffer count", errno);
return tmp;
}
void JungfraujochDevice::SetMACAddress(uint64_t addr) {
if (ioctl(fd, IOCTL_JFJOCH_SET_MAC, &addr) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed setting MAC address", errno);
}
uint64_t JungfraujochDevice::GetMACAddress() const {
uint64_t tmp;
if (ioctl(fd, IOCTL_JFJOCH_GET_MAC, &tmp) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed getting MAC address", errno);
return tmp;
}
void JungfraujochDevice::SetDefaultMACAddress() {
if (ioctl(fd, IOCTL_JFJOCH_DEFAULT_MAC) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed setting default MAC", errno);
}
uint32_t JungfraujochDevice::GetIPv4Address() const {
uint32_t tmp;
if (ioctl(fd, IOCTL_JFJOCH_GET_IPV4, &tmp) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed getting IPv4 address", errno);
return tmp;
}
void JungfraujochDevice::SetIPv4Address(uint32_t input) {
if (ioctl(fd, IOCTL_JFJOCH_SET_IPV4, &input) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed setting IPv4 address", errno);
}
void JungfraujochDevice::RunFrameGenerator(const FrameGeneratorConfig &config) {
if (ioctl(fd, IOCTL_JFJOCH_RUN_FRAME_GEN, &config) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed starting frame generator", errno);
}
void JungfraujochDevice::WriteRegister(uint32_t addr, uint32_t val) {
RegisterConfig config{.addr = addr, .val = val};
if (ioctl(fd, IOCTL_JFJOCH_WRITE_REGISTER, &config) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed writing to register", errno);
}
uint32_t JungfraujochDevice::ReadRegister(uint32_t addr) const {
RegisterConfig config;
config.addr = addr;
if (ioctl(fd, IOCTL_JFJOCH_READ_REGISTER, &config) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed reading register", errno);
return config.val;
}
void JungfraujochDevice::LoadCalibration(uint32_t modules, uint32_t storage_cells) {
DataCollectionConfig config{
.nmodules = modules,
.nstorage_cells = storage_cells
};
if (ioctl(fd, IOCTL_JFJOCH_LOAD_CALIB, &config) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed uploading calibration", errno);
}
void JungfraujochDevice::LoadInternalGeneratorFrame(uint32_t modules) {
DataCollectionConfig config{
.nmodules = modules
};
if (ioctl(fd, IOCTL_JFJOCH_LOAD_INT_GEN, &config) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed uploading internal generator frame", errno);
}
void JungfraujochDevice::LoadIntegrationMap(uint32_t modules) {
DataCollectionConfig config{
.nmodules = modules,
};
if (ioctl(fd, IOCTL_JFJOCH_LOAD_INT_MAP, &config) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed uploading integration map", errno);
}
uint16_t *JungfraujochDevice::MapKernelBuffer(uint32_t id) {
auto tmp = (uint16_t *) mmap(nullptr, FPGA_BUFFER_LOCATION_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED,
fd, FPGA_BUFFER_LOCATION_SIZE * id);
if (tmp == nullptr)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Mmap of kernel buffer error", errno);
return tmp;
}
void JungfraujochDevice::SetSpotFinderParameters(const SpotFinderParameters& params) {
if (ioctl(fd, IOCTL_JFJOCH_SPOT_FINDER_PAR, &params) != 0)
throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed settings spot finder parameters", errno);
}