Commit 8b0d60e5 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

shell: sfp add/erase/show commands for handling SFP DB in eeprom

parent 4300100f
......@@ -10,26 +10,23 @@
* placed also outside the FMC standardized EEPROM structure. The only requirement
* is that it starts with 0xdeadbeef pattern. The structure of SFP section is:
*
* --------------------------------
* | 0xdeadbeef (4B) | count (4B) |
* -------------------------------------------------------------------------------
* | SFP(1) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) |
* -------------------------------------------------------------------------------
* | SFP(2) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) |
* -------------------------------------------------------------------------------
* | (....) | (....) | (....) | (....) |
* -------------------------------------------------------------------------------
* | SFP(count) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) |
* -------------------------------------------------------------------------------
* | checksum (1B) |
* -----------------
* --------------
* | count (4B) |
* --------------------------------------------------------------------------------------------
* | SFP(1) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) | chksum(1B) |
* --------------------------------------------------------------------------------------------
* | SFP(2) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) | chksum(1B) |
* --------------------------------------------------------------------------------------------
* | (....) | (....) | (....) | (....) | (...) |
* --------------------------------------------------------------------------------------------
* | SFP(count) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) | chksum(1B) |
* --------------------------------------------------------------------------------------------
*
* Fields description:
* count - how many SFPs are described in the list (binary)
* SFP(n) part number - SFP PN as read from SFP's EEPROM (e.g. AXGE-1254-0531)
* (16 ascii chars)
* checksum - low order 8 bits of the sum of all bytes starting from
* _count_ (without 0xdeadbeef)
* checksum - low order 8 bits of the sum of all bytes for the SFP(PN,alpha,dTx,dRx)
*
*/
......@@ -61,89 +58,91 @@ int eeprom_read(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf,
return size;
}
//int eeprom_write(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
//{
// int i, busy;
//
// for(i=0;i<size;i++)
// {
// mi2c_start(i2cif);
//
// if(mi2c_put_byte(i2cif, i2c_addr << 1) < 0)
// {
// mi2c_stop(i2cif);
// return -1;
// }
// mi2c_put_byte(i2cif, (offset >> 8) & 0xff);
// mi2c_put_byte(i2cif, offset & 0xff);
// mi2c_put_byte(i2cif, *buf++);
// offset++;
// mi2c_stop(i2cif);
//
// do /* wait until the chip becomes ready */
// {
// mi2c_start(i2cif);
// busy = mi2c_put_byte(i2cif, i2c_addr << 1);
// mi2c_stop(i2cif);
// } while(busy);
//
// }
// return size;
//}
int eeprom_write(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
int i, busy;
for(i=0;i<size;i++)
{
mi2c_start(i2cif);
if(mi2c_put_byte(i2cif, i2c_addr << 1) < 0)
{
mi2c_stop(i2cif);
return -1;
}
mi2c_put_byte(i2cif, (offset >> 8) & 0xff);
mi2c_put_byte(i2cif, offset & 0xff);
mi2c_put_byte(i2cif, *buf++);
offset++;
mi2c_stop(i2cif);
do /* wait until the chip becomes ready */
{
mi2c_start(i2cif);
busy = mi2c_put_byte(i2cif, i2c_addr << 1);
mi2c_stop(i2cif);
} while(busy);
}
return size;
}
int32_t eeprom_sfpdb_erase(uint8_t i2cif, uint8_t i2c_addr)
{
uint8_t sfpcount = 0;
int32_t eeprom_sfp_section(uint8_t i2cif, uint8_t i2c_addr, size_t size, uint16_t *section_sz)
//just a dummy function that writes '0' to sfp count field of the SFP DB
if( eeprom_write(i2cif, i2c_addr, EE_BASE_SFP, &sfpcount, sizeof(sfpcount)) != sizeof(sfpcount))
return EE_RET_I2CERR;
else
return sfpcount;
}
int32_t eeprom_get_sfp(uint8_t i2cif, uint8_t i2c_addr, struct s_sfpinfo* sfp, uint8_t add, uint8_t pos)
{
uint8_t c, match;
uint16_t i;
uint32_t sfp_pattern = SFP_SECTION_PATTERN;
static uint8_t sfpcount = 0;
uint8_t i, chksum=0;
uint8_t* ptr;
match = 0x00;
*section_sz = 0x0000;
mi2c_start(i2cif);
if(mi2c_put_byte(i2cif, i2c_addr << 1) != 0)
if( pos>=SFPS_MAX )
return EE_RET_POSERR; //position in database outside the range
//read how many SFPs are in the database, but only in the first call (pos==0)
if( !pos && eeprom_read(i2cif, i2c_addr, EE_BASE_SFP, &sfpcount, sizeof(sfpcount)) != sizeof(sfpcount) )
return EE_RET_I2CERR;
if( add && sfpcount==SFPS_MAX ) //no more space in the database to add new SFPs
return EE_RET_DBFULL;
else if( !pos && !add && sfpcount==0 ) //there are no SFPs in the database to read
return sfpcount;
if(!add)
{
mi2c_stop(i2cif);
return -1;
if( eeprom_read(i2cif, i2c_addr, EE_BASE_SFP + sizeof(sfpcount) + pos*sizeof(struct s_sfpinfo), sfp,
sizeof(struct s_sfpinfo)) != sizeof(struct s_sfpinfo) )
return EE_RET_I2CERR;
ptr = (uint8_t*)sfp;
for(i=0; i<sizeof(struct s_sfpinfo)-1; ++i) //'-1' because we do not include chksum in computation
chksum = (uint8_t) ((uint16_t)chksum + *(ptr++)) & 0xff;
if(chksum != sfp->chksum)
EE_RET_CHKSUM;
}
mi2c_put_byte(i2cif, 0x00);
mi2c_put_byte(i2cif, 0x00);
mi2c_repeat_start(i2cif);
mi2c_put_byte(i2cif, (i2c_addr << 1) | 1);
for(i=0; i<size-1; ++i)
else
{
mi2c_get_byte(i2cif, &c, 0);
if(match==0x0f)
{
*section_sz = ((uint16_t)c ) << 8;
match |= 0x10;
}
else if(match==0x1f)
{
*section_sz |= ((uint16_t)c ) & 0xff;
match |= 0x20;
}
else if( c== (uint8_t)(sfp_pattern>>24) )
match = 0x01;
else if( c== (uint8_t)((sfp_pattern>>16)&0xff) )
match |= 0x02;
else if( c== (uint8_t)((sfp_pattern>>8)&0xff) )
match |= 0x04;
else if( c== (uint8_t)(sfp_pattern&0xff) )
match |= 0x08;
else
match = 0x00;
if(match == 0x3f)
{
mi2c_get_byte(i2cif, &c, 1);
mi2c_stop(i2cif);
return i+1; //first address of first SFP in the list
}
/*count checksum*/
ptr = (uint8_t*)sfp;
for(i=0; i<sizeof(struct s_sfpinfo)-1; ++i) //'-1' because we do not include chksum in computation
chksum = (uint8_t) ((uint16_t)chksum + *(ptr++)) & 0xff;
sfp->chksum = chksum;
/*add SFP at the end of DB*/
eeprom_write(i2cif, i2c_addr, EE_BASE_SFP+sizeof(sfpcount) + sfpcount*sizeof(struct s_sfpinfo), sfp, sizeof(struct s_sfpinfo));
sfpcount++;
eeprom_write(i2cif, i2c_addr, EE_BASE_SFP, &sfpcount, sizeof(sfpcount));
}
mi2c_get_byte(i2cif, &c, 1);
mi2c_stop(i2cif);
return 0;
return sfpcount;
}
int8_t eeprom_get_sfpinfo(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, struct s_sfpinfo *sfpinfo, uint16_t section_sz)
......@@ -177,61 +176,61 @@ int8_t eeprom_get_sfpinfo(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, stru
}
}
int8_t access_eeprom(char *sfp_pn, int32_t *alpha, int32_t *deltaTx, int32_t *deltaRx)
{
uint16_t i;
uint8_t j;
uint16_t sfp_sz;
int32_t sfp_adr;
struct s_sfpinfo sfpinfo[SFPINFO_MAX];
mi2c_init(WRPC_FMC_I2C);
sfp_adr = eeprom_sfp_section(WRPC_FMC_I2C, FMC_EEPROM_ADR, 64*1024, &sfp_sz);
if(sfp_adr == -1)
{
mprintf("FMC EEPROM not found\n");
return -1;
}
else if(sfp_sz > SFPINFO_MAX)
{
//Ooops, there are too many of them, print warning
mprintf("! Warning ! too many SFP entries (%d)\n", sfp_sz);
sfp_sz = SFPINFO_MAX;
}
else if(sfp_sz == 0)
{
mprintf("EEPROM: could no find SFP section, staring with defaults\n");
return -1;
}
mprintf("EEPROM: found SFP section at %d size %d\n", (uint32_t)sfp_adr, (uint32_t)sfp_sz);
if( eeprom_get_sfpinfo(WRPC_FMC_I2C, FMC_EEPROM_ADR, sfp_adr, sfpinfo, sfp_sz))
{
mprintf("EEPROM ERROR\n");
return -1;
}
for(i=0; i<sfp_sz; ++i)
{
for(j=0; j<16; ++j)
{
if(sfp_pn[j] != sfpinfo[i].pn[j])
break;
}
if( j==16 ) //which means sfp_pn = sfpinfo[i].pn
{
mprintf("match SFP%d: pn=", i+1);
for(j=0; j<16; ++j)
mprintf("%c", sfpinfo[i].pn[j]);
//mprintf(" alpha=%x deltaTx=%x deltaRx=%x\n", sfpinfo[i].alpha, sfpinfo[i].deltaTx, sfpinfo[i].deltaRx);
*alpha = sfpinfo[i].alpha;
*deltaTx = sfpinfo[i].deltaTx;
*deltaRx = sfpinfo[i].deltaRx;
}
}
return 0;
}
//int8_t access_eeprom(char *sfp_pn, int32_t *alpha, int32_t *deltaTx, int32_t *deltaRx)
//{
// uint16_t i;
// uint8_t j;
// uint16_t sfp_sz;
// int32_t sfp_adr;
// struct s_sfpinfo sfpinfo[SFPS_MAX];
//
// mi2c_init(WRPC_FMC_I2C);
//
// sfp_adr = eeprom_sfp_section(WRPC_FMC_I2C, FMC_EEPROM_ADR, 64*1024, &sfp_sz);
// if(sfp_adr == -1)
// {
// mprintf("FMC EEPROM not found\n");
// return -1;
// }
// else if(sfp_sz > SFPINFO_MAX)
// {
// //Ooops, there are too many of them, print warning
// mprintf("! Warning ! too many SFP entries (%d)\n", sfp_sz);
// sfp_sz = SFPINFO_MAX;
// }
// else if(sfp_sz == 0)
// {
// mprintf("EEPROM: could no find SFP section, staring with defaults\n");
// return -1;
// }
// mprintf("EEPROM: found SFP section at %d size %d\n", (uint32_t)sfp_adr, (uint32_t)sfp_sz);
//
// if( eeprom_get_sfpinfo(WRPC_FMC_I2C, FMC_EEPROM_ADR, sfp_adr, sfpinfo, sfp_sz))
// {
// mprintf("EEPROM ERROR\n");
// return -1;
// }
//
// for(i=0; i<sfp_sz; ++i)
// {
// for(j=0; j<16; ++j)
// {
// if(sfp_pn[j] != sfpinfo[i].pn[j])
// break;
// }
//
// if( j==16 ) //which means sfp_pn = sfpinfo[i].pn
// {
// mprintf("match SFP%d: pn=", i+1);
// for(j=0; j<16; ++j)
// mprintf("%c", sfpinfo[i].pn[j]);
// //mprintf(" alpha=%x deltaTx=%x deltaRx=%x\n", sfpinfo[i].alpha, sfpinfo[i].deltaTx, sfpinfo[i].deltaRx);
//
// *alpha = sfpinfo[i].alpha;
// *deltaTx = sfpinfo[i].deltaTx;
// *deltaRx = sfpinfo[i].deltaRx;
// }
// }
//
// return 0;
//}
......@@ -97,3 +97,18 @@ void mi2c_init(uint8_t i2cif)
M_SCL_OUT(i2cif, 1);
M_SDA_OUT(i2cif, 1);
}
//void mi2c_scan(uint8_t i2cif)
//{
// int i;
//
// //for(i=0;i<0x80;i++)
// for(i=0x50;i<0x51;i++)
// {
// mi2c_start(i2cif);
// if(!mi2c_put_byte(i2cif, i<<1)) mprintf("found : %x\n", i);
// mi2c_stop(i2cif);
//
// }
// mprintf("Nothing more found...\n");
//}
......@@ -2,20 +2,29 @@
#define __EEPROM_H
#define SFP_SECTION_PATTERN 0xdeadbeef
#define SFPINFO_MAX 4
#define SFPS_MAX 4
#define EE_BASE_SFP 4*1024
#define EE_BASE_INIT 4*1024+SFPS_MAX*29
__attribute__ ((packed)) struct s_sfpinfo
#define EE_RET_I2CERR -1
#define EE_RET_DBFULL -2
#define EE_RET_CHKSUM -3
#define EE_RET_POSERR -4
struct s_sfpinfo
{
char pn[16];
int32_t alpha;
int32_t deltaTx;
int32_t deltaRx;
};
int32_t dTx;
int32_t dRx;
uint8_t chksum;
} __attribute__((__packed__));
int eeprom_read(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size);
int eeprom_write(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size);
int32_t eeprom_sfpdb_erase(uint8_t i2cif, uint8_t i2c_addr);
int32_t eeprom_sfp_section(uint8_t i2cif, uint8_t i2c_addr, size_t size, uint16_t *section_sz);
int8_t eeprom_get_sfpinfo(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, struct s_sfpinfo *sfpinfo, uint16_t section_sz);
int8_t access_eeprom(char *sfp_pn, int32_t *alpha, int32_t *deltaTx, int32_t *deltaRx);
......
......@@ -6,15 +6,21 @@
Subcommands:
add vendor_type delta_tx delta_rx alpha - adds an SFP to the database, with given alpha/delta_rx/delta_rx values
show - shows the SFP database
erase - cleans the SFP database
detect - detects the transceiver type
*/
#include "shell.h"
#include "eeprom.h"
#include "syscon.h"
#include "sfp.h"
int cmd_sfp(const char *args[])
{
int8_t sfpcount=1, i, temp;
struct s_sfpinfo sfp;
if(args[0] && !strcasecmp(args[0], "detect"))
{
char pn[17];
......@@ -25,11 +31,60 @@ int cmd_sfp(const char *args[])
pn[16]=0;
mprintf("%s\n",pn);
return 0;
} else if (args[3] && !strcasecmp(args[0], "add"))
}
// else if (!strcasecmp(args[0], "i2cscan"))
// {
// mi2c_scan(WRPC_FMC_I2C);
// return 0;
// }
else if (!strcasecmp(args[0], "erase"))
{
if( eeprom_sfpdb_erase(WRPC_FMC_I2C, FMC_EEPROM_ADR) == EE_RET_I2CERR)
mprintf("Could not erase DB\n");
}
else if (args[4] && !strcasecmp(args[0], "add"))
{
if(strlen( args[1] )>16) temp=16;
else temp=strlen( args[1] );
for(i=0; i<temp; ++i)
sfp.pn[i]=args[1][i];
while(i<16) sfp.pn[i++]=' '; //padding
sfp.dTx = atoi(args[2]);
sfp.dRx = atoi(args[3]);
sfp.alpha = atoi(args[4]);
temp = eeprom_get_sfp(WRPC_FMC_I2C, FMC_EEPROM_ADR, &sfp, 1, 0);
if(temp == EE_RET_DBFULL)
mprintf("SFP DB is full\n");
else if(temp == EE_RET_I2CERR)
mprintf("I2C error\n");
else
mprintf("%d SFPs in DB\n", temp);
}
else if (args[0] && !strcasecmp(args[0], "show"))
{
for(i=0; i<sfpcount; ++i)
{
temp = eeprom_get_sfp(WRPC_FMC_I2C, FMC_EEPROM_ADR, &sfp, 0, i);
if(!i)
{
sfpcount=temp; //only in first round valid sfpcount is returned from eeprom_get_sfp
if(sfpcount == 0 || sfpcount == 0xFF)
{
mprintf("SFP database empty...\n");
return 0;
}
else if(sfpcount == -1)
{
mprintf("SFP database corrupted...\n");
return 0;
}
}
mprintf("%d: PN:", i+1);
for(temp=0; temp<16; ++temp)
mprintf("%c", sfp.pn[temp]);
mprintf(" dTx: %d, dRx: %d, alpha: %d\n", sfp.dTx, sfp.dRx, sfp.alpha);
}
}
return 0;
}
\ No newline at end of file
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment