Initialization kind of works!
This commit is contained in:
parent
3148925051
commit
cd5b99a904
|
@ -5,6 +5,8 @@
|
|||
namespace FM10K {
|
||||
const uint64_t BAR4_SIZE = 0x0000000004000000;
|
||||
const uint64_t BAR4_OFFSET = 0x0;
|
||||
const uint8_t PEP_COUNT = 9;
|
||||
const uint8_t EPL_COUNT = 9;
|
||||
|
||||
//These should not be set (on hw) to more than 1100 or less than 800
|
||||
constexpr uint32_t DEFAULT_VDDS_VOLTAGE = 850; //Spec says 0.9 Volts, and also 0.85
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
#include "FM10K.h"
|
||||
#include "registers/Register.h"
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
||||
FM10K::FM10K::FM10K(std::unique_ptr<Device> device) : m_device(std::move(device)) {
|
||||
if(valid()){
|
||||
auto vpd = mapRegister<registers::MGMT::VITAL_PRODUCT_DATA>();
|
||||
auto chipVersion = mapRegister<registers::MGMT::CHIP_VERSION>();
|
||||
auto fuseData = mapRegister<registers::MGMT::FUSE_DATA_0>();
|
||||
|
||||
m_hwInfo = {
|
||||
static_cast<HardwareInformation::Family>(vpd->fields.PartNumber),
|
||||
static_cast<HardwareInformation::Model>(fuseData->fields.SKU),
|
||||
static_cast<HardwareInformation::ChipVersion>(chipVersion->fields.Version),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const FM10K::FM10K::HardwareInformation& FM10K::FM10K::getHardwareInformation() const {
|
||||
return m_hwInfo;
|
||||
|
@ -52,4 +68,246 @@ std::string FM10K::FM10K::getHardwareInformationString() const {
|
|||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
bool FM10K::FM10K::initializationSequence() const {
|
||||
if(mapRegister<registers::MGMT::SOFT_RESET>()->fields.ColdReset){
|
||||
//Not yet initialized from cold reset
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mapRegister<registers::MGMT::SOFT_RESET>()->fields.SwitchReady == 1){
|
||||
return true; //Already initialized
|
||||
}
|
||||
|
||||
{
|
||||
//5.4.3.1 Clear Switch Memories
|
||||
//this needs to be done before step 19
|
||||
//All BIST-accessible memories in the FM10000 are cleared as part of the recommended chip initialization
|
||||
//(refer to Section 4.1.3.11), so the following step need not be repeated during the first switch
|
||||
//initialization after bring-up.
|
||||
auto bistCtrl = mapRegister<registers::MGMT::BIST_CTRL>();
|
||||
bistCtrl->fields.BistMode_FABRIC = 1;
|
||||
bistCtrl->fields.BistRun_FABRIC = 1;
|
||||
wait(800); //Sleep 0.8ms
|
||||
bistCtrl->fields.BistMode_FABRIC = 0;
|
||||
bistCtrl->fields.BistRun_FABRIC = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Following from step 19 of Table 4-3 on 4.1.3.11 Initialization Sequence section
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 19
|
||||
mapRegister<registers::MGMT::SOFT_RESET>()->fields.SwitchReset = 0;
|
||||
wait_ns(100);
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 20
|
||||
auto scanDataIn = mapRegister<registers::MGMT::SCAN_DATA_IN>();
|
||||
registers::MGMT::SCAN_DATA_IN scanDataIn_copy{scanDataIn->value};
|
||||
scanDataIn_copy.value = 0;
|
||||
scanDataIn->fields.UpdateNodes = 1;
|
||||
scanDataIn->fields.Passthru = 1;
|
||||
scanDataIn->value = scanDataIn_copy.value;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 22
|
||||
|
||||
//Step 21.1
|
||||
for(uint32_t pep = 0; pep < PEP_COUNT; ++pep){
|
||||
if(isPEPEnabled(pep)){
|
||||
mapRegister<registers::PCIE_PF::PCIE_CTRL_EXT>(registers::PCIE_PF::PCIE_PF_OFFSET * pep)->fields.SwitchLoopback = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Step 21.2
|
||||
for(uint32_t epl = 0; epl < EPL_COUNT; ++epl){
|
||||
mapRegister<registers::EPL::EPL_CFG_A>(registers::EPL::EPL_OFFSET * epl)->fields.Active = 0xF;
|
||||
}
|
||||
|
||||
//Step 21.3
|
||||
mapRegister<registers::TE::TE_CFG>(registers::TE::TE_OFFSET * 0)->fields.SwitchLoopbackDisable = 1;
|
||||
mapRegister<registers::TE::TE_CFG>(registers::TE::TE_OFFSET * 1)->fields.SwitchLoopbackDisable = 1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 22 (TODO add L2/L3 switching/routing here)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 22.1
|
||||
//TODO enable Congestion Management.
|
||||
auto cmGlobalCfg = mapRegister<registers::CM_USAGE::CM_GLOBAL_CFG>();
|
||||
|
||||
//Step 22.2
|
||||
//TODO Set CM_GLOBAL_WM as specified in Section 5.7.10.4, “Memory Usage Tracking and Watermarks Application”.
|
||||
auto cmGlobalWm = mapRegister<registers::CM_USAGE::CM_GLOBAL_WM>();
|
||||
//Figure 5-29 shows the global usage tracking and watermarks. Any frame received is counted in the
|
||||
//CM_GLOBAL_USAGE. At the start of each frame, the CM_GLOBAL_USAGE is compared to the
|
||||
//CM_GLOBAL_WM, which is used to limit the total number of frames allowed enter the device. Normally,
|
||||
//the CM_GLOBAL_WM should be set to the maximum number of segments possible (24,576), minus the
|
||||
//number of ports enabled x (numbers of segments per maximum size frame), minus 256 reserved
|
||||
//segments.
|
||||
|
||||
//Step 22.3
|
||||
mapRegister<registers::L2_LOOKUP_TCN::MA_TCN_IM>()->value = 0;
|
||||
mapRegister<registers::HANDLER_TAIL::FH_TAIL_IM>()->fields.TCN = 0;
|
||||
|
||||
for(uint32_t pep = 0; pep < PEP_COUNT; ++pep){
|
||||
if(isPEPEnabled(pep)){
|
||||
mapRegister<registers::MGMT::INTERRUPT_MASK_PCIE>(pep * 2)->fields.FH_TAIL = 0;
|
||||
}
|
||||
}
|
||||
//mapRegister<registers::MGMT::INTERRUPT_MASK_INT>()->fields.FH_TAIL = 0;
|
||||
//mapRegister<registers::MGMT::INTERRUPT_MASK_FIBM>()->fields.FH_TAIL = 0;
|
||||
//mapRegister<registers::MGMT::INTERRUPT_MASK_BSM>()->fields.FH_TAIL = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 23 (based on 5.4.3 Scheduler Initialization)
|
||||
//5.4.3.1 Clear Switch Memories
|
||||
for(uint32_t _class = 0; _class < registers::CM_USAGE::CLASS_ENTRIES; ++_class){
|
||||
for(auto i = 0; i < 4; ++i){ //128-bit registers
|
||||
setValue(registers::CM_USAGE::CM_EGRESS_PAUSE_COUNT__Address + 4 * _class + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//5.4.3.2 Initialization of RXQ_MCAST List
|
||||
for(auto i = 0; i < registers::SCHED::SCHED_RXQ_STORAGE_POINTERS__Entries; ++i){
|
||||
auto pointer = mapRegister<registers::SCHED::SCHED_RXQ_STORAGE_POINTERS>(i);
|
||||
pointer->fields.HeadPage = i;
|
||||
pointer->fields.TailPage = i;
|
||||
pointer->fields.HeadIdx = 0;
|
||||
pointer->fields.TailIdx = 0;
|
||||
pointer->fields.NextPage = 0;
|
||||
}
|
||||
for(auto i = 0; i < (1024 - registers::SCHED::SCHED_RXQ_STORAGE_POINTERS__Entries); ++i){
|
||||
//TODO: check how compiler optimizes this
|
||||
mapRegister<registers::SCHED::SCHED_RXQ_FREELIST_INIT>()->fields.Address = registers::SCHED::SCHED_RXQ_STORAGE_POINTERS__Entries + i;
|
||||
}
|
||||
|
||||
//5.4.3.3 Initialization of TXQ List
|
||||
//Note: All XXX_PERQ registers are indexed [0..383] which is equal to PORT*8+TC.
|
||||
for(auto i = 0; i < registers::SCHED::SCHED_TXQ_HEAD_PERQ__Entries; ++i){
|
||||
mapRegister<registers::SCHED::SCHED_TXQ_HEAD_PERQ>(i)->fields.Head = i;
|
||||
mapRegister<registers::SCHED::SCHED_TXQ_TAIL0_PERQ>(i)->fields.Tail = i;
|
||||
mapRegister<registers::SCHED::SCHED_TXQ_TAIL1_PERQ>(i)->fields.Tail = i;
|
||||
}
|
||||
for(auto i = 0; i < (24576 - registers::SCHED::SCHED_TXQ_HEAD_PERQ__Entries); ++i){
|
||||
//TODO: check how compiler optimizes this
|
||||
mapRegister<registers::SCHED::SCHED_TXQ_FREELIST_INIT>()->fields.Address = registers::SCHED::SCHED_TXQ_HEAD_PERQ__Entries + i;
|
||||
}
|
||||
|
||||
//5.4.3.4 Initialization of FREE Segment List
|
||||
for(auto i = 0; i < registers::SCHED::SCHED_SSCHED_RX_PERPORT__Entries; ++i){
|
||||
mapRegister<registers::SCHED::SCHED_SSCHED_RX_PERPORT>(i)->fields.Next = i;
|
||||
}
|
||||
for(auto i = 0; i < (24576 - registers::SCHED::SCHED_SSCHED_RX_PERPORT__Entries); ++i){
|
||||
//TODO: check how compiler optimizes this
|
||||
mapRegister<registers::SCHED::SCHED_FREELIST_INIT>()->fields.Address = registers::SCHED::SCHED_SSCHED_RX_PERPORT__Entries + i;
|
||||
}
|
||||
|
||||
//5.4.3.5 Initialization of Scheduler Polling Schedule
|
||||
// The TX and RX schedule must be initialized according to the relative speed of each port.
|
||||
/*
|
||||
// The example below is 45x10 GbE (36x10 GbE for Ethernet, 5x10 GbE for PEPs (bifurcation mode off), 2 for Tunneling Engines, 1xFIBM and 1x10 GbE for idle).
|
||||
// Logical ports 0..35 are physical ports 0..35 (Ethernet)
|
||||
for (i=0;i<36;i++)
|
||||
{
|
||||
SCHED_RX_SCHEDULE[i].Port = i;
|
||||
SCHED_RX_SCHEDULE[i].PhysPort = i;
|
||||
SCHED_RX_SCHEDULE[i].Quad = 0;
|
||||
SCHED_RX_SCHEDULE[i].Idle = 0;
|
||||
// Repeat for TX
|
||||
SCHED_TX_SCHEDULE[i].Port = i;
|
||||
SCHED_TX_SCHEDULE[i].PhysPort = i;
|
||||
SCHED_TX_SCHEDULE[i].Quad = 0;
|
||||
SCHED_TX_SCHEDULE[i].Idle = 0;
|
||||
}
|
||||
// Logical ports 36..41,46,47 are 5xPEPs and 2xTE and 1xFIBM (bifurcation ON)
|
||||
// (last logical port is mapped to PEP[8]
|
||||
int xLogPort[8] = { 36, 37, 38, 39, 40, 41, 46, 47 };
|
||||
int xPhysPort[8] = { 36, 40, 44, 48, 52, 56, 60, 63 };
|
||||
int xQuad[8] = { 1, 1, 1, 1, 1, 1, 0, 0 };
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
SCHED_RX_SCHEDULE[i+36].Port = xLogPort[i];
|
||||
SCHED_RX_SCHEDULE[i+36].PhysPort = xPhysPort[i];
|
||||
SCHED_RX_SCHEDULE[i+36].Quad = xQuad[i];
|
||||
SCHED_RX_SCHEDULE[i+36].Idle = 0;
|
||||
// Repeat for TX
|
||||
SCHED_TX_SCHEDULE[i+36].Port = xLogPort[i];
|
||||
SCHED_TX_SCHEDULE[i+36].PhysPort = xPhysPort[i];
|
||||
SCHED_TX_SCHEDULE[i+36].Quad = xQuad[i];
|
||||
SCHED_TX_SCHEDULE[i+36].Idle = 0;
|
||||
}
|
||||
// Start Scheduler
|
||||
SCHED_SCHEDULE_CTRL.RxPage = 0;
|
||||
SCHED_SCHEDULE_CTRL.RxMaxIndex = 43;
|
||||
SCHED_SCHEDULE_CTRL.RxEnable = 1;
|
||||
SCHED_SCHEDULE_CTRL.TxPage = 0;
|
||||
SCHED_SCHEDULE_CTRL.TxMaxIndex = 43;
|
||||
SCHED_SCHEDULE_CTRL.TxEnable = 1;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 24
|
||||
mapRegister<registers::MGMT::LED_CFG>()->fields.LEDEnable = 1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 25 (based on 9.9.1 Initialization of System Time)
|
||||
auto softReset = mapRegister<registers::MGMT::SOFT_RESET>();
|
||||
auto prevActive = softReset->fields.PCIeActive;
|
||||
softReset->fields.PCIeActive = mapRegister<registers::MGMT::DEVICE_CFG>()->fields.PCIeEnable;
|
||||
//TODO: set SYSTIME_CFG for IEEE-1588 support
|
||||
//PCIE_SYSTIME_CFG.Step = SYSTIME_CFG.Step
|
||||
//TE_SYSTIME_CFG.Step = SYSTIME_CFG.Step
|
||||
//TODO: set SYSTIME0
|
||||
softReset->fields.PCIeActive = prevActive;
|
||||
//De-assert the external IEEE1588_RESET_N pin (toggle from low to high) to initialize all SYSTIME
|
||||
//registers to SYSTIME0 and begin counting time
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Step 26
|
||||
mapRegister<registers::MGMT::SOFT_RESET>()->fields.SwitchReady = 1; //Allow traffic flow
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FM10K::FM10K::isPEPEnabled(uint8_t pep) const {
|
||||
return (mapRegister<registers::MGMT::DEVICE_CFG>()->fields.PCIeEnable & (1 << pep)) > 0;
|
||||
}
|
||||
|
||||
void FM10K::FM10K::wait(uint32_t microseconds) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
||||
}
|
||||
|
||||
void FM10K::FM10K::wait_ns(uint32_t nanoseconds) {
|
||||
std::this_thread::sleep_for(std::chrono::nanoseconds (nanoseconds));
|
||||
}
|
||||
|
|
|
@ -9,33 +9,26 @@
|
|||
#include "registers/MGMT.h"
|
||||
#include "Constants.h"
|
||||
|
||||
#define FM10K_GET_REGISTER(i, t) i.getType<t>(t ## __Address)
|
||||
#define FM10K_MAP_REGISTER(i, t) i.mapType<t>(t ## __Address)
|
||||
#define FM10K_SET_REGISTER(i, t, v) i.setType<t>(t ## __Address, v)
|
||||
#define FM10K_GET_REGISTER(i, t) i.getType<t>(t::ADDRESS)
|
||||
#define FM10K_MAP_REGISTER(i, t) i.mapType<t>(t::ADDRESS)
|
||||
#define FM10K_SET_REGISTER(i, t, v) i.setType<t>(t::ADDRESS, v)
|
||||
#define FM10K_SET_REGISTER_FIELD(i, t, f, v) \
|
||||
auto __f = FM10K_MAP_REGISTER(i, t); \
|
||||
__f->fields. f = v
|
||||
|
||||
#define FM10K_GET_REGISTER_OFFSET(i, t, o) i.getType<t>(t::ADDRESS + o)
|
||||
#define FM10K_MAP_REGISTER_OFFSET(i, t, o) i.mapType<t>(t::ADDRESS + o)
|
||||
#define FM10K_SET_REGISTER_OFFSET(i, t, o, v) i.setType<t>(t::ADDRESS + o, v)
|
||||
#define FM10K_SET_REGISTER_FIELD_OFFSET(i, t, o, f, v) \
|
||||
auto __f = FM10K_MAP_REGISTER(i, t, o); \
|
||||
__f->fields. f = v
|
||||
|
||||
namespace FM10K{
|
||||
|
||||
class FM10K {
|
||||
public:
|
||||
|
||||
explicit FM10K(std::unique_ptr<Device> device) : m_device(std::move(device)) {
|
||||
if(valid()){
|
||||
auto vpd = FM10K_MAP_REGISTER((*this), registers::MGMT::VITAL_PRODUCT_DATA);
|
||||
auto chipVersion = FM10K_MAP_REGISTER((*this), registers::MGMT::CHIP_VERSION);
|
||||
auto fuseData = FM10K_MAP_REGISTER((*this), registers::MGMT::FUSE_DATA_0);
|
||||
|
||||
m_hwInfo = {
|
||||
static_cast<HardwareInformation::Family>(vpd->fields.PartNumber),
|
||||
static_cast<HardwareInformation::Model>(fuseData->fields.SKU),
|
||||
static_cast<HardwareInformation::ChipVersion>(chipVersion->fields.Version),
|
||||
};
|
||||
} else {
|
||||
m_hwInfo = {};
|
||||
}
|
||||
}
|
||||
explicit FM10K(std::unique_ptr<Device> device);
|
||||
|
||||
bool valid() const{
|
||||
return m_device->valid();
|
||||
|
@ -45,20 +38,38 @@ namespace FM10K{
|
|||
return reinterpret_cast<volatile T*>(m_device->map32(address));
|
||||
}
|
||||
|
||||
template<typename T> volatile T* mapRegister(uint32_t offset = 0) const{
|
||||
return FM10K_MAP_REGISTER_OFFSET((*this), T, offset);
|
||||
}
|
||||
|
||||
template<typename T> T getType(uint32_t address) const {
|
||||
static_assert(sizeof(T) == 4 || sizeof(T) == 8, "Invalid type for FM10K::getType");
|
||||
T t;
|
||||
t.value = m_device->get32(address);
|
||||
if(sizeof(T) == 4){
|
||||
t.value = m_device->get32(address);
|
||||
}else if(sizeof(T) == 8){
|
||||
t = reinterpret_cast<T>(m_device->get64(address));
|
||||
}
|
||||
return std::move(t);
|
||||
}
|
||||
|
||||
template<typename T> void setType(uint32_t address, const T& t) const {
|
||||
t.value = m_device->set32(address, t.value);
|
||||
static_assert(sizeof(T) == 4 || sizeof(T) == 8, "Invalid type for FM10K::setType");
|
||||
if(sizeof(T) == 4){
|
||||
m_device->set32(address, t.value);
|
||||
}else if(sizeof(T) == 8){
|
||||
m_device->set64(address, reinterpret_cast<uint64_t>(t));
|
||||
}
|
||||
|
||||
return std::move(t);
|
||||
}
|
||||
|
||||
template<typename T> void setTypeMask(uint32_t address, uint32_t mask, const T& t) const {
|
||||
t.value = m_device->set32(address, t.value & mask);
|
||||
return std::move(t);
|
||||
uint32_t getValue(uint32_t address) const {
|
||||
return m_device->get32(address);
|
||||
}
|
||||
|
||||
void setValue(uint32_t address, uint32_t value) const {
|
||||
m_device->set32(address, value);
|
||||
}
|
||||
|
||||
struct HardwareInformation{
|
||||
|
@ -89,11 +100,18 @@ namespace FM10K{
|
|||
const HardwareInformation& getHardwareInformation() const;
|
||||
std::string getHardwareInformationString() const;
|
||||
|
||||
static void wait(uint32_t microseconds) ;
|
||||
static void wait_ns(uint32_t nanoseconds) ;
|
||||
|
||||
bool initializationSequence() const;
|
||||
|
||||
bool isPEPEnabled(uint8_t pep) const;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
std::unique_ptr<Device> m_device;
|
||||
HardwareInformation m_hwInfo;
|
||||
HardwareInformation m_hwInfo{};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
31
src/fm10k/registers/CM_USAGE.h
Normal file
31
src/fm10k/registers/CM_USAGE.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "Register.h"
|
||||
|
||||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace CM_USAGE {
|
||||
const uint32_t BASE_ADDRESS = 0xE60000;
|
||||
const uint32_t CLASS_ENTRIES = 48;
|
||||
|
||||
PACKEDA(CM_GLOBAL_WM, 0x852, struct {
|
||||
uint16_t watermark: 15;
|
||||
uint32_t : 17;
|
||||
}, uint32_t);
|
||||
PACKEDA(CM_GLOBAL_CFG, 0x853, struct {
|
||||
uint8_t ifgPenalty: 8;
|
||||
uint8_t forcePauseOn: 1;
|
||||
uint8_t forcePauseOff: 1;
|
||||
uint8_t WmSweeperEnable: 1;
|
||||
uint8_t PauseGenSweeperEnable: 1;
|
||||
uint8_t PauseRecSweeperEnable: 1;
|
||||
uint8_t NumSweeperPorts: 6;
|
||||
uint16_t : 13;
|
||||
}, uint32_t) ;
|
||||
|
||||
const uint32_t CM_EGRESS_PAUSE_COUNT__Address = BASE_ADDRESS + 0x1400; //128-bit entries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
25
src/fm10k/registers/EPL.h
Normal file
25
src/fm10k/registers/EPL.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "Register.h"
|
||||
|
||||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace EPL {
|
||||
const uint32_t BASE_ADDRESS = 0x0E0000;
|
||||
|
||||
const uint32_t EPL_OFFSET = 0x400;
|
||||
|
||||
PACKEDA(EPL_CFG_A, 0x304, struct {
|
||||
uint8_t SpeedUp: 1;
|
||||
uint8_t Timeout: 6;
|
||||
uint8_t Active: 4; // [0..3]
|
||||
uint8_t SkewTolerance: 6;
|
||||
uint8_t RxLaneflipEn: 1;
|
||||
uint8_t TxLaneflipEn: 1;
|
||||
uint16_t :15;
|
||||
}, uint32_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
23
src/fm10k/registers/HANDLER_TAIL.h
Normal file
23
src/fm10k/registers/HANDLER_TAIL.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "Register.h"
|
||||
|
||||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace HANDLER_TAIL {
|
||||
const uint32_t BASE_ADDRESS = 0xE30000;
|
||||
|
||||
PACKEDA(FH_TAIL_IM, 0x8E, struct {
|
||||
uint8_t SafSramErr : 2;
|
||||
uint8_t EgressPauseSramErr : 2;
|
||||
uint8_t RxStatsSramErr : 2;
|
||||
uint8_t PolicerUsageSramErr : 2;
|
||||
uint8_t TcnSramErr : 2;
|
||||
uint8_t TCN : 1;
|
||||
uint32_t : 21;
|
||||
}, uint32_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
19
src/fm10k/registers/L2_LOOKUP_TCN.h
Normal file
19
src/fm10k/registers/L2_LOOKUP_TCN.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "Register.h"
|
||||
|
||||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace L2_LOOKUP_TCN {
|
||||
const uint32_t BASE_ADDRESS = 0xE70000;
|
||||
|
||||
PACKEDA(MA_TCN_IM, 0x8C1,struct {
|
||||
uint8_t PendingEvents : 1;
|
||||
uint8_t TCN_Overflow : 1;
|
||||
uint32_t : 30;
|
||||
}, uint32_t) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace MGMT {
|
||||
|
||||
const uint32_t BASE_ADDRESS = 0x0;
|
||||
|
||||
enum class DEVICE_CFG_FeatureCode : uint8_t {
|
||||
FULL = 0b00,
|
||||
|
@ -33,7 +33,7 @@ namespace FM10K {
|
|||
uint8_t ResetCount: 8;
|
||||
uint32_t Reserved: 24;
|
||||
}, uint32_t) FATAL_COUNT;
|
||||
typedef PACKED(struct {
|
||||
PACKEDA(SOFT_RESET, 0x3, struct {
|
||||
uint8_t ColdReset: 1;
|
||||
uint8_t EPLReset: 1;
|
||||
uint8_t SwitchReset: 1;
|
||||
|
@ -41,18 +41,16 @@ namespace FM10K {
|
|||
uint16_t PCIeReset: 9; //Bitfield array [0..8]
|
||||
uint16_t PCIeActive: 9; //Bitfield array [0..8]
|
||||
uint16_t Reserved: 10;
|
||||
}, uint32_t) SOFT_RESET;
|
||||
const uint32_t SOFT_RESET__Address = 0x3;
|
||||
}, uint32_t);
|
||||
|
||||
typedef PACKED(struct {
|
||||
PACKEDA(DEVICE_CFG, 0x4, struct {
|
||||
uint8_t PCIeMode: 4; //Bitfield array [0..3]
|
||||
uint8_t Eth100GDisabled: 1;
|
||||
DEVICE_CFG_FeatureCode FeatureCode: 2;
|
||||
uint16_t PCIeEnable: 9; //Bitfield array [0..8]
|
||||
uint8_t SystimeClockSource: 1;
|
||||
uint16_t Reserved: 15;
|
||||
}, uint32_t) DEVICE_CFG;
|
||||
const uint32_t DEVICE_CFG__Address = 0x4;
|
||||
}, uint32_t);
|
||||
|
||||
typedef PACKED(struct {
|
||||
uint8_t MasterResetAssertCount: 8;
|
||||
|
@ -64,12 +62,10 @@ namespace FM10K {
|
|||
uint32_t Reserved: 31;
|
||||
}, uint32_t) WATCHDOG_CFG;
|
||||
|
||||
typedef PACKED(struct {
|
||||
PACKEDA(VITAL_PRODUCT_DATA, 0x304, struct {
|
||||
uint16_t PartNumber: 16;
|
||||
uint16_t Reserved: 16;
|
||||
}, uint32_t) VITAL_PRODUCT_DATA;
|
||||
|
||||
const uint32_t VITAL_PRODUCT_DATA__Address = 0x304;
|
||||
}, uint32_t);
|
||||
|
||||
|
||||
typedef PACKEDM(struct {
|
||||
|
@ -94,7 +90,7 @@ namespace FM10K {
|
|||
uint32_t Reserved: 21;
|
||||
}, uint32_t, 2) GLOBAL_INTERRUPT_DETECT;
|
||||
|
||||
typedef PACKEDM(struct {
|
||||
PACKEDAM(INTERRUPT_MASK_INT, 0x402, struct {
|
||||
uint16_t PCIE_BSM: 9; //Bitfield array [0..8]
|
||||
uint16_t PCIE: 9; //Bitfield array [0..8]
|
||||
uint16_t EPL: 9; //Bitfield array [0..8]
|
||||
|
@ -114,9 +110,9 @@ namespace FM10K {
|
|||
uint8_t BSM: 1;
|
||||
uint8_t XCLK: 1;
|
||||
uint32_t Reserved: 21;
|
||||
}, uint32_t, 2) INTERRUPT_MASK_INT;
|
||||
}, uint32_t, 2);
|
||||
|
||||
typedef PACKEDM(struct {
|
||||
PACKEDAM(INTERRUPT_MASK_PCIE, 0x420, struct {
|
||||
uint16_t PCIE_BSM: 9; //Bitfield array [0..8]
|
||||
uint16_t PCIE: 9; //Bitfield array [0..8]
|
||||
uint16_t EPL: 9; //Bitfield array [0..8]
|
||||
|
@ -136,10 +132,10 @@ namespace FM10K {
|
|||
uint8_t BSM: 1;
|
||||
uint8_t XCLK: 1;
|
||||
uint32_t Reserved: 21;
|
||||
}, uint32_t, 2) INTERRUPT_MASK_PCIE; // [0..8]
|
||||
}, uint32_t, 2); // [0..8]
|
||||
|
||||
|
||||
typedef PACKEDM(struct {
|
||||
PACKEDAM(INTERRUPT_MASK_FIBM, 0x440, struct {
|
||||
uint16_t PCIE_BSM: 9; //Bitfield array [0..8]
|
||||
uint16_t PCIE: 9; //Bitfield array [0..8]
|
||||
uint16_t EPL: 9; //Bitfield array [0..8]
|
||||
|
@ -159,9 +155,9 @@ namespace FM10K {
|
|||
uint8_t BSM: 1;
|
||||
uint8_t XCLK: 1;
|
||||
uint32_t Reserved: 21;
|
||||
}, uint32_t, 2) INTERRUPT_MASK_FIBM;
|
||||
}, uint32_t, 2);
|
||||
|
||||
typedef PACKEDM(struct {
|
||||
PACKEDAM(INTERRUPT_MASK_BSM, 0x442, struct {
|
||||
uint16_t PCIE_BSM: 9; //Bitfield array [0..8]
|
||||
uint16_t PCIE: 9; //Bitfield array [0..8]
|
||||
uint16_t EPL: 9; //Bitfield array [0..8]
|
||||
|
@ -181,7 +177,7 @@ namespace FM10K {
|
|||
uint8_t BSM: 1;
|
||||
uint8_t XCLK: 1;
|
||||
uint32_t Reserved: 21;
|
||||
}, uint32_t, 2) INTERRUPT_MASK_BSM;
|
||||
}, uint32_t, 2);
|
||||
|
||||
typedef PACKED(struct {
|
||||
uint8_t MODIFY: 1;
|
||||
|
@ -248,11 +244,10 @@ namespace FM10K {
|
|||
}, uint32_t) LSM_CLKOBS_CTRL;
|
||||
|
||||
|
||||
typedef PACKED(struct {
|
||||
PACKEDA(CHIP_VERSION, 0x452, struct {
|
||||
uint16_t Version: 7;
|
||||
uint32_t Reserved: 25;
|
||||
}, uint32_t) CHIP_VERSION;
|
||||
const uint32_t CHIP_VERSION__Address = 0x452;
|
||||
}, uint32_t);
|
||||
|
||||
typedef PACKED(struct {
|
||||
uint8_t Command: 4;
|
||||
|
@ -290,19 +285,17 @@ namespace FM10K {
|
|||
uint32_t Reserved: 29;
|
||||
}, uint32_t) PIN_STRAP_STAT;
|
||||
|
||||
typedef PACKED(struct {
|
||||
PACKEDA(FUSE_DATA_0, 0xC0E, struct {
|
||||
uint16_t : 11;
|
||||
uint8_t SKU: 5;
|
||||
uint8_t VDDS_VRM: 8;
|
||||
uint8_t VDDF_VRM: 8;
|
||||
}, uint32_t) FUSE_DATA_0;
|
||||
const uint32_t FUSE_DATA_0__Address = 0xC0E;
|
||||
typedef PACKED(struct {
|
||||
}, uint32_t);
|
||||
PACKEDA(FUSE_DATA_1, 0xC0F, struct {
|
||||
uint32_t : 32;
|
||||
}, uint32_t) FUSE_DATA_1;
|
||||
const uint32_t FUSE_DATA_1__Address = 0xC0F;
|
||||
}, uint32_t);
|
||||
|
||||
typedef PACKEDM(struct {
|
||||
PACKEDAM(BIST_CTRL, 0xC10, struct {
|
||||
uint16_t BistRun_PCIE: 9; //Bitfield array [0..8]
|
||||
uint8_t BistRun_EPL: 1;
|
||||
uint8_t BistRun_FABRIC: 1;
|
||||
|
@ -321,7 +314,7 @@ namespace FM10K {
|
|||
uint8_t BistMode_FIBM: 1;
|
||||
uint8_t BistMode_SBM: 1;
|
||||
uint16_t Reserved2: 16;
|
||||
}, uint32_t, 2) BIST_CTRL;
|
||||
}, uint32_t, 2);
|
||||
|
||||
typedef PACKED(struct {
|
||||
uint8_t Reset: 1;
|
||||
|
@ -422,13 +415,13 @@ namespace FM10K {
|
|||
uint8_t Reserved: 5;
|
||||
}, uint32_t) SPI_CTRL;
|
||||
|
||||
typedef PACKED(struct {
|
||||
PACKEDA(LED_CFG, 0xC2B, struct {
|
||||
uint32_t LEDFreq: 24; //TODO: enum
|
||||
uint8_t LEDEnable: 1;
|
||||
uint8_t Reserved: 7;
|
||||
}, uint32_t) LED_CFG;
|
||||
}, uint32_t);
|
||||
|
||||
typedef PACKED(struct {
|
||||
PACKEDA(SCAN_DATA_IN, 0xC2D, struct {
|
||||
uint32_t ScanData: 25;
|
||||
uint8_t ShiftIn: 1;
|
||||
uint8_t ShiftOut: 1;
|
||||
|
@ -437,9 +430,7 @@ namespace FM10K {
|
|||
uint8_t Drain: 1;
|
||||
uint8_t Passthru: 1;
|
||||
uint8_t Single: 1;
|
||||
}, uint32_t) SCAN_DATA_IN;
|
||||
|
||||
const uint32_t SCAN_DATA_IN__Address = 0xC2D;
|
||||
}, uint32_t);
|
||||
|
||||
typedef PACKED(struct {
|
||||
uint8_t Run: 1;
|
||||
|
|
30
src/fm10k/registers/PCIE_PF.h
Normal file
30
src/fm10k/registers/PCIE_PF.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "Register.h"
|
||||
|
||||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace PCIE_PF {
|
||||
const uint32_t BASE_ADDRESS = 0x100000;
|
||||
const uint32_t PCIE_PF_OFFSET = 0x100000;
|
||||
|
||||
PACKEDA(PCIE_CTRL, 0x0, struct {
|
||||
uint8_t LTSSM_ENABLE: 1;
|
||||
uint8_t REQ_RETRY_EN: 1;
|
||||
uint8_t BAR4_Allowed: 1;
|
||||
uint8_t Reserved_1: 1;
|
||||
uint8_t RxLaneflipEn: 1;
|
||||
uint8_t TxLaneflipEn: 1;
|
||||
uint32_t :26;
|
||||
}, uint32_t);
|
||||
PACKEDA(PCIE_CTRL_EXT, 0x1, struct {
|
||||
uint8_t NS_DIS: 1;
|
||||
uint8_t RO_DIS: 1;
|
||||
uint8_t SwitchLoopback: 1;
|
||||
uint32_t :29;
|
||||
}, uint32_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
#include "pack.h"
|
||||
#include "MGMT.h"
|
||||
#include "PCIE_PF.h"
|
||||
#include "EPL.h"
|
||||
#include "TE.h"
|
||||
#include "CM_USAGE.h"
|
||||
#include "L2_LOOKUP_TCN.h"
|
||||
#include "HANDLER_TAIL.h"
|
||||
#include "SCHED.h"
|
||||
|
||||
namespace FM10K{
|
||||
namespace registers{
|
||||
|
|
60
src/fm10k/registers/SCHED.h
Normal file
60
src/fm10k/registers/SCHED.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include "Register.h"
|
||||
|
||||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace SCHED {
|
||||
const uint32_t BASE_ADDRESS = 0xF00000;
|
||||
|
||||
PACKEDA(SCHED_SSCHED_RX_PERPORT, 0x20840, struct {
|
||||
uint16_t Next: 16;
|
||||
uint16_t : 16;
|
||||
}, uint32_t);
|
||||
const uint32_t SCHED_SSCHED_RX_PERPORT__Entries = 48;
|
||||
|
||||
PACKEDA(SCHED_FREELIST_INIT, 0x30244, struct {
|
||||
uint16_t Address: 16;
|
||||
uint16_t : 16;
|
||||
}, uint32_t);
|
||||
|
||||
PACKEDAM(SCHED_RXQ_STORAGE_POINTERS, 0x60400, struct {
|
||||
uint16_t HeadPage: 10;
|
||||
uint16_t TailPage: 10;
|
||||
uint16_t HeadIdx: 5;
|
||||
uint16_t TailIdx: 5;
|
||||
uint16_t NextPage: 10;
|
||||
uint32_t : 24;
|
||||
}, uint32_t, 2); //[0..7]
|
||||
const uint32_t SCHED_RXQ_STORAGE_POINTERS__Entries = 8;
|
||||
|
||||
PACKEDA(SCHED_RXQ_FREELIST_INIT, 0x60410, struct {
|
||||
uint16_t Address: 10;
|
||||
uint32_t : 22;
|
||||
}, uint32_t);
|
||||
|
||||
PACKEDA(SCHED_TXQ_HEAD_PERQ, 0x60A00, struct {
|
||||
uint16_t Head: 16;
|
||||
uint16_t : 16;
|
||||
}, uint32_t);
|
||||
const uint32_t SCHED_TXQ_HEAD_PERQ__Entries = 384;
|
||||
|
||||
PACKEDA(SCHED_TXQ_FREELIST_INIT, 0x62000, struct {
|
||||
uint16_t Address: 16;
|
||||
uint16_t : 16;
|
||||
}, uint32_t);
|
||||
|
||||
PACKEDA(SCHED_TXQ_TAIL0_PERQ, 0x60600, struct {
|
||||
uint16_t Tail: 16;
|
||||
uint16_t : 16;
|
||||
}, uint32_t);
|
||||
|
||||
PACKEDA(SCHED_TXQ_TAIL1_PERQ, 0x60800, struct {
|
||||
uint16_t Tail: 16;
|
||||
uint16_t : 16;
|
||||
}, uint32_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
28
src/fm10k/registers/TE.h
Normal file
28
src/fm10k/registers/TE.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "Register.h"
|
||||
|
||||
namespace FM10K {
|
||||
namespace registers {
|
||||
namespace TE {
|
||||
const uint32_t BASE_ADDRESS = 0xA00000;
|
||||
|
||||
const uint32_t TE_OFFSET = 0x100000;
|
||||
|
||||
PACKEDA(TE_CFG, 0x55A02, struct {
|
||||
uint8_t OuterTTL: 8;
|
||||
uint8_t OuterTOS: 8;
|
||||
uint8_t DeriveOuterTOS: 1;
|
||||
uint8_t NotIP: 2;
|
||||
uint8_t IPnotTCPnotUDP: 2;
|
||||
uint8_t IPisTCPorUDP: 2;
|
||||
uint8_t VerifyDecapCSUM: 1;
|
||||
uint8_t UpdateOldHeaderInPlaceCSUM: 1;
|
||||
uint8_t SwitchLoopbackDisable: 1;
|
||||
uint8_t Reserved: 8;
|
||||
}, uint32_t); //[0..1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
12
src/fsmd.cpp
12
src/fsmd.cpp
|
@ -29,13 +29,21 @@ int main() {
|
|||
|
||||
std::cout << "Device Model_Stepping: " << fm10k.getHardwareInformationString() << std::endl;
|
||||
|
||||
auto fuseData_0 = FM10K_MAP_REGISTER(fm10k, FM10K::registers::MGMT::FUSE_DATA_0);
|
||||
auto fuseData_0 = fm10k.mapRegister<FM10K::registers::MGMT::FUSE_DATA_0>();
|
||||
std::cout << "FUSE_DATA_0: " << tohex(fuseData_0->value) << std::endl;
|
||||
std::cout << "FUSE_DATA_0.VDDF_VRM: " << FM10K::VR12_VID_to_Millivolts(fuseData_0->fields.VDDS_VRM) << std::endl;
|
||||
std::cout << "FUSE_DATA_0.VDDF_VRM: " << FM10K::VR12_VID_to_Millivolts(fuseData_0->fields.VDDF_VRM) << std::endl;
|
||||
|
||||
auto deviceCfg = FM10K_MAP_REGISTER(fm10k, FM10K::registers::MGMT::DEVICE_CFG);
|
||||
auto deviceCfg = fm10k.mapRegister<FM10K::registers::MGMT::DEVICE_CFG>();
|
||||
std::cout << "DEVICE_CFG: " << tohex(deviceCfg->value) << std::endl;
|
||||
|
||||
std::cout << "trying to initialize: ";
|
||||
|
||||
if(fm10k.initializationSequence()){
|
||||
std::cout << "success" << std::endl;
|
||||
}else{
|
||||
std::cout << "fail" << std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
20
src/pack.h
20
src/pack.h
|
@ -33,9 +33,25 @@ union { \
|
|||
x __attribute__((packed, aligned(sizeof(s)))) fields; \
|
||||
} __attribute__((packed, aligned(sizeof(s))))
|
||||
|
||||
#define PACKEDM(x, s, n) \
|
||||
#define PACKEDA(n, a, x, s) \
|
||||
union n { \
|
||||
static const uint32_t ADDRESS = BASE_ADDRESS + a; \
|
||||
s value; \
|
||||
x __attribute__((packed, aligned(sizeof(s)))) fields; \
|
||||
} __attribute__((packed, aligned(sizeof(s))))
|
||||
|
||||
#define PACKEDM(x, s, i) \
|
||||
union { \
|
||||
s value[n]; \
|
||||
s value[i]; \
|
||||
x __attribute__((packed, aligned(sizeof(s)))) fields; \
|
||||
} __attribute__((packed, aligned(sizeof(s))))
|
||||
|
||||
|
||||
|
||||
#define PACKEDAM(n, a, x, s, i) \
|
||||
union n { \
|
||||
static const uint32_t ADDRESS = BASE_ADDRESS + a; \
|
||||
s value[i]; \
|
||||
x __attribute__((packed, aligned(sizeof(s)))) fields; \
|
||||
} __attribute__((packed, aligned(sizeof(s))))
|
||||
|
||||
|
|
Loading…
Reference in a new issue