diff options
author | Evan Lojewski <github@meklort.com> | 2019-05-02 19:59:19 -0600 |
---|---|---|
committer | Evan Lojewski <github@meklort.com> | 2019-05-02 19:59:19 -0600 |
commit | 86106d98887a390f3a0dd54edf167cb5da1c2436 (patch) | |
tree | 95ef7dfb0615a611e6ee8a3b37b8bdb5195a86d2 /libs | |
parent | d34ace3709b06d55510c7b4481f9e055ff6610e3 (diff) | |
download | bcm5719-ortega-86106d98887a390f3a0dd54edf167cb5da1c2436.tar.gz bcm5719-ortega-86106d98887a390f3a0dd54edf167cb5da1c2436.zip |
Begin moving APE tx code from the host to the APE.
Diffstat (limited to 'libs')
-rw-r--r-- | libs/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libs/Network/CMakeLists.txt | 60 | ||||
-rw-r--r-- | libs/Network/include/Network.h | 61 | ||||
-rw-r--r-- | libs/Network/init.c | 712 | ||||
-rw-r--r-- | libs/Network/tx.c | 296 |
5 files changed, 1130 insertions, 0 deletions
diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index b3fe23b..f3ef1e1 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -49,6 +49,7 @@ add_subdirectory(MII) add_subdirectory(VPD) add_subdirectory(NCSI) +add_subdirectory(Network) add_subdirectory(OptParse) diff --git a/libs/Network/CMakeLists.txt b/libs/Network/CMakeLists.txt new file mode 100644 index 0000000..e5dd1a5 --- /dev/null +++ b/libs/Network/CMakeLists.txt @@ -0,0 +1,60 @@ +################################################################################ +### +### @file libs/Network/CMakeLists.txt +### +### @project +### +### @brief Network CMake file +### +################################################################################ +### +################################################################################ +### +### @copyright Copyright (c) 2019, 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 +################################################################################ + +project(Network) + + +# Host Simulation library +simulator_add_library(${PROJECT_NAME} STATIC tx.c) +target_link_libraries(${PROJECT_NAME} PRIVATE simulator NCSI) +target_include_directories(${PROJECT_NAME} PUBLIC ../../include) +target_include_directories(${PROJECT_NAME} PUBLIC include) + +# ARM Library +arm_add_library(${PROJECT_NAME}-arm STATIC init.c tx.c) +target_link_libraries(${PROJECT_NAME}-arm PRIVATE NCSI-arm) +target_include_directories(${PROJECT_NAME}-arm PUBLIC ../../include) +target_include_directories(${PROJECT_NAME}-arm PUBLIC include) + +# add_subdirectory(tests)
\ No newline at end of file diff --git a/libs/Network/include/Network.h b/libs/Network/include/Network.h new file mode 100644 index 0000000..8bfadcf --- /dev/null +++ b/libs/Network/include/Network.h @@ -0,0 +1,61 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// @file Network.h +/// +/// @project +/// +/// @brief Network TX/RX Support Routines +/// +//////////////////////////////////////////////////////////////////////////////// +/// +//////////////////////////////////////////////////////////////////////////////// +/// +/// @copyright Copyright (c) 2019, 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 NETWORK_H +#define NETWORK_H + +#include <stdint.h> + +void Network_InitTxRx(void); + +uint32_t Network_TX_numBlocksNeeded(uint32_t frame_size); +int32_t Network_TX_allocateBlock(void); + +void Network_TX_transmitBePacket(uint8_t* packet, uint32_t length); + + + + + +#endif /* NETWORK_H */
\ No newline at end of file diff --git a/libs/Network/init.c b/libs/Network/init.c new file mode 100644 index 0000000..45be102 --- /dev/null +++ b/libs/Network/init.c @@ -0,0 +1,712 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// @file init.c +/// +/// @project +/// +/// @brief Initialization code for TX to network / RX from network. +/// +//////////////////////////////////////////////////////////////////////////////// +/// +//////////////////////////////////////////////////////////////////////////////// +/// +/// @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 +//////////////////////////////////////////////////////////////////////////////// + +#include <APE_FILTERS.h> +#include <APE_APE.h> +#include <APE_DEVICE.h> + +typedef struct { + RegFILTERSElementConfig_t cfg; + RegFILTERSElementPattern_t pat; +} FilterElementInit_t; + +static const FilterElementInit_t gElementInit[32] = { + [0] = {{0}}, + [1] = {{0}}, + [2] = {{0}}, + [3] = {{0}}, + [4] = {{0}}, + [5] = {{0}}, + [6] = {{0}}, + [7] = {{0}}, + [8] = {{0}}, + [9] = {{0}}, + [10] = {{0}}, + [11] = {{0}}, + [12] = {{0}}, + [13] = {{0}}, + [14] = {{0}}, + [15] = {{0}}, + + // 16: Check MAC address multicast bit not set. + [16] = { + .cfg = { .bits = { + .RuleOffset = 0, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_SOF, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_NE, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0x01000100}, + }, + + [17] = {{0}}, + [18] = {{0}}, + + // 19: Special VLAN match. + [19] = { + .cfg = { .bits = { + .RuleOffset = 0, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_VLAN, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0}, + }, + + // 20: IPv6 Neighbor Advertisement. + [20] = { + .cfg = { .bits = { + .RuleOffset = 0, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_ICMPV6, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 0, // Disabled + }}, + .pat = {.r32 = 0x8800FF00}, + }, + + // 21: IPv6 Router Advertisement. + [21] = { + .cfg = { .bits = { + .RuleOffset = 0, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_ICMPV6, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 0, // Disabled + }}, + .pat = {.r32 = 0x8600FF00}, + }, + + // 22: DHCPv6 Server. + [22] = { + .cfg = { .bits = { + .RuleOffset = 2, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_UDP, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 0, // Disabled + }}, + .pat = {.r32 = 0x0223FFFF}, + }, + + [23] = {{0}}, + + // 24: ARP match. + [24] = { + .cfg = { .bits = { + .RuleOffset = 12, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_SOF, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0x0806FFFF}, + }, + + // 25: DHCPv4. + [25] = { + .cfg = { .bits = { + .RuleOffset = 2, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_UDP, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0x0044FFFF}, + }, + + // 26: DHCPv4. + [26] = { + .cfg = { .bits = { + .RuleOffset = 2, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_UDP, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0x0043FFFF}, + }, + + // 27: NetBIOS + [27] = { + .cfg = { .bits = { + .RuleOffset = 2, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_UDP, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0x0088FFFC}, + }, + + // 28: Broadcast address match. + [28] = { + .cfg = { .bits = { + .RuleOffset = 0, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_SOF, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 0, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0xFFFFFFFF}, + }, + + // 29: Broadcast address match. + [29] = { + .cfg = { .bits = { + .RuleOffset = 4, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_SOF, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0xFFFFFFFF}, + }, + + // 30: IPv6 multicast. + [30] = { + .cfg = { .bits = { + .RuleOffset = 0, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_SOF, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0x3333FFFF}, + }, + // 31: Check MAC address multicast bit is set. + [31] = { + .cfg = { .bits = { + .RuleOffset = 0, + .RuleClass = 0, + .RuleHeader = FILTERS_ELEMENT_CONFIG_RULE_HEADER_SOF, + .RuleOp = FILTERS_ELEMENT_CONFIG_RULE_OP_EQ, + .reserved_23_18 = 0, + .RuleMap = 0, + .RuleDiscard = 0, + .RuleMask = 1, + .RuleP3 = 0, + .RuleP2 = 0, + .RuleP1 = 0, + .RuleAnd = 0, + .RuleEnable = 1, + }}, + .pat = {.r32 = 0x01000100}, + }, + +}; + +typedef struct { + RegFILTERSRuleSet_t set; + RegFILTERSRuleMask_t mask; +} FilterRuleInit_t; +static const FilterRuleInit_t gRuleInit[32] = { + // S-0. Unused. + [0] = {{0}}, + + // S-1. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=1, MASK=0x0003_0000. + [1] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x00030000}, + }, + + // S-2. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=1, MASK=0x0005_0000. + [2] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x00050000}, + }, + + // S-3. ACTION=TO_APE_AND_HOST, COUNT=2, ENABLE=recommend 1, MASK=0x0009_0000 + [3] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 2, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x00090000}, + }, + + // S-4. ACTION=T0_APE_AND_HOST, COUNT=0, ENABLE=1, MASK=0x0001_0000. + [4] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x00010000}, + }, + + // S-5. Not used, initialize to zero. + [5] = {{0}}, + // S-6. Not used, initialize to zero. + [6] = {{0}}, + // S-7. Not used, initialize to zero. + [7] = {{0}}, + // S-8. Not used, initialize to zero. + [8] = {{0}}, + + // S-9. ACTION=TO_APE_AND_HOST, COUNT=2, ENABLE=recommend 1, MASK=0x3008_0000. + [9] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 2, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x30080000}, + }, + + // S-10. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=1 (essential for RX), MASK=0x3100_0000. + [10] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x31000000}, + }, + + // S-11. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=1 (essential for RX), MASK=0x3200_0000. + [11] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x32000000}, + }, + + // S-12. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=1 (essential for RX), MASK=0x3400_0000. + [12] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x34000000}, + }, + + // S-13. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=1 (essential for RX), MASK=0x3800_0000. + [13] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x38000000}, + }, + + // S-14. ACTION=TO_APE_AND_HOST, COUNT=2, ENABLE=1 (essential for RX), MASK=0x3000_0000. + [14] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 2, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x30000000}, + }, + + // S-15. Not used, initialize to zero. + [15] = {{0}}, + // S-16. Not used, initialize to zero. + [16] = {{0}}, + // S-17. Not used, initialize to zero. + [17] = {{0}}, + + // S-18. ACTION=TO_APE_AND_HOST, COUNT=2, ENABLE=recommend 1, MASK=0x8008_0000. + [18] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 2, + .reserved_30_19 = 0, + .Enable = 1, + }}, + .mask = {.r32 = 0x80080000}, + }, + + // S-19. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*0). + [19] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*0)}, + }, + + // S-20. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*1). + [20] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*1)}, + }, + + // S-21. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*2). + [21] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*2)}, + }, + + // S-22. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*3). + [22] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*3)}, + }, + + // S-23. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*4). + [23] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*4)}, + }, + + // S-24. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*5). + [24] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*5)}, + }, + + // S-25. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*6). + [25] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*6)}, + }, + + // S-26. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=(0b11)<<(2*7). + [26] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = (0x3)<<(2*7)}, + }, + + // S-27. Not used, initialize to zero. + [27] = {{0}}, + + // S-28. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=0x4010_0000. + [28] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = 0x40100000}, + }, + + // S-29. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=0x4020_0000. + [29] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = 0x40200000}, + }, + + // S-30. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=0x4020_0000. + [30] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = 0x40200000}, + }, + + // S-31. ACTION=TO_APE_AND_HOST, COUNT=0, ENABLE=0, MASK=0x8000_0000. + [31] = { + .set = {.bits = { + .Action = FILTERS_RULE_SET_ACTION_TO_APE_AND_HOST, + .reserved_2_2 = 0, + .Count = 0, + .reserved_30_19 = 0, + .Enable = 0, + }}, + .mask = {.r32 = 0x80000000}, + }, +}; + +void Network_InitTxRx(void) +{ + for(int i = 0; i < 32; i++) + { + FILTERS.ElementConfig[i] = gElementInit[i].cfg; + FILTERS.ElementPattern[i] = gElementInit[i].pat; + } + + for(int i = 1; i < 32; i++) + { + FILTERS.RuleSet[i-1] = gRuleInit[i].set; + FILTERS.RuleMask[i-1] = gRuleInit[i].mask; + } + + FILTERS.RuleConfiguration.r32 = 0; + + + // REG_APE_PERFECT_MATCH1_{HIGH,LOW}. For non-broadcast/multicast traffic, the hardware uses this register to match MACs and pass traffic to the APE. + // The first two bytes of a MAC are put in the HIGH register, and the remaining four bytes in the LOW. + // Note that this is a device (PCI) register, not an APE register. Set it to the BMC MAC. + + + // REG_APE__BMC_NC_RX_SRC_MAC_MATCHN_{HIGH,LOW}. + // This appears to relate to the RMU, not network RX, but its exact purpose is unknown. + // Set it to the BMC MAC. Unlike the "perfect match" register above, it takes a different format: + // for an example MAC AABB.CCDD.EEFF, set HIGH=0xAABBCCDD, LOW=0xEEFF0000. + // *** NOTE: set to 0 in rmu.c *** + + + // Ensure REG_RECEIVE_MAC_MODE has ENABLE set. + // I recommend also setting APE_PROMISCUOUS_MODE and PROMISCUOUS_MODE, + // as these will cause you less headaches during development. + DEVICE.ReceiveMacMode.bits.Enable = 1; + DEVICE.ReceiveMacMode.bits.PromiscuousMode = 1; + DEVICE.ReceiveMacMode.bits.APEPromiscuousMode = 1; + + // Ensure REG_EMAC_MODE__ENABLE_APE_{TX,RX}_PATH are set. + // *** NOTE: Both bits are set in rmu.c ***/ + + // Enable APE channel 0/0 + RegAPEMode_t mode; + mode = APE.Mode; + mode.bits.Event1 = 1; + mode.bits.Channel0Enable = 1; + mode.bits.Channel2Enable = 1; + APE.Mode = mode; + + + + + // Enable RX for funciton 0 + RegAPERxPoolModeStatus0_t rxMode; + rxMode.r32 = 0; + rxMode.bits.Reset = 1; + APE.RxPoolModeStatus0 = rxMode; + + rxMode.bits.Reset = 0; + rxMode.bits.Enable = 1; + APE.RxPoolModeStatus0 = rxMode; + + // Enable TX for function 0 + RegAPETxToNetPoolModeStatus0_t txMode; + txMode.r32 = 0; + txMode.bits.Reset = 1; + APE.TxToNetPoolModeStatus0 = txMode; + + txMode.bits.Reset = 0; + txMode.bits.Enable = 1; + APE.TxToNetPoolModeStatus0 = txMode; + +} diff --git a/libs/Network/tx.c b/libs/Network/tx.c new file mode 100644 index 0000000..730afb6 --- /dev/null +++ b/libs/Network/tx.c @@ -0,0 +1,296 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// @file tx.c +/// +/// @project +/// +/// @brief Network transmission routines +/// +//////////////////////////////////////////////////////////////////////////////// +/// +//////////////////////////////////////////////////////////////////////////////// +/// +/// @copyright Copyright (c) 2019, 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 +//////////////////////////////////////////////////////////////////////////////// + + +#include <Network.h> +#include <Ethernet.h> +#include <APE_APE.h> +#include <APE_TX_PORT.h> + +#ifdef CXX_SIMULATOR +#include <stdio.h> +#include <endian.h> +#else +/* ARM */ +static inline uint32_t be32toh(uint32_t be32) +{ + uint32_t le32 = (be32 & 0xFF000000 >> 24) | + (be32 & 0x00FF0000 >> 8) | + (be32 & 0x0000FF00 << 8) | + (be32 & 0x000000FF << 24); + + return le32; +} +#endif + +uint32_t Network_TX_numBlocksNeeded(uint32_t frame_size) +{ + static const uint32_t first_size = 20 * sizeof(uint32_t); + static const uint32_t remaining_size = 30 * sizeof(uint32_t); + uint32_t blocks = 1; + // Block size is 128 bytes, first one has 12 words used, so 20 words available. + if(frame_size > first_size) + { + frame_size -= 20 * sizeof(uint32_t); + + // Remaining blocks can hold 30 words; + blocks += ((frame_size + remaining_size - 1) / remaining_size); + } + +#ifdef CXX_SIMULATOR + printf("%d blocks needed for packet\n", blocks); +#endif + return blocks; +} + + + +int32_t __attribute__((noinline)) Network_TX_allocateBlock(void) +{ + int32_t block = -1; + + // Wait for allocator state machine to finish. + // while(APE_TX_TO_NET_BUFFER_ALLOCATOR_0_STATE_PROCESSING == APE.TxToNetBufferAllocator0.bits.State); + + // Set the alloc bit. + RegAPETxToNetBufferAllocator0_t alloc; + alloc.r32 = 0; + alloc.bits.RequestAllocation = 1; + APE.TxToNetBufferAllocator0 = alloc; + + // Wait for state machine to finish + RegAPETxToNetBufferAllocator0_t status; + do { + status = APE.TxToNetBufferAllocator0; + } while(APE_TX_TO_NET_BUFFER_ALLOCATOR_0_STATE_PROCESSING == status.bits.State); + + if(APE_TX_TO_NET_BUFFER_ALLOCATOR_0_STATE_ALLOCATION_OK != status.bits.State) + { + block = -1; +#if CXX_SIMULATOR + printf("Error: Failed to allocate TX block.\n"); +#endif + } + else + { + block = status.bits.Index; +#if CXX_SIMULATOR + printf("Allocated TX block %d\n", block); +#endif + } + + return block; +} + +uint32_t __attribute__((noinline)) Network_TX_initFirstBlockBe(RegTX_PORTOut_t* block, uint32_t length, int32_t blocks, int32_t next_block, uint32_t* packet) +{ + int copy_length; + int i; + union { + uint32_t r32; + struct { + uint32_t payload_length:7; + uint32_t next_block:23; + uint32_t first:1; + uint32_t not_last:1; + } bits; + } control; + + control.r32 = 0; + control.bits.next_block = next_block >= 0 ? next_block : 0; + control.bits.first = 1; + + if(length > ((TX_PORT_OUT_ALL_BLOCK_WORDS - TX_PORT_OUT_ALL_FIRST_PAYLOAD_WORD)*4)) + { + copy_length = (TX_PORT_OUT_ALL_BLOCK_WORDS - TX_PORT_OUT_ALL_FIRST_PAYLOAD_WORD)*4; + control.bits.not_last = 1; + } + else + { + // Last. + copy_length = length; + control.bits.not_last = 0; + } + + // block[1] = uninitialized; + block[2].r32 = 0; + block[3].r32 = 0; + block[4].r32 = 0; + block[5].r32 = 0; + block[6].r32 = 0; + block[7].r32 = 0; + block[8].r32 = 0; + block[9].r32 = 0; + // block[10] = uninitialized; + // block[11] = uninitialized; + block[TX_PORT_OUT_ALL_FRAME_LEN_WORD].r32 = length; + block[TX_PORT_OUT_ALL_NUM_BLOCKS_WORD].r32 = blocks; + + // Copy Payload Data. + int num_words = (copy_length + sizeof(uint32_t) - 1)/sizeof(uint32_t); + for(i = 0; i < num_words; i++) + { + block[TX_PORT_OUT_ALL_FIRST_PAYLOAD_WORD + i].r32 = be32toh(packet[i]); + } + + // Pad if too small. + if(copy_length < ETHERNET_FRAME_MIN) + { + copy_length = ETHERNET_FRAME_MIN; + length = ETHERNET_FRAME_MIN; + } + num_words = (copy_length + sizeof(uint32_t) - 1)/sizeof(uint32_t); + for(; i < num_words; i++) + { + // Pad remaining with 0's + block[TX_PORT_OUT_ALL_FIRST_PAYLOAD_WORD + i].r32 = 0; + } + + control.bits.payload_length = copy_length; + + block[TX_PORT_OUT_ALL_CONTROL_WORD].r32 = control.r32; + + length -= control.bits.payload_length; + + return copy_length; +} + + +uint32_t __attribute__((noinline)) Network_TX_initAdditionalBlockBe(RegTX_PORTOut_t* block, int32_t next_block, uint32_t length, uint32_t* packet) +{ + int i; + union { + uint32_t r32; + struct { + uint32_t payload_length:7; + uint32_t next_block:23; + uint32_t first:1; + uint32_t not_last:1; + } bits; + } control; + + control.r32 = 0; + control.bits.first = 0; + control.bits.next_block = next_block; + + if(length > ((TX_PORT_OUT_ALL_BLOCK_WORDS - TX_PORT_OUT_ALL_ADDITIONAL_PAYLOAD_WORD)*4)) + { + control.bits.payload_length = (TX_PORT_OUT_ALL_BLOCK_WORDS - TX_PORT_OUT_ALL_ADDITIONAL_PAYLOAD_WORD)*4; + control.bits.not_last = 1; + } + else + { + // Last + control.bits.payload_length = length; + control.bits.not_last = 0; + } + + // block[1] = uninitialized; + + // Copy payload data. + int num_words = (length + sizeof(uint32_t) - 1)/sizeof(uint32_t); + for(i = 0; i < num_words; i++) + { + block[TX_PORT_OUT_ALL_ADDITIONAL_PAYLOAD_WORD + i].r32 = be32toh(packet[i]); + + } + + block[TX_PORT_OUT_ALL_CONTROL_WORD].r32 = control.r32; + + length -= control.bits.payload_length; + + return length; +} + +void Network_TX_transmitBePacket(uint8_t* packet, uint32_t length) +{ + uint32_t* packet_32 = (uint32_t*)packet; + uint32_t consumed = 0; + uint32_t blocks = Network_TX_numBlocksNeeded(length); + int total_blocks = blocks;; + + // First block + int32_t first = Network_TX_allocateBlock(); + int32_t next_block = -1; + if(blocks > 1) + { + next_block = Network_TX_allocateBlock(); + } + RegTX_PORTOut_t* block = (RegTX_PORTOut_t*)&TX_PORT.Out[TX_PORT_OUT_ALL_BLOCK_WORDS * first]; + + consumed += Network_TX_initFirstBlockBe(block, length, blocks, next_block, &packet_32[consumed/4]); + blocks -= 1; + while(blocks) + { + + block = (RegTX_PORTOut_t*)&TX_PORT.Out[TX_PORT_OUT_ALL_BLOCK_WORDS * next_block]; + blocks--; + if(blocks) + { + next_block = Network_TX_allocateBlock(); + consumed += Network_TX_initAdditionalBlockBe(block, next_block, length-consumed, &packet_32[consumed/4]); + } + else + { + Network_TX_initAdditionalBlockBe(block, 0, length - consumed, &packet_32[consumed/4]); + } + } + + int tail = next_block; + if(next_block == -1) + { + tail = first; + } + + RegAPETxToNetDoorbellFunc0_t doorbell; + doorbell.r32 = 0; + doorbell.bits.Head = first; + doorbell.bits.Tail = tail; + doorbell.bits.Length = total_blocks; + // doorbell.print(); + + APE.TxToNetDoorbellFunc0 = doorbell; + // APE.TxToNetDoorbellFunc0.print(); + // APE.TxToNetBufferReturn0.print(); +} |