summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorEvan Lojewski <github@meklort.com>2019-04-16 21:17:23 -0600
committerEvan Lojewski <github@meklort.com>2019-04-16 21:17:23 -0600
commitc74510e67a4abdfb8b13c864e1315715cf96bec8 (patch)
treee58dfc46fa13c96694cc3acff8b54d0ebe80d92e /libs
parent4f272db731d9875a2394da7bab4c0ec5c477b1ef (diff)
downloadbcm5719-ortega-c74510e67a4abdfb8b13c864e1315715cf96bec8.tar.gz
bcm5719-ortega-c74510e67a4abdfb8b13c864e1315715cf96bec8.zip
Begin adding support for sending the link status response.
Diffstat (limited to 'libs')
-rw-r--r--libs/NCSI/include/Ethernet.h84
-rw-r--r--libs/NCSI/ncsi.c183
2 files changed, 239 insertions, 28 deletions
diff --git a/libs/NCSI/include/Ethernet.h b/libs/NCSI/include/Ethernet.h
index 0237c54..358dcbf 100644
--- a/libs/NCSI/include/Ethernet.h
+++ b/libs/NCSI/include/Ethernet.h
@@ -65,7 +65,7 @@ _Static_assert(sizeof(EthernetHeader_t) == 16, "sizeof(EthernetHeader_t) must be
#define ETHERNET_HEADER_OFFSET 0
#define PACKET_OFFSET (12)
-typedef struct
+typedef struct
{
// Bytes 0 - 11 - Ethernet Header
uint8_t DestinationAddress[6];
@@ -173,9 +173,26 @@ typedef struct {
uint32_t AENControl_Low:16;
} AENEnable_t;
+typedef struct {
+ // Bytes 0 - 27
+ ControlPacketHeader_t header;
+
+ // Byte 28 - 31
+ uint32_t LinkSettings_High:16;
+ uint32_t headerPadding:16;
+
+ // Bytes 32 - 35
+ uint32_t OEMLinkSettings_High:16;
+ uint32_t LinkSettings_Low:16;
+
+ // Bytes 36 - 39
+ uint32_t pad:16;
+ uint32_t OEMLinkSettings_Low:16;
+} SetLink_t;
+
-typedef struct
+typedef struct
{
// Bytes 0 - 11
uint8_t DestinationAddress[6];
@@ -213,28 +230,55 @@ typedef struct
#endif
} ResponsePacketHeader_t;
+typedef struct
+{
+ // Bytes 0 - 11
+ uint8_t DestinationAddress[6];
+ uint8_t SourceAddress[6];
-// typedef union {
-// struct {
-// EthernetHeader_t header;
-// } header;
+#ifdef __LITTLE_ENDIAN__
+ // Bytes 12 - 15
+ uint32_t HeaderRevision:8; /* Should be 1 */
+ uint32_t ManagmentControllerID:8; /* Should be 0 */
+ uint32_t EtherType:16; // part of Ethernet header.
-// struct {
-// uint8_t padding[CONTROL_PACKET_OFFSET];
-// ControlPacketHeader_t header;
-// } controlPacket;
+ // Bytes 16 - 19
+ uint32_t ChannelID:8;
+ uint32_t ControlPacketType:8;
+ uint32_t InstanceID:8;
+ uint32_t reserved_0:8;
+
+ // Bytes 20 - 23
+ uint32_t reserved_2:16;
+ uint32_t PayloadLength:12;
+ uint32_t reserved_1:4;
+
+ // Bytes 24 - 27
+ uint32_t reserved_3;
-// struct {
-// uint8_t padding[CONTROL_PACKET_PAYLOAD_OFFSET];
+ // Bytes 28 - 31
+ uint16_t ResponseCode;
+ uint16_t reserved_4;
+
+ // Bytes 32 - 35
+ uint16_t LinkStatus_High;
+ uint16_t ReasonCode;
-// uint32_t checksumHigh:16;
-// uint32_t reserved:16;
+ // Bytes 36 - 39
+ uint16_t OtherIndications_High;
+ uint16_t LinkStatus_Low;
-// uint32_t pad:16
-// uint32_t checksumLow:16;
-// } selectPackage
-// } SelectPackage_t;
+ // Bytes 40 - 43
+ uint16_t OEMLinkStatus_High;
+ uint16_t OtherIndications_Low;
+ // Bytes 44 - 47
+ uint16_t pad;
+ uint16_t OEMLinkStatus_Low;
+#else
+#error Not tested
+#endif
+} LinkStatusResponsePacketHeader_t;
typedef union {
// Ethernet frame must be at least 64 bytes.
@@ -251,8 +295,12 @@ typedef union {
AENEnable_t AENEnable;
+ SetLink_t setLink;
+
/* Response Packets */
ResponsePacketHeader_t responsePacket;
+
+ LinkStatusResponsePacketHeader_t linkStatusResponse;
} NetworkFrame_t;
diff --git a/libs/NCSI/ncsi.c b/libs/NCSI/ncsi.c
index 7b58f3f..b27a7e2 100644
--- a/libs/NCSI/ncsi.c
+++ b/libs/NCSI/ncsi.c
@@ -88,7 +88,7 @@ NetworkFrame_t gResponseFrame =
.InstanceID = 0, /* Filled in by appropriate handler. */
.reserved_0 = 0,
.reserved_2 = 0,
- .PayloadLength = 0, /* Filled in by appropriate handler. */
+ .PayloadLength = 4,
.reserved_1 = 0,
.ResponseCode = 0,
@@ -98,6 +98,36 @@ NetworkFrame_t gResponseFrame =
}
};
+NetworkFrame_t gLinkStatusResponseFrame =
+{
+ .linkStatusResponse = {
+ .DestinationAddress = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ .SourceAddress = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+
+ .HeaderRevision = 1,
+ .ManagmentControllerID = 0,
+ .EtherType = ETHER_TYPE_NCSI,
+ .ChannelID = 0, /* Filled in by appropriate handler. */
+ .ControlPacketType = CONTROL_PACKET_TYPE_RESPONSE | CONTROL_PACKET_TYPE_GET_LINK_STATUS,
+ .InstanceID = 0, /* Filled in by appropriate handler. */
+ .reserved_0 = 0,
+ .reserved_2 = 0,
+ .PayloadLength = 16,
+ .reserved_1 = 0,
+
+ .ResponseCode = 0,
+ .reserved_4 = 0,
+ .LinkStatus_High = 0,
+ .ReasonCode = 0,
+ .OtherIndications_High = 0,
+ .LinkStatus_Low = 0,
+ .OEMLinkStatus_High = 0,
+ .OtherIndications_Low = 0,
+ .pad = 0,
+ .OEMLinkStatus_Low = 0,
+ }
+};
+
typedef struct {
bool selected;
@@ -106,7 +136,7 @@ typedef struct {
} package_state_t;
package_state_t gPackageState = {
- .numChannels = MAX_CHANNELS,
+ .numChannels = 1 /*MAX_CHANNELS*/,
.selected = false,
.channel = {
[0] = {
@@ -132,8 +162,17 @@ package_state_t gPackageState = {
},
};
-void sendNCSIResponse(uint8_t InstanceID, uint8_t channelID, uint16_t controlID,
- uint16_t response_code, uint16_t reasons_code);
+void sendNCSIResponse(uint8_t InstanceID,
+ uint8_t channelID,
+ uint16_t controlID,
+ uint16_t response_code,
+ uint16_t reasons_code);
+void sendNCSILinkStatusResponse(uint8_t InstanceID,
+ uint8_t channelID,
+ uint32_t LinkStatus,
+ uint32_t OEMLinkStatus,
+ uint32_t OtherIndications);
+
void resetChannel(int ch);
#if CXX_SIMULATOR
@@ -315,18 +354,100 @@ static void AENEnableHandler(NetworkFrame_t* frame)
NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
}
+
+
static void setLinkHandler(NetworkFrame_t* frame)
{
+ uint32_t LinkSettings = (frame->setLink.LinkSettings_Low | (frame->setLink.LinkSettings_High << 16));
+ uint32_t OEMLinkSettings = (frame->setLink.OEMLinkSettings_Low | (frame->setLink.OEMLinkSettings_High << 16));
#if CXX_SIMULATOR
- printf("Set Link: channel %x\n", frame->controlPacket.ChannelID);
+ printf("Set Link: LinkSettings %x\n", LinkSettings);
+ printf("Set Link: OEMLinkSettings %x\n", OEMLinkSettings);
#endif
+
+ int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
+ channel_state_t* channel = &(gPackageState.channel[ch]);
+ channel->shm->NcsiChannelSetting1.r32 = LinkSettings;
+ channel->shm->NcsiChannelSetting2.r32 = OEMLinkSettings;
+
+ sendNCSIResponse(
+ frame->controlPacket.InstanceID,
+ frame->controlPacket.ChannelID,
+ frame->controlPacket.ControlPacketType,
+ NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
}
static void getLinkStatusHandler(NetworkFrame_t* frame)
{
+ RegSHM_CHANNELNcsiChannelStatus_t linkStatus;
+ linkStatus.r32 = 0;
+ linkStatus.bits.Linkup = 1;
+ linkStatus.bits.LinkStatus = 7;
+ linkStatus.bits.SERDES = 1;
+ linkStatus.bits.AutonegotiationComplete = 1;
+ linkStatus.bits.LinkSpeed1000MFullDuplexCapable = 1;
+ linkStatus.bits.LinkSpeed1000MHalsDuplexCapable = 1;
+
+
+ uint32_t LinkStatus = linkStatus.r32;
+ uint32_t OEMLinkStatus = 0;
+ uint32_t OtherIndications = 0;
#if CXX_SIMULATOR
printf("Get Link Status: channel %x\n", frame->controlPacket.ChannelID);
#endif
+
+ sendNCSILinkStatusResponse(
+ frame->controlPacket.InstanceID,
+ frame->controlPacket.ChannelID, LinkStatus, OEMLinkStatus, OtherIndications);
+
+}
+
+static void disableVLANHandler(NetworkFrame_t* frame)
+{
+ // TODO
+#if CXX_SIMULATOR
+ int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
+ printf("Disable VLAN: channel %x\n", ch);
+#endif
+ // gPackageState.channel[ch].shm->NcsiChannelInfo.bits.Enabled = false;
+
+ sendNCSIResponse(
+ frame->controlPacket.InstanceID,
+ frame->controlPacket.ChannelID,
+ frame->controlPacket.ControlPacketType,
+ NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
+}
+
+static void setMACAddressHandler(NetworkFrame_t* frame)
+{
+ // TODO
+#if CXX_SIMULATOR
+ int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
+ printf("Set MAC: channel %x\n", ch);
+#endif
+ // gPackageState.channel[ch].shm->NcsiChannelInfo.bits.Enabled = false;
+
+ sendNCSIResponse(
+ frame->controlPacket.InstanceID,
+ frame->controlPacket.ChannelID,
+ frame->controlPacket.ControlPacketType,
+ NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
+}
+
+static void enableBroadcastFilteringHandler(NetworkFrame_t* frame)
+{
+ // TODO
+#if CXX_SIMULATOR
+ int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
+ printf("Enable Broadcast Filtering: channel %x\n", ch);
+#endif
+ // gPackageState.channel[ch].shm->NcsiChannelInfo.bits.Enabled = false;
+
+ sendNCSIResponse(
+ frame->controlPacket.InstanceID,
+ frame->controlPacket.ChannelID,
+ frame->controlPacket.ControlPacketType,
+ NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
}
// CLEAR INITIAL STATE, SELECT PACKAGE, DESELECT PACKAGE, ENABLE CHANNEL, DISABLE CHANNEL, RESET CHANNEL, ENABLE CHANNEL NETWORK TX, DISABLE CHANNEL NETWORK TX,
@@ -347,9 +468,9 @@ ncsi_handler_t gNCSIHandlers[] =
[0x0A] = {.payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = getLinkStatusHandler},
[0x0B] = {.payloadLength = 8, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
[0x0C] = {.payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
- [0x0D] = {.payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
- [0x0E] = {.payloadLength = 8, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
- [0x10] = {.payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
+ [0x0D] = {.payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = disableVLANHandler},
+ [0x0E] = {.payloadLength = 8, .ignoreInit = false, .packageCommand = false, .fn = setMACAddressHandler},
+ [0x10] = {.payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = enableBroadcastFilteringHandler},
[0x11] = {.payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
[0x12] = {.payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
[0x13] = {.payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler},
@@ -472,6 +593,49 @@ void resetChannel(int ch)
channel->shm->NcsiChannelCtrlstatRx.r32 = 0;
}
+void sendNCSILinkStatusResponse(uint8_t InstanceID, uint8_t channelID, uint32_t LinkStatus, uint32_t OEMLinkStatus, uint32_t OtherIndications)
+{
+ uint32_t packetSize = ETHERNET_FRAME_MIN - 4;
+ uint32_t packetWords = ((packetSize + 3) / 4);
+ uint32_t lastBytes = packetSize % 4;
+
+ RegAPE_PERIBmcToNcTxControl_t txControl;
+ txControl.r32 = 0;
+ txControl.bits.LastByteCount = lastBytes;
+
+ gLinkStatusResponseFrame.linkStatusResponse.ChannelID = channelID;
+ gLinkStatusResponseFrame.linkStatusResponse.InstanceID = InstanceID;
+ gLinkStatusResponseFrame.linkStatusResponse.ResponseCode = NCSI_RESPONSE_CODE_COMMAND_COMPLETE;
+ gLinkStatusResponseFrame.linkStatusResponse.ReasonCode = NCSI_REASON_CODE_NONE;
+
+ gLinkStatusResponseFrame.linkStatusResponse.LinkStatus_High = LinkStatus >> 16;
+ gLinkStatusResponseFrame.linkStatusResponse.LinkStatus_Low = LinkStatus & 0xffff;
+ gLinkStatusResponseFrame.linkStatusResponse.OEMLinkStatus_High = OEMLinkStatus >> 16;
+ gLinkStatusResponseFrame.linkStatusResponse.OEMLinkStatus_Low = OEMLinkStatus & 0xffff;
+ gLinkStatusResponseFrame.linkStatusResponse.OtherIndications_High = OtherIndications >> 16;
+ gLinkStatusResponseFrame.linkStatusResponse.OtherIndications_Low = OtherIndications & 0xffff;
+
+ // Wait for enough free space.
+ while(APE_PERI.BmcToNcTxStatus.bits.InFifo < packetWords);
+
+ // Transmit.
+ for(int i = 0; i < packetWords-1; i++)
+ {
+#if CXX_SIMULATOR
+ printf("Transmitting word %d: 0x%08x\n", i, gLinkStatusResponseFrame.words[i]);
+#endif
+ APE_PERI.BmcToNcTxBuffer.r32 = gLinkStatusResponseFrame.words[i];
+ }
+
+ APE_PERI.BmcToNcTxControl = txControl;
+
+#if CXX_SIMULATOR
+ printf("Transmitting last word %d: 0x%08x\n", packetWords - 1, gLinkStatusResponseFrame.words[packetWords - 1]);
+#endif
+
+ APE_PERI.BmcToNcTxBufferLast.r32 = gLinkStatusResponseFrame.words[packetWords - 1];
+}
+
void sendNCSIResponse(uint8_t InstanceID, uint8_t channelID, uint16_t controlID, uint16_t response_code, uint16_t reasons_code)
{
uint32_t packetSize = ETHERNET_FRAME_MIN - 4;
@@ -485,14 +649,13 @@ void sendNCSIResponse(uint8_t InstanceID, uint8_t channelID, uint16_t controlID,
gResponseFrame.responsePacket.ChannelID = channelID;
gResponseFrame.responsePacket.ControlPacketType = controlID | CONTROL_PACKET_TYPE_RESPONSE;
gResponseFrame.responsePacket.InstanceID = InstanceID;
- gResponseFrame.responsePacket.PayloadLength = 4;
// Payload data - 4 bytes
gResponseFrame.responsePacket.ResponseCode = response_code;
gResponseFrame.responsePacket.ReasonCode = reasons_code;
// NetworkFrame_t frame;
// frame.
- // Wait for enough free space.
+ // Wait for enough free space.
while(APE_PERI.BmcToNcTxStatus.bits.InFifo < packetWords);
// Transmit.
OpenPOWER on IntegriCloud