//////////////////////////////////////////////////////////////////////////////// /// /// @file Ethernet.h /// /// @project /// /// @brief Ethernet Support Routines /// //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// /// /// @copyright Copyright (c) 2018, Evan Lojewski /// @cond /// /// All rights reserved. /// /// Redistribution and use in source and binary forms, with or without /// modification, are permitted provided that the following conditions are met: /// 1. Redistributions of source code must retain the above copyright notice, /// this list of conditions and the following disclaimer. /// 2. Redistributions in binary form must reproduce the above copyright notice, /// this list of conditions and the following disclaimer in the documentation /// and/or other materials provided with the distribution. /// 3. Neither the name of the copyright holder nor the /// names of its contributors may be used to endorse or promote products /// derived from this software without specific prior written permission. /// //////////////////////////////////////////////////////////////////////////////// /// /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" /// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE /// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE /// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE /// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR /// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF /// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS /// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN /// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) /// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE /// POSSIBILITY OF SUCH DAMAGE. /// @endcond //////////////////////////////////////////////////////////////////////////////// #ifndef ETHERNET_H #define ETHERNET_H #include #define ETHERNET_FRAME_MIN (64 - 4) /* Hardware automatically adds FCS (last 4 bytes) */ typedef struct { #ifdef __LITTLE_ENDIAN__ uint8_t DestinationAddress[6]; uint8_t SourceAddress[6]; uint16_t reserved; // part of payload uint16_t EtherType; #else #error Not tested #endif } EthernetHeader_t; _Static_assert(sizeof(EthernetHeader_t) == 16, "sizeof(EthernetHeader_t) must be 16."); #define ETHER_TYPE_NCSI 0x88f8 #define ETHERNET_HEADER_OFFSET 0 #define PACKET_OFFSET (12) typedef struct { // Bytes 0 - 11 - Ethernet Header uint8_t DestinationAddress[6]; uint8_t SourceAddress[6]; #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. // 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; #else #error Not tested #endif } ControlPacketHeader_t; _Static_assert(sizeof(ControlPacketHeader_t) == 16 + PACKET_OFFSET, "sizeof(ControlPacketHeader_t) must be 16."); #define CONTROL_PACKET_PAYLOAD_OFFSET (PACKET_OFFSET + 16) #define CONTROL_PACKET_TYPE_RESPONSE (0x80) #define CONTROL_PACKET_TYPE_CLEAR_INITIAL_STATE (0x00) #define CONTROL_PACKET_TYPE_SELECT_PACKAGE (0x01) #define CONTROL_PACKET_TYPE_DESELECT_PACKAGE (0x02) #define CONTROL_PACKET_TYPE_ENABLE_CHANNEL (0x03) #define CONTROL_PACKET_TYPE_DISABLE_CHANNEL (0x04) #define CONTROL_PACKET_TYPE_RESET_CHANNEL (0x05) #define CONTROL_PACKET_TYPE_ENABLE_CHANNEL_NETWORK_TX (0x06) #define CONTROL_PACKET_TYPE_DISABLE_CHANNEL_NETWORK_TX (0x07) #define CONTROL_PACKET_TYPE_AEN_ENABLE (0x08) #define CONTROL_PACKET_TYPE_SET_LINK (0x09) #define CONTROL_PACKET_TYPE_GET_LINK_STATUS (0x0A) #define CONTROL_PACKET_TYPE_SET_VLAN_FILTER (0x0B) #define CONTROL_PACKET_TYPE_ENABLE_VLAN (0x0C) #define CONTROL_PACKET_TYPE_DISABLE_VLAN (0x0D) #define CONTROL_PACKET_TYPE_SET_MAC_ADDRESS (0x0E) // 0x0F #define CONTROL_PACKET_TYPE_ENABLE_BROADCAST_FILTERING (0x10) #define CONTROL_PACKET_TYPE_DISABLE_BROADCAST_FILTERING (0x11) #define CONTROL_PACKET_TYPE_ENABLE_GLOBAL_MULTICAST_FILTERING (0x12) #define CONTROL_PACKET_TYPE_DISABLE_GLOBAL_MULTICAST_FILTERING (0x13) #define CONTROL_PACKET_TYPE_SET_NCSI_FLOW_CONTROL (0x14) #define CONTROL_PACKET_TYPE_GET_VERSION_ID (0x15) #define CONTROL_PACKET_TYPE_GET_CAPABILITIES (0x16) #define CONTROL_PACKET_TYPE_GET_PARAMETERS (0x17) #define CONTROL_PACKET_TYPE_GET_CONTROLLER_PACKET_STATS (0x18) #define CONTROL_PACKET_TYPE_GET_NCSI_STATS (0x19) #define CONTROL_PACKET_TYPE_GET_NCSI_PASSTHRU_STATS (0x1A) #define CONTROL_PACKET_OEM_COMMAND (0x50) typedef struct { // Bytes 0 - 27 ControlPacketHeader_t header; // Byte 28 - 31 uint32_t headerPadding:16; uint32_t checksumHigh:16; // Bytes 32 - 35 uint32_t checksumLow; uint32_t pad:16; } ClearInitialState_t; typedef struct { // Bytes 0 - 27 ControlPacketHeader_t header; // Byte 28 - 31 uint32_t HardwareArbitartionDisabled:8; uint32_t reserved_0:8; uint32_t headerPadding:16; // Bytes 32 - 35 uint32_t checksumLow; uint32_t pad:16; } SelectPackage_t; typedef struct { // Bytes 0 - 27 ControlPacketHeader_t header; // Byte 28 - 31 uint32_t AEN_MC_ID:8; uint32_t reserved_0:8; uint32_t headerPadding:16; // Bytes 32 - 35 uint32_t AENControl_High:16; uint32_t reserved_1:16; // Bytes 36 - 39 uint32_t pad:16; 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 { // Bytes 0 - 27 ControlPacketHeader_t header; // Byte 28 - 31 uint32_t MAC54:16; uint32_t headerPadding:16; // Bytes 32 - 35 uint32_t MAC10:16; uint32_t MAC32:16; // Bytes 36 - 39 uint32_t pad:16; uint32_t Enable:1; uint32_t Rsvd:4; uint32_t AT:3; uint32_t MACNumber:8; } SetMACAddr_t; typedef struct { // Bytes 0 - 11 uint8_t DestinationAddress[6]; uint8_t SourceAddress[6]; #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. // 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; // Bytes 28 - 31 uint16_t ResponseCode; uint16_t reserved_4; // Bytes 32 - 35 uint16_t Checksum_High; uint16_t ReasonCode; uint16_t reserved_5; uint16_t Checksum_Low; #else #error Not tested #endif } __attribute__((packed)) ResponsePacketHeader_t; typedef struct { // Bytes 0 - 11 uint8_t DestinationAddress[6]; uint8_t SourceAddress[6]; #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. // 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; // Bytes 28 - 31 uint16_t ResponseCode; uint16_t reserved_4; // Bytes 32 - 35 uint16_t LinkStatus_High; uint16_t ReasonCode; // Bytes 36 - 39 uint16_t OtherIndications_High; uint16_t LinkStatus_Low; // Bytes 40 - 43 uint16_t OEMLinkStatus_High; uint16_t OtherIndications_Low; // Bytes 44 - 47 uint16_t Checksum_High; uint16_t OEMLinkStatus_Low; uint16_t pad; uint16_t Checksum_Low; #else #error Not tested #endif } __attribute__((packed)) LinkStatusResponsePacketHeader_t; typedef struct { // Bytes 0 - 11 uint8_t DestinationAddress[6]; uint8_t SourceAddress[6]; #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. // 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; // Bytes 28 - 31 uint16_t ResponseCode; uint16_t reserved_4; // Bytes 32 - 35 uint16_t Capabilities_High; uint16_t ReasonCode; // Bytes 36 - 39 uint16_t BroadcastCapabilities_High; uint16_t Capabilities_Low; // Bytes 40 - 43 uint16_t MilticastCapabilities_High; uint16_t BroadcastCapabilities_Low; // Bytes 44 - 47 uint16_t BufferingCapabilities_High; uint16_t MilticastCapabilities_Low; // Bytes 48 - 51 uint16_t AENControlSupport_High; uint16_t BufferingCapabilities_Low; // Bytes 52 - 45 uint8_t MixedFilterCount; uint8_t VLANFilterCount; uint16_t AENControlSupport_Low; // Bytes 56 - 59 uint16_t reserved_5; uint8_t UnicastFilterCount; uint8_t MulticastFilterCount; uint16_t Checksum_High; uint8_t ChannelCount; uint8_t VLANModeSupport; uint16_t pad; uint16_t Checksum_Low; #else #error Not tested #endif } __attribute__((packed)) CapabilitiesResponsePacket_t; typedef struct { // Bytes 0 - 11 uint8_t DestinationAddress[6]; uint8_t SourceAddress[6]; #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. // 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; // Bytes 28 - 31 uint16_t ResponseCode; uint16_t reserved_4; // Bytes 32 - 35 uint8_t NCSIMinor; uint8_t NCSIMajor; uint16_t ReasonCode; // Bytes 36 - 39 uint16_t reserved_5; uint8_t NCSIAlpha1; uint8_t NCSIUpdate; // Bytes 40 - 43 uint8_t name_10; uint8_t name_11; uint8_t NCSIAlpha2; uint8_t reserved_6; uint8_t name_6; uint8_t name_7; uint8_t name_8; uint8_t name_9; uint8_t name_2; uint8_t name_3; uint8_t name_4; uint8_t name_5; uint16_t FWVersion_High; uint8_t name_0; uint8_t name_1; uint16_t PCIVendor; uint16_t FWVersion_Low; uint16_t PCISubsystemVendor; uint16_t PCIDevice; uint16_t ManufacturerID_High; uint16_t PCISubsystemDevice; uint16_t Checksum_High; uint16_t ManufacturerID_Low; uint16_t pad; uint16_t Checksum_Low; #else #error Not tested #endif } __attribute__((packed)) VersionResponsePacket_t; #define CAPABILITIES_HARDWARE_ABSTRACTION (1 << 0) #define CAPABILITIES_OS_PRESENCE (1 << 1) #define CAPABILITIES_FLOW_CONTROL_RX (1 << 2) #define CAPABILITIES_FLOW_CONTROL_TX (1 << 3) #define CAPABILITIES_MULTICAST (1 << 4) typedef union { EthernetHeader_t header; /* Control Packets */ ControlPacketHeader_t controlPacket; ClearInitialState_t clearInitialState; SelectPackage_t selectPackage; AENEnable_t AENEnable; SetLink_t setLink; SetMACAddr_t setMACAddr; /* Response Packets */ ResponsePacketHeader_t responsePacket; LinkStatusResponsePacketHeader_t linkStatusResponse; CapabilitiesResponsePacket_t capabilities; VersionResponsePacket_t version; } __attribute__((packed)) NetworkFrame_t; // Ethernet frame must be at least 64 bytes. _Static_assert(sizeof(NetworkFrame_t) >= ETHERNET_FRAME_MIN, "NetworkFrame_t must be at least ETHERNET_FRAME_MIN bytes"); #endif /* ETHERNET_H */