mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-07 10:30:41 +02:00
Dev/xilinx mat update (#959)
* put back code to obtain adc and dac device indexafter loading device tree and then create folder iio_device_links and create symbolic links there according to device indices found. ln -sf operation not permitted, so folder has to be deleted and created everytime. Also refactored definitions to have all the xilinx name or detector specific stuff out of programbyArm.c * uncommented waittransceiverreset at startup (should work now) and return of powering off chip at startup (error for transceiver alignment reset) * updated registerdefs from firmware * minor prints and updating names from registerdefs * waittransceiverreset has been fixed in firmware and removing warnign for that, transceiver alignment check for powering off chip is not done in fw (giving a warning and returning ok for now) * fixing ipchecksum (not done), removed startperiphery, allowing readout command to be allowed for xilinx when acquiring
This commit is contained in:
parent
5b61ff24bb
commit
9f079b17a2
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -69,4 +69,9 @@ int deleteFile(char *mess, char *fname, char *errorPrefix);
|
|||||||
|
|
||||||
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix);
|
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix);
|
||||||
|
|
||||||
int readParameterFromFile(char *fname, char *parameterName, int *value);
|
int readParameterFromFile(char *fname, char *parameterName, int *value);
|
||||||
|
|
||||||
|
int createAbsoluteDirectory(char *mess, const char *absPath, char *errorPrefix);
|
||||||
|
int deleteAbsoluteDirectory(char *mess, const char *absPath, char *errorPrefix);
|
||||||
|
|
||||||
|
int deleteItem(char *mess, int isFile, const char *absPath, char *errorPrefix);
|
@ -9,4 +9,8 @@ int loadDeviceTree(char *mess);
|
|||||||
|
|
||||||
int checksBeforeCreatingDeviceTree(char *mess);
|
int checksBeforeCreatingDeviceTree(char *mess);
|
||||||
int createDeviceTree(char *mess);
|
int createDeviceTree(char *mess);
|
||||||
int verifyDeviceTree(char *mess);
|
int verifyDeviceTree(char *mess);
|
||||||
|
#ifndef VIRTUAL
|
||||||
|
int createSymbolicLinksForDevices(int adcDeviceIndex, int dacDeviceIndex,
|
||||||
|
char *mess);
|
||||||
|
#endif
|
@ -198,7 +198,6 @@ int isChipConfigured();
|
|||||||
int powerChip(int on, char *mess);
|
int powerChip(int on, char *mess);
|
||||||
int getPowerChip();
|
int getPowerChip();
|
||||||
int configureChip(char *mess);
|
int configureChip(char *mess);
|
||||||
void startPeriphery();
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(JUNGFRAUD) || defined(MOENCHD) || defined(CHIPTESTBOARDD) || \
|
#if defined(JUNGFRAUD) || defined(MOENCHD) || defined(CHIPTESTBOARDD) || \
|
||||||
defined(MYTHEN3D) || defined(GOTTHARD2D)
|
defined(MYTHEN3D) || defined(GOTTHARD2D)
|
||||||
|
@ -50,6 +50,7 @@ u_int32_t writeRegister(u_int32_t offset, u_int32_t data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mapCSP0(void) {
|
int mapCSP0(void) {
|
||||||
|
LOG(logINFO, ("Mapping memory\n"));
|
||||||
u_int32_t csps[2] = {CSP0, CSP1};
|
u_int32_t csps[2] = {CSP0, CSP1};
|
||||||
u_int32_t **cspbases[2] = {&csp0base, &csp1base};
|
u_int32_t **cspbases[2] = {&csp0base, &csp1base};
|
||||||
u_int32_t memsize[2] = {MEM_SIZE_CSP0, MEM_SIZE_CSP1};
|
u_int32_t memsize[2] = {MEM_SIZE_CSP0, MEM_SIZE_CSP1};
|
||||||
@ -58,7 +59,7 @@ int mapCSP0(void) {
|
|||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
// if not mapped
|
// if not mapped
|
||||||
if (*cspbases[i] == 0) {
|
if (*cspbases[i] == 0) {
|
||||||
LOG(logINFO, ("Mapping memory for %s\n", names[i]));
|
LOG(logINFO, ("\tMapping memory for %s\n", names[i]));
|
||||||
#ifdef VIRTUAL
|
#ifdef VIRTUAL
|
||||||
*cspbases[i] = malloc(memsize[i]);
|
*cspbases[i] = malloc(memsize[i]);
|
||||||
if (*cspbases[i] == NULL) {
|
if (*cspbases[i] == NULL) {
|
||||||
@ -67,7 +68,7 @@ int mapCSP0(void) {
|
|||||||
memsize[i], names[i]));
|
memsize[i], names[i]));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("memory allocated for %s\n", names[i]));
|
LOG(logINFO, ("\tmemory allocated for %s\n", names[i]));
|
||||||
#else
|
#else
|
||||||
int fd = open("/dev/mem", O_RDWR | O_SYNC, 0);
|
int fd = open("/dev/mem", O_RDWR | O_SYNC, 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@ -75,7 +76,7 @@ int mapCSP0(void) {
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logDEBUG1,
|
LOG(logDEBUG1,
|
||||||
("/dev/mem opened for %s, (CSP:0x%x)\n", names[i], csps[i]));
|
("\t/dev/mem opened for %s, (CSP:0x%x)\n", names[i], csps[i]));
|
||||||
*cspbases[i] =
|
*cspbases[i] =
|
||||||
(u_int32_t *)mmap(0, memsize[i], PROT_READ | PROT_WRITE,
|
(u_int32_t *)mmap(0, memsize[i], PROT_READ | PROT_WRITE,
|
||||||
MAP_FILE | MAP_SHARED, fd, csps[i]);
|
MAP_FILE | MAP_SHARED, fd, csps[i]);
|
||||||
@ -85,11 +86,11 @@ int mapCSP0(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
LOG(logINFO,
|
LOG(logINFO,
|
||||||
("%s mapped of size %d from %p to %p,(CSP:0x%x) \n", names[i],
|
("\t%s mapped of size %d from %p to %p,(CSP:0x%x) \n", names[i],
|
||||||
memsize[i], *cspbases[i], *cspbases[i] + memsize[i], csps[i]));
|
memsize[i], *cspbases[i], *cspbases[i] + memsize[i], csps[i]));
|
||||||
// LOG(logINFO, ("Status Register: %08x\n", bus_r(STATUS_REG)));
|
// LOG(logINFO, ("Status Register: %08x\n", bus_r(STATUS_REG)));
|
||||||
} else
|
} else
|
||||||
LOG(logINFO, ("Memory %s already mapped before\n", names[i]));
|
LOG(logINFO, ("\tMemory %s already mapped before\n", names[i]));
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <libgen.h> // dirname
|
#include <libgen.h> // dirname
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/stat.h> // stat
|
||||||
#include <sys/utsname.h> // uname
|
#include <sys/utsname.h> // uname
|
||||||
#include <unistd.h> // readlink
|
#include <unistd.h> // readlink
|
||||||
|
|
||||||
@ -677,31 +678,7 @@ int deleteFile(char *mess, char *fname, char *errorPrefix) {
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (access(fullname, F_OK) == 0) {
|
return deleteItem(mess, 1, fullname, errorPrefix);
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
|
||||||
|
|
||||||
if (snprintf(cmd, MAX_STR_LENGTH, "rm %s", fullname) >=
|
|
||||||
MAX_STR_LENGTH) {
|
|
||||||
sprintf(mess, "Could not %s. Command to delete is too long\n",
|
|
||||||
errorPrefix);
|
|
||||||
LOG(logERROR, (mess));
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
|
||||||
"Could not %s. (deleting file %s). %s\n", errorPrefix,
|
|
||||||
fullname, retvals);
|
|
||||||
LOG(logERROR, (mess));
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
LOG(logINFO, ("\tDeleted file: %s (%s)\n", fullname, errorPrefix));
|
|
||||||
} else {
|
|
||||||
LOG(logINFO,
|
|
||||||
("\tFile does not exist anyway: %s (%s)\n", fullname, errorPrefix));
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix) {
|
int deleteOldServers(char *mess, char *newServerPath, char *errorPrefix) {
|
||||||
@ -758,4 +735,60 @@ int readParameterFromFile(char *fname, char *parameterName, int *value) {
|
|||||||
|
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
return OK;
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int createAbsoluteDirectory(char *mess, const char *absPath,
|
||||||
|
char *errorPrefix) {
|
||||||
|
// check if folder exists
|
||||||
|
if (access(absPath, F_OK) == 0) {
|
||||||
|
LOG(logINFO, ("Folder %s already exists\n", absPath));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// folder does not exist, create it
|
||||||
|
if (mkdir(absPath, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
|
||||||
|
sprintf(mess, "Could not %s. Could not create folder %s\n", errorPrefix,
|
||||||
|
absPath);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tCreated folder: %s (%s)\n", absPath, errorPrefix));
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int deleteAbsoluteDirectory(char *mess, const char *absPath,
|
||||||
|
char *errorPrefix) {
|
||||||
|
return deleteItem(mess, 0, absPath, errorPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
int deleteItem(char *mess, int isFile, const char *absPath, char *errorPrefix) {
|
||||||
|
// item does not exist
|
||||||
|
if (access(absPath, F_OK) != 0) {
|
||||||
|
LOG(logINFO, ("\t%s does not exist anyway: %s (%s)\n",
|
||||||
|
(isFile ? "File" : "Folder"), absPath, errorPrefix));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete item
|
||||||
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
|
if (snprintf(cmd, MAX_STR_LENGTH, "rm %s %s", (isFile ? "-f" : "-rf"),
|
||||||
|
absPath) >= MAX_STR_LENGTH) {
|
||||||
|
sprintf(mess, "Could not %s. Command to delete is too long\n",
|
||||||
|
errorPrefix);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
|
snprintf(mess, MAX_STR_LENGTH, "Could not %s. (deleting %s %s). %s\n",
|
||||||
|
errorPrefix, (isFile ? "file" : "folder"), absPath, retvals);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tDeleted %s: %s (%s)\n", (isFile ? "file" : "folder"),
|
||||||
|
absPath, errorPrefix));
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
@ -2,20 +2,19 @@
|
|||||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
#include "programViaArm.h"
|
#include "programViaArm.h"
|
||||||
#include "clogger.h"
|
#include "clogger.h"
|
||||||
|
#include "common.h"
|
||||||
#include "sls/sls_detector_defs.h"
|
#include "sls/sls_detector_defs.h"
|
||||||
|
#include "slsDetectorServer_defs.h"
|
||||||
|
|
||||||
#include <string.h> //memset
|
#include <string.h> //memset
|
||||||
#include <unistd.h> // access
|
#include <unistd.h> // access
|
||||||
|
|
||||||
#define CMD_ARM_LOAD_BIT_FILE \
|
#define CMD_ARM_LOAD_BIT_FILE "~/fpgautil/fpgautil -b " FIRMWARE_FILE " -f Full"
|
||||||
"~/fpgautil/fpgautil -b /root/apps/xilinx-ctb/XilinxCTB.bit -f Full"
|
#define CMD_ARM_LOAD_DEVICE_TREE \
|
||||||
#define CMD_ARM_DEVICE_TREE_API_FOLDER \
|
"cat " DEVICE_TREE_OVERLAY_FILE " > " DEVICE_TREE_API_FOLDER "/dtbo"
|
||||||
"/sys/kernel/config/device-tree/overlays/spidr"
|
#define CMD_ARM_SYM_LINK_FORMAT \
|
||||||
#define CMD_ARM_DEVICE_TREE_OVERLAY_FILE "/root/apps/xilinx-ctb/pl.dtbo"
|
"ln -sf " DEVICE_TREE_DST "%d " IIO_DEVICE_FOLDER "/%s"
|
||||||
#define CMD_ARM_LOAD_DEVICE_TREE_FORMAT "cat %s > %s/dtbo"
|
#define TIME_LOAD_DEVICE_TREE_MS (500)
|
||||||
#define CMD_ARM_DEVICE_TREE_DST "/sys/bus/iio/devices/iio:device"
|
|
||||||
#define CMD_ARM_DEVICE_NAME "xilinx-ams", "ad7689", "dac@0", "dac@1", "dac@2"
|
|
||||||
#define TIME_LOAD_DEVICE_TREE_MS (500)
|
|
||||||
|
|
||||||
extern int executeCommand(char *command, char *result, enum TLogLevel level);
|
extern int executeCommand(char *command, char *result, enum TLogLevel level);
|
||||||
|
|
||||||
@ -56,54 +55,54 @@ int loadDeviceTree(char *mess) {
|
|||||||
|
|
||||||
int checksBeforeCreatingDeviceTree(char *mess) {
|
int checksBeforeCreatingDeviceTree(char *mess) {
|
||||||
// check if device tree overlay file exists
|
// check if device tree overlay file exists
|
||||||
if (access(CMD_ARM_DEVICE_TREE_OVERLAY_FILE, F_OK) != 0) {
|
if (access(DEVICE_TREE_OVERLAY_FILE, F_OK) != 0) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Device tree overlay file (%s) does not exist\n",
|
"Device tree overlay file (%s) does not exist\n",
|
||||||
CMD_ARM_DEVICE_TREE_OVERLAY_FILE);
|
DEVICE_TREE_OVERLAY_FILE);
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tDevice tree overlay file exists (%s)\n",
|
LOG(logINFO,
|
||||||
CMD_ARM_DEVICE_TREE_OVERLAY_FILE));
|
("\tDevice tree overlay file exists (%s)\n", DEVICE_TREE_OVERLAY_FILE));
|
||||||
|
|
||||||
// check if device tree folder exists. If it does, remove it
|
// check if device tree folder exists. If it does, remove it
|
||||||
if (access(CMD_ARM_DEVICE_TREE_API_FOLDER, F_OK) == 0) {
|
if (access(DEVICE_TREE_API_FOLDER, F_OK) == 0) {
|
||||||
// remove it
|
// remove it
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
memset(cmd, 0, MAX_STR_LENGTH);
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
sprintf(cmd, "rmdir %s", CMD_ARM_DEVICE_TREE_API_FOLDER);
|
sprintf(cmd, "rmdir %s", DEVICE_TREE_API_FOLDER);
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
memset(retvals, 0, MAX_STR_LENGTH);
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not unload device tree overlay api with %s (%s)\n",
|
"Could not unload device tree overlay api with %s (%s)\n",
|
||||||
cmd, retvals);
|
cmd, retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tUnloaded existing device tree overlay api (%s)\n",
|
LOG(logINFO, ("\tUnloaded existing device tree overlay api (%s)\n",
|
||||||
CMD_ARM_DEVICE_TREE_API_FOLDER));
|
DEVICE_TREE_API_FOLDER));
|
||||||
} else {
|
} else {
|
||||||
LOG(logINFO, ("\tNo existing device tree overlay api found(%s)\n",
|
LOG(logINFO, ("\tNo existing device tree overlay api found(%s)\n",
|
||||||
CMD_ARM_DEVICE_TREE_API_FOLDER));
|
DEVICE_TREE_API_FOLDER));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create device tree overlay folder
|
// create device tree overlay folder
|
||||||
{
|
{
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
memset(cmd, 0, MAX_STR_LENGTH);
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
sprintf(cmd, "mkdir %s", CMD_ARM_DEVICE_TREE_API_FOLDER);
|
sprintf(cmd, "mkdir %s", DEVICE_TREE_API_FOLDER);
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
memset(retvals, 0, MAX_STR_LENGTH);
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not create device tree overlay api with %s (%s)\n",
|
"Could not create device tree overlay api with %s (%s)\n",
|
||||||
cmd, retvals);
|
cmd, retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tDevice tree overlay api created (%s)\n",
|
LOG(logINFO, ("\tDevice tree overlay api created (%s)\n",
|
||||||
CMD_ARM_DEVICE_TREE_API_FOLDER));
|
DEVICE_TREE_API_FOLDER));
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@ -112,15 +111,14 @@ int checksBeforeCreatingDeviceTree(char *mess) {
|
|||||||
int createDeviceTree(char *mess) {
|
int createDeviceTree(char *mess) {
|
||||||
char cmd[MAX_STR_LENGTH] = {0};
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
memset(cmd, 0, MAX_STR_LENGTH);
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
sprintf(cmd, CMD_ARM_LOAD_DEVICE_TREE_FORMAT,
|
strcpy(cmd, CMD_ARM_LOAD_DEVICE_TREE);
|
||||||
CMD_ARM_DEVICE_TREE_OVERLAY_FILE, CMD_ARM_DEVICE_TREE_API_FOLDER);
|
|
||||||
char retvals[MAX_STR_LENGTH] = {0};
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
memset(retvals, 0, MAX_STR_LENGTH);
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not load device tree overlay with %s (%s)\n", cmd,
|
"Could not load device tree overlay with %s (%s)\n", cmd,
|
||||||
retvals);
|
retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tDevice tree overlay created (cmd: %s)\n", cmd));
|
LOG(logINFO, ("\tDevice tree overlay created (cmd: %s)\n", cmd));
|
||||||
@ -131,20 +129,27 @@ int createDeviceTree(char *mess) {
|
|||||||
|
|
||||||
int verifyDeviceTree(char *mess) {
|
int verifyDeviceTree(char *mess) {
|
||||||
LOG(logINFOBLUE, ("Verifying Device Tree...\n"));
|
LOG(logINFOBLUE, ("Verifying Device Tree...\n"));
|
||||||
#ifndef VIRTUAL
|
|
||||||
|
#ifdef VIRTUAL
|
||||||
|
LOG(logINFOBLUE, ("Device tree verified successfully\n"));
|
||||||
|
return OK;
|
||||||
|
#else
|
||||||
|
|
||||||
// check if iio:device0-4 exists in device tree destination
|
// check if iio:device0-4 exists in device tree destination
|
||||||
int hardcodedDeviceIndex = 0;
|
int hardcodedDeviceIndex = 0;
|
||||||
|
int adcDeviceIndex = 1;
|
||||||
|
int dacDeviceIndex = 2;
|
||||||
|
|
||||||
for (int i = 0; i != 5; ++i) {
|
for (int i = 0; i != 5; ++i) {
|
||||||
char deviceName[MAX_STR_LENGTH] = {0};
|
char deviceName[MAX_STR_LENGTH] = {0};
|
||||||
memset(deviceName, 0, MAX_STR_LENGTH);
|
memset(deviceName, 0, MAX_STR_LENGTH);
|
||||||
sprintf(deviceName, "%s%d/name", CMD_ARM_DEVICE_TREE_DST, i);
|
sprintf(deviceName, "%s%d/name", DEVICE_TREE_DST, i);
|
||||||
// check if device exist
|
// check if device exist
|
||||||
if (access(deviceName, F_OK) != 0) {
|
if (access(deviceName, F_OK) != 0) {
|
||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not verify device tree. Device %s does not exist\n",
|
"Could not verify device tree. Device %s does not exist\n",
|
||||||
deviceName);
|
deviceName);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
// find name
|
// find name
|
||||||
@ -157,24 +162,26 @@ int verifyDeviceTree(char *mess) {
|
|||||||
snprintf(mess, MAX_STR_LENGTH,
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
"Could not retrieve device name from device %s (%s)\n",
|
"Could not retrieve device name from device %s (%s)\n",
|
||||||
deviceName, retvals);
|
deviceName, retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
// verify name
|
// verify name
|
||||||
char *deviceNames[] = {CMD_ARM_DEVICE_NAME};
|
char *deviceNames[] = {DEVICE_NAME_LIST};
|
||||||
if (strstr(retvals, deviceNames[hardcodedDeviceIndex]) == NULL) {
|
if (strstr(retvals, deviceNames[hardcodedDeviceIndex]) == NULL) {
|
||||||
// dacs got loaded first
|
// dacs got loaded first
|
||||||
if (i == 1 &&
|
if (i == 1 &&
|
||||||
strstr(retvals, deviceNames[hardcodedDeviceIndex + 1]) !=
|
strstr(retvals, deviceNames[hardcodedDeviceIndex + 1]) !=
|
||||||
NULL) {
|
NULL) {
|
||||||
++hardcodedDeviceIndex;
|
++hardcodedDeviceIndex;
|
||||||
|
adcDeviceIndex = 4;
|
||||||
|
dacDeviceIndex = 1;
|
||||||
} else {
|
} else {
|
||||||
snprintf(
|
snprintf(
|
||||||
mess, MAX_STR_LENGTH,
|
mess, MAX_STR_LENGTH,
|
||||||
"Could not verify device tree. Device %s expected %s but "
|
"Could not verify device tree. Device %s expected %s but "
|
||||||
"got %s\n",
|
"got %s\n",
|
||||||
deviceName, deviceNames[i], retvals);
|
deviceName, deviceNames[i], retvals);
|
||||||
LOG(logWARNING, (mess));
|
LOG(logERROR, (mess));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,7 +190,66 @@ int verifyDeviceTree(char *mess) {
|
|||||||
if (hardcodedDeviceIndex == 5)
|
if (hardcodedDeviceIndex == 5)
|
||||||
hardcodedDeviceIndex = 1;
|
hardcodedDeviceIndex = 1;
|
||||||
}
|
}
|
||||||
|
LOG(logINFOBLUE, ("Device tree verified successfully [temp: 0, adc:%d, "
|
||||||
|
"dac:%d, %d, %d]\n",
|
||||||
|
adcDeviceIndex, dacDeviceIndex, dacDeviceIndex + 1,
|
||||||
|
dacDeviceIndex + 2));
|
||||||
|
|
||||||
|
return createSymbolicLinksForDevices(adcDeviceIndex, dacDeviceIndex, mess);
|
||||||
#endif
|
#endif
|
||||||
LOG(logINFOBLUE, ("Device tree verified successfully\n"));
|
}
|
||||||
|
|
||||||
|
#ifndef VIRTUAL
|
||||||
|
int createSymbolicLinksForDevices(int adcDeviceIndex, int dacDeviceIndex,
|
||||||
|
char *mess) {
|
||||||
|
|
||||||
|
// delete andcreate iio device links folder (deleting because cannot
|
||||||
|
// overwrite symbolic links with -sf)
|
||||||
|
if (deleteAbsoluteDirectory(mess, IIO_DEVICE_FOLDER,
|
||||||
|
"create sym links for device trees") ==
|
||||||
|
FAIL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (createAbsoluteDirectory(mess, IIO_DEVICE_FOLDER,
|
||||||
|
"create sym links for device trees") ==
|
||||||
|
FAIL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *deviceNames[] = {DEVICE_NAME_LIST};
|
||||||
|
// create symbolic links for adc
|
||||||
|
{
|
||||||
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
|
sprintf(cmd, CMD_ARM_SYM_LINK_FORMAT, adcDeviceIndex, deviceNames[1]);
|
||||||
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
|
"Could not create sym link [adc] (%s)\n", retvals);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tSym link [adc] created (%s)\n", cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
// create symbolic links for dacs
|
||||||
|
for (int idac = 0; idac != 3; ++idac) {
|
||||||
|
char cmd[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(cmd, 0, MAX_STR_LENGTH);
|
||||||
|
sprintf(cmd, CMD_ARM_SYM_LINK_FORMAT, dacDeviceIndex + idac,
|
||||||
|
deviceNames[idac + 2]);
|
||||||
|
char retvals[MAX_STR_LENGTH] = {0};
|
||||||
|
memset(retvals, 0, MAX_STR_LENGTH);
|
||||||
|
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
|
||||||
|
snprintf(mess, MAX_STR_LENGTH,
|
||||||
|
"Could not create sym link [dac%d] (%s)\n", idac,
|
||||||
|
retvals);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tSym link [dac%d] created (%s)\n", idac, cmd));
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
@ -8470,7 +8470,7 @@ int start_readout(int file_des) {
|
|||||||
#else
|
#else
|
||||||
if (Server_VerifyLock() == OK) {
|
if (Server_VerifyLock() == OK) {
|
||||||
enum runStatus s = getRunStatus();
|
enum runStatus s = getRunStatus();
|
||||||
if (s == RUNNING || s == WAITING) {
|
if ((s == RUNNING || s == WAITING) && (myDetectorType != XILINX_CHIPTESTBOARD)) {
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
strcpy(mess, "Could not start readout because the detector is "
|
strcpy(mess, "Could not start readout because the detector is "
|
||||||
"already running!\n");
|
"already running!\n");
|
||||||
|
@ -817,18 +817,16 @@
|
|||||||
|
|
||||||
#define MATTERHORNSPICTRL (0x608)
|
#define MATTERHORNSPICTRL (0x608)
|
||||||
|
|
||||||
#define MATTERHORNSPICTRL_EN_OFST (0)
|
#define CONFIGSTART_P_OFST (0)
|
||||||
#define MATTERHORNSPICTRL_EN_MSK (0x00000001 << MATTERHORNSPICTRL_EN_OFST)
|
#define CONFIGSTART_P_MSK (0x00000001 << CONFIGSTART_P_OFST)
|
||||||
#define CONFIGSTART_OFST (1)
|
#define PERIPHERYRST_P_OFST (1)
|
||||||
#define CONFIGSTART_MSK (0x00000001 << CONFIGSTART_OFST)
|
#define PERIPHERYRST_P_MSK (0x00000001 << PERIPHERYRST_P_OFST)
|
||||||
#define START_P_OFST (2)
|
#define STARTREAD_P_OFST (2)
|
||||||
#define START_P_MSK (0x00000001 << START_P_OFST)
|
#define STARTREAD_P_MSK (0x00000001 << STARTREAD_P_OFST)
|
||||||
#define STARTREAD_P_OFST (3)
|
#define BUSY_OFST (3)
|
||||||
#define STARTREAD_P_MSK (0x00000001 << STARTREAD_P_OFST)
|
#define BUSY_MSK (0x00000001 << BUSY_OFST)
|
||||||
#define BUSY_OFST (4)
|
#define READOUTFROMASIC_OFST (4)
|
||||||
#define BUSY_MSK (0x00000001 << BUSY_OFST)
|
#define READOUTFROMASIC_MSK (0x00000001 << READOUTFROMASIC_OFST)
|
||||||
#define READOUTFROMASIC_OFST (5)
|
|
||||||
#define READOUTFROMASIC_MSK (0x00000001 << READOUTFROMASIC_OFST)
|
|
||||||
|
|
||||||
#define EMPTY60CREG (0x60C)
|
#define EMPTY60CREG (0x60C)
|
||||||
|
|
||||||
@ -905,6 +903,8 @@
|
|||||||
#define RESETRXPLLANDDATAPATH_MSK (0x00000001 << RESETRXPLLANDDATAPATH_OFST)
|
#define RESETRXPLLANDDATAPATH_MSK (0x00000001 << RESETRXPLLANDDATAPATH_OFST)
|
||||||
#define RESETRXDATAPATHIN_OFST (4)
|
#define RESETRXDATAPATHIN_OFST (4)
|
||||||
#define RESETRXDATAPATHIN_MSK (0x00000001 << RESETRXDATAPATHIN_OFST)
|
#define RESETRXDATAPATHIN_MSK (0x00000001 << RESETRXDATAPATHIN_OFST)
|
||||||
|
#define RXPOLARITY_OFST (5)
|
||||||
|
#define RXPOLARITY_MSK (0x0000000f << RXPOLARITY_OFST)
|
||||||
|
|
||||||
#define EMPTY65CREG (0x65C)
|
#define EMPTY65CREG (0x65C)
|
||||||
|
|
||||||
|
Binary file not shown.
@ -387,15 +387,15 @@ void setupDetector() {
|
|||||||
initializePatternWord();
|
initializePatternWord();
|
||||||
#endif
|
#endif
|
||||||
// initialization only at start up (restart fpga)
|
// initialization only at start up (restart fpga)
|
||||||
// initError = waitTransceiverReset(initErrorMessage);
|
initError = waitTransceiverReset(initErrorMessage);
|
||||||
// if (initError == FAIL) {
|
if (initError == FAIL) {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
// // power off chip
|
// power off chip
|
||||||
initError = powerChip(0, initErrorMessage);
|
initError = powerChip(0, initErrorMessage);
|
||||||
// if (initError == FAIL) {
|
if (initError == FAIL) {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
LTC2620_D_SetDefines(DAC_MIN_MV, DAC_MAX_MV, DAC_DRIVER_FILE_NAME, NDAC,
|
LTC2620_D_SetDefines(DAC_MIN_MV, DAC_MAX_MV, DAC_DRIVER_FILE_NAME, NDAC,
|
||||||
NPWR, DAC_POWERDOWN_DRIVER_FILE_NAME);
|
NPWR, DAC_POWERDOWN_DRIVER_FILE_NAME);
|
||||||
@ -469,11 +469,6 @@ int waitTransceiverReset(char *mess) {
|
|||||||
sprintf(mess, "Resetting transceiver timed out, time:%.2fs\n",
|
sprintf(mess, "Resetting transceiver timed out, time:%.2fs\n",
|
||||||
(timeNs / (1E9)));
|
(timeNs / (1E9)));
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
|
|
||||||
LOG(logINFORED, ("Waiting for Firmware to be fixed here. Skipping "
|
|
||||||
"this error for now.\n"));
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
usleep(0);
|
usleep(0);
|
||||||
@ -557,9 +552,6 @@ int powerChip(int on, char *mess) {
|
|||||||
if (configureChip(mess) == FAIL)
|
if (configureChip(mess) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
startPeriphery();
|
|
||||||
|
|
||||||
chipConfigured = 1;
|
|
||||||
} else {
|
} else {
|
||||||
LOG(logINFOBLUE, ("Powering chip: off\n"));
|
LOG(logINFOBLUE, ("Powering chip: off\n"));
|
||||||
bus_w(addr, bus_r(addr) & ~mask);
|
bus_w(addr, bus_r(addr) & ~mask);
|
||||||
@ -573,6 +565,11 @@ int powerChip(int on, char *mess) {
|
|||||||
if (isTransceiverAligned()) {
|
if (isTransceiverAligned()) {
|
||||||
sprintf(mess, "Transceiver alignment not reset\n");
|
sprintf(mess, "Transceiver alignment not reset\n");
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
|
|
||||||
|
// to be removed when fixed later
|
||||||
|
LOG(logWARNING, ("Bypassing this error for now. To be fixed later...\n"));
|
||||||
|
return OK;
|
||||||
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
LOG(logINFO, ("\tTransceiver alignment has been reset\n"));
|
LOG(logINFO, ("\tTransceiver alignment has been reset\n"));
|
||||||
@ -598,8 +595,8 @@ int configureChip(char *mess) {
|
|||||||
|
|
||||||
// start configuration
|
// start configuration
|
||||||
uint32_t addr = MATTERHORNSPICTRL;
|
uint32_t addr = MATTERHORNSPICTRL;
|
||||||
bus_w(addr, bus_r(addr) | CONFIGSTART_MSK);
|
bus_w(addr, bus_r(addr) | CONFIGSTART_P_MSK);
|
||||||
bus_w(addr, bus_r(addr) & ~CONFIGSTART_MSK);
|
bus_w(addr, bus_r(addr) & ~CONFIGSTART_P_MSK);
|
||||||
|
|
||||||
// wait until configuration is done
|
// wait until configuration is done
|
||||||
#ifndef VIRTUAL
|
#ifndef VIRTUAL
|
||||||
@ -615,16 +612,11 @@ int configureChip(char *mess) {
|
|||||||
configDone = (bus_r(MATTERHORNSPICTRL) & BUSY_MSK);
|
configDone = (bus_r(MATTERHORNSPICTRL) & BUSY_MSK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
chipConfigured = 1;
|
||||||
LOG(logINFOBLUE, ("\tChip configured\n"));
|
LOG(logINFOBLUE, ("\tChip configured\n"));
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void startPeriphery() {
|
|
||||||
LOG(logINFOBLUE, ("\tStarting periphery\n"));
|
|
||||||
bus_w(MATTERHORNSPICTRL, bus_r(MATTERHORNSPICTRL) | START_P_MSK);
|
|
||||||
// TODO ?
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set parameters - dr */
|
/* set parameters - dr */
|
||||||
|
|
||||||
int setDynamicRange(int dr) {
|
int setDynamicRange(int dr) {
|
||||||
@ -1223,14 +1215,21 @@ void calcChecksum(udp_header *udp) {
|
|||||||
|
|
||||||
// ignore ethertype (from udp header)
|
// ignore ethertype (from udp header)
|
||||||
addr++;
|
addr++;
|
||||||
|
// ignore udp_srcmac_lsb (from udp header)
|
||||||
|
addr++;
|
||||||
|
addr++;
|
||||||
|
|
||||||
// from identification to srcip_lsb
|
// from ip_protocol to ip_checksum
|
||||||
while (count > 2) {
|
while (count > 2) {
|
||||||
sum += *addr++;
|
sum += *addr++;
|
||||||
count -= 2;
|
count -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore src udp port (from udp header)
|
// ignore udp_checksum (from udp header)
|
||||||
|
addr++;
|
||||||
|
// ignore udp_destport (from udp header)
|
||||||
|
addr++;
|
||||||
|
// ignore udp_srcport (from udp header)
|
||||||
addr++;
|
addr++;
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
@ -1240,6 +1239,7 @@ void calcChecksum(udp_header *udp) {
|
|||||||
long int checksum = sum & 0xffff;
|
long int checksum = sum & 0xffff;
|
||||||
checksum += UDP_IP_HEADER_LENGTH_BYTES;
|
checksum += UDP_IP_HEADER_LENGTH_BYTES;
|
||||||
udp->ip_checksum = checksum;
|
udp->ip_checksum = checksum;
|
||||||
|
LOG(logINFO, ("\tIP checksum: 0x%x\n", checksum));
|
||||||
}
|
}
|
||||||
|
|
||||||
int configureMAC() {
|
int configureMAC() {
|
||||||
@ -1334,7 +1334,7 @@ int startStateMachine() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOG(logINFOBLUE, ("Starting State Machine\n"));
|
LOG(logINFOBLUE, ("Starting State Machine\n"));
|
||||||
cleanFifos();
|
//cleanFifos(); removing this for now as its done before readout pattern
|
||||||
|
|
||||||
// start state machine
|
// start state machine
|
||||||
bus_w(FLOW_CONTROL_REG, bus_r(FLOW_CONTROL_REG) | START_F_MSK);
|
bus_w(FLOW_CONTROL_REG, bus_r(FLOW_CONTROL_REG) | START_F_MSK);
|
||||||
@ -1356,6 +1356,7 @@ int startStateMachine() {
|
|||||||
usleep(0);
|
usleep(0);
|
||||||
commaDet = (bus_r(TRANSCEIVERSTATUS) & RXCOMMADET_MSK);
|
commaDet = (bus_r(TRANSCEIVERSTATUS) & RXCOMMADET_MSK);
|
||||||
}
|
}
|
||||||
|
LOG(logINFORED, ("Kwords or end of acquisition detected\n"));
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -1516,6 +1517,7 @@ int startReadOut() {
|
|||||||
usleep(0);
|
usleep(0);
|
||||||
streamingBusy = (bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK);
|
streamingBusy = (bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK);
|
||||||
}
|
}
|
||||||
|
LOG(logINFORED, ("Streaming done\n"));
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -25,16 +25,20 @@
|
|||||||
#define DYNAMIC_RANGE (16)
|
#define DYNAMIC_RANGE (16)
|
||||||
#define NUM_BYTES_PER_PIXEL (DYNAMIC_RANGE / 8)
|
#define NUM_BYTES_PER_PIXEL (DYNAMIC_RANGE / 8)
|
||||||
|
|
||||||
#define DAC_DRIVER_FILE_NAME ("/root/apps/xilinx-ctb/current_board_links/ao%d")
|
#define MAIN_APP_FOLDER "/root/apps/xilinx-ctb"
|
||||||
#define DAC_POWERDOWN_DRIVER_FILE_NAME \
|
#define FIRMWARE_FILE MAIN_APP_FOLDER "/XilinxCTB.bit"
|
||||||
("/root/apps/xilinx-ctb/current_board_links/ao%d_pd")
|
#define DEVICE_TREE_OVERLAY_FILE MAIN_APP_FOLDER "/pl.dtbo"
|
||||||
|
#define CURRENT_BOARD_LINKS_FOLDER MAIN_APP_FOLDER "/current_board_links"
|
||||||
|
#define IIO_DEVICE_FOLDER MAIN_APP_FOLDER "/iio_device_links"
|
||||||
|
|
||||||
#define SLOWADC_DRIVER_FILE_NAME \
|
#define DEVICE_TREE_DST "/sys/bus/iio/devices/iio:device"
|
||||||
("/root/apps/xilinx-ctb/mythenIII_0.2_1.1/links/ai%d")
|
#define DEVICE_NAME_LIST "xilinx-ams", "ad7689", "dac@0", "dac@1", "dac@2"
|
||||||
// #define SLOWDAC_CONVERTION_FACTOR_TO_UV (62.500953)
|
#define DEVICE_TREE_API_FOLDER "/sys/kernel/config/device-tree/overlays/spidr"
|
||||||
|
|
||||||
#define TEMP_DRIVER_FILE_NAME \
|
#define DAC_DRIVER_FILE_NAME CURRENT_BOARD_LINKS_FOLDER "/ao%d"
|
||||||
("/sys/bus/iio/devices/iio:device0/in_temp7_input")
|
#define DAC_POWERDOWN_DRIVER_FILE_NAME CURRENT_BOARD_LINKS_FOLDER "/ao%d_pd"
|
||||||
|
#define SLOWADC_DRIVER_FILE_NAME CURRENT_BOARD_LINKS_FOLDER "/ai%d"
|
||||||
|
#define TEMP_DRIVER_FILE_NAME DEVICE_TREE_DST "0/in_temp7_input"
|
||||||
|
|
||||||
/** Default Parameters */
|
/** Default Parameters */
|
||||||
#define DEFAULT_NUM_FRAMES (1)
|
#define DEFAULT_NUM_FRAMES (1)
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
#define RELEASE "developer"
|
#define RELEASE "developer"
|
||||||
#define APILIB "developer 0x230224"
|
#define APILIB "developer 0x230224"
|
||||||
#define APIRECEIVER "developer 0x230224"
|
#define APIRECEIVER "developer 0x230224"
|
||||||
#define APICTB "developer 0x240822"
|
#define APICTB "developer 0x240910"
|
||||||
#define APIGOTTHARD "developer 0x240822"
|
#define APIGOTTHARD "developer 0x240910"
|
||||||
#define APIGOTTHARD2 "developer 0x240822"
|
#define APIGOTTHARD2 "developer 0x240910"
|
||||||
#define APIMYTHEN3 "developer 0x240822"
|
#define APIJUNGFRAU "developer 0x240910"
|
||||||
#define APIMOENCH "developer 0x240822"
|
#define APIMYTHEN3 "developer 0x240910"
|
||||||
#define APIXILINXCTB "developer 0x240822"
|
#define APIMOENCH "developer 0x240910"
|
||||||
#define APIEIGER "developer 0x240822"
|
#define APIXILINXCTB "developer 0x240910"
|
||||||
#define APIJUNGFRAU "developer 0x240822"
|
#define APIEIGER "developer 0x240910"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user