diff --git a/README.md b/README.md index 67de363..59ae540 100644 --- a/README.md +++ b/README.md @@ -188,4 +188,89 @@ devices, set 8N1 @ 115200 baud and power up the switch. The device will perform some examples and provide a minimal console, the documentation of which can be found in the source code rtlplayground.c`. +## The command line +The command line is very rudimentary and mostly for testing purposes. +The following is a boot-log with some examples: +``` +Detecting CPU +RTL8373 detected +Starting up... + Flash controller + +NIC reset +rtl8372_init called + +RTL837X_REG_SDS_MODES: 0x00000bed + +phy_config_8224 called + +phy_config_8224 done + +rtl8224_phy_enable called + +rtl8224_phy_enable done +X +rtl8372_init done + +A minimal prompt to explore the RTL8372: + +CPU detected: RTL8373 +Clock register: 0x00001101 +Register 0x7b20/RTL837X_REG_SDS_MODES: 0x00000bed +Verifying PHY settings: + + Port State Link TxGood TxBad RxGood RxBad +1 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +2 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +3 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +4 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +5 On 2.5G 0x00000008 0x00000000 0x00000000 0x00000000 +6 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +7 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +8 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +9 NO SFP Down 0x00000000 0x00000000 0x00000000 0x00000000 + +> port 5 1g + CMD: port 5 1g +PORT 04 1G + +> stat + CMD: stat + Port State Link TxGood TxBad RxGood RxBad +1 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +2 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +3 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +4 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +5 On 1000M 0x00000035 0x00000000 0x00000017 0x00000000 +6 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +7 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +8 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +9 NO SFP Down 0x00000000 0x00000000 0x00000000 0x00000000 + +> + + + Rate: 67 Encoding: 01 +Lightron Inc. WSPXG-ES3LC-IHA 0000 + + +> stat + CMD: stat + Port State Link TxGood TxBad RxGood RxBad +1 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +2 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +3 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +4 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +5 On 1000M 0x00000065 0x00000000 0x0000003b 0x00000000 +6 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +7 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +8 On Down 0x00000000 0x00000000 0x00000000 0x00000000 +9 SFP OK 10G 0x00000000 0x00000000 0x0000001c 0x00000000 + +> sfp + CMD: sfp +Rate: 67 Encoding: 01 +Lightron Inc. WSPXG-ES3LC-IHA 0000 + +``` Enjoy playing! diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 63cdf35..12f92eb 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -4,10 +4,13 @@ * This code is in the Public Domain */ +// #define REGDBG + #include #include "rtl837x_common.h" #include "rtl837x_sfr.h" #include "rtl837x_regs.h" +#include "rtl837x_phy.h" #pragma codeseg BANK1 @@ -37,7 +40,7 @@ P000001.1e000400:c45c P000001.1e0003f8:c18c p001e.03f8:418c */ -__code uint16_t rtl8224_ca[41] = { +__code uint16_t rtl8224_ca[42] = { 0x4480, 0xc842, 0x0400, 0xc9c2, 0x6d02, 0xcc42, @@ -306,3 +309,51 @@ void phy_config_8224(void) __banked print_string("\r\nphy_config_8224 done\r\n"); } + + +/* + * Set Speed, duplex and flow control mode of a PHY + * See e.g. RTL8221B datasheet + */ +void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t duplex) __banked +{ + uint16_t v; + phy_read(port, 0x1f, 0xa610); + v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0; + if (speed == PHY_OFF) { + phy_write(bit_mask[port], 0x1f, 0xa4610, v | 0x0800); + return; + } + // Port is on, make sure of it: + if (v & 0x0800) + phy_write(bit_mask[port], 0x1f, 0xa4610, v & 0xf7ff); + + if (speed == PHY_SPEED_AUTO) { + // AN Advertisement Register (MMD 7.0x0010) + phy_write(bit_mask[port], 0x07, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used + // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) + phy_write(bit_mask[port], 0x07, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed + phy_write(bit_mask[port], 0x07, 0x00, 0x3200); // Restart AN + } else { + // AN Control Register (MMD 7.0x0000) + phy_write(bit_mask[port], 0x07, 0x00, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) + // AN Advertisement Register (MMD 7.0x0010) + phy_write(bit_mask[port], 0x07, 0x10, 0x1001); // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used + if (speed == PHY_SPEED_1G) { + // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) + phy_write(bit_mask[port], 0x07, 0x20, 0x6001); // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed + // GBCR (1000Base-T Control Register, MMD 31.0xA412) + phy_read(port, 0x1f, 0xa412); + v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0; + phy_write(bit_mask[port], 0x1f, 0xa412, v | 0x0200); + } else if (speed == PHY_SPEED_2G5) { + // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) + phy_write(bit_mask[port], 0x07, 0x20, 0x6081); // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed + // GBCR (1000Base-T Control Register, MMD 31.0xA412) + phy_read(port, 0x1f, 0xa412); + v = (((uint16_t)SFR_DATA_8) << 8) | SFR_DATA_0; + phy_write(bit_mask[port], 0x1f, 0xa412, v & 0xfdff); + } + phy_write(bit_mask[port], 0x07, 0x00, 0x3200); // Enable AN + } +} diff --git a/rtl837x_phy.h b/rtl837x_phy.h index 58e9875..9a471c2 100644 --- a/rtl837x_phy.h +++ b/rtl837x_phy.h @@ -1,8 +1,14 @@ #ifndef _RTL837X_PHY_H_ #define _RTL837X_PHY_H_ +#define PHY_SPEED_AUTO 0x1 +#define PHY_SPEED_1G 0x2 +#define PHY_SPEED_2G5 0x3 +#define PHY_OFF 0xff + void rtl8224_phy_enable(void) __banked; void phy_config(uint8_t phy) __banked; void phy_config_8224(void) __banked; +void phy_set_mode(uint8_t port, uint8_t speed, uint8_t flow_control, uint8_t duplex) __banked; #endif diff --git a/rtlplayground.c b/rtlplayground.c index c72eb32..5727a98 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1492,11 +1492,6 @@ void setup_serial(void) } -__code struct command commands[N_COMMANDS] = { - { "reset", 1 }, -}; - - uint8_t cmd_compare(uint8_t start, uint8_t * __code cmd) { signed char i; @@ -1569,6 +1564,7 @@ void bootloader(void) rtl8224_enable(); // Power on the RTL8224 } +#ifdef DEBUG // Reset seconds counter print_string("\r\nTIMER-TEST: \r\n"); REG_SET(RTL837X_REG_SEC_COUNTER, 0x0); @@ -1582,27 +1578,19 @@ void bootloader(void) print_reg(RTL837X_REG_SEC_COUNTER); REG_SET(RTL837X_REG_SEC_COUNTER, 0x3); write_char(' '); print_reg(RTL837X_REG_SEC_COUNTER); +#endif print_string("\r\nStarting up...\r\n"); print_string(" Flash controller\r\n"); flash_init(0); - // The following will only show something else then 0xff if it was programmed for a managed switch - print_string("\r\n Testing read Securty Register 1\r\n"); - flash_read_security(0x0001000, 40); - print_string("\r\n Testing read Securty Register 2\r\n"); - flash_read_security(0x0002000, 40); - print_string("\r\n Testing read Securty Register 3\r\n"); - flash_read_security(0x0003000, 40); - print_string("\r\n"); - - // r0024:00000f80 R0024-00000f84 r0024:00000f80 // Reset NIC reg_bit_set(0x24, 2); do { reg_read(0x24); } while (SFR_DATA_0 & 0x4); print_string("\r\nNIC reset"); + rtl8372_init(); REG_SET(0x7f94, 0x0); // BUG: Only for testing, otherwise: clear bits 0-3 nic_setup(); @@ -1659,12 +1647,13 @@ void bootloader(void) // Identify command signed char i = cmd_words_b[0]; if (i >= 0 && cmd_words_b[1] >= 0) { - // print_string("\r\n THERE may be a command: "); - // print_short(i); print_string("\r\n"); - // print_short(cmd_words_b[0]); print_string("\r\n"); - // print_short(cmd_words_b[1]); print_string("\r\n"); - // print_short(cmd_words_b[2]); print_string("\r\n"); - // print_short(cmd_words_b[3]); print_string("\r\n"); +/* print_string("\r\n THERE may be a command: "); + print_short(i); print_string("\r\n"); + print_short(cmd_words_b[0]); print_string("\r\n"); + print_short(cmd_words_b[1]); print_string("\r\n"); + print_short(cmd_words_b[2]); print_string("\r\n"); + print_short(cmd_words_b[3]); print_string("\r\n"); +*/ if (cmd_compare(0, "reset")) { print_string("\r\nRESET\n\n"); reset_chip(); @@ -1683,6 +1672,13 @@ void bootloader(void) if (cmd_compare(0, "stat")) { port_stats_print(); } + if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'r') { + print_string("\r\nPRINT SECURITY REGISTERS\r\n"); + // The following will only show something else then 0xff if it was programmed for a managed switch + flash_read_security(0x0001000, 40); + flash_read_security(0x0002000, 40); + flash_read_security(0x0003000, 40); + } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'd') { print_string("\r\nDUMPING FLASH\r\n"); flash_dump(0, 255); @@ -1712,6 +1708,27 @@ void bootloader(void) flash_buf[i] = greeting[i]; flash_write_bytes(0x20000, flash_buf, 20); } + if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { + print_string("\r\nPORT "); + uint8_t p = sbuf[cmd_words_b[1]] - '1'; + print_byte(p); + if (cmd_words_b[2] > 0 && cmd_compare(2, "2g5")) { + print_string(" 2.5G\r\n"); + phy_set_mode(p, PHY_SPEED_2G5, 0, 0); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "1g")) { + print_string(" 1G\r\n"); + phy_set_mode(p, PHY_SPEED_1G, 0, 0); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "auto")) { + print_string(" AUTO\r\n"); + phy_set_mode(p, PHY_SPEED_AUTO, 0, 0); + } + if (cmd_words_b[2] > 0 && cmd_compare(2, "off")) { + print_string(" OFF\r\n"); + phy_set_mode(p, PHY_OFF, 0, 0); + } + } } print_string("\r\n> "); }