diff options
author | Evan Lojewski <github@meklort.com> | 2019-06-18 20:12:26 -0600 |
---|---|---|
committer | Evan Lojewski <github@meklort.com> | 2019-06-18 20:12:26 -0600 |
commit | 2d4d71129d367997cdd9b588ef4131cc5093e508 (patch) | |
tree | 4cd54f8159a8afd347554d36b2ec7fc3630845a3 /libs/NCSI/ncsi.c | |
parent | 6350644655e18c0bae30bbada3bfe27bf6b0266a (diff) | |
download | bcm5719-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.c | 289 |
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; } } } |