Initialization kind of works!

This commit is contained in:
DataHoarder 2021-10-25 01:34:49 +02:00
parent 3148925051
commit cd5b99a904
14 changed files with 581 additions and 65 deletions

View file

@ -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

View file

@ -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));
}

View file

@ -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{};
};
}

View 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
View 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);
}
}
}

View 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);
}
}
}

View 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) ;
}
}
}

View file

@ -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;

View 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);
}
}
}

View file

@ -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{

View 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
View 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]
}
}
}

View file

@ -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;
}

View file

@ -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))))