diff options
author | Evan Lojewski <github@meklort.com> | 2019-04-29 20:15:40 -0600 |
---|---|---|
committer | Evan Lojewski <github@meklort.com> | 2019-04-29 20:15:40 -0600 |
commit | 2323b1274be2c91708c3c713811f54c3cbfe7107 (patch) | |
tree | 7412eaefc61c59b4b7375e72a609d05f69c4ee6e | |
parent | 62ae2a62375aab0d15f96abc1a4b115348065bf4 (diff) | |
download | bcm5719-ortega-2323b1274be2c91708c3c713811f54c3cbfe7107.tar.gz bcm5719-ortega-2323b1274be2c91708c3c713811f54c3cbfe7107.zip |
Test out transmitting to the network.
-rw-r--r-- | utils/bcmregtool/main.cpp | 402 |
1 files changed, 401 insertions, 1 deletions
diff --git a/utils/bcmregtool/main.cpp b/utils/bcmregtool/main.cpp index c706e3d..e98b2ab 100644 --- a/utils/bcmregtool/main.cpp +++ b/utils/bcmregtool/main.cpp @@ -72,6 +72,7 @@ #include <APE_FILTERS.h> #include <APE_NVIC.h> #include <APE_APE_PERI.h> +#include <APE_TX_PORT.h> #include <Ethernet.h> #include <NCSI.h> @@ -84,6 +85,17 @@ using optparse::OptionParser; elfio gELFIOReader; +uint8_t ping_packet[] = { + 0x00, 0x0c, 0x29, 0x64, 0x66, 0xe2, 0x2c, 0x09, 0x4d, 0x00, 0x01, 0x4a, 0x08, 0x00, 0x45, 0x00, + 0x00, 0x54, 0x12, 0xe1, 0x40, 0x00, 0x40, 0x01, 0x40, 0xbb, 0xc0, 0xa8, 0x20, 0x62, 0x04, 0x02, + 0x02, 0x01, 0x08, 0x00, 0xa1, 0xae, 0x15, 0x5f, 0x00, 0x52, 0xdc, 0xf1, 0x63, 0xae, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, +}; +uint32_t ping_packet_len = sizeof(ping_packet); + const char* regnames[32] = { "$zero", /* Zero register - always 0 */ "$at", /* Assembler register */ @@ -302,6 +314,247 @@ void writeMemory(uint32_t rxAddr, uint32_t value) DEVICE.RxRiscMode = mode; } + +uint32_t allocationBlocksNeeded(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); + } + + printf("%d blocks needed for packet\n", blocks); + return blocks; +} +int32_t allocateTXBlock(void) +{ +#if 1 + 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; + printf("Error: Failed to allocate TX block.\n"); + } + else + { + block = status.bits.Index; + printf("Allocated block %d\n", block); + } + + return block; +#else + static int block = 1; + int this_block = block; + block++; + printf("Allocated block %d\n", this_block); + return this_block; +#endif +} + +uint32_t initFirstBlock(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; + } + + + // 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]); + printf("Block[%d]: 0x%08X\n", i+TX_PORT_OUT_ALL_FIRST_PAYLOAD_WORD, 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; + printf("Block[%d]: pad(0)\n", i+TX_PORT_OUT_ALL_FIRST_PAYLOAD_WORD); + } + + control.bits.payload_length = copy_length; + + printf("Control: %x\n", control.r32); + block[TX_PORT_OUT_ALL_CONTROL_WORD].r32 = control.r32; + // block[1] = uninitialized; + block[2].r32 = 0; + block[TX_PORT_OUT_ALL_FRAME_LEN_WORD].r32 = length; + block[4].r32 = 0; + block[5].r32 = 0; + block[6].r32 = 0; + block[7].r32 = 0; + block[8].r32 = 0; + block[TX_PORT_OUT_ALL_NUM_BLOCKS_WORD].r32 = blocks; + // block[10] = uninitialized; + // block[11] = uninitialized; + + for(i = 0; i < 12; i++) + { + // printf("Block[%d]: 0x%08X\n", i, (uint32_t)block[i].r32); + } + + + length -= control.bits.payload_length; + + return copy_length; +} + +uint32_t initAdditionalBlock(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; + } + + printf("Control: %x\n", control.r32); + block[TX_PORT_OUT_ALL_CONTROL_WORD].r32 = control.r32; + // block[1] = uninitialized; + + for(i = 0; i < 2; i++) + { + // printf("ABlock[%d]: 0x%08X\n", i, (uint32_t)block[i].r32); + } + + // 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]); + printf("ABlock[%d]: 0x%08X\n", i+TX_PORT_OUT_ALL_ADDITIONAL_PAYLOAD_WORD, packet[i]); + + } + + length -= control.bits.payload_length; + + return length; +} + + +void transmitPacket(uint8_t* packet, uint32_t length) +{ + uint32_t* packet_32 = (uint32_t*)packet; + uint32_t consumed = 0; + uint32_t blocks = allocationBlocksNeeded(length); + int total_blocks = blocks;; + + // First block + int32_t first = allocateTXBlock(); + int32_t next_block = -1; + if(blocks > 1) + { + next_block = allocateTXBlock(); + } + RegTX_PORTOut_t* block = &TX_PORT.Out[TX_PORT_OUT_ALL_BLOCK_WORDS * first]; + + consumed += initFirstBlock(block, length, blocks, next_block, &packet_32[consumed/4]); + blocks -= 1; + while(blocks) + { + + block = &TX_PORT.Out[TX_PORT_OUT_ALL_BLOCK_WORDS * next_block]; + blocks--; + if(blocks) + { + next_block = allocateTXBlock(); + consumed += initAdditionalBlock(block, next_block, length-consumed, &packet_32[consumed/4]); + } + else + { + initAdditionalBlock(block, 0, length - consumed, &packet_32[consumed/4]); + } + } + + int tail = next_block; + + printf("Head: %d, Tail: %d\n", first, tail); + + RegAPETxToNetDoorbellFunc0_t doorbell; + doorbell.r32 = 0; + doorbell.bits.Head = first; + doorbell.bits.Tail = tail; + doorbell.bits.Length = total_blocks; + doorbell.print(); + + APE.TxToNetDoorbellFunc0 = doorbell; + +} + void step(void) { uint32_t oldPC = DEVICE.RxRiscProgramCounter.r32; @@ -315,7 +568,7 @@ void step(void) // Force a re-load of the next word. uint32_t newPC = DEVICE.RxRiscProgramCounter.r32; - if(oldPC +4 != newPC) + if(oldPC + 4 != newPC) { // branched. Re-read PC to re-read opcode DEVICE.RxRiscProgramCounter.r32 = DEVICE.RxRiscProgramCounter.r32; @@ -383,11 +636,30 @@ int main(int argc, char const *argv[]) .action("store_true") .help("Print ape information registers."); + parser.add_option("-rx", "--rx") + .dest("rx") + .set_default("0") + .action("store_true") + .help("Print rx information registers."); + + parser.add_option("-tx", "--tx") + .dest("tx") + .set_default("0") + .action("store_true") + .help("Print tx information registers."); + parser.add_option("-p", "--apeboot") .dest("apeboot") .metavar("APE_FILE") .help("File to boot on the APE."); + + parser.add_option("-apereset", "--apereset") + .dest("apereset") + .set_default("0") + .action("store_true") + .help("File to boot on the APE."); + parser.add_option("-m", "--mii") .dest("mii") .set_default("0") @@ -574,6 +846,9 @@ int main(int argc, char const *argv[]) // Set the payload address APE.GpioMessage.r32 = 0x10D800|2; + // Clear the signature. + SHM.SegSig.r32 = 0xBAD0C0DE; + // Boot mode.bits.Halt = 0; mode.bits.FastBoot = 1; @@ -583,6 +858,49 @@ int main(int argc, char const *argv[]) exit(0); } + if(options.get("apereset")) + { + + // Halt + RegAPEMode_t mode; + mode.r32 = 0; + mode.bits.Halt = 1; + mode.bits.FastBoot = 0; + APE.Mode = mode; + + // Boot + mode.bits.Halt = 0; + mode.bits.FastBoot = 0; + mode.bits.Reset = 1; + APE.Mode = mode; + + exit(0); + } + + if(options.get("rx")) + { + DEVICE.ReceiveMacMode.print(); + APE.RxPoolModeStatus0.print(); + APE.RxbufoffsetFunc0.print(); + exit(0); + } + + if(options.get("tx")) + { + APE.TxState0.print(); + APE.TxToNetPoolModeStatus0.print(); + APE.TxToNetBufferAllocator0.print(); + APE.TxToNetDoorbellFunc0.print(); + exit(0); + // APE.RxbufoffsetFunc0.print(); + transmitPacket(ping_packet, ping_packet_len); + + APE.TxToNetPoolModeStatus0.print(); + APE.TxState0.print(); + + exit(0); + } + if(options.get("ape")) { APE.Mode.print(); @@ -605,6 +923,88 @@ int main(int argc, char const *argv[]) printf("APE RCPU PCI Vendor/Device ID: 0x%08X\n", (uint32_t)SHM.RcpuPciVendorDeviceId.r32); printf("APE RCPU PCI Subsystem ID: 0x%08X\n", (uint32_t)SHM.RcpuPciSubsystemId.r32); + // boot_ape_loader(); + // printf("Loader Command: 0x%08X\n", (uint32_t)SHM.LoaderCommand.r32); + // printf("Loader Arg0: 0x%08X\n", (uint32_t)SHM.LoaderArg0.r32); + // printf("Loader Arg1: 0x%08X\n", (uint32_t)SHM.LoaderArg1.r32); + + // SHM.LoaderArg0.r32 = 0x00100040; + // SHM.LoaderCommand.bits.Command = SHM_LOADER_COMMAND_COMMAND_READ_MEM; + + // // Wait for command to be handled. + // while(0 != SHM.LoaderCommand.bits.Command); + // printf("Loader Command: 0x%08X\n", (uint32_t)SHM.LoaderCommand.r32); + // printf("Loader Arg0: 0x%08X\n", (uint32_t)SHM.LoaderArg0.r32); + // printf("Loader Arg1: 0x%08X\n", (uint32_t)SHM.LoaderArg1.r32); + + // // boot_ape_loader(); + // FILTERS.ElementConfig[0].print(); + // FILTERS.ElementConfig[15].print(); + // FILTERS.ElementConfig[16].print(); + // FILTERS.RuleConfiguration.print(); + // FILTERS.RuleSet[0].print(); + // FILTERS.RuleSet[1].print(); + // FILTERS.RuleSet[2].print(); + + // NVIC.VectorTableOffset.print(); + + // NVIC.InterruptControlType.print(); + // NVIC.SystickControlAndStatus.print(); + // NVIC.SystickControlAndStatus.bits.ENABLE = 1; + // NVIC.SystickControlAndStatus.print(); + + // NVIC.SystickReloadValue.print(); + // // NVIC.SystickReloadValue.bits.RELOAD=0xFFFFFFFF; + // NVIC.SystickCurrentValue.print(); + // NVIC.SystickCurrentValue.print(); + // NVIC.SystickCalibrationValue.print(); + APE_PERI.RmuControl.bits.AutoDrv =1; + APE_PERI.RmuControl.print(); +#if 0 + uint32_t buffer[1024]; + + RegAPE_PERIBmcToNcRxStatus_t stat; + stat.r32 = APE_PERI.BmcToNcRxStatus.r32; + stat.print(); + + if(stat.bits.New) + { + int32_t bytes = stat.bits.PacketLength; + int i = 0; + while(bytes > 0) + { + uint32_t word = (APE_PERI.BmcToNcReadBuffer.r32); + buffer[i] = word; + printf("Word %d: 0x%08X\n", i, word); + i++; + bytes -= 4; + } + + NetworkFrame_t *frame = ((NetworkFrame_t*)buffer); + + if(stat.bits.Bad) + { + // TODO: ACK bad packet. + APE_PERI.BmcToNcRxControl.bits.ResetBad = 1; + while(APE_PERI.BmcToNcRxControl.bits.ResetBad); + } + else if(!stat.bits.Passthru) + { + handleNCSIFrame(frame); + } + else + { + // Pass through to network + } + } + + // printf("REG_APE__NC_BMC_TX_STATUS__IN_FIFO") + // APE_PERI.BmcToNcTxStatus.print(); + // APE_PERI.BmcToNcTxControl.print(); + // APE_PERI.BmcToNcRxControl.print(); + // APE_PERI.ArbControl.print(); + printf("RegAPENcsiChannel0CtrlstatRx: 0x%08X\n", (uint32_t)SHM_CHANNEL0.NcsiChannelCtrlstatRx.r32); +#endif exit(0); } |