diff options
author | Evan Lojewski <github@meklort.com> | 2019-04-16 21:17:23 -0600 |
---|---|---|
committer | Evan Lojewski <github@meklort.com> | 2019-04-16 21:17:23 -0600 |
commit | c74510e67a4abdfb8b13c864e1315715cf96bec8 (patch) | |
tree | e58dfc46fa13c96694cc3acff8b54d0ebe80d92e /libs | |
parent | 4f272db731d9875a2394da7bab4c0ec5c477b1ef (diff) | |
download | bcm5719-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.h | 84 | ||||
-rw-r--r-- | libs/NCSI/ncsi.c | 183 |
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. |