Newer
Older
/*-------------------------------------------------------------------------------*\
regconfig: From PCIe40 board to access register of FEE through belle2link
2020.03.06 0.01 first version based on reghs.c
\*--------------------------------------------------------------------------------*/
#include "pcie40_b2slc.h"
#include "pcie40_reg.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <vector>
#define MAX_SLOT 3
#define SLC_BAR 2
// parse
int dev_slot = 0; // default device slot number, If use multiple PCIe40 on a server, change it with --dev xx option
int ch = -1;
bool USE_FEE8 = false;
bool USE_FEE32 = false;
bool READ_ONLY = false;
bool WRITE = false;
bool STREAM = false;
bool STREAM_ARICH = false;
bool OP_FLAG = false;
/* 0 parameter */
#define PCIE40_NOP 0x100
#define PCIE40_LINK 0x101
#define PCIE40_CHECKFEE 0x102
#define PCIE40_TRGOFF 0x104
#define PCIE40_TRGON 0x105
#define PCIE40_RESETB2L 0x110
#define PCIE40_CONFPLL 0x111
#define PCIE40_SETMASK 0x112
#define PCIE40_SETUNMASK 0x113
#define PCIE40_SET_BANKMASK 0x114
#define PCIE40_SET_BANKUNMASK 0x115
/* 0 parameter (obsolete, unused) */
#define PCIE40_TTTRG 0x106
#define PCIE40_DUMTRG 0x107
/* 0 parameter (CDC special) */
#define PCIE40_SUPMODE 0x108
#define PCIE40_RAWMODE 0x109
/* 1 parameter */
#define PCIE40_STREAM 0x200
/* 1 parameter (CDC special) */
#define PCIE40_PDSTLALL 0x201
#define PCIE40_ADCTH 0x202
#define PCIE40_TDCTH 0x203
#define PCIE40_DELAY 0x204
#define PCIE40_WINDOW 0x205
/* 2 parameters */
#define PCIE40_FEE8 0x300
#define PCIE40_FEE32 0x301
/* 2 parameters (CDC special) */
#define PCIE40_PDSTL 0x302
/* defined address */
#define REG_FEEHWTYPE 0x0
#define REG_FEESERIAL 0x0
#define REG_FEEFWTYPE 0x0
#define REG_FEEFWVER 0x0
std::vector<std::string> splitpath(const std::string str, const char del) {
size_t first = 0;
size_t last = str.find_first_of(del);
while (first < str.size()) {
std::string subStr(str, first, last - first);
result.push_back(subStr);
first = last + 1;
last = str.find_first_of(del, first);
if (last == std::string::npos) {
}
}
return result;
}
void argument(int argc, char **argv){
std::string ss = argv[i];
if(ss=="--dev"){
dev_slot = atoi(argv[++i]);
if( dev_slot<0 || dev_slot >= MAX_SLOT){
fprintf(stderr, "Invalid device slot %d, Valid slot [0, %d]\n", dev_slot, MAX_SLOT);
}
}
if(ss=="--pcie40"){
PCIE40_REG = true;
}
if(ss=="--ch"){
ch = atoi(argv[++i]);
if( ch<0 || ch >= MAX_NUM_CH){
fprintf(stderr, "Invalid channel ID %d, Valid ID [0, %d]\n", ch, MAX_NUM_CH-1);
}
}
if(ss=="--bank"){
bank = atoi(argv[++i]);
if( bank<0 || bank >= MAX_NUM_BANK){
fprintf(stderr, "Invalid bank ID %d, Valid ID [0, %d]\n", ch, MAX_NUM_BANK-1);
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
}
}
if(ss=="--fee8"){
USE_FEE8 = true;
}
if(ss=="--fee32"){
USE_FEE32 = true;
}
if(ss=="-r" || ss=="--read"){
READ_ONLY = true;
addr = strtoul(argv[++i], 0, 16);
}
if(ss=="-w" || ss=="--write"){
WRITE = true;
addr = strtoul(argv[++i], 0, 16);
data = strtoul(argv[++i], 0, 16);
//printf("add = %02x data = %08x\n", addr, data);
}
if(ss=="--stream"){
STREAM = true;
filename = argv[++i];
std::string file_str = filename;
char delims = '.';
std::vector<std::string> path = splitpath(file_str, delims);
if(path.back() == "bin" || path.back() == "bit"){
STREAM_ARICH = true;
}
}
if(ss=="--op"){
OP_FLAG = true;
operation = argv[++i];
}
if(ss=="-h" || ss=="-help"){
fprintf(stderr, "%s version %d.%02d date %d\n"
, ARGV0, VERSION/100, VERSION%100, MOD_DATE);
fprintf(stderr, "usage: %s --pcie40 -r 0x00050010\n", ARGV0);
fprintf(stderr, " %s --ch 0 --fee32 -w 0x12 0x0\n"
" --pcie40 #access the register of pcie40\n"
" --ch xx #link channel number\n"
" --fee8 or --fee32 #use A7D8 or A16D32 for access register\n"
" -r xx or -w xx xx #read or write register with address xx[hex] or data xx[hex]\n\n"
" --op operation name writen in check hsreg()\n\n"
" %s --ch 0 --stream /path/firmware.bit\n"
" --stream /path/filename #streaming a file by using stream file method\n\n"
return;
}
}
}
/* ---------------------------------------------------------------------- *\
hsreg
\* ---------------------------------------------------------------------- */
int
hsreg(const char *name)
{
static struct { const char *name; int adrs; } regs[] = {
{ "link", PCIE40_LINK } ,
{ "checkfee", PCIE40_CHECKFEE },
{ "resetb2l", PCIE40_RESETB2L },
{ "confpll", PCIE40_CONFPLL },
{ "setmask", PCIE40_SETMASK },
{ "setunmask", PCIE40_SETUNMASK },
{ "setbankmask", PCIE40_SET_BANKMASK },
{ "setbankunmask", PCIE40_SET_BANKUNMASK },
{ "trghold", PCIE40_TRGOFF },
{ "trigger", PCIE40_TRGON },
{ "realtrg", PCIE40_TTTRG },
{ "simtrg", PCIE40_DUMTRG },
{ "simple", PCIE40_SUPMODE },
{ "verbose", PCIE40_RAWMODE },
{ "supmode", PCIE40_SUPMODE },
{ "rawmode", PCIE40_RAWMODE },
{ "pdstl", PCIE40_PDSTL },
{ "pdstlall", PCIE40_PDSTLALL },
{ "adcth", PCIE40_ADCTH },
{ "tdcth", PCIE40_TDCTH },
{ "delay", PCIE40_DELAY },
{ "window", PCIE40_WINDOW },
if (isdigit(name[0])) {
return strtoul(name, 0, 16);
}
for (i = 0; i<sizeof(regs)/sizeof(regs[0]); i++) {
if (strcmp(regs[i].name, name) == 0) {
return regs[i].adrs;
}
}
i = strtoul(name, 0, 16);
return (i > 0 && i < 0x100) ? i : -1;
}
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
//----------------------------------------------------------------------
// getfee
// ----------------------------------------------------------------------
int
getfee(pcie40reg_t *pcie40)
{
int hwtype;
int serial;
int fwtype;
int fwver;
hwtype = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEEHWTYPE);
serial = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEESERIAL);
fwtype = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEEFWTYPE);
fwver = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEEFWVER);
pcie40->feeser = (serial | (hwtype << 8)) & 0xfff;
pcie40->feever = (fwver | (fwtype << 8)) & 0xfff;
pcie40->feehw = (hwtype >> 4) & 0x0f;
pcie40->feefw = (fwtype >> 4) & 0x0f;
pcie40->feecrce = pcie40_readfee8(dev_slot, ch, PCIE40REG_CRCERR);
return 0;
}
/* ---------------------------------------------------------------------- *\
pcie40_op
\* ---------------------------------------------------------------------- */
int
pcie40_op(int dev, int ch, int op_addr, int addr, int data, pcie40reg_t pcie40)
{
int i;
int cmd = 0;
int cmd_cdc = 0;
switch (op_addr) {
case PCIE40_LINK: cmd = 0x01; break;
case PCIE40_TRGOFF: cmd = 0x03; break;
case PCIE40_TRGON: cmd = 0x04; break;
case PCIE40_SUPMODE: cmd_cdc = 0x07; break; /* suppress mode */
case PCIE40_RAWMODE: cmd_cdc = 0x08; break; /* raw mode */
}
if (op_addr == PCIE40_CHECKFEE) {
if (!pcie40_b2l_status(dev_slot, ch)) {
printf("Failed: b2l is down\n");
pcie40reg_t *pcie = &pcie40;
memset(pcie, 0, sizeof(*pcie));
pcie->feeser = 0xffff;
pcie->feever = 0xffff;
getfee(pcie);
if (pcie->feeser & 0x8000) {
printf("fee info is not available\n");
printf("%s serial %d version %d\n",
feename(pcie->feehw, pcie->feefw), pcie->feeser, pcie->feever);
} else if (op_addr == PCIE40_RESETB2L) {
pcie40_resetMinipodLink(dev, ch);
printf("B2LINK-%02d is %s\n",ch,
pcie40_b2l_status(dev_slot, ch)?"UP":"DOWN or NOT READY");
} else if (op_addr == PCIE40_CONFPLL) {
pcie40_configurePLLs(dev);
} else if (op_addr == PCIE40_SETMASK) {
pcie40_b2l_set_mask(dev_slot, ch, true);
} else if (op_addr == PCIE40_SETUNMASK) {
pcie40_b2l_set_mask(dev_slot, ch, false);
pcie40_writefee8(dev, ch, PCIE40REG_FEECONT, cmd);
pcie40_writefee8(dev, ch, PCIE40REG_CDCCONT, cmd_cdc);
}else if (op_addr == PCIE40_PDSTL) {
if (addr <= 0 || addr > 48) {
printf("pedestal channel %d out of range [1,48]\n", addr);
return -1;
}
pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (addr-1)*2+0, (data>>0) & 0xff);
pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (addr-1)*2+1, (data>>8) & 0xff);
} else if (op_addr == PCIE40_PDSTLALL) {
for (i=1; i<=48; i++) {
pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (i-1)*2+0, (addr>>0) & 0xff);
pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (i-1)*2+1, (addr>>8) & 0xff);
} else if (op_addr == PCIE40_ADCTH || op_addr == PCIE40_TDCTH) {
int adr = (op_addr == PCIE40_ADCTH) ? PCIE40REG_ADCTH : PCIE40REG_TDCTH;
if (addr != -1) {
pcie40_writefee8(dev, ch, adr + 0, (addr>>0) & 0xff);
pcie40_writefee8(dev, ch, adr + 1, (addr>>8) & 0xff);
} else {
printf("reg%02x = %02x%02x\n", adr,
pcie40_readfee8(dev, ch, adr + 1) & 0xff,
pcie40_readfee8(dev, ch, adr + 0) & 0xff);
}
}else if (op_addr == PCIE40_WINDOW || op_addr == PCIE40_DELAY) {
int adr = (op_addr == PCIE40_WINDOW) ? PCIE40REG_WINDOW : PCIE40REG_DELAY;
if (addr != -1) {
pcie40_writefee8(dev, ch, adr, addr & 0xff);
} else {
printf("reg%02x = %02x\n", adr, pcie40_readfee8(dev, ch, adr));
}
return 0;
}
int main(int argc, char** argv){
// parse arguments
argument(argc, argv);
// open pcie40 device driver for current process
ecs_open( dev_slot , SLC_BAR );
int result = -1;
if(PCIE40_REG && READ_ONLY){
result = ecs_read( dev_slot , SLC_BAR , addr);
printf("reg%08x = %08x\n", addr, result);
}
//register access via b2l
if(USE_FEE8 || USE_FEE32 || STREAM){
if(USE_FEE8 && READ_ONLY){
result = pcie40_readfee8( dev_slot , ch , addr );
printf("reg%04x = %08x\n", addr, result);
}else if(USE_FEE8 && WRITE){
result = pcie40_writefee8( dev_slot , ch , addr, data );
if(result == 0)
printf("Write 0x%04x to register 0x%04x\n", data, addr);
else
printf("ERROR: Failed to write 0x%04x to register 0x%04x\n", data, addr);
}else if(USE_FEE32 && READ_ONLY){
result = pcie40_readfee32( dev_slot , ch , addr );
printf("reg%04x = %08x\n", addr, result);
}else if(USE_FEE32 && WRITE){
result = pcie40_writefee32( dev_slot , ch , addr, data );
if(result == 0)
printf("Write 0x%08x to register 0x%04x\n", data, addr);
else
printf("ERROR: Failed to write 0x%08x to register %04x\n", data, addr);
}else if(STREAM){
if(STREAM_ARICH){
const char* detector = "ARICH";
result = pcie40_writestream( dev_slot , ch , filename, detector) ;
}else{
const char* detector = "KLM";
result = pcie40_writestream( dev_slot , ch , filename, detector) ;
}
if(result == 0)
std::cerr<<"Succeed streaming file: " << filename << std::endl;
else
std::cerr<<"ERROR: Failed streaming file: " << filename << std::endl;
}
}else{
printf("ERROR: b2link-%02d is down or not ready\n", ch);
//This is frame for register operation
//Expert usage: specify the addr and data with "-r" or "-w" if needed
if(OP_FLAG){
unsigned int op_addr = hsreg( operation );
pcie40_op(dev_slot, ch, op_addr, addr, data, pcie40);
}