diff options
author | Evan Lojewski <github@meklort.com> | 2019-06-22 18:01:29 -0600 |
---|---|---|
committer | Evan Lojewski <github@meklort.com> | 2019-06-22 18:01:29 -0600 |
commit | b4668768e1281ad943cc04deca0bd5feabd3b448 (patch) | |
tree | 56f6e0c72b4ad3ec0eed2095e3441b2432c8720a /utils | |
parent | a8dbe49f6c799f213d68b013c7961c591e019f03 (diff) | |
download | bcm5719-ortega-b4668768e1281ad943cc04deca0bd5feabd3b448.tar.gz bcm5719-ortega-b4668768e1281ad943cc04deca0bd5feabd3b448.zip |
Add a simple printf implimentation to the APE firmware.
Diffstat (limited to 'utils')
-rw-r--r-- | utils/CMakeLists.txt | 2 | ||||
-rw-r--r-- | utils/apeconsole/CMakeLists.txt | 12 | ||||
-rw-r--r-- | utils/apeconsole/apeloader/CMakeLists.txt | 66 | ||||
-rw-r--r-- | utils/apeconsole/apeloader/ape.ld | 46 | ||||
-rw-r--r-- | utils/apeconsole/apeloader/main.c | 95 | ||||
-rw-r--r-- | utils/apeconsole/main.cpp | 291 | ||||
-rw-r--r-- | utils/apeconsole/main.cpp2 | 835 |
7 files changed, 1347 insertions, 0 deletions
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 75a8220..12f54c8 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -45,5 +45,7 @@ add_subdirectory(bcmregtool) add_subdirectory(bcmflash) +add_subdirectory(apeconsole) + add_subdirectory(ape2elf) add_subdirectory(elf2ape) diff --git a/utils/apeconsole/CMakeLists.txt b/utils/apeconsole/CMakeLists.txt new file mode 100644 index 0000000..8906bfd --- /dev/null +++ b/utils/apeconsole/CMakeLists.txt @@ -0,0 +1,12 @@ +project(apeconsole) + +add_definitions(-Wall -Werror) +set(SOURCES + main.cpp +) + +simulator_add_executable(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} PRIVATE APE ) +target_link_libraries(${PROJECT_NAME} PRIVATE simulator OptParse elfio) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION .) diff --git a/utils/apeconsole/apeloader/CMakeLists.txt b/utils/apeconsole/apeloader/CMakeLists.txt new file mode 100644 index 0000000..80c8df8 --- /dev/null +++ b/utils/apeconsole/apeloader/CMakeLists.txt @@ -0,0 +1,66 @@ +################################################################################ +### +### @file CMakeLists.txt +### +### @project bcm5719 +### +### @brief First binary stage for the bcm5719 +### +################################################################################ +### +################################################################################ +### +### @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 +################################################################################ + + +project(apeloader) + +# Firmware +set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/ape.ld") +arm_add_executable(${PROJECT_NAME} + main.c + ) +arm_linker_script(${PROJECT_NAME} ${LINKER_SCRIPT}) + +target_link_libraries(${PROJECT_NAME} APE-arm) +target_link_libraries(${PROJECT_NAME} bcm5719-arm) +target_compile_options(${PROJECT_NAME} PRIVATE -nodefaultlibs) + + +# Simulator add_executable +# simulator_add_executable(sim-${PROJECT_NAME} + # init_hw.c + # main.c) + +# target_link_libraries(sim-${PROJECT_NAME} simulator) +# target_link_libraries(sim-${PROJECT_NAME} NVRam MII VPD APE) diff --git a/utils/apeconsole/apeloader/ape.ld b/utils/apeconsole/apeloader/ape.ld new file mode 100644 index 0000000..3b26fae --- /dev/null +++ b/utils/apeconsole/apeloader/ape.ld @@ -0,0 +1,46 @@ +OUTPUT_FORMAT(binary) +ENTRY(__start) + +SECTIONS +{ + .text 0x00100000 : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.init)) + *(.text) + } + + + .data . : ALIGN(4) SUBALIGN(4) + { + *(.data*) + *(.rodata*) + } + + _fbss = .; + .bss . : ALIGN(4) SUBALIGN(4) + { + *(.bss*) + } + _ebss = .; + + + .stack . (NOLOAD) : ALIGN(4) SUBALIGN(4) + { + _fstack = .; + _estack = 00118000; + } + + + /DISCARD/ : + { + *(.comment) + *(.note.GNU-stack) + *(.eh_frame) + *(.got) + *(.ARM.exidx*) + *(.reginfo) + *(.mdebug.abi32) + *(.pdr) + } +} + diff --git a/utils/apeconsole/apeloader/main.c b/utils/apeconsole/apeloader/main.c new file mode 100644 index 0000000..f1e886b --- /dev/null +++ b/utils/apeconsole/apeloader/main.c @@ -0,0 +1,95 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// @file main.c +/// +/// @project +/// +/// @brief Main stage1 code +/// +//////////////////////////////////////////////////////////////////////////////// +/// +//////////////////////////////////////////////////////////////////////////////// +/// +/// @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_SHM.h> + +int __start() +{ + // Update SHM.Sig to signal ready. + SHM.SegSig.bits.Sig = SHM_SEG_SIG_SIG_LOADER; + SHM.FwStatus.bits.Ready = 1; + + for (;;) + { + uint32_t command = SHM.LoaderCommand.bits.Command; + if (!command) + { + continue; + } + + uint32_t arg0 = SHM.LoaderArg0.r32; + uint32_t arg1 = SHM.LoaderArg1.r32; + + switch (command) + { + default: + break; + + case SHM_LOADER_COMMAND_COMMAND_READ_MEM: + { + // Read word address specified in arg0 + uint32_t *addr = ((void *)arg0); + SHM.LoaderArg0.r32 = *addr; + break; + } + case SHM_LOADER_COMMAND_COMMAND_WRITE_MEM: + { + // Write word address specified in arg0 with arg1 + uint32_t *addr = ((void *)arg0); + *addr = arg1; + break; + } + case SHM_LOADER_COMMAND_COMMAND_CALL: + { + // call address specified in arg0. + void (*function)(uint32_t) = ((void *)arg0); + function(arg1); + break; + } + } + + // Mark command as handled. + SHM.LoaderCommand.bits.Command = 0; + } +}
\ No newline at end of file diff --git a/utils/apeconsole/main.cpp b/utils/apeconsole/main.cpp new file mode 100644 index 0000000..425c550 --- /dev/null +++ b/utils/apeconsole/main.cpp @@ -0,0 +1,291 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// @file main.cpp +/// +/// @project +/// +/// @brief Main bcm regiuster tool for decoding BCM5179 registers. +/// +//////////////////////////////////////////////////////////////////////////////// +/// +//////////////////////////////////////////////////////////////////////////////// +/// +/// @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 "HAL.hpp" + +#include <endian.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <OptionParser.h> +#include <vector> +#include <string> +#include <iostream> +#include <APE.h> +#include <bcm5719_SHM.h> +#include <elfio/elfio.hpp> + +#include <types.h> +#include <APE_APE_PERI.h> +#include <APE_NVIC.h> + +#include "../NVRam/bcm5719_NVM.h" + +using namespace std; +using namespace ELFIO; +using optparse::OptionParser; + +#ifdef __ppc64__ +#define BARRIER() do { asm volatile ("sync 0\neieio\n" ::: "memory"); } while(0) +#else +#define BARRIER() do { asm volatile ("" ::: "memory"); } while(0) +#endif + +int main(int argc, char const *argv[]) +{ + OptionParser parser = OptionParser().description("BCM Register Utility"); + + parser.add_option("-f", "--function") + .dest("function") + .type("int") + .set_default("0") + .metavar("FUNCTION") + .help("Read registers from the specified pci function."); + + optparse::Values options = parser.parse_args(argc, argv); + vector<string> args = parser.args(); + + + if(!initHAL(NULL, 1)) + { + cerr << "Unable to locate pci device with function 1 for the debug console." << endl; + exit(-1); + } + + + if(options.get("ape")) + { + APE.Mode.print(); + APE.Status.print(); + APE.Gpio.print(); + SHM.FwStatus.print(); + SHM.FwFeatures.print(); + SHM.FwVersion.print(); + + printf("APE SegSig: 0x%08X\n", (uint32_t)SHM.SegSig.r32); + printf("APE SegLen: 0x%08X\n", (uint32_t)SHM.ApeSegLength.r32); + printf("APE RcpuApeResetCount: 0x%08X\n", (uint32_t)SHM.RcpuApeResetCount.r32); + + printf("APE RCPU SegSig: 0x%08X\n", (uint32_t)SHM.RcpuSegSig.r32); + printf("APE RCPU SegLen: 0x%08X\n", (uint32_t)SHM.RcpuSegLength.r32); + printf("APE RCPU Init Count: 0x%08X\n", (uint32_t)SHM.RcpuInitCount.r32); + printf("APE RCPU FW Version: 0x%08X\n", (uint32_t)SHM.RcpuFwVersion.r32); + + printf("APE RCPU CfgFeature: 0x%08X\n", (uint32_t)SHM.RcpuCfgFeature.r32); + 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); + + APE_PERI.RmuControl.print(); + APE_PERI.ArbControl.print(); + + // APE.Mode.print(); + // APE.Status.print(); + // APE.GpioMessage.print(); + // APE.Event.print(); + // APE.RxbufoffsetFunc0.print(); + // APE.RxbufoffsetFunc1.print(); + // APE.TxToNetDoorbellFunc0.print(); + // APE.TxState0.print(); + // APE.Mode2.print(); + // APE.Status2.print(); + // APE.LockGrantObsolete.print(); + // APE.RxPoolModeStatus0.print(); + // APE.RxPoolModeStatus1.print(); + // APE.RxPoolRetire0.print(); + // APE.RxPoolRetire1.print(); + // APE.TxToNetPoolModeStatus0.print(); + // APE.TxToNetBufferAllocator0.print(); + // APE.TxToNetBufferReturn0.print(); + // APE.TxToNetBufferRing0.print(); + // APE.Tick1mhz.print(); + // APE.Tick1khz.print(); + // APE.Tick10hz.print(); + // APE.Gpio.print(); + // APE.Gint.print(); + // APE.OtpControl.print(); + // APE.OtpStatus.print(); + // APE.OtpAddr.print(); + // APE.OtpReadData.print(); + // APE.CpuStatus.print(); + // APE.TxToNetPoolModeStatus1.print(); + // APE.TxToNetBufferAllocator1.print(); + // APE.TxToNetDoorbellFunc1.print(); + // APE.RxbufoffsetFunc2.print(); + // APE.TxToNetDoorbellFunc2.print(); + // APE.RxPoolModeStatus2.print(); + // APE.RxPoolRetire2.print(); + // APE.TxToNetPoolModeStatus2.print(); + // APE.TxToNetBufferAllocator2.print(); + // APE.RxbufoffsetFunc3.print(); + // APE.TxToNetDoorbellFunc3.print(); + // APE.RxPoolModeStatus3.print(); + // APE.RxPoolRetire3.print(); + // APE.TxToNetPoolModeStatus3.print(); + // APE.TxToNetBufferAllocator3.print(); + + // APE.print(); + + DEVICE.PerfectMatch1High.print(); + DEVICE.PerfectMatch1Low.print(); + + printf("\n======= Port 0 =======\n"); + APE.TxToNetPoolModeStatus0.print(); + APE.RxPoolModeStatus0.print(); + + printf("APE SegSig: 0x%08X\n", (uint32_t)SHM.SegSig.r32); + printf("APE SegLen: 0x%08X\n", (uint32_t)SHM.ApeSegLength.r32); + + exit(0); + } + + + if(options.get("info")) + { + DEVICE.ChipId.print(); + DEVICE.PciVendorDeviceId.print(); + DEVICE.PciSubsystemId.print(); + DEVICE.PciClassCodeRevision.print(); + DEVICE.Status.print(); + + + // GenCfgFeature + // GenCfgHw + // GenCfgShared + // GenCfgHw2 + // GenCfg5 + + printf("\n"); + + uint64_t serial = (((uint64_t)(DEVICE.PciSerialNumberHigh.r32)) << 32) | DEVICE.PciSerialNumberLow.r32; + printf("Serial Number: 0x%016lX\n", serial); + + printf("\n"); + + printf("Power Budget[0]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget0.r32); + printf("Power Budget[1]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget1.r32); + printf("Power Budget[2]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget2.r32); + printf("Power Budget[3]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget3.r32); + printf("Power Budget[4]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget4.r32); + printf("Power Budget[5]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget5.r32); + printf("Power Budget[6]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget6.r32); + printf("Power Budget[7]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget7.r32); + + printf("\n"); + + uint64_t mac0 = (((uint64_t)(DEVICE.EmacMacAddresses0High.r32)) << 32) | DEVICE.EmacMacAddresses0Low.r32; + uint64_t mac1 = (((uint64_t)(DEVICE.EmacMacAddresses1High.r32)) << 32) | DEVICE.EmacMacAddresses1Low.r32; + uint64_t mac2 = (((uint64_t)(DEVICE.EmacMacAddresses2High.r32)) << 32) | DEVICE.EmacMacAddresses2Low.r32; + uint64_t mac3 = (((uint64_t)(DEVICE.EmacMacAddresses3High.r32)) << 32) | DEVICE.EmacMacAddresses3Low.r32; + printf("MAC0: 0x%012lX\n", mac0); + printf("MAC1: 0x%012lX\n", mac1); + printf("MAC2: 0x%012lX\n", mac2); + printf("MAC3: 0x%012lX\n", mac3); + + printf("\n"); + + printf("Reg 6408: 0x%08X\n", (uint32_t)DEVICE._6408.r32); + printf("Reg 64c0: 0x%08X\n", (uint32_t)DEVICE._64c0.r32); + printf("Reg 64c8: 0x%08X\n", (uint32_t)DEVICE._64c8.r32); + printf("Reg 64dc: 0x%08X\n", (uint32_t)DEVICE._64dc.r32); + printf("Reg 6530: 0x%08X\n", (uint32_t)DEVICE._6530.r32); + printf("Reg 6550: 0x%08X\n", (uint32_t)DEVICE._6550.r32); + printf("Reg 65f4: 0x%08X\n", (uint32_t)DEVICE._65f4.r32); + printf("Reg 7c04: 0x%08X\n", (uint32_t)DEVICE._7c04.r32); + + printf("LedControl: 0x%08X\n", (uint32_t)DEVICE.LedControl.r32); + printf("GrcModeControl: 0x%08X\n", (uint32_t)DEVICE.GrcModeControl.r32); + DEVICE.GrcModeControl.bits.NVRAMWriteEnable = 1; + DEVICE.GrcModeControl.print(); + printf("GphyControlStatus: 0x%08X\n", (uint32_t)DEVICE.GphyControlStatus.r32); + printf("TopLevelMiscellaneousControl1: 0x%08X\n", (uint32_t)DEVICE.TopLevelMiscellaneousControl1.r32); + printf("MiscellaneousLocalControl: 0x%08X\n", (uint32_t)DEVICE.MiscellaneousLocalControl.r32); + + DEVICE.RxRiscMode.print(); + DEVICE.RxRiscStatus.print(); + + DEVICE.RxCpuEventEnable.print(); + DEVICE.RxCpuEvent.print(); + exit(0); + } + + uint32_t* DEBUG = (uint32_t*)&gAPEBase[0x4000]; + volatile uint32_t* write_pointer = &DEBUG[0]; + volatile uint32_t* read_pointer = &DEBUG[1]; + uint32_t buffer_size = 0x1000 - 8; + volatile uint32_t* buffer = &DEBUG[2]; + + printf("Write Pointer: %d\n", *write_pointer); + printf("Read Pointer: %d\n", *read_pointer); + + for(int i = 0; i < 16; i++) + printf("DEBUG[i] = %08Xx\n", DEBUG[i]); + + for(;;) + { + BARRIER(); + uint32_t cached_pointer = *read_pointer; + if(cached_pointer != *write_pointer) + { + BARRIER(); + char character = (uint8_t)buffer[cached_pointer]; + // printf("Buffer[%d] = %c\n", cached_pointer, character); + putchar(character); + + if(cached_pointer++ >= buffer_size/4) + { + cached_pointer = 0; + } + *read_pointer = cached_pointer; + } + } + + return 0; +} diff --git a/utils/apeconsole/main.cpp2 b/utils/apeconsole/main.cpp2 new file mode 100644 index 0000000..63c32a3 --- /dev/null +++ b/utils/apeconsole/main.cpp2 @@ -0,0 +1,835 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// @file main.cpp +/// +/// @project +/// +/// @brief Main bcm regiuster tool for decoding BCM5179 registers. +/// +//////////////////////////////////////////////////////////////////////////////// +/// +//////////////////////////////////////////////////////////////////////////////// +/// +/// @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 "HAL.hpp" + +#include <NVRam.h> +#include <MII.h> +#include <bcm5719_eeprom.h> +#include <dirent.h> +#include <endian.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <OptionParser.h> +#include <vector> +#include <string> +#include <iostream> +#include <bcm5719_GEN.h> +#include <APE.h> +#include <bcm5719_SHM.h> +#include <bcm5719_SHM_CHANNEL0.h> +#include <bcm5719_SHM_CHANNEL1.h> +#include <elfio/elfio.hpp> + +#include <types.h> +#include <APE_APE_PERI.h> +#include <APE_NVIC.h> + +#include "../NVRam/bcm5719_NVM.h" + +using namespace std; +using namespace ELFIO; +using optparse::OptionParser; + +elfio gELFIOReader; + +const char* regnames[32] = { + "$zero", /* Zero register - always 0 */ + "$at", /* Assembler register */ + "$v0", "$v1", /* Results */ + "$a0", "$a1", "$a2", "$a3", /* Aguments */ + "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", /* Temp, not saved */ + "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", /* Saved registers */ + "$t8", "$t9", /* Temp, not saved */ + "$k0", "$k1", /* Kernel / OS */ + "$gp", "$sp", "$fp", /* Pointers */ + "$ra", /* return address */ +}; + + +void boot_ape_loader() +{ + extern unsigned char apeloader_bin[]; + extern unsigned int apeloader_bin_len; + + int numWords = apeloader_bin_len/4; + + RegAPEMode_t mode; + mode.r32 = 0; + mode.bits.Halt = 1; + mode.bits.FastBoot = 1; + APE.Mode = mode; + + // We hijack the complete SHM here. + + + // load file. + for(int i = 0; i < numWords; i++) + { + SHM.write(0x0B00 + i*4, ((uint32_t*)apeloader_bin)[i]); + } + + + // Mark fw as not read. + SHM.FwStatus.bits.Ready = 0; + // Start the file + APE.GpioMessage.r32 = 0x60220B00|2; + + mode.bits.Halt = 0; + mode.bits.FastBoot = 1; + mode.bits.Reset = 1; + APE.Mode = mode; + + // Wait for ready. + while(0 == SHM.FwStatus.bits.Ready); +} + +uint32_t loader_read_mem(uint32_t addr) +{ + SHM.LoaderArg0.r32 = addr; + SHM.LoaderCommand.bits.Command = SHM_LOADER_COMMAND_COMMAND_READ_MEM; + + // Wait for command to be handled. + while(0 != SHM.LoaderCommand.bits.Command); + + return (uint32_t)SHM.LoaderArg0.r32; +} + +void loader_write_mem(uint32_t addr, uint32_t value) +{ + SHM.LoaderArg0.r32 = addr; + SHM.LoaderArg1.r32 = value; + SHM.LoaderCommand.bits.Command = SHM_LOADER_COMMAND_COMMAND_WRITE_MEM; + + // Wait for command to be handled. + while(0 != SHM.LoaderCommand.bits.Command); +} + +const string symbol_for_address(uint32_t address, uint32_t &offset) +{ + Elf_Half sec_num = gELFIOReader.sections.size(); + + for ( int i = 0; i < sec_num; ++i ) { + section* psec = gELFIOReader.sections[i]; + // Check section type + if ( psec->get_type() == SHT_SYMTAB ) { + const symbol_section_accessor symbols( gELFIOReader, psec ); + for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j ) { + std::string name; + Elf64_Addr value; + Elf_Xword size; + unsigned char bind; + unsigned char type; + Elf_Half section_index; + unsigned char other; + + // Read symbol properties + symbols.get_symbol( j, name, value, size, bind, + type, section_index, other ); + + + if(value <= address && + value + size > address) + { + offset = address - value; + return name; + } + } + } + } + + return string("unknown"); +} + +void print_context(void) +{ + uint32_t r[32]; + uint32_t pc; + uint32_t opcode; + + // Read out the device context. + pc = DEVICE.RxRiscProgramCounter.r32; + opcode = DEVICE.RxRiscCurrentInstruction.r32; + r[0] = DEVICE.RxRiscRegister0.r32; + r[1] = DEVICE.RxRiscRegister1.r32; + r[2] = DEVICE.RxRiscRegister2.r32; + r[3] = DEVICE.RxRiscRegister3.r32; + r[4] = DEVICE.RxRiscRegister4.r32; + r[5] = DEVICE.RxRiscRegister5.r32; + r[6] = DEVICE.RxRiscRegister6.r32; + r[7] = DEVICE.RxRiscRegister7.r32; + r[8] = DEVICE.RxRiscRegister8.r32; + r[9] = DEVICE.RxRiscRegister9.r32; + r[10] = DEVICE.RxRiscRegister10.r32; + r[11] = DEVICE.RxRiscRegister11.r32; + r[12] = DEVICE.RxRiscRegister12.r32; + r[13] = DEVICE.RxRiscRegister13.r32; + r[14] = DEVICE.RxRiscRegister14.r32; + r[15] = DEVICE.RxRiscRegister15.r32; + r[16] = DEVICE.RxRiscRegister16.r32; + r[17] = DEVICE.RxRiscRegister17.r32; + r[18] = DEVICE.RxRiscRegister18.r32; + r[19] = DEVICE.RxRiscRegister19.r32; + r[20] = DEVICE.RxRiscRegister20.r32; + r[21] = DEVICE.RxRiscRegister21.r32; + r[22] = DEVICE.RxRiscRegister22.r32; + r[23] = DEVICE.RxRiscRegister23.r32; + r[24] = DEVICE.RxRiscRegister24.r32; + r[25] = DEVICE.RxRiscRegister25.r32; + r[26] = DEVICE.RxRiscRegister26.r32; + r[27] = DEVICE.RxRiscRegister27.r32; + r[28] = DEVICE.RxRiscRegister28.r32; + r[29] = DEVICE.RxRiscRegister29.r32; + r[30] = DEVICE.RxRiscRegister30.r32; + r[31] = DEVICE.RxRiscRegister31.r32; + + printf("==== Context ===\n"); + uint32_t sym_offset = 0; + string symbol = symbol_for_address(pc, sym_offset); + printf(" pc: 0x%08X (%s+%d) opcode: 0x%08X \n", pc, symbol.c_str(), sym_offset, opcode); + int numCols = 4; + int offset = 32 / numCols; + for(int i = 0; i < ARRAY_ELEMENTS(r)/4; i++) + { + for(int j = 0; j < numCols; j++) + { + printf("$%d(%5s): 0x%08X ", i + j*offset, regnames[i + j*offset], r[i + j*offset]); + } + printf("\n"); + } +} + +void writeMemory(uint32_t rxAddr, uint32_t value) +{ + cout << "Updating " << std::hex << rxAddr << " to " << std::hex << value << endl; + // Halt. + RegDEVICERxRiscMode_t mode; + mode.r32 = 0; + mode.bits.Halt = 1; + DEVICE.RxRiscMode = mode; + + DEVICE.RxRiscMode.print(); + + // Save old state that we will clobber so we can restore it afterwards. + uint32_t oldIP = DEVICE.RxRiscProgramCounter.r32; + uint32_t oldT6 = DEVICE.RxRiscRegister14.r32; + uint32_t oldT7 = DEVICE.RxRiscRegister15.r32; + + // Check that the instructions we are expecting to use are correct. This will + // break if the ROM is different. + DEVICE.RxRiscProgramCounter.r32 = 0x40000038; + + + cout << "PC is now " << (uint32_t)DEVICE.RxRiscProgramCounter.r32 << endl; + uint32_t iw = DEVICE.RxRiscCurrentInstruction.r32; + if (iw != 0xADCF0000) + { // sw $t7, 0($t6) + fprintf(stderr, "cannot set RX word via forced store because the device has an unknown ROM (got 0x%08X)\n", iw); + return; + } + + DEVICE.RxRiscRegister14.r32 = rxAddr; + DEVICE.RxRiscRegister15.r32 = value; + + mode.bits.SingleStep = 1; + DEVICE.RxRiscMode = mode; + + // Don't remove this, it creates a small delay which seems to sometimes be + // necessary. + uint32_t pc = DEVICE.RxRiscProgramCounter.r32; + if (pc != 0x4000003C) + { + fprintf(stderr, " bad2 0x%08x\n", pc); + } + + // Restore. + DEVICE.RxRiscRegister15.r32 = oldT7; + DEVICE.RxRiscRegister14.r32 = oldT6; + DEVICE.RxRiscProgramCounter.r32 = oldIP; + + mode.bits.SingleStep = 0; + DEVICE.RxRiscMode = mode; +} + +void step(void) +{ + uint32_t oldPC = DEVICE.RxRiscProgramCounter.r32; + + RegDEVICERxRiscMode_t mode; + mode.r32 = 0; + mode.bits.SingleStep = 1; + mode.bits.Halt = 1; + DEVICE.RxRiscMode = mode; + + // Force a re-load of the next word. + uint32_t newPC = DEVICE.RxRiscProgramCounter.r32; + + if(oldPC + 4 != newPC) + { + // branched. Re-read PC to re-read opcode + DEVICE.RxRiscProgramCounter.r32 = DEVICE.RxRiscProgramCounter.r32; + } +} + +int main(int argc, char const *argv[]) +{ + OptionParser parser = OptionParser().description("BCM Register Utility"); + + parser.add_option("--elf") + .dest("debugfile") + .metavar("DEBUG_FILE") + .help("Elf file used for improved context decoding."); + + parser.add_option("-f", "--function") + .dest("function") + .type("int") + .set_default("0") + .metavar("FUNCTION") + .help("Read registers from the specified pci function."); + + parser.add_option("-s", "--step") + .dest("step") + .set_default("0") + .action("store_true") + .help("Single step the CPU."); + + parser.add_option("-t", "--stepto") + .dest("stepto") + .metavar("ADDR") + .help("Single step the CPU."); + + parser.add_option("--halt") + .dest("halt") + .set_default("0") + .action("store_true") + .help("Halt the CPU."); + + parser.add_option("-pc", "--pc") + .dest("pc") + .help("Force the PC to the specified value."); + + parser.add_option("-c", "--context") + .dest("context") + .set_default("0") + .action("store_true") + .help("Print the current CPU context."); + + parser.add_option("-g", "--run") + .dest("run") + .set_default("0") + .action("store_true") + .help("Continue CPU execution."); + + parser.add_option("-i", "--info") + .dest("info") + .set_default("0") + .action("store_true") + .help("Print device information registers."); + + parser.add_option("-a", "--ape") + .dest("ape") + .set_default("0") + .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("-n", "--network") + .dest("network") + .set_default("0") + .action("store_true") + .help("Print network information / status."); + + parser.add_option("-apereset", "--apereset") + .dest("apereset") + .set_default("0") + .action("store_true") + .help("File to boot on the APE."); + + parser.add_option("-reset", "--reset") + .dest("reset") + .set_default("0") + .action("store_true") + .help("File to boot on the APE."); + + parser.add_option("-m", "--mii") + .dest("mii") + .set_default("0") + .action("store_true") + .help("Print MII information registers."); + + + optparse::Values options = parser.parse_args(argc, argv); + vector<string> args = parser.args(); + + + if(!initHAL(NULL, options.get("function"))) + { + cerr << "Unable to locate pci device with function " << (int)options.get("function") << endl; + exit(-1); + } + + if(options.is_set("debugfile")) + { + if(!gELFIOReader.load(options["debugfile"])) + { + cerr << "Unablt to read elf file " << options["debugfile"] << endl; + exit(-1); + } + } + + if(options.get("step")) + { + do { + cout << "Stepping...\n"; + step(); + print_context(); + + } while(DEVICE.RxRiscProgramCounter.r32 > 0x40000000); + exit(0); + } + + if(options.is_set("stepto")) + { + uint32_t addr = stoi(options["stepto"], nullptr, 0); + do { + cout << "Stepping...\n"; + + step(); + print_context(); + + } while(DEVICE.RxRiscProgramCounter.r32 != addr); + exit(0); + + } + + + + if(options.get("halt")) + { + cout << "Halting...\n"; + RegDEVICERxRiscMode_t mode; + mode.r32 = 0; + mode.bits.Halt = 1; + DEVICE.RxRiscMode = mode; + + print_context(); + exit(0); + } + + if(options.is_set("pc")) + { + uint32_t pc = stoi(options["pc"], nullptr, 0); + cout << "Updating PC to " << std::hex << pc << endl; + RegDEVICERxRiscMode_t mode; + mode.r32 = 0; + mode.bits.Halt = 1; + DEVICE.RxRiscMode = mode; + + DEVICE.RxRiscProgramCounter.r32 = pc; + print_context(); + exit(0); + } + + if(options.get("context")) + { + print_context(); + exit(0); + } + + if(options.get("run")) + { + cout << "Running...\n"; + RegDEVICERxRiscMode_t mode; + mode.r32 = 0; // Ensure single-step and halt are cleared + DEVICE.RxRiscMode = mode; + exit(0); + } + + if(options.get("mii")) + { + uint8_t phy = MII_getPhy(); + + printf("MII Phy: %d\n", phy); + printf("MII Status: 0x%04X\n", MII_readRegister(phy, (mii_reg_t)REG_MII_STATUS)); + printf("MII PHY ID[high]: 0x%04X\n", MII_readRegister(phy, (mii_reg_t)REG_MII_PHY_ID_HIGH)); + printf("MII PHY ID[low]: 0x%04X\n", MII_readRegister(phy, (mii_reg_t)REG_MII_PHY_ID_LOW)); + + RegMIIControl_t control; + control.r16 = MII_readRegister(phy, (mii_reg_t)REG_MII_CONTROL); + control.print(); + + RegMIIAutonegotiationAdvertisement_t auto_neg_advert; + auto_neg_advert.r16 = MII_readRegister(phy, (mii_reg_t)REG_MII_AUTONEGOTIATION_ADVERTISEMENT); + auto_neg_advert.print(); + + RegMII1000baseTControl_t gig_control; + gig_control.r16 = MII_readRegister(phy, (mii_reg_t)REG_MII_1000BASE_T_CONTROL); + gig_control.print(); + + RegMIISpareControl3_t sc3; + sc3.r16 = MII_readRegister(phy, (mii_reg_t)REG_MII_SPARE_CONTROL_3); + sc3.print(); + + exit(0); + } + + if(options.is_set("apeboot")) + { + boot_ape_loader(); + + int fileLength = 0; + int fileWords = 0; + #define NVRAM_SIZE (1024u * 256u) /* 256KB */ + + union { + uint8_t bytes[NVRAM_SIZE]; + uint32_t words[NVRAM_SIZE/4]; + } ape; + + string &file = options["apeboot"]; + + fstream infile; + infile.open(file, fstream::in | fstream::binary); + if(infile.is_open()) + { + // get length of file: + infile.seekg(0, infile.end); + fileLength = infile.tellg(); + fileWords = fileLength / 4; + infile.seekg(0, infile.beg); + + // Read in file + infile.read((char*)ape.bytes, fileLength); + + infile.close(); + } + else + { + cerr << " Unable to open file '" << file << "'" << endl; + exit(-1); + } + + if(ape.words[0] == be32toh(APE_HEADER_MAGIC)) + { + // The file is swapped... fix it. + for(int i = 0; i < sizeof(ape)/sizeof(ape.words[0]); i++) + { + ape.words[i] = be32toh(ape.words[i]); + } + } + + + // load file. + for(int i = 0; i < fileWords; i++) + { + uint32_t addr = 0x10D800 + i*4; + loader_write_mem(addr, ape.words[i]); + } + + + RegAPEMode_t mode; + mode.r32 = 0; + mode.bits.Halt = 1; + mode.bits.FastBoot = 1; + APE.Mode = mode; + + + // 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; + mode.bits.Reset = 1; + APE.Mode = mode; + + 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("reset")) + { + + DEVICE.MiscellaneousConfig.bits.GRCReset = 1; + exit(0); + } + + + + if(options.get("rx")) + { + DEVICE.ReceiveMacMode.print(); + DEVICE.EmacMode.print(); + APE.RxbufoffsetFunc0.print(); + APE.RxPoolModeStatus0.print(); + + exit(0); + } + + if(options.get("tx")) + { + DEVICE.GrcModeControl.print(); + DEVICE.EmacMode.print(); + APE.Mode.print(); + APE.Status.print(); + APE.TxState0.print(); + APE.TxToNetPoolModeStatus0.print(); + APE.TxToNetBufferAllocator0.print(); + APE.TxToNetBufferRing0.print(); + APE.TxToNetBufferReturn0.print(); + APE.TxToNetDoorbellFunc0.print(); + if(APE.TxToNetDoorbellFunc0.bits.TXQueueFull) + { + fprintf(stderr, "TX Queue Full\n"); + } + + exit(0); + } + + if(options.get("ape")) + { + APE.Mode.print(); + APE.Status.print(); + APE.Gpio.print(); + SHM.FwStatus.print(); + SHM.FwFeatures.print(); + SHM.FwVersion.print(); + + printf("APE SegSig: 0x%08X\n", (uint32_t)SHM.SegSig.r32); + printf("APE SegLen: 0x%08X\n", (uint32_t)SHM.ApeSegLength.r32); + printf("APE RcpuApeResetCount: 0x%08X\n", (uint32_t)SHM.RcpuApeResetCount.r32); + + printf("APE RCPU SegSig: 0x%08X\n", (uint32_t)SHM.RcpuSegSig.r32); + printf("APE RCPU SegLen: 0x%08X\n", (uint32_t)SHM.RcpuSegLength.r32); + printf("APE RCPU Init Count: 0x%08X\n", (uint32_t)SHM.RcpuInitCount.r32); + printf("APE RCPU FW Version: 0x%08X\n", (uint32_t)SHM.RcpuFwVersion.r32); + + printf("APE RCPU CfgFeature: 0x%08X\n", (uint32_t)SHM.RcpuCfgFeature.r32); + 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); + + APE_PERI.RmuControl.print(); + + DEVICE.PerfectMatch1High.print(); + DEVICE.PerfectMatch1Low.print(); + + printf("\n======= Port 0 =======\n"); + APE.TxToNetPoolModeStatus0.print(); + APE.RxPoolModeStatus0.print(); + + SHM_CHANNEL0.NcsiChannelStatus.print(); + + printf("\n======= Port 1 =======\n"); + APE.TxToNetPoolModeStatus1.print(); + APE.RxPoolModeStatus1.print(); + + SHM_CHANNEL1.NcsiChannelStatus.print(); + + exit(0); + } + + if(options.get("network")) + { + // If Sgmii + DEVICE.SgmiiStatus.print(); + + // If not + RegMIIStatus_t stat; + RegMIIIeeeExtendedStatus_t ext_stat; + ext_stat.r16 = 0; + + uint8_t phy = MII_getPhy(); + APE_aquireLock(); + uint16_t status_value = MII_readRegister(phy, (mii_reg_t)REG_MII_STATUS); + stat.r16 = status_value; + if(stat.bits.ExtendedStatusSupported) + { + uint16_t ext_status_value = MII_readRegister(phy, (mii_reg_t)REG_MII_IEEE_EXTENDED_STATUS); + ext_stat.r16 = ext_status_value; + } + + APE_releaseLock(); + + stat.r16 = status_value; + stat.print(); + ext_stat.print(); + + exit(0); + } + + + if(options.get("info")) + { + GEN.GenDataSig.print(); + GEN.GenFwMbox.print(); + GEN.GenAsfStatusMbox.print(); + GEN.GenFwVersion.print(); + DEVICE.ChipId.print(); + DEVICE.PciVendorDeviceId.print(); + DEVICE.PciSubsystemId.print(); + DEVICE.PciClassCodeRevision.print(); + DEVICE.Status.print(); + + + // GenCfgFeature + // GenCfgHw + // GenCfgShared + // GenCfgHw2 + // GenCfg5 + + printf("\n"); + + uint64_t serial = (((uint64_t)(DEVICE.PciSerialNumberHigh.r32)) << 32) | DEVICE.PciSerialNumberLow.r32; + printf("Serial Number: 0x%016lX\n", serial); + + uint64_t genmac = (((uint64_t)(GEN.GenMacAddrHighMbox.r32)) << 32) | GEN.GenMacAddrLowMbox.r32; + printf("GEN Mac Addr: 0x%016lX\n", genmac); + + printf("\n"); + + printf("Power Budget[0]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget0.r32); + printf("Power Budget[1]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget1.r32); + printf("Power Budget[2]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget2.r32); + printf("Power Budget[3]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget3.r32); + printf("Power Budget[4]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget4.r32); + printf("Power Budget[5]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget5.r32); + printf("Power Budget[6]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget6.r32); + printf("Power Budget[7]: 0x%08X\n", (uint32_t)DEVICE.PciPowerBudget7.r32); + + printf("\n"); + + uint64_t mac0 = (((uint64_t)(DEVICE.EmacMacAddresses0High.r32)) << 32) | DEVICE.EmacMacAddresses0Low.r32; + uint64_t mac1 = (((uint64_t)(DEVICE.EmacMacAddresses1High.r32)) << 32) | DEVICE.EmacMacAddresses1Low.r32; + uint64_t mac2 = (((uint64_t)(DEVICE.EmacMacAddresses2High.r32)) << 32) | DEVICE.EmacMacAddresses2Low.r32; + uint64_t mac3 = (((uint64_t)(DEVICE.EmacMacAddresses3High.r32)) << 32) | DEVICE.EmacMacAddresses3Low.r32; + printf("MAC0: 0x%012lX\n", mac0); + printf("MAC1: 0x%012lX\n", mac1); + printf("MAC2: 0x%012lX\n", mac2); + printf("MAC3: 0x%012lX\n", mac3); + + printf("\n"); + + printf("Reg 6408: 0x%08X\n", (uint32_t)DEVICE._6408.r32); + printf("Reg 64c0: 0x%08X\n", (uint32_t)DEVICE._64c0.r32); + printf("Reg 64c8: 0x%08X\n", (uint32_t)DEVICE._64c8.r32); + printf("Reg 64dc: 0x%08X\n", (uint32_t)DEVICE._64dc.r32); + printf("Reg 6530: 0x%08X\n", (uint32_t)DEVICE._6530.r32); + printf("Reg 6550: 0x%08X\n", (uint32_t)DEVICE._6550.r32); + printf("Reg 65f4: 0x%08X\n", (uint32_t)DEVICE._65f4.r32); + printf("Reg 7c04: 0x%08X\n", (uint32_t)DEVICE._7c04.r32); + + printf("LedControl: 0x%08X\n", (uint32_t)DEVICE.LedControl.r32); + printf("GrcModeControl: 0x%08X\n", (uint32_t)DEVICE.GrcModeControl.r32); + DEVICE.GrcModeControl.bits.NVRAMWriteEnable = 1; + DEVICE.GrcModeControl.print(); + printf("GphyControlStatus: 0x%08X\n", (uint32_t)DEVICE.GphyControlStatus.r32); + printf("TopLevelMiscellaneousControl1: 0x%08X\n", (uint32_t)DEVICE.TopLevelMiscellaneousControl1.r32); + printf("MiscellaneousLocalControl: 0x%08X\n", (uint32_t)DEVICE.MiscellaneousLocalControl.r32); + + DEVICE.RxRiscMode.print(); + DEVICE.RxRiscStatus.print(); + + DEVICE.RxCpuEventEnable.print(); + DEVICE.RxCpuEvent.print(); + exit(0); + } + + + printf("APEChipId: %x\n", (uint32_t)SHM.ChipId.r32); + + printf("EmacMode.PortMode: %0x\n", (uint32_t)DEVICE.EmacMode.bits.PortMode); + printf("RxRiscMode: %0x\n", (uint32_t)DEVICE.RxRiscMode.r32); + + // printf("HostDriverId: %0x\n", APE.HostDriverId.r32); + // printf("RcpuPciSubsystemId: %0x\n", APE.RcpuPciSubsystemId.r32); + + print_context(); + + return 0; +} |