// Copyright (2019-2023) Paul Scherrer Institute #include #include #include #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, ¶ms) != 0) throw JFJochException(JFJochExceptionCategory::PCIeError, "Failed settings spot finder parameters", errno); }