mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Merge branch 'main' into syslog
This commit is contained in:
+93
-261
@@ -15,6 +15,7 @@
|
||||
#include "rtl837x_igmp.h"
|
||||
#include "rtl837x_leds.h"
|
||||
#include "rtl837x_bandwidth.h"
|
||||
#include "rtl837x_init.h"
|
||||
#include "dhcp.h"
|
||||
#include "cmd_parser.h"
|
||||
#include "cmd_editor.h"
|
||||
@@ -141,8 +142,49 @@ __xdata bool button_last;
|
||||
__xdata uint8_t button_sec_counter_last;
|
||||
volatile __bit tx_buf_empty;
|
||||
|
||||
struct eth_in {
|
||||
struct uip_eth_addr dst;
|
||||
struct uip_eth_addr src;
|
||||
struct rtl_tag rtl_tag;
|
||||
struct vlan_tag vlan_tag;
|
||||
u16_t ether_type;
|
||||
};
|
||||
|
||||
// Dot 1Q tag size is the size of tpid + tci
|
||||
#define DOT_1Q_TAG_SIZE 4
|
||||
|
||||
struct q_frame {
|
||||
uint8_t tx_seq;
|
||||
uint8_t chksum_flags; // 0x7 enables Checksums for frame header, L2 and L3
|
||||
uint8_t reserved_1 [2];
|
||||
uint16_t len; // Length is Little Endian
|
||||
uint8_t reserved_2 [2];
|
||||
struct uip_eth_addr dst;
|
||||
struct uip_eth_addr src;
|
||||
uint16_t tpid;
|
||||
uint16_t tci;
|
||||
};
|
||||
|
||||
struct nonq_frame {
|
||||
uint8_t padding[DOT_1Q_TAG_SIZE];
|
||||
uint8_t tx_seq;
|
||||
uint8_t chksum_flags; // 0x7 enables Checksums for frame header, L2 and L3
|
||||
uint8_t reserved_1 [2];
|
||||
uint16_t len; // Length is Little Endian
|
||||
uint8_t reserved_2 [2];
|
||||
struct uip_eth_addr dst;
|
||||
struct uip_eth_addr src;
|
||||
};
|
||||
|
||||
#define ETH_IN ((__xdata struct eth_in *)&uip_buf[0])
|
||||
#define ETHERTYPE_OFFSET (12 + VLAN_TAG_SIZE + RTL_TAG_SIZE)
|
||||
|
||||
// The output frame structure with initial frame descriptor including padding
|
||||
#define FRAME ((__xdata struct nonq_frame *)&uip_buf[0])
|
||||
|
||||
// The output frame structure with 802.1Q field and the padding moved before the buffer-start
|
||||
#define FRAME_Q ((__xdata struct q_frame *)&uip_buf[0])
|
||||
|
||||
void isr_timer0(void) __interrupt(1)
|
||||
{
|
||||
}
|
||||
@@ -581,15 +623,38 @@ void nic_rx_packet(register uint16_t buffer, register uint16_t ring_ptr)
|
||||
*/
|
||||
void nic_tx_packet(uint16_t ring_ptr)
|
||||
{
|
||||
// uint16_t buffer = (uint16_t) tx_buf;
|
||||
uint16_t buffer = (uint16_t) uip_buf + VLAN_TAG_SIZE;
|
||||
SFR_NIC_DATA_U16LE = buffer;
|
||||
|
||||
uint16_t len;
|
||||
|
||||
/* If we have a management VLAN, we have inserted a dot1Q-tag into the frame and
|
||||
* the frame starts at the beginning of uip_buf with the RTL TX descriptor,
|
||||
* otherwise the frame is a normal Ethernet frame which starts with
|
||||
* an RTL TX descriptor being padded at the beginning, in the second case
|
||||
* we need to skip the padding for the sending of the frame.
|
||||
*/
|
||||
if (management_vlan) {
|
||||
SFR_NIC_DATA_U16LE = (uint16_t) uip_buf;
|
||||
len = FRAME_Q->len;
|
||||
/*
|
||||
(__xdata struct rtl_dot1q_frame *)uip_buf
|
||||
#define FRAME (((__xdata struct rtl_dot1q_frame *)&uip_buf[0]).nonq_frame)*/
|
||||
} else {
|
||||
SFR_NIC_DATA_U16LE = (uint16_t) uip_buf + VLAN_TAG_SIZE;
|
||||
len = FRAME->len;
|
||||
}
|
||||
|
||||
#ifdef RXTXDBG
|
||||
print_string("TX: \n");
|
||||
for (uint8_t i = 0; i < 100; i++) {
|
||||
print_byte(uip_buf[i]);
|
||||
write_char(' ');
|
||||
}
|
||||
write_char('\n');
|
||||
#endif
|
||||
|
||||
ring_ptr <<= 3;
|
||||
ring_ptr |= 0x8000;
|
||||
SFR_NIC_RING_U16LE = ring_ptr;
|
||||
|
||||
uint16_t len = (((uint16_t)uip_buf[VLAN_TAG_SIZE + 5]) << 8) | uip_buf[VLAN_TAG_SIZE + 4];
|
||||
|
||||
len += 0xf;
|
||||
len >>= 3;
|
||||
SFR_NIC_CTRL = len;
|
||||
@@ -947,26 +1012,27 @@ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg)
|
||||
void tcpip_output(void)
|
||||
{
|
||||
// Add TX-TAG
|
||||
uip_buf[VLAN_TAG_SIZE] = tx_seq++;
|
||||
uip_buf[VLAN_TAG_SIZE + 1] = 0x07; // Enable all checksums
|
||||
uip_buf[VLAN_TAG_SIZE + 5] = uip_len >> 8;
|
||||
uip_buf[VLAN_TAG_SIZE + 4] = uip_len;
|
||||
uip_buf[VLAN_TAG_SIZE + 2] = uip_buf[VLAN_TAG_SIZE + 3] = 0;
|
||||
uip_buf[VLAN_TAG_SIZE + 6] = uip_buf[VLAN_TAG_SIZE + 7] = 0;
|
||||
FRAME->tx_seq = tx_seq++;
|
||||
FRAME->chksum_flags = 0x07; // Enable all checksums
|
||||
FRAME->reserved_1[0] = 0x00; FRAME->reserved_1[1] = 0x00;
|
||||
FRAME->len = uip_len;
|
||||
FRAME->reserved_2[0] = 0x00; FRAME->reserved_2[1] = 0x00;
|
||||
|
||||
// For the management VLAN we insert an 802.1Q VLAN tag
|
||||
if (management_vlan) {
|
||||
// Shift the ethernet header before the HW type including the rtl_frame_desc to the beginning of uip_buf
|
||||
// to allow space to insert the dot 1Q tag
|
||||
for (uint8_t i = 0; i < sizeof(struct q_frame) - DOT_1Q_TAG_SIZE; i++)
|
||||
uip_buf[i] = uip_buf[i + DOT_1Q_TAG_SIZE];
|
||||
FRAME_Q->len += DOT_1Q_TAG_SIZE;
|
||||
FRAME_Q->tpid = HTONS(0x8100); // Change ether-type to Dot1Q
|
||||
FRAME_Q->tci = HTONS(management_vlan);
|
||||
}
|
||||
|
||||
reg_read_m(RTL837X_REG_CPU_TX_CURR_PKT);
|
||||
uint16_t ring_ptr = ((uint16_t)sfr_data[2]) << 8;
|
||||
ring_ptr |= sfr_data[3];
|
||||
|
||||
#ifdef RXTXDBG
|
||||
print_string("TX: \n");
|
||||
for (uint8_t i = 0; i < 120; i++) {
|
||||
print_byte(uip_buf[i]);
|
||||
write_char(' ');
|
||||
}
|
||||
write_char('\n');
|
||||
#endif
|
||||
|
||||
// Move data over from xmem buffer to ASIC side using DMA
|
||||
nic_tx_packet(ring_ptr);
|
||||
|
||||
@@ -1010,14 +1076,13 @@ void handle_rx(void)
|
||||
REG_SET(RTL837X_REG_NIC_RXCMD, 1);
|
||||
uip_len = (((uint16_t)rx_headers[5]) << 8) | rx_headers[4];
|
||||
|
||||
// Retrieve VLAN from VLAN-tag
|
||||
rx_packet_vlan = uip_buf[2 * sizeof (struct uip_eth_addr) + RTL_TAG_SIZE + 2] & 0xf;
|
||||
rx_packet_vlan <<= 8;
|
||||
rx_packet_vlan |= uip_buf[2 * sizeof (struct uip_eth_addr) + RTL_TAG_SIZE + 3];
|
||||
rx_packet_vlan = NTOHS(ETH_IN->vlan_tag.vlan) & 0x0fff;
|
||||
|
||||
#ifdef RXTXDBG
|
||||
print_string(" RX-VLAN: "); print_short(rx_packet_vlan); write_char('\n');
|
||||
print_string(" RX dst: "); print_byte(uip_buf[0]); print_byte(uip_buf[1]); print_byte(uip_buf[2]);
|
||||
print_byte(uip_buf[3]); print_byte(uip_buf[4]); print_byte(uip_buf[5]); write_char('\n');
|
||||
print_string(" MGMT-VLAN: "); print_short(management_vlan); write_char('\n');
|
||||
#endif
|
||||
if (stpEnabled && uip_buf[0] == 0x01 && uip_buf[1] == 0x80 && uip_buf[2] == 0xc2 // STP packet?
|
||||
&& uip_buf[3] == 0x00 && uip_buf[4] == 0x00 && uip_buf[5] == 0x00) {
|
||||
@@ -1032,12 +1097,12 @@ void handle_rx(void)
|
||||
if (uip_len) {
|
||||
tcpip_output();
|
||||
}
|
||||
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x06) { // ARP?
|
||||
} else if (ETH_IN->ether_type == HTONS(0x0806)) { // ARP
|
||||
uip_arp_arpin();
|
||||
if (uip_len) {
|
||||
tcpip_output();
|
||||
}
|
||||
} else if (uip_buf[ETHERTYPE_OFFSET] == 0x08 && uip_buf[ETHERTYPE_OFFSET + 1] == 0x00) { // IP?
|
||||
} else if (ETH_IN->ether_type == HTONS(0x0800)) { // IPv4
|
||||
if (!management_vlan || management_vlan == rx_packet_vlan) {
|
||||
uip_arp_ipin(); // Learn MAC addresses in TCP packets
|
||||
uip_input();
|
||||
@@ -1560,78 +1625,6 @@ void nic_setup(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Configure the PHY-Side of the SDS-SDS link between SoC and PHY
|
||||
*/
|
||||
void sds_init(void)
|
||||
{
|
||||
/*
|
||||
p001e.000d:9535 R02f8-00009535 R02f4-0000953a P000001.1e00000d:953a
|
||||
p001e.000d:953a p001e.000d:953a R02f8-0000953a R02f4-00009530 P000001.1e00000d:9530
|
||||
|
||||
RTL8373:
|
||||
p001e.000d:0010 R02f8-00000010 R02f4-0000001a P000001.1e00000d:b7fe
|
||||
p001e.000d:0010 p001e.000d:0010 R02f8-00000010 R02f4-00000010 P000001.1e00000d:b7fe
|
||||
*/
|
||||
phy_read(0, PHY_MMD30, 0xd);
|
||||
uint16_t pval = SFR_DATA_U16;
|
||||
|
||||
// PHY Initialization:
|
||||
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
|
||||
delay(20);
|
||||
|
||||
pval &= 0xfff0;
|
||||
pval |= 0x0a;
|
||||
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
|
||||
delay(10);
|
||||
|
||||
phy_write_mask(0x1, PHY_MMD30, 0xd, pval);
|
||||
|
||||
phy_read(0, PHY_MMD30, 0xd);
|
||||
pval = SFR_DATA_U16;
|
||||
|
||||
REG_WRITE(0x2f8, 0, 0, pval >> 8, pval);
|
||||
|
||||
pval &= 0xfff0;
|
||||
REG_WRITE(0x2f4, 0, 0, pval >> 8, pval);
|
||||
|
||||
phy_write_mask(0x1, PHY_MMD30, 0xd, pval);
|
||||
|
||||
if (machine_detected.isN) {
|
||||
uint16_t pval;
|
||||
|
||||
print_string(" N-settings");
|
||||
// Serdes 0 RX PN swap for 64B/66B
|
||||
sds_read(1, 6, 2);
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(1, 6, 2, pval | 0x2000);
|
||||
|
||||
// Serdes 1 RX PN swap for 8B/10B
|
||||
sds_read(1, 0, 0);
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(1, 0, 0, pval | 0x200);
|
||||
|
||||
// Serdes 0 RX PN swap for 64B/66B
|
||||
sds_read(0, 6, 2);
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 6, 2, pval | 0x2000);
|
||||
|
||||
if (machine_detected.isRTL8373) {
|
||||
// RTL8224: Serdes 0 RX PN swap for 64B/66B
|
||||
// We assume that RTL8373N always paired with RTL8224N.
|
||||
// This sds register value is 0x0000 at reset.
|
||||
// So only write to it.
|
||||
RTL8224_SDS_WRITE(0, 6, 2, 0x2000);
|
||||
} else {
|
||||
// Serdes 0 RX PN swap for 8B/10B
|
||||
sds_read(0, 0, 0);
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 0, 0, pval | 0x200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void set_sys_led_state(uint8_t state)
|
||||
{
|
||||
reg_read_m(RTL837X_REG_LED_MODE);
|
||||
@@ -1653,167 +1646,6 @@ void rtl8373_revision(void)
|
||||
}
|
||||
|
||||
|
||||
void rtl8373_init(void)
|
||||
{
|
||||
print_string("\nrtl8373_init called\n");
|
||||
|
||||
// r65d8:3ffbedff R65d8-3ffbedff
|
||||
reg_bit_set(0x65d8, 0x1d);
|
||||
|
||||
sds_init();
|
||||
// Disable all SERDES for configuration
|
||||
REG_SET(RTL837X_REG_SDS_MODES, 0x000037ff);
|
||||
|
||||
// q000601:c800 Q000601:c804 q000601:c804 Q000601:c800
|
||||
sds_read(0, 0x06, 0x01);
|
||||
uint16_t pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 0x06, 0x01, pval | 0x04);
|
||||
delay(50);
|
||||
sds_read(0, 0x06, 0x01);
|
||||
pval = SFR_DATA_U16;
|
||||
sds_write_v(0, 0x06, 0x01, pval & 0xfffb);
|
||||
|
||||
phy_config_8224();
|
||||
sds_config_mac(1, SDS_OFF); // Off for now until SFP+ port used
|
||||
sds_config_mac(2, SDS_SGMII); // For RTL8224
|
||||
sds_config(0, SDS_QXGMII);
|
||||
|
||||
// SDS 1 setup
|
||||
// q012100:4902 Q012100:4906 q013605:0000 Q013605:4000 Q011f02:001f q011f15:0086
|
||||
sds_write_v(1, 0x21, 0x00, 0x4906);
|
||||
sds_write_v(1, 0x36, 0x05, 0x4000);
|
||||
sds_write_v(1, 0x1f, 0x02, 0x001f);
|
||||
sds_read(1, 0x1f, 0x15);
|
||||
pval = SFR_DATA_U16;
|
||||
|
||||
// r0a90:000000f3 R0a90-000000fc
|
||||
reg_read_m(RTL837X_CFG_PHY_MDI_REVERSE);
|
||||
sfr_mask_data(0, 0x0f,0x0c);
|
||||
reg_write_m(RTL837X_CFG_PHY_MDI_REVERSE);
|
||||
|
||||
if (machine_detected.isN) {
|
||||
print_string(" TX_POLARITY_SWAP\n");
|
||||
// FOR N-Version: #TX_POLARITY_SWAP
|
||||
reg_read_m(RTL837X_CFG_PHY_TX_POLARITY_SWAP);
|
||||
sfr_data[2] = 0x59;
|
||||
sfr_data[3] = 0x6a;
|
||||
reg_write_m(RTL837X_CFG_PHY_TX_POLARITY_SWAP);
|
||||
}
|
||||
|
||||
rtl8224_phy_enable();
|
||||
|
||||
// Disable PHYs for configuration
|
||||
phy_write_mask(0xff,PHY_MMD31,0xa610,0x2858);
|
||||
|
||||
// Set bits 0x13 and 0x14 of 0x5fd4
|
||||
// r5fd4:0002914a R5fd4-001a914a
|
||||
reg_bit_set(0x5fd4, 0x13);
|
||||
reg_bit_set(0x5fd4, 0x14);
|
||||
|
||||
// Configure ports
|
||||
uint16_t reg = 0x1238; // Port base register for the bits we set
|
||||
for (char i = 0; i < 9; i++) {
|
||||
// Bit 7 (0x40) enables replacement of the RTL-VLAN tag with an 802.1Q VLAN tag
|
||||
REG_SET(reg, 0xe77);
|
||||
reg += 0x100;
|
||||
}
|
||||
|
||||
// r0b7c:000000d8 R0b7c-000000f8 r6040:00000030 R6040-00000031
|
||||
reg_bit_set(0xb7c, 5);
|
||||
|
||||
// R7124-00001050 R7128-00001050 R712c-00001050 R7130-00001050 R7134-00001050 R7138-00001050
|
||||
// R713c-00001050 R7140-00001050 R7144-00001050 R7148-00001050
|
||||
REG_SET(0x7124, 0x1050); REG_SET(0x7128, 0x1050); REG_SET(0x712c, 0x1050);
|
||||
REG_SET(0x7130, 0x1050); REG_SET(0x7134, 0x1050); REG_SET(0x7138, 0x1050);
|
||||
REG_SET(0x713c, 0x1050); REG_SET(0x7140, 0x1050); REG_SET(0x7144, 0x1050);
|
||||
REG_SET(0x7148, 0x1050);
|
||||
|
||||
reg_bit_set(RTL837X_REG_HW_CONF, 0);
|
||||
|
||||
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
|
||||
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
|
||||
|
||||
// TODO: patch the PHYs
|
||||
|
||||
// Re-enable PHY after configuration
|
||||
phy_write_mask(0xff,PHY_MMD31,0xa610,0x2058);
|
||||
|
||||
// Enables MAC access
|
||||
// Set bits 0xc-0x14 of 0x632c to 0x1f8, see rtl8372_init
|
||||
// r632c:00000540 R632c-001f8540 // RTL8373: 001ff540
|
||||
reg_read_m(0x632c);
|
||||
sfr_mask_data(1, 0x70, 0xf0); // The ports of the RTL8824
|
||||
sfr_mask_data(2, 0x10, 0x1f);
|
||||
reg_write_m(0x632c);
|
||||
|
||||
print_string("\nrtl8373_init done\n");
|
||||
}
|
||||
|
||||
|
||||
void rtl8372_init(void)
|
||||
{
|
||||
print_string("\nrtl8372_init called\n");
|
||||
|
||||
sds_init();
|
||||
phy_config(8); // PHY configuration: External 8221B?
|
||||
phy_config(3); // PHY configuration: all internal PHYs?
|
||||
// Set the MAC SerDes Modes Bits 0-4: SDS 0 = 0x2 (0x2), Bits 5-9: SDS 1: 1f (off)
|
||||
// r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-00000bff r7b20:00000bff R7b20-000003ff r7b20:000003ff R7b20-000003e2 r7b20:000003e2 R7b20-000003e2
|
||||
reg_read_m(RTL837X_REG_SDS_MODES);
|
||||
sfr_mask_data(1, 0, 0x03);
|
||||
sfr_mask_data(0, 0, 0xe2);
|
||||
reg_write_m(RTL837X_REG_SDS_MODES);
|
||||
|
||||
// r0a90:000000f3 R0a90-000000fc
|
||||
reg_read_m(RTL837X_CFG_PHY_MDI_REVERSE);
|
||||
sfr_mask_data(0, 0x0f, 0x0c);
|
||||
reg_write_m(RTL837X_CFG_PHY_MDI_REVERSE);
|
||||
|
||||
// Disable PHYs for configuration
|
||||
phy_write_mask(0xf0,PHY_MMD31,0xa610,0x2858);
|
||||
|
||||
// Set bits 0x13 and 0x14 of 0x5fd4
|
||||
// r5fd4:0002914a R5fd4-001a914a
|
||||
reg_bit_set(0x5fd4, 0x13);
|
||||
reg_bit_set(0x5fd4, 0x14);
|
||||
|
||||
// Configure ports 3-8:
|
||||
//
|
||||
// r1538:00000e33 R1538-00000e37 r1538:00000e37 R1538-00000e37 r1538:00000e37 R1538-00000f37
|
||||
// [...]
|
||||
///
|
||||
uint16_t reg = 0x1238 + 0x300; // Port base register for the bits we set
|
||||
for (char i = machine.min_port; i <= machine.max_port; i++) {
|
||||
// Bit 7 (0x40) enables replacement of the RTL-VLAN tag with an 802.1Q VLAN tag
|
||||
REG_SET(reg, 0xe77);
|
||||
reg += 0x100;
|
||||
}
|
||||
|
||||
// r0b7c:000000d8 R0b7c-000000f8 r6040:00000030 R6040-00000031
|
||||
reg_bit_set(0xb7c, 5);
|
||||
|
||||
reg_bit_set(RTL837X_REG_HW_CONF, 0);
|
||||
|
||||
|
||||
// enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
|
||||
port_eee_enable_all(EEE_2G5 | EEE_NORESET);
|
||||
|
||||
// TODO: patch the PHYs
|
||||
|
||||
// Re-enable PHY after configuration
|
||||
phy_write_mask(0xf0,PHY_MMD31,0xa610,0x2058);
|
||||
|
||||
// Enables MAC access
|
||||
// Set bits 0xc-0x14 of 0x632c to 0x1f8, see rtl8372_init
|
||||
// r632c:00000540 R632c-001f8540 // RTL8373: 001ff540
|
||||
reg_read_m(0x632c);
|
||||
sfr_mask_data(1, 0x70, 0x80);
|
||||
sfr_mask_data(2, 0x10, 0x1f);
|
||||
reg_write_m(0x632c);
|
||||
print_string("\nrtl8372_init done\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The SoC manages Link-State for steering the LEDs and can set PHY-settings
|
||||
* automatically through Realtek's SMI (Simple Managagement) Interface, a
|
||||
@@ -2205,7 +2037,7 @@ void main(void)
|
||||
uip_arp_init();
|
||||
httpd_init();
|
||||
|
||||
management_vlan = 0; // Disabled
|
||||
management_vlan = 1; // Default management VLAN is 1
|
||||
|
||||
setup_i2c();
|
||||
setup_sfp_gpio();
|
||||
|
||||
Reference in New Issue
Block a user