diff --git a/Makefile b/Makefile index 2a3f01f..5e1d1df 100644 --- a/Makefile +++ b/Makefile @@ -103,14 +103,17 @@ httpd: html_data.h $(SUBDIRS): $(MAKE) -C $@ -clean: +clean: $(SUBDIRSCLEAN) -rm -f html_data.c html_data.h $(VERSION_HEADER) -if [ -d $(BUILDDIR) ]; then find $(BUILDDIR) -type f ! -name "*.bin" -delete; fi -distclean: +distclean: $(SUBDIRSCLEAN) -rm -f html_data.c html_data.h $(VERSION_HEADER) -rm -rf $(BUILDDIR) +$(SUBDIRSCLEAN): + $(MAKE) -C $(@:clean=) clean + $(BUILDDIR)/%.rel: %.c | create_build_dir html_data.h $(CC) -MMD $(CC_FLAGS) -o $@ -c $< @@ -133,7 +136,7 @@ $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.i tools/output/crc_calculator -u $@ ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin output/rtlplayground.bin -.PHONY: clean all $(SUBDIRS) $(VERSION_HEADER) create_build_dir +.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) $(VERSION_HEADER) create_build_dir .PHONY: machine_check: diff --git a/dhcp.c b/dhcp.c index ad5c536..d821f80 100644 --- a/dhcp.c +++ b/dhcp.c @@ -351,7 +351,12 @@ void dhcp_start(void) __banked return; } get_random_32(); - dhcp_state.transaction_id = SFR_DATA_U32; + // Workaround SDCC bug 4070: dhcp_state.transaction_id = SFR_DATA_U32; + __xdata uint8_t * tid = &dhcp_state.transaction_id; + *tid++ = SFR_DATA_24; + *tid++ = SFR_DATA_16; + *tid++ = SFR_DATA_8; + *tid = SFR_DATA_0; dhcp_state.state = DHCP_START; print_string("dhcp_start done\n"); } diff --git a/httpd/httpd.c b/httpd/httpd.c index 9728254..4ee8d0f 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -773,8 +773,13 @@ void httpd_appcall(void) goto do_send; } - if (is_word(p, "GET")) - dbg_string("GET request "); + // We only expect a GET request here. + if (!is_word(p, "GET")) { + send_bad_request(); + goto do_send; + } + + dbg_string("GET request "); p += 4; scan_header(p); __xdata uint8_t *q = p; diff --git a/rtl837x_igmp.c b/rtl837x_igmp.c index feddf9a..da02903 100644 --- a/rtl837x_igmp.c +++ b/rtl837x_igmp.c @@ -92,8 +92,11 @@ void igmp_setup(void) __banked REG_SET(RTL837X_IPV6_PORT_MC_LM_ACT, LOOKUP_MISS_FLOOD); // Define ports where unknown MC addresses are flooded to: - REG_SET(RTL837X_IPV4_UNKN_MC_FLD_PMSK, machine_detected.isRTL8373? PMASK_9: PMASK_6); - REG_SET(RTL837X_IPV6_UNKN_MC_FLD_PMSK, machine_detected.isRTL8373? PMASK_9: PMASK_6); + uint16_t mask = PMASK_6; + if (machine_detected.isRTL8373) + mask = PMASK_9; + REG_SET(RTL837X_IPV4_UNKN_MC_FLD_PMSK, mask); + REG_SET(RTL837X_IPV6_UNKN_MC_FLD_PMSK, mask); // Enable lookup of IPv4 MC addresses in table reg_bit_set(RTL837X_L2_CTRL, L2_CTRL_LUT_IPMC_HASH); diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 240d1d0..a338354 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -468,9 +468,13 @@ void phy_show(uint8_t port) __banked phy_read(port, PHY_MMD_PMAPMD, 0); v = SFR_DATA_U16; print_string("\nForced speed: "); print_short(v); write_char('\n'); - uint8_t s1 = ((v & 0x40) ? 0x2 : 0x0) | ((v & 0x2000) ? 0x1 : 0x0); - uint8_t s2 = (v >> 2) & 0xf; - switch(s1) { + uint8_t s1 = 0x00; + if ((uint8_t)v & 0x40) + s1 = 0x2; + if (v & 0x2000) + s1 |= 0x1; + uint8_t s2 = ((uint8_t)v >> 2) & 0xf; + switch(s1 & 0x3) { case 0: print_string("10M\n"); break; @@ -495,8 +499,6 @@ void phy_show(uint8_t port) __banked print_string("Unknown\n"); } break; - default: - print_string("Unknown\n"); } phy_read(port, PHY_MMD31, PHY_MMD31_FEDCR); v = SFR_DATA_U16; @@ -582,7 +584,7 @@ void phy_reset(uint8_t port) __banked // Reading only reads the lower 16-bit part of the 32-bit register. // When also needing read the upper 16-bits, use register address + 1. // Readed values it return via sfr-data. -void inline rtl8224_read_reg_u16(uint16_t reg) __banked +void rtl8224_read_reg_u16(uint16_t reg) __banked { // void phy_read(uint8_t phy_id, uint8_t dev_id, uint16_t reg) // phy_read(RTL8224_PHY_ID, PHY_MMD30, reg); @@ -590,7 +592,7 @@ void inline rtl8224_read_reg_u16(uint16_t reg) __banked SFR_SMI_REG_U16 = reg; // c2, c2 SFR_SMI_PHY = RTL8224_PHY_ID; // a5 - SFR_SMI_DEV = PHY_MMD30 << 3 | 2; // c4 + SFR_SMI_DEV = (uint8_t)PHY_MMD30 << 3 | 2; // c4 SFR_EXEC_GO = SFR_EXEC_READ_SMI; do { @@ -601,7 +603,7 @@ void inline rtl8224_read_reg_u16(uint16_t reg) __banked // Registers names are the same as on the RTL837x. // Writing only the lower 16-bit part of the 32-bit register. // When also needing to write the upper 16-bits, use register address + 1. -void inline rtl8224_write_reg_u16(uint16_t reg, uint16_t val) __banked +void rtl8224_write_reg_u16(uint16_t reg, uint16_t val) __banked { SFR_DATA_U16 = val; // SFR_A6, SFR_A7 SFR_SMI_REG_U16 = reg; // SFR_C2, SFR_C3 @@ -633,7 +635,7 @@ void inline rtl8224_write_reg_u16(uint16_t reg, uint16_t val) __banked // Write to the RTL8224 SDS registers. -void rtl8224_sds_write(uint16_t sds_cmd, uint16_t value) __banked +void rtl8224_sds_write(uint16_t sds_cmd, __xdata uint16_t value) __banked { // Wait for command bit is cleared do { diff --git a/rtl837x_phy.h b/rtl837x_phy.h index 932516a..91e675d 100644 --- a/rtl837x_phy.h +++ b/rtl837x_phy.h @@ -28,14 +28,16 @@ void phy_show(uint8_t port) __banked; void phy_reset(uint8_t port) __banked; void rtl8224_read_reg_u16(uint16_t reg) __banked; void rtl8224_write_reg_u16(uint16_t reg, uint16_t val) __banked; -void rtl8224_sds_write(uint16_t sds_cmd, uint16_t val) __banked; +void rtl8224_sds_write(uint16_t sds_cmd, __xdata uint16_t val) __banked; void phy_config_8261(uint8_t phy, uint8_t sds) __banked; -#define RTL8224_SDS_WRITE(sds_id, page, reg, v) uint16_t _sdscmd = (uint16_t)(sds_id & 0x01) | (1 << 14) | (1 << 15); \ +#define RTL8224_SDS_WRITE(sds_id, page, reg, v) do { \ + uint16_t _sdscmd = (uint16_t)(sds_id & 0x01) | (1 << 14) | (1 << 15); \ _sdscmd |= (page & 0x3F) << 1; \ _sdscmd |= ((uint16_t)(reg & 0x1f)) << 7; \ print_string("CMD: "); print_short(_sdscmd); \ write_char('-'); print_short(v); \ - rtl8224_sds_write(_sdscmd, v); + rtl8224_sds_write(_sdscmd, v); \ + } while (0) #endif diff --git a/rtl837x_port.c b/rtl837x_port.c index 8eea5a3..325256f 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -87,10 +87,9 @@ vlan_ingress_mode_t port_ingress_filter_get(__xdata uint8_t port) __banked /* * Define a Primary VLAN ID for a port */ -void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked +static void port_pvid_write(uint8_t port, __xdata uint16_t pvid) { // r4e1c:00001001 R4e1c-000017d0 r6738:00000000 R6738-00000000 (no filtering) - print_string("\nport_pvid_set called \n"); uint16_t reg = RTL837x_PVID_BASE_REG + ((port >> 1) << 2); reg_read_m(reg); @@ -101,6 +100,22 @@ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked } } +void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked +{ + uint8_t lag = port_lag_of(port); + + print_string("\nport_pvid_set called \n"); + if (lag == PORT_LAG_NONE) { + port_pvid_write(port, pvid); + return; + } + + uint16_t members = port_lag_members_get(lag); + for (uint8_t i = 0; i < 10; i++) + if ((members >> i) & 1) + port_pvid_write(i, pvid); +} + uint16_t port_pvid_get(uint8_t port) __banked { uint16_t reg = RTL837x_PVID_BASE_REG + ((port >> 1) << 2); @@ -339,7 +354,10 @@ uint8_t port_l2_forget(void) __banked REG_SET(RTL837x_L2_TBL_FLUSH_CNF, 0x0); // Flush L2 table for all ports by setting the ports and the flush-exec bit (bit 16) - REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | (machine_detected.isRTL8373 ? PMASK_9 : PMASK_6)); + uint16_t mask = PMASK_6; + if (machine_detected.isRTL8373) + mask = PMASK_9; + REG_SET(RTL837x_L2_TBL_FLUSH_CTRL, L2_TBL_FLUSH_EXEC | mask); // Wait for flush completed do { @@ -445,12 +463,14 @@ void port_l2_setup(void) __banked for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { // Limit the number of automatically learned MAC-Entries per port to 0x1040 - uint16_t reg = RTL837X_L2_LRN_PORT_CONSTRAINT + (i << 2); - REG_SET(reg, 0x00001040); + uint8_t idx = (i << 2); + REG_SET(RTL837X_L2_LRN_PORT_CONSTRAINT + idx, 0x00001040); // All ports may communicate with each other and CPU-Port - reg = RTL837X_PORT_ISOLATION_BASE + (i << 2); - REG_SET(reg, PMASK_CPU | (machine_detected.isRTL8373? PMASK_9 : PMASK_6)); + uint16_t mask = PMASK_CPU | PMASK_6; + if (machine_detected.isRTL8373) + mask = PMASK_CPU | PMASK_9; + REG_SET(RTL837X_PORT_ISOLATION_BASE + idx, mask); } // When maximim entries learned, then simply flood the packet reg_bit_set(RTL837X_L2_LRN_PORT_CONSTRT_ACT, 0); @@ -777,6 +797,14 @@ uint16_t port_lag_members_get(uint8_t lag) __banked return ((uint16_t)SFR_DATA_8 << 8) | SFR_DATA_0; } +uint8_t port_lag_of(uint8_t port) __banked +{ + for (uint8_t lag = 0; lag < 4; lag++) + if ((port_lag_members_get(lag) >> port) & 1) + return lag; + return PORT_LAG_NONE; +} + /* * Configure LAGs @@ -861,19 +889,23 @@ void vlan_dump(void) __banked /** Set the ingress VLAN filtering */ -bool port_ingress_vlan_filter_set(__xdata uint8_t port, __xdata bool enabled) __banked +bool port_ingress_vlan_filter_set(uint8_t port, __xdata bool enabled) __banked { - if (port < machine.min_port || port > machine.max_port && port != 9) { + if (port < machine.min_port || port > machine.max_port && port != CPU_PORT) { return false; } - reg_bit_set(RTL837X_VLAN_PORT_IGR_FLTR, port); + if (enabled) + reg_bit_set(RTL837X_VLAN_PORT_IGR_FLTR, port); + else + reg_bit_clear(RTL837X_VLAN_PORT_IGR_FLTR, port); + return true; } /** Get the ingress VLAN filtering status */ -bool port_ingress_vlan_filter_get(__xdata uint8_t port) __banked +bool port_ingress_vlan_filter_get(uint8_t port) __banked { - if (port < machine.min_port || port > machine.max_port && port != 9) { + if (port < machine.min_port || port > machine.max_port && port != CPU_PORT) { return false; } diff --git a/rtl837x_port.h b/rtl837x_port.h index 2c88cf0..692a14d 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -8,11 +8,12 @@ #define STAT_COUNTER_RX_PKTS 47 #define STAT_COUNTER_ERR_PKTS 48 -#define STAT_GET(cnt, port) \ +#define STAT_GET(cnt, port) do { \ REG_WRITE(RTL837X_STAT_GET, 0x00, 0x00, cnt >> 3, (cnt << 5) | (port << 1) | 1); \ do { \ reg_read_m(RTL837X_STAT_GET); \ - } while (sfr_data[3] & 0x1); + } while (sfr_data[3] & 0x1); \ + } while (0) // Possible values for ingress filter type typedef enum { @@ -64,6 +65,8 @@ void port_mirror_del(void) __banked; bool port_ingress_filter(__xdata uint8_t port, __xdata vlan_ingress_mode_t type) __banked; void port_l2_setup(void) __banked; uint16_t port_lag_members_get(uint8_t lag) __banked; +#define PORT_LAG_NONE 0xff +uint8_t port_lag_of(uint8_t port) __banked; void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked; void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked; void port_eee_enable_all(__xdata uint8_t speed) __banked; @@ -73,8 +76,8 @@ void port_eee_enable(__xdata uint8_t port, __xdata uint8_t speed) __banked; void port_eee_disable(uint8_t port) __banked; void port_eee_status(uint8_t port) __banked; void print_port_ingress_filter_mode(vlan_ingress_mode_t mode) __banked; -bool port_ingress_vlan_filter_set(__xdata uint8_t port, __xdata bool enabled) __banked; -bool port_ingress_vlan_filter_get(__xdata uint8_t port) __banked; +bool port_ingress_vlan_filter_set(uint8_t port, __xdata bool enabled) __banked; +bool port_ingress_vlan_filter_get(uint8_t port) __banked; vlan_ingress_mode_t port_ingress_filter_get(__xdata uint8_t port) __banked; void port_isolate(uint8_t port, __xdata uint16_t pmask) __banked; uint16_t port_isolation_get(uint8_t port) __banked; diff --git a/rtl837x_sfr.h b/rtl837x_sfr.h index f3e4a72..45c117a 100644 --- a/rtl837x_sfr.h +++ b/rtl837x_sfr.h @@ -5,8 +5,13 @@ __sfr16 __at(0xa2a3) SFR_REG_ADDR_U16; __sfr __at(0xa2) SFR_REG_ADDRH; __sfr __at(0xa3) SFR_REG_ADDRL; __sfr16 __at(0xa6a7) SFR_DATA_U16; -__sfr32 __at(0xa4a5a6a7) SFR_DATA_U32; -__sfr32 __at(0xa7a6a5a4) SFR_DATA_U32LE; +// Disabling until the SDCC bug #4070 is fixed. +// Generate wrong address for `a4` location. +// Both read from and write to `SFR_DATA_U32`. +// __sfr32 __at(0xa4a5a6a7) SFR_DATA_U32; +// __sfr32 __at(0xa7a6a5a4) SFR_DATA_U32LE; +// This is the upper part of the U32 as a workaround for SDCC bug #4070. +__sfr16 __at(0xa4a5) SFR_DATA_U16_UPPER; __sfr __at(0xa4) SFR_DATA_24; __sfr __at(0xa5) SFR_DATA_16; __sfr __at(0xa6) SFR_DATA_8; diff --git a/rtlplayground.c b/rtlplayground.c index a853e42..70b8582 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1846,18 +1846,35 @@ void init_smi(void) /* Set the SMI(i.e.I2C) type for PHY polling, 0b01 is 2.5/10G PHY. Disable (0b00) for the SFP-ports * which are at port 8 and additionally at port 3 for a dual SFP device */ + + // Default: 0x00005555 + // Workaround for SDCC BUG 4070: SFR_DATA_U32 = 0x00005555; + SFR_DATA_U16_UPPER = 0x0000; + SFR_DATA_U16 = 0x5555; if (machine.n_10g == 2) { - REG_SET(RTL837X_REG_SMI_MAC_TYPE, 0x00015555); - } else { - REG_SET(RTL837X_REG_SMI_MAC_TYPE, machine.n_sfp == 2 ? 0x00005515 : 0x00005555); - } + // 0x00015555, only change the bytes that differs from the default. + SFR_DATA_16 = 0x01; + } else if (machine.n_sfp == 2) + // 0x00005515 + SFR_DATA_0 = 0x15; + reg_write(RTL837X_REG_SMI_MAC_TYPE); // Configure polling of all PHYs by the MAC to detect link-state changes - if (machine_detected.isRTL8373) { - REG_SET(RTL837X_REG_SMI_PORT_POLLING, 0xff); - } else { - REG_SET(RTL837X_REG_SMI_PORT_POLLING, machine.n_sfp == 2 ? 0xf0 : 0x1f8); + // Default: 0x000000ff + // Workaround for SDCC BUG 4070: SFR_DATA_U32 = 0x000000ff; + SFR_DATA_U16_UPPER = 0x0000; + SFR_DATA_U16 = 0x00ff; + if (!machine_detected.isRTL8373) { + if (machine.n_sfp == 2) { + // 0x000000f0, only change the bytes that differs from the default. + SFR_DATA_0 = 0xf0; + } else { + // 0x000001f8, only change the bytes that differs from the default. + SFR_DATA_8 = 0x01; + SFR_DATA_0 = 0xf8; + } } + reg_write(RTL837X_REG_SMI_PORT_POLLING); // Enable MDC reg_read_m(RTL837X_REG_SMI_CTRL); sfr_mask_data(1, 0, 0x70); // Set bits 12-14 to enable MDC for SMI0-SMI2 diff --git a/uip/uip.c b/uip/uip.c index 1d015fc..47ba3af 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -373,11 +373,10 @@ uip_udpchksum(void) void uip_init(void) __banked { - uint8_t c; - for(c = 0; c < UIP_LISTENPORTS; ++c) { + for(uint8_t c = 0; c < UIP_LISTENPORTS; c++) { uip_listenports[c] = 0; } - for(c = 0; c < UIP_CONNS; ++c) { + for(uint8_t c = 0; c < UIP_CONNS; c++) { uip_conns[c].tcpstateflags = UIP_CLOSED; } #if UIP_ACTIVE_OPEN @@ -385,7 +384,7 @@ uip_init(void) __banked #endif /* UIP_ACTIVE_OPEN */ #if UIP_UDP - for(c = 0; c < UIP_UDP_CONNS; ++c) { + for(uint8_t c = 0; c < UIP_UDP_CONNS; c++) { uip_udp_conns[c].lport = 0; } #endif /* UIP_UDP */ @@ -1461,7 +1460,7 @@ uip_process(u8_t flag) __banked } /* Do different things depending on in what state the connection is. */ - switch(uip_connr->tcpstateflags & UIP_TS_MASK) { + switch(uip_connr->tcpstateflags & (uint8_t)UIP_TS_MASK) { /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not implemented, since we force the application to close when the peer sends a FIN (hence the application goes directly from