summaryrefslogtreecommitdiffstats
path: root/libs/NCSI/ncsi.c
diff options
context:
space:
mode:
authorEvan Lojewski <github@meklort.com>2019-06-18 20:12:26 -0600
committerEvan Lojewski <github@meklort.com>2019-06-18 20:12:26 -0600
commit2d4d71129d367997cdd9b588ef4131cc5093e508 (patch)
tree4cd54f8159a8afd347554d36b2ec7fc3630845a3 /libs/NCSI/ncsi.c
parent6350644655e18c0bae30bbada3bfe27bf6b0266a (diff)
downloadbcm5719-ortega-2d4d71129d367997cdd9b588ef4131cc5093e508.tar.gz
bcm5719-ortega-2d4d71129d367997cdd9b588ef4131cc5093e508.zip
Begin adding support for additional NCSI commants.
Diffstat (limited to 'libs/NCSI/ncsi.c')
-rw-r--r--libs/NCSI/ncsi.c289
1 files changed, 243 insertions, 46 deletions
diff --git a/libs/NCSI/ncsi.c b/libs/NCSI/ncsi.c
index d39d30a..b58c8a6 100644
--- a/libs/NCSI/ncsi.c
+++ b/libs/NCSI/ncsi.c
@@ -55,6 +55,7 @@
#include <Network.h>
#include <types.h>
+#define NUM_CHANNELS 1
#define MAX_CHANNELS 4
#define PACKAGE_ID_SHIFT 5
@@ -96,6 +97,8 @@ NetworkFrame_t gResponseFrame =
.reserved_4 = 0,
.reserved_5 = 0,
.ReasonCode = 0,
+ .Checksum_High = 0,
+ .Checksum_Low = 0,
},
};
@@ -126,6 +129,112 @@ NetworkFrame_t gLinkStatusResponseFrame =
.OtherIndications_Low = 0,
.pad = 0,
.OEMLinkStatus_Low = 0,
+
+ .Checksum_High = 0,
+ .Checksum_Low = 0,
+ },
+};
+
+NetworkFrame_t gCapabilitiesFrame =
+{
+ .capabilities = {
+ .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_CAPABILITIES,
+ .InstanceID = 0, /* Filled in by appropriate handler. */
+ .reserved_0 = 0,
+ .reserved_2 = 0,
+ .PayloadLength = 32,
+ .reserved_1 = 0,
+
+ .ResponseCode = NCSI_RESPONSE_CODE_COMMAND_COMPLETE,
+ .reserved_4 = 0,
+
+ .Capabilities_High = 0,
+ .ReasonCode = NCSI_REASON_CODE_NONE,
+ .BroadcastCapabilities_High = 0,
+ .Capabilities_Low = 0,
+ .MilticastCapabilities_High = 0,
+ .BroadcastCapabilities_Low = 0xF,
+ .BufferingCapabilities_High = 0,
+ .MilticastCapabilities_Low = 0x7,
+ .AENControlSupport_High = 0,
+ .BufferingCapabilities_Low = 0x7,
+ .VLANFilterCount = 1,
+ .MixedFilterCount = 1,
+ .AENControlSupport_Low = 0,
+ .ChannelCount = NUM_CHANNELS,
+ .VLANModeSupport = 0x7,
+ .MulticastFilterCount = 1,
+ .UnicastFilterCount = 1,
+
+ .Checksum_High = 0,
+ .Checksum_Low = 0,
+ },
+};
+
+NetworkFrame_t gVersionFrame =
+{
+ .version = {
+ .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_VERSION_ID,
+ .InstanceID = 0, /* Filled in by appropriate handler. */
+ .reserved_0 = 0,
+ .reserved_2 = 0,
+ .PayloadLength = 40,
+ .reserved_1 = 0,
+
+ .ResponseCode = NCSI_RESPONSE_CODE_COMMAND_COMPLETE,
+ .ReasonCode = NCSI_REASON_CODE_NONE,
+
+ // NCSI Version
+ .NCSIMajor = 1,
+ .NCSIMinor = 2,
+ .NCSIUpdate = 4,
+ .NCSIAlpha1 = 'a',
+ .NCSIAlpha2 = 'b',
+
+ // Firmware Name
+ .name_11 = 'B',
+ .name_10 = 'C',
+ .name_9 = 'M',
+ .name_8 = '5',
+ .name_7 = '7',
+ .name_6 = '1',
+ .name_5 = '9',
+ .name_4 = ' ',
+ .name_3 = 'N',
+ .name_2 = 'C',
+ .name_1 = 'S',
+ .name_0 = 'I',
+
+ // Firmware Version
+ .FWVersion_High = 0x0102,
+ .FWVersion_Low = 0x01A0,
+
+ // Populated based on NVM
+ .PCIVendor = 0xFFFF,
+ .PCIDevice = 0xFFFF,
+ .PCISubsystemVendor = 0xFFFF,
+ .PCISubsystemDevice = 0xFFFF,
+
+ // Manufacturer ID
+ .ManufacturerID_High = 0x5454,
+ .ManufacturerID_Low = 0x3232,
+
+ .Checksum_High = 0,
+ .Checksum_Low = 0,
},
};
@@ -137,7 +246,7 @@ typedef struct
} package_state_t;
package_state_t gPackageState = {
- .numChannels = 1 /*MAX_CHANNELS*/,
+ .numChannels = NUM_CHANNELS,
.selected = false,
.channel = {
[0] = {
@@ -161,6 +270,8 @@ package_state_t gPackageState = {
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 sendNCSICapabilitiesResponse(uint8_t InstanceID, uint8_t channelID, uint16_t controlID);
+void sendNCSIVersionResponse(uint8_t InstanceID, uint8_t channelID, uint16_t controlID);
void resetChannel(int ch);
@@ -213,6 +324,7 @@ static void selectPackageHandler(NetworkFrame_t *frame)
printf("Package enabled. HardwareArbitartionDisabled: %d\n", frame->selectPackage.HardwareArbitartionDisabled);
#endif
gPackageState.selected = true;
+ SHM.ApeSegLength.r32 |= 0x800;
sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
}
@@ -222,10 +334,10 @@ static void deselectPackageHandler(NetworkFrame_t *frame)
#if CXX_SIMULATOR
printf("Package disabled.\n");
#endif
- gPackageState.selected = false;
-
+ SHM.ApeSegLength.r32 |= 0x80;
sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
+ gPackageState.selected = false;
}
static void enableChannelHandler(NetworkFrame_t *frame)
@@ -274,7 +386,7 @@ static void enableChannelNetworkTXHandler(NetworkFrame_t *frame)
#if CXX_SIMULATOR
printf("Enable Channel Network TX: channel %x\n", ch);
#endif
- gPackageState.channel[ch].shm->NcsiChannelInfo.bits.TXPassthrough = false;
+ gPackageState.channel[ch].shm->NcsiChannelInfo.bits.TXPassthrough = true;
sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
@@ -289,7 +401,7 @@ static void disableChannelNetworkTXHandler(NetworkFrame_t *frame)
#if CXX_SIMULATOR
printf("Disable Channel Network TX: channel %x\n", ch);
#endif
- gPackageState.channel[ch].shm->NcsiChannelInfo.bits.TXPassthrough = true;
+ gPackageState.channel[ch].shm->NcsiChannelInfo.bits.TXPassthrough = false;
sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType, response, reason);
}
@@ -392,6 +504,38 @@ static void disableVLANHandler(NetworkFrame_t *frame)
NCSI_RESPONSE_CODE_COMMAND_COMPLETE, NCSI_REASON_CODE_NONE);
}
+static void getCapabilities(NetworkFrame_t *frame)
+{
+ // TODO:
+ // int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
+ // channel_state_t *channel = &(gPackageState.channel[ch]);
+ sendNCSICapabilitiesResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType);
+}
+
+static void getVersionID(NetworkFrame_t *frame)
+{
+ // TODO:
+ // int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
+ // channel_state_t *channel = &(gPackageState.channel[ch]);
+ sendNCSIVersionResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType);
+}
+
+
+static void enableVLANHandler(NetworkFrame_t *frame)
+{
+ // TODO
+ int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
+ channel_state_t *channel = &(gPackageState.channel[ch]);
+ channel->shm->NcsiChannelInfo.bits.VLAN = false;
+
+#if CXX_SIMULATOR
+ printf("Enable VLAN: channel %x\n", ch);
+#endif
+
+ 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)
{
int ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
@@ -436,9 +580,12 @@ static void enableBroadcastFilteringHandler(NetworkFrame_t *frame)
// AEN ENABLE, SET LINK; then you need GET LINK STATUS
ncsi_handler_t gNCSIHandlers[] = {
+ /* Package / Initialization commands */
[0x00] = { .payloadLength = 0, .ignoreInit = true, .packageCommand = false, .fn = clearInitialStateHandler },
- [0x01] = { .payloadLength = 4, .ignoreInit = true, .packageCommand = true, .fn = selectPackageHandler },
- [0x02] = { .payloadLength = 0, .ignoreInit = true, .packageCommand = true, .fn = deselectPackageHandler },
+ [0x01] = { .payloadLength = 4, .ignoreInit = false, .packageCommand = true, .fn = selectPackageHandler },
+ [0x02] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = true, .fn = deselectPackageHandler },
+
+ /* Channel Specific commands */
[0x03] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = enableChannelHandler },
[0x04] = { .payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = disableChannelHandler },
[0x05] = { .payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = resetChannelHandler },
@@ -448,7 +595,7 @@ ncsi_handler_t gNCSIHandlers[] = {
[0x09] = { .payloadLength = 8, .ignoreInit = false, .packageCommand = false, .fn = setLinkHandler },
[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 },
+ [0x0C] = { .payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = enableVLANHandler },
[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 },
@@ -456,8 +603,8 @@ ncsi_handler_t gNCSIHandlers[] = {
[0x12] = { .payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler },
[0x13] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler },
[0x14] = { .payloadLength = 4, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler }, // Optional
- [0x15] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler },
- [0x16] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler },
+ [0x15] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = getVersionID },
+ [0x16] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = getCapabilities },
[0x17] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler },
[0x18] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler }, // Optional
[0x19] = { .payloadLength = 0, .ignoreInit = false, .packageCommand = false, .fn = unknownHandler }, // Optional
@@ -466,46 +613,21 @@ ncsi_handler_t gNCSIHandlers[] = {
void handleNCSIFrame(NetworkFrame_t *frame)
{
+ uint8_t package = frame->controlPacket.ChannelID >> PACKAGE_ID_SHIFT;
+ if(package != 0)
+ {
+ // Ignore - not us.
+ return;
+ }
uint8_t ch = frame->controlPacket.ChannelID & CHANNEL_ID_MASK;
uint8_t command = frame->controlPacket.ControlPacketType;
uint16_t payloadLength = frame->controlPacket.PayloadLength;
ncsi_handler_t *handler = &gNCSIHandlers[command];
- channel_state_t *channel = ((ch == CHANNEL_ID_PACKAGE) ? 0 : &gPackageState.channel[ch]);
+ channel_state_t *channel = ((ch >= gPackageState.numChannels) ? 0 : &gPackageState.channel[ch]);
if (handler->fn)
{
- if (ch != CHANNEL_ID_PACKAGE && ch >= gPackageState.numChannels)
- {
- channel = 0;
-#if CXX_SIMULATOR
- printf("[%x] Invalid channel: %d\n", command, ch);
-#endif
- // Channel does not exist.
- sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
- NCSI_RESPONSE_CODE_COMMAND_FAILED, NCSI_REASON_CODE_INVALID_PARAM);
- }
- else if ((true == handler->packageCommand && channel) || (false == handler->packageCommand && !channel))
- {
-#if CXX_SIMULATOR
- printf("[%x] Invalid channel for command: %d\n", command, ch);
-#endif
- // Command not targeting correct channel/package..
- sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
- NCSI_RESPONSE_CODE_COMMAND_FAILED, NCSI_REASON_CODE_INVALID_PARAM);
- }
- else if (false == handler->ignoreInit && false == handler->packageCommand && /* Pacakge commands don't target a channel */
- false == gPackageState.channel[ch].shm->NcsiChannelInfo.bits.Ready)
- {
-#if CXX_SIMULATOR
- printf("[%x] Channel not initialized: %d\n", command, ch);
- printf(" Ignore Init: %d\n", handler->ignoreInit);
- printf(" Initialized: %d\n", (uint32_t)gPackageState.channel[ch].shm->NcsiChannelInfo.bits.Ready);
-#endif
- // Initialization required for the channel
- sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
- NCSI_RESPONSE_CODE_COMMAND_FAILED, NCSI_REASON_CODE_INITIALIZATION_REQUIRED);
- }
- else if (handler->payloadLength != payloadLength)
+ if (handler->payloadLength != payloadLength)
{
#if CXX_SIMULATOR
printf("[%x] Unexpected payload length: 0x%04x != 0x%04x\n", command, handler->payloadLength, payloadLength);
@@ -514,15 +636,55 @@ void handleNCSIFrame(NetworkFrame_t *frame)
sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
NCSI_RESPONSE_CODE_COMMAND_FAILED, NCSI_REASON_CODE_INVALID_PAYLOAD_LENGTH);
}
- else
+ else if((handler->packageCommand && ch == CHANNEL_ID_PACKAGE) || // Package commands are always accepted.
+ (handler->ignoreInit && ch < gPackageState.numChannels))
{
+ // Package command. Must handle.
if (channel)
{
++channel->shm->NcsiChannelCtrlstatRx.r32;
}
gPackageState.selected = true;
+ SHM.SegSig.r32 |= (1 << command);
handler->fn(frame);
}
+ else
+ {
+ if (ch >= gPackageState.numChannels)
+ {
+
+#if CXX_SIMULATOR
+ printf("[%x] Invalid channel: %d\n", command, ch);
+#endif
+ // Channel does not exist.
+ sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
+ NCSI_RESPONSE_CODE_COMMAND_FAILED, NCSI_REASON_CODE_INVALID_PARAM);
+ }
+ else
+ {
+ gPackageState.selected = true;
+ if (false == gPackageState.channel[ch].shm->NcsiChannelInfo.bits.Ready)
+ {
+#if CXX_SIMULATOR
+ printf("[%x] Channel not initialized: %d\n", command, ch);
+ printf(" Ignore Init: %d\n", handler->ignoreInit);
+ printf(" Initialized: %d\n", (uint32_t)gPackageState.channel[ch].shm->NcsiChannelInfo.bits.Ready);
+#endif
+ // Initialization required for the channel
+ sendNCSIResponse(frame->controlPacket.InstanceID, frame->controlPacket.ChannelID, frame->controlPacket.ControlPacketType,
+ NCSI_RESPONSE_CODE_COMMAND_FAILED, NCSI_REASON_CODE_INITIALIZATION_REQUIRED);
+ }
+ else
+ {
+ if (channel)
+ {
+ ++channel->shm->NcsiChannelCtrlstatRx.r32;
+ }
+ SHM.SegSig.r32 |= (1 << command);
+ handler->fn(frame);
+ }
+ }
+ }
}
else
{
@@ -578,7 +740,7 @@ void NCSI_TxPacket(uint32_t *packet, uint32_t packet_len)
}
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 packetSize = MAX(sizeof(gLinkStatusResponseFrame.linkStatusResponse), ETHERNET_FRAME_MIN - 4);
gLinkStatusResponseFrame.linkStatusResponse.ChannelID = channelID;
gLinkStatusResponseFrame.linkStatusResponse.InstanceID = InstanceID;
@@ -595,9 +757,41 @@ void sendNCSILinkStatusResponse(uint8_t InstanceID, uint8_t channelID, uint32_t
NCSI_TxPacket(gLinkStatusResponseFrame.words, packetSize);
}
+void sendNCSICapabilitiesResponse(uint8_t InstanceID, uint8_t channelID, uint16_t controlID)
+{
+ uint32_t packetSize = MAX(sizeof(gCapabilitiesFrame.capabilities), ETHERNET_FRAME_MIN - 4);
+
+ gCapabilitiesFrame.capabilities.ChannelID = channelID;
+ gCapabilitiesFrame.capabilities.ControlPacketType = controlID | CONTROL_PACKET_TYPE_RESPONSE;
+ gCapabilitiesFrame.capabilities.InstanceID = InstanceID;
+ gCapabilitiesFrame.capabilities.ResponseCode = NCSI_RESPONSE_CODE_COMMAND_COMPLETE;
+ gCapabilitiesFrame.capabilities.ReasonCode = NCSI_REASON_CODE_NONE;
+
+ NCSI_TxPacket(gCapabilitiesFrame.words, packetSize);
+}
+
+void sendNCSIVersionResponse(uint8_t InstanceID, uint8_t channelID, uint16_t controlID)
+{
+ uint32_t packetSize = MAX(sizeof(gVersionFrame.version), ETHERNET_FRAME_MIN - 4);
+
+ gVersionFrame.version.ChannelID = channelID;
+ gVersionFrame.version.ControlPacketType = controlID | CONTROL_PACKET_TYPE_RESPONSE;
+ gVersionFrame.version.InstanceID = InstanceID;
+ gVersionFrame.version.ResponseCode = NCSI_RESPONSE_CODE_COMMAND_COMPLETE;
+ gVersionFrame.version.ReasonCode = NCSI_REASON_CODE_NONE;
+
+ gVersionFrame.version.PCIVendor = DEVICE.PciVendorDeviceId.bits.VendorID;
+ gVersionFrame.version.PCIDevice = DEVICE.PciVendorDeviceId.bits.DeviceID;
+ gVersionFrame.version.PCISubsystemVendor = DEVICE.PciSubsystemId.bits.SubsystemVendorID;
+ gVersionFrame.version.PCISubsystemDevice = DEVICE.PciSubsystemId.bits.SubsystemID;
+
+ NCSI_TxPacket(gVersionFrame.words, packetSize);
+}
+
+
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;
+ uint32_t packetSize = MAX(sizeof(gResponseFrame.responsePacket), ETHERNET_FRAME_MIN - 4);
gResponseFrame.responsePacket.ChannelID = channelID;
gResponseFrame.responsePacket.ControlPacketType = controlID | CONTROL_PACKET_TYPE_RESPONSE;
@@ -615,6 +809,8 @@ void NCSI_init(void)
{
gPackageState.channel[i].shm->NcsiChannelInfo.bits.Ready = false;
}
+ SHM.SegSig.r32 = 0;// (1 << command);
+
}
void NCSI_handlePassthrough(void)
@@ -625,6 +821,7 @@ void NCSI_handlePassthrough(void)
if (channel->shm->NcsiChannelInfo.bits.Ready)
{
Network_PassthroughRxPatcket(channel->port);
+ ++channel->shm->NcsiChannelCtrlstatAllTx.r32;
}
}
}
OpenPOWER on IntegriCloud