diff --git a/.gitignore b/.gitignore index f5c8e8c7..11f5c4ed 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ version.h tools/httpd_sim tools/injector tools/fileadder +build/ # host-test stand-ins for the two generated headers !test/stub/html_data.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c490505..b66c3013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ ## Added +- Devices + - Support the hongyavision HYWS-SGT0204S (PCB marking `2G5F4_10G2_V1.01`), an + RTL8372 based 4x2.5G + 2xSFP+ unmanaged switch with a 512 KB Bright Moon + `T25S40` flash. It is a sibling of the KP-9000-6XH-X2 (2M-PCB43-V1.1) with + the two SFP+ cages wired the other way round (physical 5 is on SDS1, + physical 6 on SDS0), no reset button fitted, wrong silkscreen labels on the + serial header, `LED_GLB_IO_EN` bit 6 has to be set for the port LEDs to + work, and the fitted T25S40 cannot be read in DIO mode on this board, so the + target selects single-IO flash reads (`flash_sio`). New machine target + `MACHINE_2G5F4_10G2_V1_01`, see `doc/devices/2G5F4_10G2_V1.01.md`. + - Web UI - Compress the embedded assets (minify + gzip) and switch to a single-page layout. #315 - Replace the multi-page UI with a themed single-page app: light, dark and Selenized themes following the browser by default, diff --git a/Makefile b/Makefile index 00bbf7b9..c95f12af 100644 --- a/Makefile +++ b/Makefile @@ -103,6 +103,7 @@ SRCS += \ rtl837x_flash.c \ rtl837x_igmp.c \ rtl837x_init.c \ + rtl837x_nic.c \ rtl837x_leds.c \ rtl837x_leds_dump.c \ rtl837x_phy.c \ diff --git a/boot.c b/boot.c index 81a37fab..18e9a79d 100644 --- a/boot.c +++ b/boot.c @@ -125,18 +125,6 @@ void early_boot_handle_button(void) __banked void sds_config(uint8_t sds, uint8_t mode) __banked { print_string("sds_config sds: "); print_byte(sds); print_string(", mode: "); print_byte(mode); write_char('\n'); - sds_config_mac(sds, mode); - - if (mode == SDS_10GR || mode == SDS_QXGMII) - sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480 - else - sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480 - sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400 - sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02 - sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e - sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002 - sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390 - sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f uint8_t page = 0; uint16_t v = 0; @@ -165,6 +153,21 @@ void sds_config(uint8_t sds, uint8_t mode) __banked print_string("Error in SDS Mode\n"); return; } + + sds_config_mac(sds, mode); + + if (mode == SDS_10GR || mode == SDS_QXGMII) + sds_write_v(sds, 0x21, 0x10, 0x4480); // Q002110:6480 + else + sds_write_v(sds, 0x21, 0x10, 0x6480); // Q002110:6480 + + sds_write_v(sds, 0x21, 0x13, 0x0400); // Q002113:0400 + sds_write_v(sds, 0x21, 0x18, 0x6d02); // Q002118:6d02 + sds_write_v(sds, 0x21, 0x1b, 0x424e); // Q00211b:424e + sds_write_v(sds, 0x21, 0x1d, 0x0002); // Q00211d:0002 + sds_write_v(sds, 0x36, 0x1c, 0x1390); // Q00361c:1390 + sds_write_v(sds, 0x36, 0x14, 0x003f); // Q003614:003f + sds_write_v(sds, 0x36, 0x10, v); // Q003610:0200 if (page == 0x2e) { // 10G Fiber / SDS_QXGMII @@ -257,7 +260,7 @@ void nic_setup(void) __banked // This sets the size of the RX buffer, the filling level is in 0x7874 // R7848-000004ff - REG_SET(RTL837X_REG_NIC_RXBUFF_RX, 0x4ff); + REG_SET(RTL837X_REG_NIC_RXBUFF_RX, RTL837X_NIC_RX_LAST_SLOT); // R7844-000007fe REG_SET(RTL837X_REG_NIC_BUFFSIZE_TX, 0x7fe); diff --git a/doc/CpuPort.md b/doc/CpuPort.md index c10d0a15..652b1cbb 100644 --- a/doc/CpuPort.md +++ b/doc/CpuPort.md @@ -34,6 +34,21 @@ Next, transfer the actual packet over by repeating the SFR function with a pointer to the frame on the ASIC directly after the frame header and a length as given by the length in the frame header + 7, again divided by 8. +The RX ring's inclusive last slot is configured as `0x4ff`, giving a byte +range of `0x0000` through `0x27ff`. If the descriptor occupies the last slot +at `0x27f8`, its payload starts at `0x0000`, not `0x2800`. The RX copy code +normalizes that starting address before DMA. It relies on the hardware to +wrap transfers that start inside the ring and cross its end, as observed +on SWTGW218AS. Programming an initial address of `0x2800` does not wrap +and can instead read zeros or stale TX data outside the RX ring. + +Frame lengths are checked against `UIP_CONF_BUFFER_SIZE` before copying. +DMA works in whole eight-byte units. `UIP_CONF_BUFFER_ALLOC_SIZE` rounds +the backing storage up to the next complete word: 1,560 bytes for the +1,556-byte logical frame limit. This padding allows a maximum-size frame +to be transferred directly without a separate tail copy. The logical +frame limit and advertised MSS are unchanged. + The received frame will have an RTL proprietary Ethernet frame type of 0x8899 (RRPC) where normally the frame type 0x0800 for IPv4 would be located. Further 6 bytes follow describing the frame, before the normal IPv4 data diff --git a/doc/adding-a-device.md b/doc/adding-a-device.md index 0063dd71..312f318f 100644 --- a/doc/adding-a-device.md +++ b/doc/adding-a-device.md @@ -1,6 +1,6 @@ # Adding a new device -A device is supported by adding one board definition `.h` and board configuration `.c` file +A device is supported by adding one board header `.h` and board definition `.c` file under `machine/`. the build selects the definition by name, and CI compiles every file it finds. @@ -14,27 +14,34 @@ make MACHINE= | File | Purpose | |------|---------| | `machine/.c` | the `struct machine machine` board definition | -| `machine/.h` | `MACHINE_MODEL`, the model string shown in the UI and the CLI | +| `machine/.h` | `MACHINE_MODEL` (the model string shown in the UI and the CLI) and `MACHINE_CHIPSET` (`RTL8372` or `RTL8373`) | | `doc/devices/.md` + `doc/supported_devices.md` | (only if the board is verified and you want to support it publicly) user-facing documentation | `` is the machine symbol without its `MACHINE_` prefix, so `MACHINE` is passed exactly as spelled on the command line: `make MACHINE=MY_BOARD_1_0` needs `machine/MY_BOARD_1_0.c` and `machine/MY_BOARD_1_0.h`. -## Step 1: the model header +## Step 1: the board header -`machine/.h` only carries the product string. Use the existing files as -the template: +`machine/.h` carries the product string and the SoC family. Use the +existing files as the template: ```c #ifndef _MACHINE_MY_BOARD_1_0_H_ #define _MACHINE_MY_BOARD_1_0_H_ #define MACHINE_MODEL "Brand Model V1.0" +#define MACHINE_CHIPSET RTL8373 #endif ``` +`MACHINE_CHIPSET` is `RTL8373` or `RTL8372`; a build without it will fail. It selects the default +logical port range: `min_port` is `0` for RTL8373 and `3` for RTL8372, while `max_port` is `8`, +the highest logical port index. A board with a different range defines +`MACHINE_MIN_PORT` and/or `MACHINE_MAX_PORT` in its header to override the +defaults. + The device product string is what the CLI or the Web-Interface will print to identify the device; `machine.h` includes it by name. > [!NOTE] @@ -55,10 +62,7 @@ ports and the same number of SFP+ cages. #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, @@ -89,13 +93,16 @@ __code const struct machine machine = { }; ``` +`MACHINE_COMMON_SETTING` (from `machine_defs.h`) initializes `machine_name`, +`isRTL8373`, `min_port` and `max_port` from the header's `MACHINE_MODEL` and +`MACHINE_CHIPSET`. Keep it as the first initializer and list the +board-specific fields after it. + ### Fields | Field | Meaning | |-------|---------| -| `machine_name` | always `MACHINE_MODEL` | -| `isRTL8373` | `1` for an RTL8373 SoC, `0` for RTL8372 | -| `min_port` / `max_port` | range of logical port numbers the device has; `min_port` is `0` for RTL8373 boards and `3` for RTL8372 boards (logical ports 1–2 are the SoC's internal ports on the 8372), `max_port` is usually 8. | +| `MACHINE_COMMON_SETTING` | expands to `machine_name` (`MACHINE_MODEL`), `isRTL8373` (`1` for `RTL8373`, `0` for `RTL8372`), `min_port` and `max_port`; all are derived from the header's `MACHINE_CHIPSET` (see Step 1) | | `n_sfp` | number of SFP+ cages | | `n_10g` | SerDes 10G capability used by the RTL837xN init: `0` none, `1` one, `2` two 10G-capable SerDes | | `log_to_phys_port[9]` | logical port (0-based index) → physical front-panel port number | @@ -130,8 +137,10 @@ apart: ln -s KP_9000_6XHML_X2.c machine/MY_BOARD_1_0.c ``` -The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on the PCB) with its own -`MACHINE_MODEL`, because `MACHINE_MODEL` is what distinguishes the products. +The new board still needs `machine/MY_BOARD_1_0.h` (pick the version number on +the PCB) with its own `MACHINE_MODEL` and `MACHINE_CHIPSET`: `MACHINE_MODEL` is +what distinguishes the products, and `MACHINE_CHIPSET` must match the SoC of +the board definition being reused. Existing examples: `machine/PCB_K0402WS_V3.c`, `machine/KP_9000_9XHML_X_V3_2.c` and the six `KP_9000_*` revision variants. @@ -177,3 +186,20 @@ Once the board has been tested on hardware: `doc/devices/KP-9000-6XH-X2.md` and document which `MACHINE` to pick for which silkscreen. +### Identifying the CPU variant + +For RTL8373-based devices, use the read-only console command below to distinguish +the N and non-N CPU variants: + +```text +regget 4 +``` + +| Register 0x0004 value | CPU | +|---|---| +| `0x83730000` | RTL8373 (non-N) | +| `0x83737000` | RTL8373N | + +Record the identified CPU in the device documentation. These values identify +only the CPU variant; document PHY and flash-chip models separately when verified. + diff --git a/doc/devices/2G5F4_10G2_V1.01.md b/doc/devices/2G5F4_10G2_V1.01.md new file mode 100644 index 00000000..fc3803a2 --- /dev/null +++ b/doc/devices/2G5F4_10G2_V1.01.md @@ -0,0 +1,178 @@ +hongyavision HYWS-SGT0204S + +RTL8372-based 4×2.5G + 2×SFP+ unmanaged switch. + +Also marked on the PCB as `2G5F4_10G2_V1.01`. + +Stock firmware runs a factory test console on UART at 9600 baud 8N1 (banner +`RTL8371B start`, prompt `RTL8371B:`). There is no management CLI and no Web +interface. + +Using SPI clamp in-board is the only method for initial installation and update. +Erase the whole chip and verify the write (`flashrom -v`) before powering the +board, so an incomplete write is caught before the board is powered up. + +Stock flash chip is 512 KB (Bright Moon `T25S40`, 4 Mbit, SOP-8), which the +RTLPlayground image fills exactly. + +### Label specifications + +Case, top / front / nameplate: + + + + + +- **Manufacturer**: hongyavision (Shenzhen Hongyavision Electronic Technology + Co., Ltd.) +- **Model**: HYWS-SGT0204S — the nameplate is printed in Chinese and reads + "10/100/1000/2500M fibre switch" and "4x 2.5G copper port + 2x 10G SFP+ + optical port" +- **Ports**: + - 4 × RJ45: 10/100/1000/2500 Mbps + - 2 × SFP+: 1G / 2.5G / 10G +- **Power**: 12 V DC, 2 A +- **Serial number**: `S/N-YYYYMMDDNNNN`, e.g. `S/N-202312010028` + +The top of the case only carries generic printing ("2.5G+10G High Speed Fiber +Transceiver / 4-Port 2.5G Ethernet Switch+10G Fiber"), so the nameplate on the +bottom is what identifies the device. + +### What works + +- All four 2.5GBASE-T RJ45 ports at 10/100/1000/2500 Mbps +- Both SFP+ ports supporting 1G, 2.5G and 10G modules +- Copper LEDs: white (2.5G) and blue (link/activity) +- SFP LEDs: one single LED per port (link/activity) +- SFP EEPROM and DDM readable on both cages, verified with a 10G module + (`Rate: 0x67`, module identity and DDM values via the `sfp` console command) +- Serial console at 115200 8N1 (RTLPlayground) / 9600 8N1 (stock) + +### Not verified + +- The reset button footprint is unpopulated and the case has no opening for it, + so it could not be tested. + +### PCB overview + +**Board markings** +- Top silkscreen: `2G5F4_10G2_V1.01` + +**Key components** +- Main switch: RTL8372 (RTL8371B family), reported as `RTL8372` (non-N) by + RTLPlayground. The chip sits under a heatsink and its package marking is not + readable. +- U1: SPI NOR flash, Bright Moon `T25S40`, 4 Mbit / 512 KB, SOP-8 +- A 3-hole reset button footprint is present but unpopulated, and the case has + no opening for it, so there is no usable reset button + +Top side: + + + +Bottom: + + + +The stock flash chip, Bright Moon `T25S40` (SOP-8, 4 Mbit / 512 KB): + + + +### Port layout + +| Front panel position | Logical port | Physical port | Type | +|----------------------|--------------|---------------|---------| +| SFP left | 8 | 5 | SFP+ | +| RJ45 1 | 4 | 1 | Copper | +| RJ45 2 | 5 | 2 | Copper | +| RJ45 3 | 6 | 3 | Copper | +| RJ45 4 | 7 | 4 | Copper | +| SFP right | 3 | 6 | SFP+ | + +Copper ports 1–4 match the KP-9000-6XH-X2 (2M-PCB43-V1.1) layout, which this +board is a sibling of. The two SFP+ cages are wired the other way round +compared to that board: physical port 5 is on SDS1 and physical port 6 is on +SDS0. + +### Serial console + +The board has three through-holes used as the serial console, next to the +heatsink in the middle of the board and visible in the top side photo above (the +silkscreen labels are printed rotated by 90°). **The silkscreen labels are +wrong**: they are shifted relative to the actual signals. + +| Silkscreen label | Actual signal | +|------------------|---------------| +| TX | GND | +| RX | TX | +| GND | RX | + +Wiring (following the measured signals, not the labels): + +| USB-TTL adapter | Board pad | +|-----------------|----------------------| +| GND | pad labelled `TX` | +| RX | pad labelled `RX` | +| TX | pad labelled `GND` | + +- **Settings**: 115200 baud / 8N1 / 3.3V TTL (RTLPlayground), 9600 baud for the + stock firmware +- The stock firmware only prints a few bytes and a factory test menu + (`?`, `rst`, `f`, `r`, `10`, `100`, `g1`, `sd`, `eye`, …); it is not an + interactive management console + +### LED configuration + +Case silkscreen, below the RJ45 ports: + +``` +White : 2.5G Blue : 1000M/2500M L/A +``` + +The front panel also carries a `PWR` LED and one LED per SFP cage (`SFP1`, +`SFP2`) on the right hand side. + +| Port | LED | Linked, idle | With traffic | +|------------|--------------|--------------|--------------| +| Copper | white | 2.5G only | same | +| Copper | blue | solid | blinks (L/A) | +| SFP | single LED | solid | blinks (L/A) | + +Measured LED-ID mapping (from the RTL837x LED set registers): + +| LED-ID | Function | +|--------|---------------------------------| +| LED-ID0| copper blue LED | +| LED-ID1| copper white LED | +| LED-ID2| SFP single LED | + +**Important**: `RTL837X_REG_LED_GLB_IO_EN` bit 6 must be set in +`machine_custom_init()`. Without it the RTL837x "solid" conditions (LINK/speed) +do not drive the LEDs at all and only `ACT` does, which makes the white LED +glow faintly at non-2.5G speeds. + +### SFP GPIO assignments + +| SFP | pin\_detect (ModAbs) | pin\_los | SerDes | I2C SDA | I2C SCL | +|-------------------|-------------------------------|------------------|--------|-------------------------|--------------------------| +| Left (logical 8, physical 5) | GPIO30\_ACL\_BIT3\_EN | GPIO37 | SDS1 | GPIO39\_I2C\_SDA4 | GPIO40\_I2C\_SCL3\_MDC1 | +| Right (logical 3, physical 6)| GPIO50\_I2C\_SCL2\_UART1\_TX | GPIO10\_LED10 | SDS0 | GPIO41\_I2C\_SDA3\_MDIO1 | GPIO40\_I2C\_SCL3\_MDC1 | + +`pin_tx_disable` is GPIO\_NA on both ports. Both I2C buses are confirmed +working: with the same 10G module inserted, the `sfp` console command reads its +vendor and model from the left cage (`Slot 1`) and from the right cage +(`Slot 2`), DDM values included. The insertion also shows which SerDes drives +each cage - the left cage reports `sds_config sds: 01` and the right cage +`sds: 00`, which matches the table above. + +### Machine target + +Build for this device with `make MACHINE=2G5F4_10G2_V1_01`, which selects the +`machine/2G5F4_10G2_V1_01.c` board definition. It is derived from +`machine/KP_9000_6XHML_X2.c` with the SFP cage order and the reset pin changed. +The fitted T25S40 cannot be read in DIO mode on this board: an image that leaves +DIO enabled does not come up at all, both at the default read clock divider of 4 +and at 8 (two boards tested), while the same image with single-IO boots and runs +normally. The board definition therefore sets `flash_sio`, which makes +`flash_init()` use `CMD_FREAD` at divider 8. Only the management plane is +slower, the ASIC keeps forwarding in hardware. diff --git a/doc/devices/Hasivo-S1100P-8GT-1SX-S.md b/doc/devices/Hasivo-S1100P-8GT-1SX-S.md new file mode 100644 index 00000000..9fc60186 --- /dev/null +++ b/doc/devices/Hasivo-S1100P-8GT-1SX-S.md @@ -0,0 +1,41 @@ +# Hasivo S1100P-8GT-1SX-S + +RTL8373N switch with 8 × 2.5G RJ45 ports and 1 × SFP port. GD25Q16 2 MiB flash. + +## Port mapping + +| Front port | ASIC MAC | Interface | +| --- | --- | --- | +| 1–8 | 0–7 | RJ45 | +| 9 | 8 | SFP (SDS1) | + +## Board signals + +| Function | GPIO | +| --- | --- | +| SFP detect | 38 | +| SFP LOS | 37 | +| SFP TX disable | Not connected (`GPIO_NA`) | +| SFP I2C SDA / SCL | 39 / 40 | +| Reset | 54 | + +PoE is managed by an RTL8238B and a separate STC8H8K64U controller, not directly by the RTL8373N. RTLPlayground does not control PoE on this board. + +## Build + +`make MACHINE=HASIVO_S1100P_8GT_1SX_S CI=1` + +## Photos + +Front panel: + +![Front panel](photos/Hasivo-S1100P-8GT-1SX-S/front.jpg) + +PCB top: + +![PCB top](photos/Hasivo-S1100P-8GT-1SX-S/pcb_top.jpg) + +PCB bottom: + +![PCB bottom](photos/Hasivo-S1100P-8GT-1SX-S/pcb_bottom.jpg) + diff --git a/doc/devices/SIRIVISION_S25G2206FP_V1_1.md b/doc/devices/SIRIVISION_S25G2206FP_V1_1.md new file mode 100644 index 00000000..529ac1fc --- /dev/null +++ b/doc/devices/SIRIVISION_S25G2206FP_V1_1.md @@ -0,0 +1,32 @@ +### SIRIVISION_S25G2206FP_V1_1 + +## Brands +|Brand|Type|Managed|PCB|Flash|Chip RTL| +|---|---|---|---|---|---| +| YuanLey | YS25-0402M | Yes | SIRIVISION_S25G2206FP_V1_1 | 2M | 8372 | + +### Label specifications + +- **Name**: +- **Ports**: + - 4 × RJ45: 10/100/1000/2500 Mbps + - 2 × SFP+: 1000 / 2500 / 10000 Mbps +- **Power**: 12V DC, 1A 5525 connector + +### What works +The device is fully supported: +- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps +- ALL SFP+ ports support 1G, 2.5G and 10G modules +- LEDs work with the same indiciations as the OEM firmware +### PCB overview + +**Board markings** +- Top silkscreen: SIRIVISION S25G2206FP V1.1 + +Top side + + + +## Power supply + +Input power is delivered via barell plug, `12V 1A` adapter was provided. diff --git a/doc/devices/SWTG018AS_A_V2_0.md b/doc/devices/SWTG018AS_A_V2_0.md index 1460ce61..28447b85 100644 --- a/doc/devices/SWTG018AS_A_V2_0.md +++ b/doc/devices/SWTG018AS_A_V2_0.md @@ -5,6 +5,7 @@ | Ampcom | SWTG018AS-A V2.0 | No | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N | | Horaco | HC-SWTGW218AS-A | Yes | SWTG018AS-A V2.0 | 2MB(25Q16JVSIQ) | 8273N + 8224N | | GoodTop | GT-ST018M | Yes | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N | +| MokerLink | 2G08110GSN | No | SWTG018AS-A V2.0 | 512KB(25Q40) | 8273N + 8224N | The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`. diff --git a/doc/devices/SWTG024AS-A-V2.0.1_4C_2SFP.md b/doc/devices/SWTG024AS-A-V2.0.1_4C_2SFP.md index 2189dd8b..ddb3b1fc 100644 --- a/doc/devices/SWTG024AS-A-V2.0.1_4C_2SFP.md +++ b/doc/devices/SWTG024AS-A-V2.0.1_4C_2SFP.md @@ -2,10 +2,11 @@ It is highly similar to SWTG024AS-V2.0, with the only difference being the GPIO configuration for the SFP port. ## Brands -|Brand|Type|Managed|PCB|Flash|Chip RTL| -|---|---|---|---|---|---| -| Horaco | ZX-SG4T2 | | PCB-SWTG024AS-A-V2.0.1_19650 | P25D40SH | ??? | -| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | ??? | +|Brand |Type |Managed|PCB |Flash |Chip RTL| +|---------|--------------|-------|------------------------------|----------------|--------| +| Horaco | ZX-SG4T2 | No | PCB-SWTG024AS-A-V2.0.1_19650 | 512K (P25D40SH)| 8372N | +| Horaco | HC-SWTG124AS | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M (W25Q16JV)| 8372N | +| GoodTop | GT-ST024M | Yes | PCB-SWTG024AS-A-V2.0.1 | 2M | 8372N | ### Label specifications diff --git a/doc/devices/SWTG024AS-V2.0.md b/doc/devices/SWTG024AS-V2.0.md index c787428b..69724577 100644 --- a/doc/devices/SWTG024AS-V2.0.md +++ b/doc/devices/SWTG024AS-V2.0.md @@ -46,4 +46,4 @@ Note,`R52`、`R53`may not be installed.You need to bridge them using either sold ## Power supply -Input power is delivered via barell plug, `12V 1A` adapter was provided. \ No newline at end of file +Input power is delivered via barell plug, `12V 1A` adapter was provided. diff --git a/doc/devices/SWTGW218AS.md b/doc/devices/SWTGW218AS.md index 4797125b..485584f9 100644 --- a/doc/devices/SWTGW218AS.md +++ b/doc/devices/SWTGW218AS.md @@ -5,9 +5,15 @@ |---|---|---|---|---|---| | Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N | | Sodola | | | | | | -| Horaco | | | | | | +| Horaco | HC-SWTGW218AS | Yes | SWTG118AS-V2.1 | 2MB | 8373 (non-N) | | XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | | +All boards in this table use `MACHINE=SWTGW218AS`. The Horaco HC-SWTGW218AS is also sold with the +[SWTG018AS-A V2.0](SWTG018AS_A_V2_0.md) board, which needs a different firmware. Check the marking +on the PCB before flashing. + +The PHY and flash-chip models for the tested Horaco units remain unverified. + ## Photos diff --git a/doc/devices/photos/2G5F4_10G2_V1.01/assembled-bottom.jpg b/doc/devices/photos/2G5F4_10G2_V1.01/assembled-bottom.jpg new file mode 100644 index 00000000..8108ce66 Binary files /dev/null and b/doc/devices/photos/2G5F4_10G2_V1.01/assembled-bottom.jpg differ diff --git a/doc/devices/photos/2G5F4_10G2_V1.01/assembled-front.jpg b/doc/devices/photos/2G5F4_10G2_V1.01/assembled-front.jpg new file mode 100644 index 00000000..2cb1782b Binary files /dev/null and b/doc/devices/photos/2G5F4_10G2_V1.01/assembled-front.jpg differ diff --git a/doc/devices/photos/2G5F4_10G2_V1.01/assembled-top.jpg b/doc/devices/photos/2G5F4_10G2_V1.01/assembled-top.jpg new file mode 100644 index 00000000..e3ea7733 Binary files /dev/null and b/doc/devices/photos/2G5F4_10G2_V1.01/assembled-top.jpg differ diff --git a/doc/devices/photos/2G5F4_10G2_V1.01/flash_t25s40.jpg b/doc/devices/photos/2G5F4_10G2_V1.01/flash_t25s40.jpg new file mode 100644 index 00000000..a1af18ac Binary files /dev/null and b/doc/devices/photos/2G5F4_10G2_V1.01/flash_t25s40.jpg differ diff --git a/doc/devices/photos/2G5F4_10G2_V1.01/pcb_bottom.jpg b/doc/devices/photos/2G5F4_10G2_V1.01/pcb_bottom.jpg new file mode 100644 index 00000000..0c8cbabb Binary files /dev/null and b/doc/devices/photos/2G5F4_10G2_V1.01/pcb_bottom.jpg differ diff --git a/doc/devices/photos/2G5F4_10G2_V1.01/pcb_top.jpg b/doc/devices/photos/2G5F4_10G2_V1.01/pcb_top.jpg new file mode 100644 index 00000000..421462a2 Binary files /dev/null and b/doc/devices/photos/2G5F4_10G2_V1.01/pcb_top.jpg differ diff --git a/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/front.jpg b/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/front.jpg new file mode 100644 index 00000000..e2836b96 Binary files /dev/null and b/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/front.jpg differ diff --git a/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/pcb_bottom.jpg b/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/pcb_bottom.jpg new file mode 100644 index 00000000..3d2a6f6c Binary files /dev/null and b/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/pcb_bottom.jpg differ diff --git a/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/pcb_top.jpg b/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/pcb_top.jpg new file mode 100644 index 00000000..06d972cd Binary files /dev/null and b/doc/devices/photos/Hasivo-S1100P-8GT-1SX-S/pcb_top.jpg differ diff --git a/doc/devices/photos/SIRIVISION_S25G2206FP_V1_1/dev_pcb_top.jpg b/doc/devices/photos/SIRIVISION_S25G2206FP_V1_1/dev_pcb_top.jpg new file mode 100644 index 00000000..dfa6ec8f Binary files /dev/null and b/doc/devices/photos/SIRIVISION_S25G2206FP_V1_1/dev_pcb_top.jpg differ diff --git a/doc/supported_devices.md b/doc/supported_devices.md index 9711d97e..3d3d5ba2 100644 --- a/doc/supported_devices.md +++ b/doc/supported_devices.md @@ -15,9 +15,12 @@ The following devices have been tested and are fully working: | Hisource | Hi-K0402WS | No | [PCB-K0402WS-V2.0](devices/PCB-K0402WS-V2.0.md) | 2M | 4 + 2 | | Hisource | Hi-K0402WS | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 | | Hisource | Hi-K0801WS | No | [PCB-KO801W-V2.0](devices/HI-K0801WS.md) | | 8 + 1 | +| hongyavision | HYWS-SGT0204S | No | [2G5F4_10G2_V1.01](devices/2G5F4_10G2_V1.01.md) | 0.5M | 4 + 2 | | hongyavision | LG-SG5T1 | No | [PCB-SWTG024AS-V2.0_16895](devices/SWTG024AS-V2.0.md) | 0.5M | 5 + 1 | +| Horaco | HC-SWTG124AS | Yes | [SWTG024AS-A-V2.0.1](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 2M | 4 + 2 | | Horaco | HC-SWTGW215AS | Yes | [SWTG024AS-A-V2.0.1_19650 5C 1SFP](devices/SWTG024AS-A-V2.0.1_5C_1SFP.md) | ? | 5 + 1 | | Horaco | HC-SWTGW218AS | Yes | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | | 8 + 1 | +| Horaco | HC-SWTGW218AS | Yes | [SWTG118AS-V2.1](devices/SWTGW218AS.md) | 2M | 8 + 1 | | Horaco | ZX310S-4T2XH | Yes | [PCB-SL310S-4T1T1X-V1.0.1-24107](devices/ZX310S-4T2XH.md) | 2M | 5 + 1 | | Horaco | ZX310S-4T2XT | Yes | [PCB-SL310S-4T2XT-V1.0.0-22273](devices/ZX310S-4T2XT.md) | 2M | 6 | | Horaco | ZX-SG4T2 | No | [SWTG024AS-A-V2.0.1_19650_4C_2SFP](devices/SWTG024AS-A-V2.0.1_4C_2SFP.md) | 0.5M | 4 + 2 | @@ -32,6 +35,7 @@ The following devices have been tested and are fully working: | MokerLink| 2G040210GSM | Yes | [2M-PCB43-V1.1](devices/2M-PCB43-V1.1.md) | | 4 + 2 | | MokerLink| POE-2G080110GS | No | [2M-PCB51-ML-V1.1](devices/2M-PCB51-ML-V1_1.md) | 4M | 8 + 1 | | MokerLink| ZX-SWTGW218AS | Yes | [SWTG118AS-V2.0-16029](devices/SWTGW218AS.md) | 2M | 8 + 1 | +| MokerLink| 2G08110GSN | No | [SWTG018AS-A V2.0](devices/SWTG018AS_A_V2_0.md) | 0.5M | 8 + 1 | | Netcore | GS9 | No | [PB-2132](devices/PB-2132.md) | 4M | 8 + 1 | | ONT | ONT-S207CW-62TS-SE | No | [PCB-SWTG024AS-A-2.0.1](devices/ONT-S207CW-62TS-SE.md) | 0.5M | 4 + 2 | | Ruiying | RY-4GT-2SX | No | [FG-4GT-2SX_V2.0](devices/FG-4GT-2SX_V2.0.md) | 4M | 4 + 2 | @@ -44,6 +48,7 @@ The following devices have been tested and are fully working: | XikeStor | SKS3200-8E1X | Yes | [SWTG118AS-V2.1-17462](devices/SWTGW218AS.md) | 2M | 8 + 1 | | YuanLey | YS25-0402 | No | [PCB-K0402WS-V1.0](devices/PCB-K0402WS-V1.0.md) | 2M | 4 + 2 | | YuanLey | YS25-0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | 2M | 4 + 2 | +| YuanLey | YS25-0402M | Yes | [SIRIVISION_S25G2206FP_V1_1](devices/SIRIVISION_S25G2206FP_V1_1.md) | 2M | 4 + 2 | | Ztyuav | Z-QWYT0402 | No | [PCB-K0402WS-V3.0](devices/PCB-K0402WS-V3.0.md) | | 4 + 2 | For KP-9000-6XH-X2 / KP-9000-6XHML-X2 / Mokerlink 2G040210GSM devices, select diff --git a/httpd/httpd.c b/httpd/httpd.c index f2ca2d36..d167d30e 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -55,8 +55,8 @@ __xdata uint8_t boundary[72]; #define CONFIG_UPLOAD_BUF (CONFIG_LEN + 384) __xdata uint8_t config_upload; __xdata uint8_t config_buf[CONFIG_UPLOAD_BUF]; -// bytes buffered in config_buf so far (config body, or a firmware part -// header); accumulates across TCP segments +// bytes buffered in config_buf so far (HTTP header, POST body, or a firmware +// part header); accumulates across TCP segments __xdata uint16_t pre_acc; __xdata uint8_t * __xdata content_type = 0; __xdata uint8_t * __xdata session = 0; @@ -75,9 +75,6 @@ __xdata uint8_t postbody_endpoint; __xdata uint16_t postbody_start; __xdata char passwd[21]; -// Set when a verified firmware upload awaits its response ACK, after -// which the chip resets to apply the staged image -__xdata uint8_t fw_reset_pending; __xdata char session_id[SESSION_ID_LENGTH + 1]; __xdata uint8_t authenticated; __xdata uint32_t now; @@ -90,6 +87,7 @@ __xdata uint32_t last_session_use; #define TSTATE_POST 4 #define TSTATE_MULTIPART 5 #define TSTATE_POSTBODY 6 +#define TSTATE_HEADER 7 extern __xdata uint16_t crc_value; __xdata uint16_t crc_final; @@ -109,8 +107,8 @@ void httpd_init(void) __banked uip_listen(HTONS(80)); // Not through uip_conn: it only points at a connection while uIP is // handling one, and nothing has set it yet at init time. - uip_conns[0].appstate.tstate = TSTATE_CLOSED; - fw_reset_pending = 0; // xdata is not zeroed by the startup code + for (uint8_t i = 0; i < UIP_CONNS; i++) + uip_conns[i].appstate.tstate = TSTATE_CLOSED; } @@ -511,7 +509,7 @@ uint8_t stream_upload(void) "Content-Type: text/plain\r\n\r\n" "OK: checksum verified, rebooting\n"); // Reset once the response is fully ACKed - fw_reset_pending = 1; + s->fw_reset_pending = 1; } else { print_string("Checksum incorrect! Aborting.\n"); slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nContent-Length: 33\r\n" @@ -746,7 +744,42 @@ static void post_body_continue(void) } -void handle_post(void) + +/* + * Buffer an HTTP request header across TCP receive events. Stop copying at + * CRLFCRLF so any body bytes in the final segment stay in uip_appdata. + * + * Return the body offset in the current receive buffer, 0 while incomplete, + * or 0xffff after sending an error response. + */ +static uint16_t request_header_take(void) +{ + uint16_t i; + + for (i = 0; i < uip_len; i++) { + if (pre_acc + 1 >= CONFIG_UPLOAD_BUF) { + uip_conn->appstate.tstate = TSTATE_NONE; + send_bad_request(); + return 0xffff; + } + config_buf[pre_acc++] = ((__xdata uint8_t *)uip_appdata)[i]; + config_buf[pre_acc] = NUL; + if (pre_acc >= 4 + && config_buf[pre_acc - 4] == '\r' + && config_buf[pre_acc - 3] == '\n' + && config_buf[pre_acc - 2] == '\r' + && config_buf[pre_acc - 1] == '\n') { + uip_conn->appstate.tstate = TSTATE_NONE; + return i + 1; + } + } + + postbody_start = ticks; + uip_conn->appstate.tstate = TSTATE_HEADER; + return 0; +} + +void handle_post(uint16_t body_off) { __xdata struct httpd_state * __xdata s = &(uip_conn->appstate); __xdata uint8_t *p = uip_appdata; @@ -759,6 +792,9 @@ void handle_post(void) // Was the multipart header sent in multiple packets? if (s->tstate != TSTATE_MULTIPART) { + p = config_buf; + request_path = p + 6; + dbg_string("Is POST\n"); p += 5; // Skip post // Find end of request path @@ -772,9 +808,12 @@ void handle_post(void) dbg_string("Boundary: >"); dbg_string_x(boundary); dbg_string("<\n"); if (!*p || !content_type) { dbg_string("Bad Request!\n"); - send_not_found(); + send_bad_request(); return; } + + pre_acc = 0; + p = (__xdata uint8_t *)uip_appdata + body_off; if (is_word(request_path, "upload")) { if (!authenticated) { send_unauthorized(); @@ -800,7 +839,10 @@ void handle_post(void) dbg_string("Configuration upload\n"); verify_crc = 0; config_upload = 1; - pre_acc = 0; + // config_take() matches CRLF-prefixed delimiters, including the first. + config_buf[0] = '\r'; + config_buf[1] = '\n'; + pre_acc = 2; } // Check for other POST requests, which are not multipart, below } else { @@ -824,7 +866,6 @@ void handle_post(void) handle_firmware_fragment(p); return; } else if (is_word(request_path, "cmd")) { - p += 4; if (!authenticated) { send_unauthorized(); return; @@ -843,7 +884,6 @@ void handle_post(void) return; } - p += 4; postbody_endpoint = POSTBODY_LOGIN; if (!post_body_take(p)) return; @@ -874,9 +914,10 @@ void httpd_appcall(void) print_byte(s->tstate); write_char(' '); #endif - if(uip_connected() && s->tstate == TSTATE_CLOSED) { + if(uip_connected()) { dbg_string("Connected...\n"); s->tstate = TSTATE_NONE; + s->fw_reset_pending = 0; // explicitly initialize reused XDATA appstate } else if (uip_closed()) { dbg_string("Connection closed\n"); s->tstate = TSTATE_CLOSED; @@ -890,9 +931,9 @@ void httpd_appcall(void) dbg_string("Closing because everything has been transmitted\n"); uip_close(); s->tstate = TSTATE_CLOSED; - } else if (s->tstate == TSTATE_POSTBODY + } else if ((s->tstate == TSTATE_POSTBODY || s->tstate == TSTATE_HEADER) && (uint16_t)ticks - postbody_start > POSTBODY_TIMEOUT) { - dbg_string("Body never arrived\n"); + dbg_string("HTTP request never completed\n"); uip_abort(); s->tstate = TSTATE_CLOSED; } @@ -928,7 +969,7 @@ void httpd_appcall(void) cont_len -= slen; cont_addr += slen; s->tstate = TSTATE_TX; - } else if (fw_reset_pending) { + } else if (s->fw_reset_pending) { // The upload verdict has been fully ACKed by the client; // now it is safe to reset and apply the staged image print_string("Resetting to apply update\n"); @@ -955,6 +996,7 @@ void httpd_appcall(void) cont_len = 0; dbg_char('<'); dbg_short(uip_len); dbg_char('\n'); __xdata uint8_t *p = uip_appdata; + uint16_t body_off = 0; // Mark end of request header with \0 p[uip_len] = 0; #ifdef DEBUG @@ -963,9 +1005,21 @@ void httpd_appcall(void) dbg_char('\n'); #endif p = uip_appdata; - if (is_word(p, "POST") || s->tstate == TSTATE_MULTIPART - || s->tstate == TSTATE_POSTBODY) { - handle_post(); + if (s->tstate != TSTATE_MULTIPART && s->tstate != TSTATE_POSTBODY) { + if (s->tstate != TSTATE_HEADER) + pre_acc = 0; + body_off = request_header_take(); + if (!body_off) { + uip_len = 0; + return; + } + if (body_off == 0xffff) + goto do_send; + } + + if (s->tstate == TSTATE_MULTIPART || s->tstate == TSTATE_POSTBODY + || is_word(config_buf, "POST")) { + handle_post(body_off); // If this is an ongoing post stream, then wait for the next packet if (s->tstate == TSTATE_POST || s->tstate == TSTATE_MULTIPART || s->tstate == TSTATE_POSTBODY) { @@ -975,12 +1029,11 @@ void httpd_appcall(void) goto do_send; } - // We only expect a GET request here. + p = config_buf; if (!is_word(p, "GET")) { send_bad_request(); goto do_send; } - dbg_string("GET request "); p += 4; scan_header(p); diff --git a/httpd/httpd.h b/httpd/httpd.h index 91b83b22..5cabe3d5 100644 --- a/httpd/httpd.h +++ b/httpd/httpd.h @@ -12,6 +12,7 @@ for each TCP connection. */ typedef struct httpd_state { uint8_t tstate; + uint8_t fw_reset_pending; } uip_tcp_appstate_t; /* Finally we define the application function to be called by uIP. */ diff --git a/machine.h b/machine.h index d0b85fc1..70d75e8b 100644 --- a/machine.h +++ b/machine.h @@ -15,8 +15,48 @@ #define MACHINE_INC(dir,file) MACHINE_STR(dir/file) +#define RTL8370 0x70 +#define RTL8372 0x72 +#define RTL8373 0x73 + #include MACHINE_INC(MACHINE_DEF_DIR,MACHINE_NAME.h) + +#ifndef MACHINE_CHIPSET +#error "MACHINE_CHIPSET shall be defined in .h file" +#endif + +#ifndef MACHINE_MIN_PORT +#if MACHINE_CHIPSET == RTL8372 +#define MACHINE_MIN_PORT 3 +#else +#define MACHINE_MIN_PORT 0 +#endif +#endif + +#ifndef MACHINE_MAX_PORT +#if MACHINE_CHIPSET == RTL8370 +#define MACHINE_MAX_PORT 7 +#else +#define MACHINE_MAX_PORT 8 +#endif +#endif + +// auto derive SOC_FAMILY +#define RTL836X 6 +#define RTL837X 7 + +#ifdef SOC_FAMILY +#error "SOC_FAMILY can not be manually defined, shall be auto derived" +#endif +#if (MACHINE_CHIPSET == RTL8372) || (MACHINE_CHIPSET == RTL8373) +#define SOC_FAMILY RTL837X +#elif (MACHINE_CHIPSET == RTL8370 ) +#define SOC_FAMILY RTL836X +#else +#error "Unsupported MACHINE_CHIPSET is specified!" +#endif + #define LED_27 1 // SYSTEM LED #define LED_28_SYS 2 @@ -64,6 +104,12 @@ struct machine { uint8_t led_mux_custom; uint8_t led_mux[28]; uint32_t mac_flash_offset; + // Read the flash with single-IO (CMD_FREAD) instead of DIO for MMIO/code + // fetch. Set for boards whose flash chip is not usable in DIO mode, which + // shows up as a board that does not boot at all, garbled console output or + // random resets. Costs management-plane speed only, the ASIC keeps + // forwarding in hardware. + uint8_t flash_sio; }; struct machine_runtime diff --git a/machine/2G08110GSN.c b/machine/2G08110GSN.c new file mode 120000 index 00000000..c46221ee --- /dev/null +++ b/machine/2G08110GSN.c @@ -0,0 +1 @@ +SWTG018AS_A_V_2_0.c \ No newline at end of file diff --git a/machine/2G08110GSN.h b/machine/2G08110GSN.h new file mode 100644 index 00000000..46cd230f --- /dev/null +++ b/machine/2G08110GSN.h @@ -0,0 +1,7 @@ +#ifndef _MACHINE_2G08110GSN_H_ +#define _MACHINE_2G08110GSN_H_ + +#define MACHINE_MODEL "MokerLink 2G08110GSN" +#define MACHINE_CHIPSET RTL8373 + +#endif diff --git a/machine/2G5F4_10G2_V1_01.c b/machine/2G5F4_10G2_V1_01.c new file mode 100644 index 00000000..e4a78ad1 --- /dev/null +++ b/machine/2G5F4_10G2_V1_01.c @@ -0,0 +1,51 @@ +#include "machine_defs.h" + +__code const struct machine machine = { + MACHINE_COMMON_SETTING, + .n_sfp = 2, + /* Same 2M-PCB43-V1.1 board family as the KP-9000-6XH-X2 (see + * machine/KP_9000_6XHML_X2.c), but the two SFP+ cages (physical ports 5 and + * 6) are wired the other way round: physical 5 is on SDS1, physical 6 on + * SDS0. Copper ports 1-4 match the KP-9000 layout. */ + .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, + .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, + .is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1}, + // Left SFP cage (physical port 5) = SDS1 + .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, + .sfp_port[0].pin_los = GPIO37, + .sfp_port[0].pin_tx_disable = GPIO_NA, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), + // Right SFP cage (physical port 6) = SDS0 + .sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX, + .sfp_port[1].pin_los = GPIO10_LED10, + .sfp_port[1].pin_tx_disable = GPIO_NA, + .sfp_port[1].sds = 0, + .sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ), + /* The board has a 3-hole reset button footprint, but it is unpopulated and + * the case has no opening for it, so reset_pin stays GPIO_NA. GPIO54, the + * reset pin on the KP-9000 layout, reads as permanently pressed here. */ + .reset_pin = GPIO_NA, + /* The fitted T25S40 does not work in DIO mode on this board, so read the flash + * with single-IO; see doc/devices/2G5F4_10G2_V1.01.md. */ + .flash_sio = 1, + .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 }, + .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* Conditions for LED on: + * dual led orange: ledset_0 & ledset_2 + * dual led green: ledset_2 & !ledset_0 + * single right led green: ledset_0 & !ledset_1 + * + * Measured on this board: LED-ID0 is the copper blue LED, LED-ID1 the + * copper white one (setting LED-ID0 to 0 killed blue while leaving white on + * at 2.5G only) and LED-ID2 carries the SFP single LED. The "solid" + * conditions (LINK/speed) barely drive the LEDs here and ACT is what + * actually lights them, which is why the white LED used to glow faintly at + * non-2.5G speeds; the fix for that is LED_GLB_IO_EN bit 6, set in + * machine_init.c. */ + .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, + LEDS_2G5 | LEDS_LINK | LEDS_10G, + LEDS_1G | LEDS_LINK, + 0 }, + }, +}; diff --git a/machine/2G5F4_10G2_V1_01.h b/machine/2G5F4_10G2_V1_01.h new file mode 100644 index 00000000..80a90fbd --- /dev/null +++ b/machine/2G5F4_10G2_V1_01.h @@ -0,0 +1,7 @@ +#ifndef _MACHINE_2G5F4_10G2_V1_01_H_ +#define _MACHINE_2G5F4_10G2_V1_01_H_ + +#define MACHINE_MODEL "2G5F4_10G2_V1.01 / SGT0204S" +#define MACHINE_CHIPSET RTL8372 + +#endif diff --git a/machine/DEFAULT_8C_1SFP.c b/machine/DEFAULT_8C_1SFP.c deleted file mode 100644 index 2a923596..00000000 --- a/machine/DEFAULT_8C_1SFP.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "machine_defs.h" - -__code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, - .n_sfp = 1, - .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, - .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, - .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, - .sfp_port[0].pin_los = GPIO37, - .sfp_port[0].pin_tx_disable = GPIO_NA, - .sfp_port[0].sds = 1, - .sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), - .reset_pin = GPIO_NA, - .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 }, - .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, - .led_sets = { { LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5, - LEDS_2G5 | LEDS_LINK, - LEDS_1G | LEDS_LINK, - LEDS_2G5 | LEDS_LINK | LEDS_ACT }, - }, -}; diff --git a/machine/DEFAULT_8C_1SFP.c b/machine/DEFAULT_8C_1SFP.c new file mode 120000 index 00000000..f00039af --- /dev/null +++ b/machine/DEFAULT_8C_1SFP.c @@ -0,0 +1 @@ +KP_9000_9XH_X_EU.c \ No newline at end of file diff --git a/machine/DEFAULT_8C_1SFP.h b/machine/DEFAULT_8C_1SFP.h index 2b802a30..f19507e1 100644 --- a/machine/DEFAULT_8C_1SFP.h +++ b/machine/DEFAULT_8C_1SFP.h @@ -2,5 +2,6 @@ #define _MACHINE_DEFAULT_8C_1SFP_H_ #define MACHINE_MODEL "8+1 SFP Port Switch" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/F7008_2_5.c b/machine/F7008_2_5.c index e2d08e61..df6643cc 100644 --- a/machine/F7008_2_5.c +++ b/machine/F7008_2_5.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/F7008_2_5.h b/machine/F7008_2_5.h index c3b0cbbf..f8c78cae 100644 --- a/machine/F7008_2_5.h +++ b/machine/F7008_2_5.h @@ -2,5 +2,6 @@ #define _MACHINE_F7008_2_5_H_ #define MACHINE_MODEL "F7008-2.5 8+1 SFP Port Switch" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/FG_4GT_2SX_V2_0.c b/machine/FG_4GT_2SX_V2_0.c index 9590c6f0..9931a1a1 100644 --- a/machine/FG_4GT_2SX_V2_0.c +++ b/machine/FG_4GT_2SX_V2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/FG_4GT_2SX_V2_0.h b/machine/FG_4GT_2SX_V2_0.h index 8f9697e7..8c819abf 100644 --- a/machine/FG_4GT_2SX_V2_0.h +++ b/machine/FG_4GT_2SX_V2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_FG_4GT_2SX_V2_0_H_ #define MACHINE_MODEL "FG-4GT-2SX_V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/FG_8GT_1SX.c b/machine/FG_8GT_1SX.c index 0fd3dee0..c232d92a 100644 --- a/machine/FG_8GT_1SX.c +++ b/machine/FG_8GT_1SX.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/FG_8GT_1SX.h b/machine/FG_8GT_1SX.h index e75a9946..789d8a9b 100644 --- a/machine/FG_8GT_1SX.h +++ b/machine/FG_8GT_1SX.h @@ -2,5 +2,6 @@ #define _MACHINE_FG_8GT_1SX_H_ #define MACHINE_MODEL "FG-8GT-1SX" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/FNS1200P.c b/machine/FNS1200P.c deleted file mode 100644 index 71334029..00000000 --- a/machine/FNS1200P.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "machine_defs.h" - -__code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, - .n_sfp = 2, - .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, - .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, - .is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1}, - - /* Left SFP (logical 8, SDS1): GPIO30=ModAbs, GPIO37=RX_LOS */ - .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, - .sfp_port[0].pin_los = GPIO37, - .sfp_port[0].pin_tx_disable = GPIO_NA, - .sfp_port[0].sds = 1, - .sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), - - /* Right SFP (logical 3, SDS0): GPIO50=ModAbs, GPIO51=RX_LOS */ - .sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX, - .sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX, - .sfp_port[1].pin_tx_disable = GPIO_NA, - .sfp_port[1].sds = 0, - .sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ), - - .reset_pin = GPIO_NA, - - .high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 }, - - /* Copper ports use SET0; SFP ports use SET1 */ - .port_led_set = {0, 0, 0, 1, 0, 0, 0, 0, 1}, - - .led_sets = { - { /* SET0: copper — LED0=amber (2.5G), LED2=green (1G/100M/10M) */ - LEDS_2G5 | LEDS_LINK | LEDS_ACT, - 0, - LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, - 0 - }, - { /* SET1: SFP — all speeds link/act */ - LEDS_10G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, - 0, - 0, 0 - }, - }, - - .led_mux_custom = 1, - .led_mux = { - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* GPIO0-7: unused */ - 0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, /* GPIO8-14 */ - 0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, /* GPIO15-20 */ - 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 /* GPIO21-27 */ - }, -}; diff --git a/machine/FNS1200P.c b/machine/FNS1200P.c new file mode 120000 index 00000000..c836c871 --- /dev/null +++ b/machine/FNS1200P.c @@ -0,0 +1 @@ +PCB_K0402WS_V2.c \ No newline at end of file diff --git a/machine/FNS1200P.h b/machine/FNS1200P.h index e5691b48..f058e5eb 100644 --- a/machine/FNS1200P.h +++ b/machine/FNS1200P.h @@ -2,5 +2,6 @@ #define _MACHINE_FNS1200P_H_ #define MACHINE_MODEL "FNS-1200P" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/GT_ST018M.h b/machine/GT_ST018M.h index c4550c26..66b0c51f 100644 --- a/machine/GT_ST018M.h +++ b/machine/GT_ST018M.h @@ -2,5 +2,6 @@ #define _MACHINE_GT_ST018M_H_ #define MACHINE_MODEL "GoodTop GT-ST018M" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/GT_ST024M.h b/machine/GT_ST024M.h index be57f788..8662bb31 100644 --- a/machine/GT_ST024M.h +++ b/machine/GT_ST024M.h @@ -2,5 +2,6 @@ #define _MACHINE_GT_ST024M_H_ #define MACHINE_MODEL "GoodTop GT-ST024M" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HASIVO_S1100P_8GT_1SX_S.c b/machine/HASIVO_S1100P_8GT_1SX_S.c new file mode 100644 index 00000000..9af4d8c3 --- /dev/null +++ b/machine/HASIVO_S1100P_8GT_1SX_S.c @@ -0,0 +1,37 @@ +#include "machine_defs.h" + +__code const struct machine machine = { + MACHINE_COMMON_SETTING, + .mac_flash_offset = 0x1FC000, + .n_sfp = 1, + .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, + .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, + .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = GPIO38, + .sfp_port[0].pin_los = GPIO37, + .sfp_port[0].pin_tx_disable = GPIO_NA, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), + .reset_pin = GPIO54_ACL_BIT2_EN, + .high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 }, + .port_led_set = {0, 0, 0, 0, 0, 0, 0, 0, 1}, + .led_sets = { + { + LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // LED0: orange + 0, + LEDS_2G5 | LEDS_LINK | LEDS_ACT, // LED2: green + 0 + }, + { + LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED0: green (both SFP LEDs are green) + 0, 0, 0 + } + }, + .led_mux_custom = 1, + .led_mux = { + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x09, + 0x0e, 0x10, 0x12, 0x0e, 0x14, 0x11, 0x12, 0x16, + 0x15, 0x16, 0x18, 0x19, 0x1a, 0x1a, 0x1d, 0x1e, + 0x1c, 0x1e, 0x20, 0x21 + }, +}; diff --git a/machine/HASIVO_S1100P_8GT_1SX_S.h b/machine/HASIVO_S1100P_8GT_1SX_S.h new file mode 100644 index 00000000..89f03ce5 --- /dev/null +++ b/machine/HASIVO_S1100P_8GT_1SX_S.h @@ -0,0 +1,7 @@ +#ifndef _MACHINE_HASIVO_S1100P_8GT_1SX_S_H_ +#define _MACHINE_HASIVO_S1100P_8GT_1SX_S_H_ + +#define MACHINE_MODEL "Hasivo S1100P-8GT-1SX-S" +#define MACHINE_CHIPSET RTL8373 + +#endif diff --git a/machine/HASIVO_S1100WP_8GT_1SX_SE.c b/machine/HASIVO_S1100WP_8GT_1SX_SE.c deleted file mode 100644 index 7500ba94..00000000 --- a/machine/HASIVO_S1100WP_8GT_1SX_SE.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "machine_defs.h" - -__code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .mac_flash_offset = 0x1FC000, - .min_port = 0, - .max_port = 8, - .n_sfp = 1, - .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, - .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, - .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, - .sfp_port[0].pin_los = GPIO37, - .sfp_port[0].pin_tx_disable = GPIO_NA, - .sfp_port[0].sds = 1, - .sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), - .reset_pin = GPIO54_ACL_BIT2_EN, - .high_leds = { .mux = LED_27 | LED_28_SYS | LED_29, .enable = LED_28_SYS | LED_29 }, - .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1}, - .led_sets = { { LEDS_2G5 | LEDS_LINK | LEDS_ACT, // Green LED (right) - 0, - LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, // Amber LED (left) - 0 - }, - { LEDS_10G | LEDS_5G | LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, // SFP LED - 0, - 0, - 0 - }, - }, -}; diff --git a/machine/HASIVO_S1100WP_8GT_1SX_SE.c b/machine/HASIVO_S1100WP_8GT_1SX_SE.c new file mode 120000 index 00000000..1fc0cdb2 --- /dev/null +++ b/machine/HASIVO_S1100WP_8GT_1SX_SE.c @@ -0,0 +1 @@ +SWTGW218AS.c \ No newline at end of file diff --git a/machine/HASIVO_S1100WP_8GT_1SX_SE.h b/machine/HASIVO_S1100WP_8GT_1SX_SE.h index d50dfc22..433a42f2 100644 --- a/machine/HASIVO_S1100WP_8GT_1SX_SE.h +++ b/machine/HASIVO_S1100WP_8GT_1SX_SE.h @@ -2,5 +2,6 @@ #define _MACHINE_HASIVO_S1100WP_8GT_1SX_SE_H_ #define MACHINE_MODEL "Hasivo S1100WP-8GT-1SX-SE" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/HASIVO_S600W_4GT_2XGT_SE.c b/machine/HASIVO_S600W_4GT_2XGT_SE.c index e43477d8..223c990f 100644 --- a/machine/HASIVO_S600W_4GT_2XGT_SE.c +++ b/machine/HASIVO_S600W_4GT_2XGT_SE.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 0, .n_10g = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, diff --git a/machine/HASIVO_S600W_4GT_2XGT_SE.h b/machine/HASIVO_S600W_4GT_2XGT_SE.h index 97beb686..dcb40306 100644 --- a/machine/HASIVO_S600W_4GT_2XGT_SE.h +++ b/machine/HASIVO_S600W_4GT_2XGT_SE.h @@ -2,5 +2,6 @@ #define _MACHINE_HASIVO_S600W_4GT_2XGT_SE_H_ #define MACHINE_MODEL "Hasivo S600W-4GT-2XGT-SE" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HC_SWTG124AS.c b/machine/HC_SWTG124AS.c new file mode 120000 index 00000000..f0f8441d --- /dev/null +++ b/machine/HC_SWTG124AS.c @@ -0,0 +1 @@ +PCB_SWTG024AS_A_2_0_1.c \ No newline at end of file diff --git a/machine/HC_SWTG124AS.h b/machine/HC_SWTG124AS.h new file mode 100644 index 00000000..f1936317 --- /dev/null +++ b/machine/HC_SWTG124AS.h @@ -0,0 +1,7 @@ +#ifndef _MACHINE_HC_SWTG124AS_H_ +#define _MACHINE_HC_SWTG124AS_H_ + +#define MACHINE_MODEL "Horaco HC-SWTG124AS" +#define MACHINE_CHIPSET RTL8372 + +#endif diff --git a/machine/HG0402XG_V1_1.c b/machine/HG0402XG_V1_1.c index 5d7be1e9..5f20e295 100644 --- a/machine/HG0402XG_V1_1.c +++ b/machine/HG0402XG_V1_1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/HG0402XG_V1_1.h b/machine/HG0402XG_V1_1.h index 628dc168..5b578acc 100644 --- a/machine/HG0402XG_V1_1.h +++ b/machine/HG0402XG_V1_1.h @@ -2,5 +2,6 @@ #define _MACHINE_HG0402XG_V1_1_H_ #define MACHINE_MODEL "HG0402XG V1.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HI_K0402WS.c b/machine/HI_K0402WS.c index 3ad7b241..2c59d8bc 100644 --- a/machine/HI_K0402WS.c +++ b/machine/HI_K0402WS.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/HI_K0402WS.h b/machine/HI_K0402WS.h index d930fce9..18416117 100644 --- a/machine/HI_K0402WS.h +++ b/machine/HI_K0402WS.h @@ -2,5 +2,6 @@ #define _MACHINE_HI_K0402WS_H_ #define MACHINE_MODEL "PCB-K0402WS-V3.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/HI_K0801WS.c b/machine/HI_K0801WS.c index 8fba5e82..cc06d550 100644 --- a/machine/HI_K0801WS.c +++ b/machine/HI_K0801WS.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/HI_K0801WS.h b/machine/HI_K0801WS.h index 4321d0fe..ff5a7721 100644 --- a/machine/HI_K0801WS.h +++ b/machine/HI_K0801WS.h @@ -2,5 +2,6 @@ #define _MACHINE_HI_K0801WS_H_ #define MACHINE_MODEL "Hi-Source HI-k0801WS" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/K0501W_V2_0.c b/machine/K0501W_V2_0.c index 75f36c6b..51224523 100644 --- a/machine/K0501W_V2_0.c +++ b/machine/K0501W_V2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/K0501W_V2_0.h b/machine/K0501W_V2_0.h index dbe10df6..b657edf4 100644 --- a/machine/K0501W_V2_0.h +++ b/machine/K0501W_V2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_K0501W_V2_0_H_ #define MACHINE_MODEL "K0501W V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2.c b/machine/KP_9000_6XHML_X2.c index a6520f01..850d7e2a 100644 --- a/machine/KP_9000_6XHML_X2.c +++ b/machine/KP_9000_6XHML_X2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/KP_9000_6XHML_X2.h b/machine/KP_9000_6XHML_X2.h index da850ae4..67551b56 100644 --- a/machine/KP_9000_6XHML_X2.h +++ b/machine/KP_9000_6XHML_X2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML-X2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2_V1_1.h b/machine/KP_9000_6XHML_X2_V1_1.h index 1e8b2c49..8d491998 100644 --- a/machine/KP_9000_6XHML_X2_V1_1.h +++ b/machine/KP_9000_6XHML_X2_V1_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_V1_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML V1.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2_V1_2.h b/machine/KP_9000_6XHML_X2_V1_2.h index 484ff3e2..df5fd559 100644 --- a/machine/KP_9000_6XHML_X2_V1_2.h +++ b/machine/KP_9000_6XHML_X2_V1_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_V1_2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML V1.2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XHML_X2_V2_1.h b/machine/KP_9000_6XHML_X2_V2_1.h index 4cea1de7..3b276ac7 100644 --- a/machine/KP_9000_6XHML_X2_V2_1.h +++ b/machine/KP_9000_6XHML_X2_V2_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XHML_X2_V2_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XHML V2.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X.c b/machine/KP_9000_6XH_X.c index 50dcc10b..bd4b52a3 100644 --- a/machine/KP_9000_6XH_X.c +++ b/machine/KP_9000_6XH_X.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/KP_9000_6XH_X.h b/machine/KP_9000_6XH_X.h index f52d0ad6..664c830b 100644 --- a/machine/KP_9000_6XH_X.h +++ b/machine/KP_9000_6XH_X.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH-X" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2.c b/machine/KP_9000_6XH_X2.c index aa6a2655..9ea09451 100644 --- a/machine/KP_9000_6XH_X2.c +++ b/machine/KP_9000_6XH_X2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/KP_9000_6XH_X2.h b/machine/KP_9000_6XH_X2.h index 5493dc79..2d7a8374 100644 --- a/machine/KP_9000_6XH_X2.h +++ b/machine/KP_9000_6XH_X2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH-X2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2_V1_1.h b/machine/KP_9000_6XH_X2_V1_1.h index 183cc276..f3d2d068 100644 --- a/machine/KP_9000_6XH_X2_V1_1.h +++ b/machine/KP_9000_6XH_X2_V1_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_V1_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH V1.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2_V1_2.h b/machine/KP_9000_6XH_X2_V1_2.h index 4fcd94af..2de3183e 100644 --- a/machine/KP_9000_6XH_X2_V1_2.h +++ b/machine/KP_9000_6XH_X2_V1_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_V1_2_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH V1.2" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_6XH_X2_V2_1.h b/machine/KP_9000_6XH_X2_V2_1.h index a144dc96..dd1a954c 100644 --- a/machine/KP_9000_6XH_X2_V2_1.h +++ b/machine/KP_9000_6XH_X2_V2_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_6XH_X2_V2_1_H_ #define MACHINE_MODEL "keepLink KP-9000-6XH-X2 V2.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/KP_9000_9XHML_X_V2_2.c b/machine/KP_9000_9XHML_X_V2_2.c index e73a7514..6c8338b0 100644 --- a/machine/KP_9000_9XHML_X_V2_2.c +++ b/machine/KP_9000_9XHML_X_V2_2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, .phys_to_log_port = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, diff --git a/machine/KP_9000_9XHML_X_V2_2.h b/machine/KP_9000_9XHML_X_V2_2.h index 2d6d0a7f..4bb261ac 100644 --- a/machine/KP_9000_9XHML_X_V2_2.h +++ b/machine/KP_9000_9XHML_X_V2_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XHML_X_V2_2_H_ #define MACHINE_MODEL "keepLink KP-9000-9XHML-X V2.2" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/KP_9000_9XHML_X_V3_1.c b/machine/KP_9000_9XHML_X_V3_1.c index 26ea751f..515b59ac 100644 --- a/machine/KP_9000_9XHML_X_V3_1.c +++ b/machine/KP_9000_9XHML_X_V3_1.c @@ -2,10 +2,7 @@ // 2M-PCB23-V3.2 is wired like V3.1 (SFP detection, LEDs, factory MAC location) __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/KP_9000_9XHML_X_V3_1.h b/machine/KP_9000_9XHML_X_V3_1.h index c100b5f8..ae5e8e55 100644 --- a/machine/KP_9000_9XHML_X_V3_1.h +++ b/machine/KP_9000_9XHML_X_V3_1.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XHML_X_V3_1_H_ #define MACHINE_MODEL "keepLink KP-9000-9XHML-X V3.1" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/KP_9000_9XHML_X_V3_2.h b/machine/KP_9000_9XHML_X_V3_2.h index e3b4eec2..416cb327 100644 --- a/machine/KP_9000_9XHML_X_V3_2.h +++ b/machine/KP_9000_9XHML_X_V3_2.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XHML_X_V3_2_H_ #define MACHINE_MODEL "keepLink KP-9000-9XHML-X V3.2" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/KP_9000_9XH_X_EU.c b/machine/KP_9000_9XH_X_EU.c index 7209e82b..17562565 100644 --- a/machine/KP_9000_9XH_X_EU.c +++ b/machine/KP_9000_9XH_X_EU.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/KP_9000_9XH_X_EU.h b/machine/KP_9000_9XH_X_EU.h index 2269b8fb..74c20b33 100644 --- a/machine/KP_9000_9XH_X_EU.h +++ b/machine/KP_9000_9XH_X_EU.h @@ -2,5 +2,6 @@ #define _MACHINE_KP_9000_9XH_X_EU_H_ #define MACHINE_MODEL "keepLink KP-9000-9XH-X-EU" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/LIANGUO_HYWS_SGT0108S.c b/machine/LIANGUO_HYWS_SGT0108S.c index aff1713c..1160585a 100644 --- a/machine/LIANGUO_HYWS_SGT0108S.c +++ b/machine/LIANGUO_HYWS_SGT0108S.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {2, 1, 4, 3, 5, 6, 7, 8, 9}, .phys_to_log_port = {1, 0, 3, 2, 4, 5, 6, 7, 8}, diff --git a/machine/LIANGUO_HYWS_SGT0108S.h b/machine/LIANGUO_HYWS_SGT0108S.h index f82bd128..310ee653 100644 --- a/machine/LIANGUO_HYWS_SGT0108S.h +++ b/machine/LIANGUO_HYWS_SGT0108S.h @@ -2,5 +2,6 @@ #define _MACHINE_LIANGUO_HYWS_SGT0108S_H_ #define MACHINE_MODEL "Lianguo HYWS-SGT0108S" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/LIANGUO_ZX_SWTGW215AS.c b/machine/LIANGUO_ZX_SWTGW215AS.c index 70414eca..dfd48f49 100644 --- a/machine/LIANGUO_ZX_SWTGW215AS.c +++ b/machine/LIANGUO_ZX_SWTGW215AS.c @@ -1,11 +1,8 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, + MACHINE_COMMON_SETTING, .mac_flash_offset = 0x1FC000, - .min_port = 3, - .max_port = 8, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/LIANGUO_ZX_SWTGW215AS.h b/machine/LIANGUO_ZX_SWTGW215AS.h index 6c4e2210..840acd4a 100644 --- a/machine/LIANGUO_ZX_SWTGW215AS.h +++ b/machine/LIANGUO_ZX_SWTGW215AS.h @@ -2,5 +2,6 @@ #define _MACHINE_LIANGUO_ZX_SWTGW215AS_H_ #define MACHINE_MODEL "Lianguo ZX-SWTGW215AS" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/ONT_S207CW_62TS_SE.c b/machine/ONT_S207CW_62TS_SE.c index 6ba60778..65e339e6 100644 --- a/machine/ONT_S207CW_62TS_SE.c +++ b/machine/ONT_S207CW_62TS_SE.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 4, 3, 2, 1, 6}, .phys_to_log_port = {7, 6, 5, 4, 3, 8, 0, 0, 0}, diff --git a/machine/ONT_S207CW_62TS_SE.h b/machine/ONT_S207CW_62TS_SE.h index 9938b004..1367900c 100644 --- a/machine/ONT_S207CW_62TS_SE.h +++ b/machine/ONT_S207CW_62TS_SE.h @@ -2,5 +2,6 @@ #define _MACHINE_ONT_S207CW_62TS_SE_H_ #define MACHINE_MODEL "ONT-S207CW-62TS-SE / Binardat 2G06-04210GSM / Binardat 2G06-04210GS" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PB_2132.c b/machine/PB_2132.c index 8822c066..55388d98 100644 --- a/machine/PB_2132.c +++ b/machine/PB_2132.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/PB_2132.h b/machine/PB_2132.h index a3668767..ac50906b 100644 --- a/machine/PB_2132.h +++ b/machine/PB_2132.h @@ -2,5 +2,6 @@ #define _MACHINE_PB_2132_H_ #define MACHINE_MODEL "PB-2132" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/PCB_K0402WS_V1.c b/machine/PCB_K0402WS_V1.c index 0f365025..59b62387 100644 --- a/machine/PCB_K0402WS_V1.c +++ b/machine/PCB_K0402WS_V1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/PCB_K0402WS_V1.h b/machine/PCB_K0402WS_V1.h index d1170aa7..189da400 100644 --- a/machine/PCB_K0402WS_V1.h +++ b/machine/PCB_K0402WS_V1.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_K0402WS_V1_H_ #define MACHINE_MODEL "PCB-K0402WS-V1.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PCB_K0402WS_V2.c b/machine/PCB_K0402WS_V2.c index c37e6201..33a9a93d 100644 --- a/machine/PCB_K0402WS_V2.c +++ b/machine/PCB_K0402WS_V2.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/PCB_K0402WS_V2.h b/machine/PCB_K0402WS_V2.h index eb5337ab..36352e43 100644 --- a/machine/PCB_K0402WS_V2.h +++ b/machine/PCB_K0402WS_V2.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_K0402WS_V2_H_ #define MACHINE_MODEL "PCB-K0402WS-V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PCB_K0402WS_V3.h b/machine/PCB_K0402WS_V3.h index f206079d..b31bd3bb 100644 --- a/machine/PCB_K0402WS_V3.h +++ b/machine/PCB_K0402WS_V3.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_K0402WS_V3_H_ #define MACHINE_MODEL "PCB-K0402WS-V3.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/PCB_SWTG018AS_V2_1_0.c b/machine/PCB_SWTG018AS_V2_1_0.c index 1501de45..1eb77872 100644 --- a/machine/PCB_SWTG018AS_V2_1_0.c +++ b/machine/PCB_SWTG018AS_V2_1_0.c @@ -2,11 +2,8 @@ __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, + MACHINE_COMMON_SETTING, .mac_flash_offset = 0x1FC000, - .min_port = 0, - .max_port = 8, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/PCB_SWTG018AS_V2_1_0.h b/machine/PCB_SWTG018AS_V2_1_0.h index fce78470..546fe4d0 100644 --- a/machine/PCB_SWTG018AS_V2_1_0.h +++ b/machine/PCB_SWTG018AS_V2_1_0.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_SWTG018AS_V2_1_0_H_ #define MACHINE_MODEL "SWTGW218AS (SWTG018AS-V2.1.0)" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/PCB_SWTG024AS_A_2_0_1.c b/machine/PCB_SWTG024AS_A_2_0_1.c index 169e479a..0d20de50 100644 --- a/machine/PCB_SWTG024AS_A_2_0_1.c +++ b/machine/PCB_SWTG024AS_A_2_0_1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/PCB_SWTG024AS_A_2_0_1.h b/machine/PCB_SWTG024AS_A_2_0_1.h index 2d3b5c22..6785140a 100644 --- a/machine/PCB_SWTG024AS_A_2_0_1.h +++ b/machine/PCB_SWTG024AS_A_2_0_1.h @@ -2,5 +2,6 @@ #define _MACHINE_PCB_SWTG024AS_A_2_0_1_H_ #define MACHINE_MODEL "PCB-SWTG024AS-A-2.0.1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/POE_2G080110GS.c b/machine/POE_2G080110GS.c index 73f6dc8c..acd4129f 100644 --- a/machine/POE_2G080110GS.c +++ b/machine/POE_2G080110GS.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/POE_2G080110GS.h b/machine/POE_2G080110GS.h index 40ce3415..3fafc0d5 100644 --- a/machine/POE_2G080110GS.h +++ b/machine/POE_2G080110GS.h @@ -2,5 +2,6 @@ #define _MACHINE_POE_2G080110GS_H_ #define MACHINE_MODEL "MokerLink POE-2G080110GS" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/SIRIVISION_S25G2206FP_V1_1.c b/machine/SIRIVISION_S25G2206FP_V1_1.c new file mode 100644 index 00000000..3f0db022 --- /dev/null +++ b/machine/SIRIVISION_S25G2206FP_V1_1.c @@ -0,0 +1,38 @@ +#include "machine_defs.h" + +__code const struct machine machine = { + MACHINE_COMMON_SETTING, + .n_sfp = 2, + .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, + .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, + .is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1}, + // Left SFP port (J4) + .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, + .sfp_port[0].pin_los = GPIO37, + .sfp_port[0].pin_tx_disable = GPIO_NA, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = I2CBUS( GPIO39_I2C_SDA4, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 39 */ + // Right SFP port (J2) + .sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX, + .sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX, + .sfp_port[1].pin_tx_disable = GPIO_NA, + .sfp_port[1].sds = 0, + .sfp_port[1].i2c = I2CBUS( GPIO41_I2C_SDA3_MDIO1, GPIO40_I2C_SCL3_MDC1 ), /* GPIO 40 */ + .reset_pin = GPIO36_PWM_OUT, + .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 }, + .port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1}, + .led_sets = { + { /* RJ45: Green LED */ + LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, + 0, + /* Amber LED */ + LEDS_2G5 | LEDS_LINK | LEDS_ACT, + 0 + }, { /* SFP PORT: SINGLE GREEN LED */ + LEDS_10M | LEDS_100M | LEDS_1G | LEDS_2G5 | LEDS_10G | LEDS_LINK | LEDS_ACT, + 0, + 0, + 0, + }, + }, +}; diff --git a/machine/SIRIVISION_S25G2206FP_V1_1.h b/machine/SIRIVISION_S25G2206FP_V1_1.h new file mode 100644 index 00000000..7bb5c9a2 --- /dev/null +++ b/machine/SIRIVISION_S25G2206FP_V1_1.h @@ -0,0 +1,7 @@ +#ifndef _MACHINE_SIRIVISION_S25G2206FP_V1_1_H_ +#define _MACHINE_SIRIVISION_S25G2206FP_V1_1_H_ + +#define MACHINE_MODEL "SIRIVISION S25G2206FP V1.1" +#define MACHINE_CHIPSET RTL8372 + +#endif diff --git a/machine/SKS3200_8E1X.c b/machine/SKS3200_8E1X.c new file mode 120000 index 00000000..2eb54be2 --- /dev/null +++ b/machine/SKS3200_8E1X.c @@ -0,0 +1 @@ +PCB_SWTG018AS_V2_1_0.c \ No newline at end of file diff --git a/machine/SKS3200_8E1X.h b/machine/SKS3200_8E1X.h new file mode 100644 index 00000000..ca1e7846 --- /dev/null +++ b/machine/SKS3200_8E1X.h @@ -0,0 +1,8 @@ +#ifndef _MACHINE_SKS3200_8E1X_H_ +#define _MACHINE_SKS3200_8E1X_H_ + +#define MACHINE_MODEL "XikeStor SKS3200-8E1X" +#define MACHINE_CHIPSET RTL8373 + +#endif + diff --git a/machine/STEAMEMO_IG204_V1.c b/machine/STEAMEMO_IG204_V1.c index 23d876a7..a7d765e3 100644 --- a/machine/STEAMEMO_IG204_V1.c +++ b/machine/STEAMEMO_IG204_V1.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/STEAMEMO_IG204_V1.h b/machine/STEAMEMO_IG204_V1.h index 170840d7..752493d2 100644 --- a/machine/STEAMEMO_IG204_V1.h +++ b/machine/STEAMEMO_IG204_V1.h @@ -2,5 +2,6 @@ #define _MACHINE_STEAMEMO_IG204_V1_H_ #define MACHINE_MODEL "Steamemo IG204 V1" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWGT024_V2_0_MANAGED.c b/machine/SWGT024_V2_0_MANAGED.c index ad52bc5b..b3997fd3 100644 --- a/machine/SWGT024_V2_0_MANAGED.c +++ b/machine/SWGT024_V2_0_MANAGED.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/SWGT024_V2_0_MANAGED.h b/machine/SWGT024_V2_0_MANAGED.h index c5f95a04..4ee99e67 100644 --- a/machine/SWGT024_V2_0_MANAGED.h +++ b/machine/SWGT024_V2_0_MANAGED.h @@ -2,5 +2,6 @@ #define _MACHINE_SWGT024_V2_0_MANAGED_H_ #define MACHINE_MODEL "SWGT024 V2.0 Managed" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWGT024_V2_0_UNMANAGED.c b/machine/SWGT024_V2_0_UNMANAGED.c index 9008bb4b..b07f6d8f 100644 --- a/machine/SWGT024_V2_0_UNMANAGED.c +++ b/machine/SWGT024_V2_0_UNMANAGED.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/SWGT024_V2_0_UNMANAGED.h b/machine/SWGT024_V2_0_UNMANAGED.h index 8391b42a..cf286b04 100644 --- a/machine/SWGT024_V2_0_UNMANAGED.h +++ b/machine/SWGT024_V2_0_UNMANAGED.h @@ -2,5 +2,6 @@ #define _MACHINE_SWGT024_V2_0_UNMANAGED_H_ #define MACHINE_MODEL "SWGT024 V2.0 Unmanaged" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWTG018AS_A_V_2_0.c b/machine/SWTG018AS_A_V_2_0.c index 8304bf7e..7d749fde 100644 --- a/machine/SWTG018AS_A_V_2_0.c +++ b/machine/SWTG018AS_A_V_2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, - .min_port = 0, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/SWTG018AS_A_V_2_0.h b/machine/SWTG018AS_A_V_2_0.h index 82b7f632..60c499ec 100644 --- a/machine/SWTG018AS_A_V_2_0.h +++ b/machine/SWTG018AS_A_V_2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTG018AS_A_V_2_0_H_ #define MACHINE_MODEL "SWTG018AS-A V2.0" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/SWTG024AS_A_2_0_1_5C_1SFP.c b/machine/SWTG024AS_A_2_0_1_5C_1SFP.c index 2a3ad97b..de37693e 100644 --- a/machine/SWTG024AS_A_2_0_1_5C_1SFP.c +++ b/machine/SWTG024AS_A_2_0_1_5C_1SFP.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/SWTG024AS_A_2_0_1_5C_1SFP.h b/machine/SWTG024AS_A_2_0_1_5C_1SFP.h index f492765f..6345a9ce 100644 --- a/machine/SWTG024AS_A_2_0_1_5C_1SFP.h +++ b/machine/SWTG024AS_A_2_0_1_5C_1SFP.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTG024AS_A_2_0_1_5C_1SFP_H_ #define MACHINE_MODEL "SWTG024AS-A-V2.0.1-5C-1SFP" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWTG024AS_V2_0.c b/machine/SWTG024AS_V2_0.c index eb0652e2..b1902329 100644 --- a/machine/SWTG024AS_V2_0.c +++ b/machine/SWTG024AS_V2_0.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, diff --git a/machine/SWTG024AS_V2_0.h b/machine/SWTG024AS_V2_0.h index bd37eece..53287e84 100644 --- a/machine/SWTG024AS_V2_0.h +++ b/machine/SWTG024AS_V2_0.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTG024AS_V2_0_H_ #define MACHINE_MODEL "SWTG024AS-V2.0" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/SWTGW218AS.c b/machine/SWTGW218AS.c index cbb2a2f0..0d9d3f6e 100644 --- a/machine/SWTGW218AS.c +++ b/machine/SWTGW218AS.c @@ -2,11 +2,8 @@ __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 1, + MACHINE_COMMON_SETTING, .mac_flash_offset = 0x1FC000, - .min_port = 0, - .max_port = 8, .n_sfp = 1, .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, diff --git a/machine/SWTGW218AS.h b/machine/SWTGW218AS.h index ed9c9e54..33812670 100644 --- a/machine/SWTGW218AS.h +++ b/machine/SWTGW218AS.h @@ -2,5 +2,6 @@ #define _MACHINE_SWTGW218AS_H_ #define MACHINE_MODEL "SWTGW218AS 8+1 Managed Switch" +#define MACHINE_CHIPSET RTL8373 #endif diff --git a/machine/TRENDNET_TEG_S562.c b/machine/TRENDNET_TEG_S562.c index 3cfc12c5..a37bc84a 100644 --- a/machine/TRENDNET_TEG_S562.c +++ b/machine/TRENDNET_TEG_S562.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 2, .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5}, .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, diff --git a/machine/TRENDNET_TEG_S562.h b/machine/TRENDNET_TEG_S562.h index c08ae7a9..724369ea 100644 --- a/machine/TRENDNET_TEG_S562.h +++ b/machine/TRENDNET_TEG_S562.h @@ -2,5 +2,6 @@ #define _MACHINE_TRENDNET_TEG_S562_H_ #define MACHINE_MODEL "Trendnet TEG-S562" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/YS25_0402M.c b/machine/YS25_0402M.c new file mode 120000 index 00000000..ebd3a9a3 --- /dev/null +++ b/machine/YS25_0402M.c @@ -0,0 +1 @@ +SIRIVISION_S25G2206FP_V1_1.c \ No newline at end of file diff --git a/machine/YS25_0402M.h b/machine/YS25_0402M.h new file mode 100644 index 00000000..67550200 --- /dev/null +++ b/machine/YS25_0402M.h @@ -0,0 +1,7 @@ +#ifndef _MACHINE_YS25_0402M_H_ +#define _MACHINE_YS25_0402M_H_ + +#define MACHINE_MODEL "YuanLey YS25-0402M" +#define MACHINE_CHIPSET RTL8372 + +#endif diff --git a/machine/ZX310S_4T2XH.c b/machine/ZX310S_4T2XH.c index f5313e02..583263e4 100644 --- a/machine/ZX310S_4T2XH.c +++ b/machine/ZX310S_4T2XH.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 1, .n_10g = 1, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, diff --git a/machine/ZX310S_4T2XH.h b/machine/ZX310S_4T2XH.h index f0873be3..1f51c9dd 100644 --- a/machine/ZX310S_4T2XH.h +++ b/machine/ZX310S_4T2XH.h @@ -2,5 +2,6 @@ #define _MACHINE_ZX310S_4T2XH_H_ #define MACHINE_MODEL "ZX310S-4T2XH" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/ZX310S_4T2XT.c b/machine/ZX310S_4T2XT.c index c7ec95b9..825cf810 100644 --- a/machine/ZX310S_4T2XT.c +++ b/machine/ZX310S_4T2XT.c @@ -1,10 +1,7 @@ #include "machine_defs.h" __code const struct machine machine = { - .machine_name = MACHINE_MODEL, - .isRTL8373 = 0, - .min_port = 3, - .max_port = 8, + MACHINE_COMMON_SETTING, .n_sfp = 0, .n_10g = 2, .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, diff --git a/machine/ZX310S_4T2XT.h b/machine/ZX310S_4T2XT.h index 15b76217..8903d9f6 100644 --- a/machine/ZX310S_4T2XT.h +++ b/machine/ZX310S_4T2XT.h @@ -2,5 +2,6 @@ #define _MACHINE_ZX310S_4T2XT_H_ #define MACHINE_MODEL "ZX310S_4T2XT" +#define MACHINE_CHIPSET RTL8372 #endif diff --git a/machine/default_machine.h b/machine/default_machine.h index 0919674f..56233fee 100644 --- a/machine/default_machine.h +++ b/machine/default_machine.h @@ -11,7 +11,11 @@ * MACHINE_MODEL is deliberately not defined here: a build that reaches this * header must not silently pick up some default model string. Any code that * needs MACHINE_MODEL therefore fails to compile unless a real machine is - * selected. + * selected. MACHINE_CHIPSET has to be present because machine.h requires it; + * the tests supply their own `machine` object, so the chipset-derived port + * defaults below it are unused. */ +#define MACHINE_CHIPSET RTL8373 + #endif diff --git a/machine/machine_defs.h b/machine/machine_defs.h index 94b989c4..4775a58f 100644 --- a/machine/machine_defs.h +++ b/machine/machine_defs.h @@ -41,4 +41,10 @@ (scl_pin) == GPIO50_I2C_SCL2_UART1_TX ? 2 : \ (scl_pin) == GPIO40_I2C_SCL3_MDC1 ? 3 : I2CBUS_INVALID) +#define MACHINE_COMMON_SETTING \ + .machine_name = MACHINE_MODEL, \ + .isRTL8373 = MACHINE_CHIPSET == RTL8373, \ + .min_port = MACHINE_MIN_PORT, \ + .max_port = MACHINE_MAX_PORT + #endif diff --git a/machine_init.c b/machine_init.c index 0e88002a..efb16e61 100644 --- a/machine_init.c +++ b/machine_init.c @@ -19,6 +19,7 @@ defined(MACHINE_HI_K0402WS) || \ defined(MACHINE_PCB_K0402WS_V2) || \ defined(MACHINE_PCB_K0402WS_V3) || \ + defined(MACHINE_2G5F4_10G2_V1_01) || \ defined(MACHINE_FNS1200P) void machine_custom_init(void) __banked { diff --git a/rtl837x_common.h b/rtl837x_common.h index b0589ca5..4d4047f9 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -142,7 +142,7 @@ extern __xdata bool stp_enabled; * advertises it as the System Name TLV) read it from here. */ extern __xdata char hostname[24]; -extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; +extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; extern __xdata struct uip_eth_addr uip_ethaddr; // Headers for calls in the common code area (HOME/BANK0) diff --git a/rtl837x_igmp.c b/rtl837x_igmp.c index b5513b4d..35940446 100644 --- a/rtl837x_igmp.c +++ b/rtl837x_igmp.c @@ -28,7 +28,7 @@ extern __xdata uint8_t igmpEnabled; extern __xdata uint8_t cpuPort; extern __xdata uint8_t sfr_data[4]; extern __xdata struct machine_runtime machine_detected; -extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2]; +extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; __xdata uint16_t idx; #define IGMP_IP_HDR offsetof(struct igmp_pkt, hlen) diff --git a/rtl837x_lacp.c b/rtl837x_lacp.c index c1bf4dc2..2573bc34 100644 --- a/rtl837x_lacp.c +++ b/rtl837x_lacp.c @@ -21,7 +21,7 @@ extern __code const struct machine machine; extern __xdata struct machine_runtime machine_detected; extern __xdata uint16_t management_vlan; extern __xdata struct uip_eth_addr uip_ethaddr; -extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2]; +extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; /* 20-byte Actor/Partner information body (802.3ad 43.4.2.2), network byte order */ struct lacp_info { diff --git a/rtl837x_nic.c b/rtl837x_nic.c new file mode 100644 index 00000000..af755628 --- /dev/null +++ b/rtl837x_nic.c @@ -0,0 +1,90 @@ +#include "rtl837x_common.h" +#include "rtl837x_regs.h" +#include "rtl837x_sfr.h" +#include "rtl837x_nic.h" + +extern __xdata uint8_t rx_headers[16]; + + +#ifndef RTLP_HOST_TEST +/* One RX DMA operation, starting inside the configured ring. The hardware + * wraps transfers that cross its end; the initial address must be normalized. + * Host tests supply a simulated DMA engine for this hardware boundary. */ +bool nic_rx_dma(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant +{ + uint16_t guard = 0; + + SFR_NIC_DATA_U16LE = (uint16_t)buffer; + SFR_NIC_RING_U16LE = ring_ptr; + SFR_NIC_CTRL = words; + while (SFR_NIC_CTRL != 0) { + if (++guard == 0) { + print_string("NIC: RX transfer did not complete\n"); + return false; + } + } + return true; +} +#endif + +static bool nic_rx_copy(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant +{ + if (ring_ptr > RTL837X_NIC_RX_RING_BYTES || (ring_ptr & 7)) + return false; + if (ring_ptr == RTL837X_NIC_RX_RING_BYTES) + ring_ptr = 0; + + return nic_rx_dma(buffer, ring_ptr, words); +} + + +bool nic_rx_header(uint16_t ring_ptr) __reentrant +{ + if (ring_ptr >= RTL837X_NIC_RX_RING_BYTES) + return false; + return nic_rx_copy(rx_headers, ring_ptr, 1); +} + + +bool nic_rx_packet(__xdata uint8_t *buffer, uint16_t ring_ptr) __reentrant +{ + uint16_t len = ((uint16_t)rx_headers[5] << 8) | rx_headers[4]; + + if (!len || len > UIP_CONF_BUFFER_SIZE) + return false; + return nic_rx_copy(buffer, ring_ptr, (len + 7) >> 3); +} + + +/* + * Transfers data in XMEM to the ASIC for transmission by the NIC + */ +void nic_tx_packet(__xdata uint8_t *buffer, uint16_t len, uint16_t ring_ptr) +{ + uint16_t guard = 0; + + SFR_NIC_DATA_U16LE = (uint16_t)(uintptr_t)buffer; + +#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; + + len += 0xf; + len >>= 3; + SFR_NIC_CTRL = len; + while (SFR_NIC_CTRL != 0) { + if (++guard == 0) { + print_string("NIC: TX transfer did not complete\n"); + return; + } + } +} diff --git a/rtl837x_nic.h b/rtl837x_nic.h new file mode 100644 index 00000000..2eb54d21 --- /dev/null +++ b/rtl837x_nic.h @@ -0,0 +1,20 @@ +#ifndef RTL837X_NIC_H +#define RTL837X_NIC_H + +#include +#include + +// #define RXTXDBG 1 + +bool nic_rx_header(uint16_t ring_ptr) __reentrant; +bool nic_rx_packet(__xdata uint8_t *buffer, uint16_t ring_ptr) __reentrant; + +/* buffer starts at the eight-byte NIC descriptor; len excludes that + * descriptor. ring_ptr is the ASIC TX position in eight-byte slots. */ +void nic_tx_packet(__xdata uint8_t *buffer, uint16_t len, uint16_t ring_ptr); + +/* RX DMA in eight-byte units. ring_ptr must start inside the configured + * RX ring; the hardware wraps transfers that cross its end. */ +bool nic_rx_dma(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant; + +#endif diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 93eb7f44..5527039b 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -147,6 +147,9 @@ */ #define RTL837X_REG_NIC_BUFFSIZE_TX 0x7844 #define RTL837X_REG_NIC_RXBUFF_RX 0x7848 +/* RX ring: inclusive final eight-byte slot, as programmed by nic_setup(). */ +#define RTL837X_NIC_RX_LAST_SLOT 0x04ff +#define RTL837X_NIC_RX_RING_BYTES ((RTL837X_NIC_RX_LAST_SLOT + 1U) * 8U) #define RTL837X_REG_NIC_RXCMD 0x784c #define RTL837X_REG_NIC_TXCMD 0x7850 #define RTL837X_REG_RX_CTRL 0x785c diff --git a/rtl837x_stp.c b/rtl837x_stp.c index ff451f2d..bc810d96 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -30,7 +30,7 @@ extern __xdata struct machine_runtime machine_detected; extern __xdata struct uip_eth_addr uip_ethaddr; -extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2]; +extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE]; extern __xdata uint8_t cmd_words_len; diff --git a/rtlplayground.c b/rtlplayground.c index 06c02ae3..0afa93c8 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -2,7 +2,6 @@ #include // #define REGDBG 1 -// #define RXTXDBG 1 #include "rtl837x_sfr.h" #include "rtl837x_regs.h" @@ -12,6 +11,7 @@ #include "rtl837x_phy.h" #include "rtl837x_port.h" #include "rtl837x_trap.h" +#include "rtl837x_nic.h" #include "rtl837x_stp.h" #include "rtl837x_lacp.h" #include "rtl837x_igmp.h" @@ -123,8 +123,8 @@ __code const uint8_t * __code const hex = "0123456789abcdef"; __xdata uint8_t flash_buf[FLASH_BUF_SIZE]; // NIC buffers for packet RX/TX -__xdata uint8_t rx_headers[16]; // Packet header(s) on RX -__xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; +__xdata uint8_t rx_headers[16]; // RX descriptor +__xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; __xdata uint16_t rx_packet_vlan; __xdata uint16_t management_vlan; @@ -714,108 +714,6 @@ void get_random_32(void) } -/* - * Transfer Network Interface RX data from the ASIC to the 8051 XMEM - * data will be stored in the rx_header structure - * len is the length of data to be transferred - */ -bool nic_rx_header(uint16_t ring_ptr) -{ - uint16_t buffer = (uint16_t) &rx_headers[0]; - uint16_t guard = 0; - - SFR_NIC_DATA_U16LE = buffer; - SFR_NIC_RING_U16LE = ring_ptr; - SFR_NIC_CTRL = 1; - while (SFR_NIC_CTRL != 0) { - if (++guard == 0) { - print_string("NIC: RX header transfer did not complete\n"); - return false; - } - } - return true; -} - - -/* - * Transfer Network Interface RX data from the ASIC to the 8051 XMEM - * the description of the packet must be in the rx_headers data structure - * data will be returned in the xmem buffer points to - * ring_ptr is the current position of the RX Ring on the ASIC side - */ -bool nic_rx_packet(uint16_t buffer, uint16_t ring_ptr) -{ - uint16_t guard = 0; - - SFR_NIC_DATA_U16LE = buffer; - SFR_NIC_RING_U16LE = ring_ptr; - - uint16_t len = (((uint16_t)rx_headers[5]) << 8) | rx_headers[4]; - len += 7; - len >>= 3; -#ifdef RXTXDBG - print_string(" len: "); - print_short(len); -#endif - SFR_NIC_CTRL = len; - while (SFR_NIC_CTRL != 0) { - if (++guard == 0) { - print_string("NIC: RX transfer did not complete\n"); - return false; - } - } - return true; -} - - -/* - * Transfers data in XMEM to the ASIC for transmission by the nic - */ -void nic_tx_packet(uint16_t ring_ptr) -{ - uint16_t len; - uint16_t guard = 0; - - /* A frame that got a dot1Q tag was shifted forward over its padding, so it - * starts at uip_buf and carries the q_frame layout. One that did not keeps - * the padding in front and the nonq_frame layout, so the padding is skipped. - */ - if (frame_tagged) { - 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; - - len += 0xf; - len >>= 3; - SFR_NIC_CTRL = len; - while (SFR_NIC_CTRL != 0) { - if (++guard == 0) { - print_string("NIC: TX transfer did not complete\n"); - return; - } - } -} - - /* Read flash using the MMIO capabilities of the DW8051 core * Bank is < 0x3f and is the MSB * addr gives the address in the bank @@ -999,8 +897,12 @@ void tcpip_output(void) uint16_t ring_ptr = ((uint16_t)sfr_data[2]) << 8; ring_ptr |= sfr_data[3]; - // Move data over from xmem buffer to ASIC side using DMA - nic_tx_packet(ring_ptr); + // Move data over from xmem buffer to ASIC side using DMA. A VLAN-tagged + // frame starts at uip_buf; an untagged frame retains four bytes of padding. + if (frame_tagged) + nic_tx_packet(uip_buf, FRAME_Q->len, ring_ptr); + else + nic_tx_packet(uip_buf + VLAN_TAG_SIZE, FRAME->len, ring_ptr); // New position of the ring-pointer on the NIC-side indicates number of bytes transmitted reg_read_m(RTL837X_REG_NIC_TX_CURR_PKT); @@ -1037,7 +939,7 @@ void handle_rx(void) write_char(' '); } #endif - if (!nic_rx_packet((uint16_t) &uip_buf[0], ring_ptr + 8)) { + if (!nic_rx_packet(uip_buf, ring_ptr + 8)) { REG_SET(RTL837X_REG_NIC_RXCMD, 1); return; } @@ -1684,7 +1586,7 @@ void main(void) // Flash controller should be initialized before any code in other banks is being fetched // See this issue: https://github.com/logicog/RTLPlayground/issues/70 print_string("\nInitializing Flash controller\n"); - flash_init(1); + flash_init(machine.flash_sio ? 0 : 1); // Set default for SFP pins so we can start up a module already inserted sfp_pins_last = 0x33; // signal LOS and no module inserted (for both slots, even if only 1 present) diff --git a/sfp.c b/sfp.c index 05599717..57065289 100644 --- a/sfp.c +++ b/sfp.c @@ -59,8 +59,9 @@ static inline uint8_t sfp_rate_to_sds_config(uint8_t rate) return SDS_1000BX_FIBER; if (rate >= 0x19 && rate <= 0x20) // Ethernet 2.5 GBit return SDS_HSG; - if (rate >= 0x62 && rate < 0x70) + if (rate >= 0x62 /* && rate < 0x70 */) // Force higher rates to 10G (e.g., 25G, 50G) return SDS_10GR; + return 0xff; } diff --git a/test/Makefile b/test/Makefile index cdb27355..5e4dd292 100644 --- a/test/Makefile +++ b/test/Makefile @@ -29,6 +29,7 @@ TESTS = $(BUILDDIR)/test_cmd_editor \ $(BUILDDIR)/test_page_json \ $(BUILDDIR)/test_httpd_tx \ $(BUILDDIR)/test_tick_gate \ + $(BUILDDIR)/test_nic_rx \ $(BUILDDIR)/test_lacp # The table tests link the register mock and one environment file; stub/ @@ -52,6 +53,11 @@ $(BUILDDIR)/test_port_tables: test_port_tables.c $(TABLE_ENV) hw_mock.h | $(BUIL $(BUILDDIR)/test_tick_gate: test_tick_gate.c support.c $(SRCROOT)/cmd_editor.c | $(BUILDDIR) $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) +# Exercise the production RX ring reader; only the hardware DMA edge is mocked. +# Discard unused TX functions so this RX fixture needs no TX register mocks. +$(BUILDDIR)/test_nic_rx: test_nic_rx.c $(SRCROOT)/rtl837x_nic.c $(SRCROOT)/rtl837x_nic.h | $(BUILDDIR) + $(CC) $(CFLAGS) -ffunction-sections -fdata-sections $(filter %.c,$^) -o $@ $(LDFLAGS) -Wl,--gc-sections + $(BUILDDIR)/test_page_json: test_page_json.c $(TABLE_ENV) hw_mock.h | $(BUILDDIR) $(CC) $(CFLAGS) $(filter %.c,$^) -o $@ $(LDFLAGS) diff --git a/test/test_httpd_tx.c b/test/test_httpd_tx.c index 3f056030..f2ea4172 100644 --- a/test/test_httpd_tx.c +++ b/test/test_httpd_tx.c @@ -46,6 +46,9 @@ #define FILE_START FDATA_START_login_html #define FILE_NAME "/login.html" #define FILE_LEN 6000 +#define PROTECTED_FILE_NAME "/index.html" +#define PROTECTED_FILE_START (FILE_START + FILE_LEN + 64) +#define PROTECTED_FILE_LEN 64 #define STREAM_MAX 16384 static int failures; @@ -75,11 +78,17 @@ uint8_t flash_buf[FLASH_BUF_SIZE]; uint8_t rx_headers[16]; struct flash_region_t flash_region; +static uint8_t written_config[CONFIG_LEN]; +static uint16_t written_config_len; +static uint32_t config_erase_addr, config_write_addr; +static int config_erases, config_writes; + const char * const mime_strings[] = { "text/html", "image/svg+xml", "image/x-icon", "image/png", "text/javascript", "text/css", "text/plain" }; const struct f_data f_data[] = { { FILE_NAME, FILE_START, FILE_LEN, mime_HTML, 0 }, + { PROTECTED_FILE_NAME, PROTECTED_FILE_START, PROTECTED_FILE_LEN, mime_HTML, 0 }, { 0, 0, 0, mime_HTML, 0 }, }; @@ -90,11 +99,24 @@ void flash_read_bulk(uint8_t *dst) } void flash_init(uint8_t enable_dio) { (void)enable_dio; } -void flash_sector_erase(void) { } -void flash_write_bytes(uint8_t *ptr) { (void)ptr; } +void flash_sector_erase(void) +{ + config_erases++; + config_erase_addr = flash_region.addr; +} + +void flash_write_bytes(uint8_t *ptr) +{ + config_writes++; + config_write_addr = flash_region.addr; + written_config_len = flash_region.len; + if (written_config_len <= sizeof(written_config)) + memcpy(written_config, ptr, written_config_len); +} const char *get_flash_size_str(void) { return "512 kB"; } void crc16_bank1(uint8_t *v) { (void)v; } -void reset_chip(void) { } +static unsigned reset_calls; +void reset_chip(void) { reset_calls++; } void delay(uint16_t t) { (void)t; } void write_char(char c) { (void)c; } void write_char_no_syslog(char c) { (void)c; } @@ -112,7 +134,7 @@ void read_reg_timer(uint32_t *tmr) { *tmr = 0; } /* uip-conf.h asks uIP not to define the packet buffer: on the switch it lives * at a fixed XDATA address, so the bench provides the storage itself. */ -u8_t uip_buf[UIP_BUFSIZE + 2]; +u8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; uint16_t strlen_x(const char *s) { return (uint16_t)strlen(s); } @@ -156,6 +178,8 @@ void send_vlanlist(void) { } void send_lldp(void) {} extern uint8_t authenticated; +extern char session_id[]; +extern char passwd[21]; /* uip.c defines the listen table but no header declares it; the bench reads it * to confirm the port httpd_init() asked for is the one uIP is watching. */ @@ -362,6 +386,22 @@ static int first_body_mismatch(void) return -1; } +static int stream_contains(const char *needle) +{ + size_t n = strlen(needle); + + for (int i = 0; i + (int)n <= stream_len; i++) + if (!memcmp(stream + i, needle, n)) + return 1; + return 0; +} + +static void login_session_start(void) +{ + session_start(MSS_FULL); + strcpy(passwd, "1234"); +} + static void report(const char *tag) { if (verbose) @@ -493,6 +533,485 @@ static void scenario_bad_l4_checksum(void) "bad checksum control: the file that follows is intact"); } + +/* Private HTTP lifecycle values; drive the real callback, not a model. */ +enum { TSTATE_NONE = 0, TSTATE_TX = 1 }; +extern uint16_t slen, cont_len, sent_len, bindex, crc_final, write_len; +extern uint8_t boundary[], verify_crc, outbuf[]; +extern struct { uint8_t *p; uint16_t bptr, plen; } upload_settings; +extern uint8_t stream_upload(void); + +static void scenario_upload_reset_owner(void) +{ + uint8_t byte = 0; + uint8_t get[] = "GET " FILE_NAME " HTTP/1.1\r\nHost: sw\r\n\r\n"; + int initialized = 1; + + /* The firmware has one TCP slot. Its appstate can contain stale bytes. */ + uip_conn = &uip_conns[0]; + reset_calls = 0; + for (unsigned state = 0; state <= 0xff; state++) { + uip_conn->appstate.tstate = state; + uip_conn->appstate.fw_reset_pending = 0xaa; + uip_flags = UIP_CONNECTED; + httpd_appcall(); + if (uip_conn->appstate.tstate != TSTATE_NONE + || uip_conn->appstate.fw_reset_pending != 0) + initialized = 0; + } + CHECK(initialized, "connect initializes both fields for every stale state"); + CHECK(reset_calls == 0, "connection initialization does not reset"); + + /* End-of-part verdict with flash/CRC hardware edges mocked. */ + boundary[0] = 0; + bindex = 0; + verify_crc = 1; + crc_final = 0xb001; + write_len = 0; + upload_settings.p = &byte; + upload_settings.bptr = 0; + upload_settings.plen = 1; + stream_upload(); + CHECK(uip_conn->appstate.fw_reset_pending == 1, + "verified upload records reset intent in its slot"); + + uip_conn->appstate.tstate = TSTATE_TX; + uip_conn->mss = MSS_FULL; + slen = 10; + sent_len = 5; + cont_len = 0; + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 0 && slen == 5 && sent_len == 5, + "partial verdict ACK sends the remainder without resetting"); + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 1 && slen == 0, + "final verdict ACK resets after all response bytes are acknowledged"); + + /* No verdict ACK: a later connection reuses the same slot. */ + reset_calls = 0; + uip_conn->appstate.tstate = TSTATE_TX; + uip_conn->appstate.fw_reset_pending = 1; + uip_flags = UIP_CONNECTED; + httpd_appcall(); + CHECK(uip_conn->appstate.tstate == TSTATE_NONE + && uip_conn->appstate.fw_reset_pending == 0, + "slot reuse clears an unacknowledged upload's reset intent"); + uip_appdata = get; + uip_len = strlen((char *)get); + uip_flags = UIP_NEWDATA; + httpd_appcall(); + CHECK(uip_conn->appstate.tstate == TSTATE_TX && slen > 0, + "reused slot serves a subsequent plain GET"); + for (unsigned i = 0; i < 20 && uip_conn->appstate.tstate == TSTATE_TX; i++) { + uip_flags = UIP_ACKDATA; + httpd_appcall(); + } + CHECK(reset_calls == 0 && slen == 0 && cont_len == 0, + "subsequent GET response ACKs cannot inherit reset intent"); + + for (unsigned i = 0; i < 2; i++) { + uip_conn->appstate.tstate = TSTATE_TX; + uip_conn->appstate.fw_reset_pending = 1; + reset_calls = 0; + uip_flags = i ? UIP_TIMEDOUT : UIP_ABORT; + httpd_appcall(); + CHECK(reset_calls == 0, "abort/timeout does not reset"); + uip_flags = UIP_CONNECTED; + httpd_appcall(); + CHECK(uip_conn->appstate.tstate == TSTATE_NONE + && uip_conn->appstate.fw_reset_pending == 0, + "connect after abort/timeout clears old upload intent"); + uip_conn->appstate.tstate = TSTATE_TX; + slen = 0; + cont_len = 0; + sent_len = 0; + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 0, "new connection ACK cannot inherit reset"); + } + + crc_final = 0; + bindex = 0; + stream_upload(); + CHECK(uip_conn->appstate.fw_reset_pending == 0, + "failed CRC does not request reset"); + CHECK(strstr((char *)outbuf, "HTTP/1.1 400 Bad Request") != NULL, + "failed CRC returns an error verdict"); + uip_conn->appstate.tstate = TSTATE_TX; + sent_len = slen; + cont_len = 0; + uip_flags = UIP_ACKDATA; + httpd_appcall(); + CHECK(reset_calls == 0, "failed CRC verdict ACK does not reset"); + +} + +static void scenario_fragmented_post_header(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Host: sw\r\n" + "Content-Len"; + static const char second[] = + "gth: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n" + "pwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented header: incomplete first fragment has no response"); + + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 302 Found\r\n"), + "fragmented header: split Content-Length is accepted"); + CHECK(stream_contains("Location: index.html\r\n"), + "fragmented header: login body is parsed after reassembly"); +} + +static void scenario_split_content_type(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Ty"; + static const char second[] = + "pe: application/x-www-form-urlencoded\r\n" + "\r\n" + "pwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "split Content-Type: incomplete header has no response"); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("Location: index.html\r\n"), + "split Content-Type: field name can span receive events"); +} + +static void scenario_split_header_terminator(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r"; + static const char second[] = "\npwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "split terminator: CRLFCR fragment has no premature response"); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("Location: index.html\r\n"), + "split terminator: CRLFCRLF can span receive events"); +} + +static void scenario_header_then_body(void) +{ + static const char header[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, header, (int)strlen(header)); + CHECK(stream_len == 0, + "header-only segment: waits for the declared body"); + client_send(TCP_ACK | TCP_PSH, "pwd=1234", 8); + CHECK(stream_contains("Location: index.html\r\n"), + "header-only segment: following body completes login"); +} + +static void scenario_header_with_partial_body(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "\r\n" + "pwd="; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "partial body: waits when final header segment has only part of body"); + client_send(TCP_ACK | TCP_PSH, "1234", 4); + CHECK(stream_contains("Location: index.html\r\n"), + "partial body: existing body reassembly takes over correctly"); +} + +static void scenario_post_header_timeout(void) +{ + static const char partial[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"; + + login_session_start(); + ticks = 0; + client_send(TCP_ACK | TCP_PSH, partial, (int)strlen(partial)); + CHECK(stream_len == 0, + "header timeout: incomplete header has no immediate response"); + + /* The firmware timeout is 5 seconds; 2000 host ticks is safely beyond it. */ + ticks = 2000; + run_periodic(1); + CHECK(!uip_conn_active(0), + "header timeout: connection is aborted when the header never completes"); +} + +static void scenario_oversized_post_header(void) +{ + static const char start[] = + "POST /login HTTP/1.1\r\n" + "X-Fill: "; + char fill[1200]; + + login_session_start(); + memset(fill, 'a', sizeof(fill)); + client_send(TCP_ACK | TCP_PSH, start, (int)strlen(start)); + + /* Keep extending a header with no CRLFCRLF until the fixed buffer refuses it. */ + for (int i = 0; i < 16 && !stream_contains("400 Bad Request"); i++) + client_send(TCP_ACK | TCP_PSH, fill, (int)sizeof(fill)); + + CHECK(stream_contains("HTTP/1.1 400 Bad Request\r\n"), + "oversized header: rejected before the header buffer overflows"); +} + +static void scenario_fragmented_missing_content_length(void) +{ + static const char first[] = + "POST /login HTTP/1.1\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"; + static const char second[] = "\r\npwd=1234"; + + login_session_start(); + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 411 Length Required\r\n"), + "fragmented header: missing Content-Length still returns 411"); +} + + +static void scenario_fragmented_get_cookie(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n" + "Cook"; + static const char second[] = + "ie: session=0123456789ab\r\n" + "\r\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented GET cookie: no redirect before the header completes"); + + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 200 OK\r\n"), + "fragmented GET cookie: protected index is served"); + CHECK(!stream_contains("Location: login.html\r\n"), + "fragmented GET cookie: session is not lost on the redirected GET"); +} + +static void scenario_fragmented_get_cookie_value(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n" + "Cookie: session=012345"; + static const char second[] = + "6789ab\r\n" + "\r\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented GET cookie value: waits for the rest of the header"); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 200 OK\r\n"), + "fragmented GET cookie value: split session value authenticates"); +} + +static void scenario_split_get_header_terminator(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Cookie: session=0123456789ab\r\n" + "\r"; + static const char second[] = "\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + CHECK(stream_len == 0, + "fragmented GET terminator: CRLFCR does not trigger parsing"); + client_send(TCP_ACK | TCP_PSH, second, 1); + CHECK(stream_contains("HTTP/1.1 200 OK\r\n"), + "fragmented GET terminator: CRLFCRLF may span receive events"); +} + +static void scenario_fragmented_get_without_cookie(void) +{ + static const char first[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n"; + static const char second[] = "\r\n"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + + client_send(TCP_ACK | TCP_PSH, first, (int)strlen(first)); + client_send(TCP_ACK | TCP_PSH, second, (int)strlen(second)); + CHECK(stream_contains("HTTP/1.1 302 Found\r\n"), + "fragmented GET without cookie: protected file still redirects"); + CHECK(stream_contains("Location: login.html\r\n"), + "fragmented GET without cookie: authentication is not carried over"); +} + +static void scenario_get_header_timeout(void) +{ + static const char partial[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Host: sw\r\n" + "Cookie: session=012345"; + + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + ticks = 0; + + client_send(TCP_ACK | TCP_PSH, partial, (int)strlen(partial)); + CHECK(stream_len == 0, + "fragmented GET timeout: incomplete header has no immediate response"); + + ticks = 2000; + run_periodic(1); + CHECK(!uip_conn_active(0), + "fragmented GET timeout: incomplete request is eventually aborted"); +} + +static void scenario_oversized_get_header(void) +{ + static const char start[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "X-Fill: "; + char fill[1200]; + + session_start(MSS_FULL); + memset(fill, 'a', sizeof(fill)); + + client_send(TCP_ACK | TCP_PSH, start, (int)strlen(start)); + for (int i = 0; i < 16 && !stream_contains("400 Bad Request"); i++) + client_send(TCP_ACK | TCP_PSH, fill, (int)sizeof(fill)); + + CHECK(stream_contains("HTTP/1.1 400 Bad Request\r\n"), + "oversized GET header: fixed header buffer is bounds checked"); +} + +static void scenario_split_method_names(void) +{ + static const char get[] = + "GET " PROTECTED_FILE_NAME " HTTP/1.1\r\n" + "Cookie: session=0123456789ab\r\n\r\n"; + static const char post[] = + "POST /login HTTP/1.1\r\n" + "Content-Length: 8\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n\r\n" + "pwd=1234"; + int get_waits = 1, get_ok = 1, post_waits = 1, post_ok = 1; + + for (int split = 1; split < 3; split++) { + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + client_send(TCP_ACK | TCP_PSH, get, split); + if (stream_len) + get_waits = 0; + client_send(TCP_ACK | TCP_PSH, get + split, (int)strlen(get) - split); + if (!stream_contains("HTTP/1.1 200 OK\r\n")) + get_ok = 0; + } + CHECK(get_waits, "split GET method: incomplete verb waits for the header"); + CHECK(get_ok, "split GET method: every split inside GET serves the file"); + + for (int split = 1; split < 4; split++) { + login_session_start(); + client_send(TCP_ACK | TCP_PSH, post, split); + if (stream_len) + post_waits = 0; + client_send(TCP_ACK | TCP_PSH, post + split, (int)strlen(post) - split); + if (!stream_contains("Location: index.html\r\n")) + post_ok = 0; + } + CHECK(post_waits, "split POST method: incomplete verb waits for the header"); + CHECK(post_ok, "split POST method: every split inside POST completes login"); +} + +static void scenario_config_upload(void) +{ + static const char expected[] = "hostname upload-test\nip 10.0.0.1\n"; + static const char body[] = + "--upload-boundary\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"config.txt\"\r\n" + "Content-Type: text/plain\r\n\r\n" + "hostname upload-test\nip 10.0.0.1\n" + "\r\n--upload-boundary--\r\n"; + char request[768]; + int request_len, first_bad_response = -1, first_bad_flash = -1; + + request_len = snprintf(request, sizeof(request), + "POST /config HTTP/1.1\r\n" + "Host: sw\r\n" + "Cookie: session=0123456789ab\r\n" + "Content-Type: multipart/form-data; boundary=upload-boundary\r\n" + "Content-Length: %zu\r\n\r\n%s", sizeof(body) - 1, body); + if (request_len < 0 || request_len >= (int)sizeof(request)) { + CHECK(0, "multipart/config: test request fits the client buffer"); + return; + } + + /* The same well-formed request must work in one event and with a split + * anywhere in its HTTP header, first multipart delimiter, part headers, + * configuration, or closing delimiter. No extra CRLF is added to the body. */ + for (int split = 0; split <= request_len; split++) { + session_start(MSS_FULL); + strcpy(session_id, "0123456789ab"); + config_erases = config_writes = 0; + written_config_len = 0; + memset(written_config, 0xa5, sizeof(written_config)); + if (split) + client_send(TCP_ACK | TCP_PSH, request, split); + if (split < request_len) + client_send(TCP_ACK | TCP_PSH, request + split, request_len - split); + if (!stream_contains("HTTP/1.1 200 OK\r\n") && first_bad_response < 0) + first_bad_response = split; + if ((config_erases != 1 || config_writes != 1 + || config_erase_addr != CONFIG_START || config_write_addr != CONFIG_START + || written_config_len != sizeof(expected) + || memcmp(written_config, expected, sizeof(expected))) && first_bad_flash < 0) + first_bad_flash = split; + } + if (first_bad_response >= 0) + printf(" multipart/config: first rejected request split at byte %d\n", first_bad_response); + if (first_bad_flash >= 0) + printf(" multipart/config: first incorrect flash write at split %d\n", first_bad_flash); + CHECK(first_bad_response < 0, + "multipart/config: complete request and every two-event split return 200"); + CHECK(first_bad_flash < 0, + "multipart/config: every split writes the exact configuration and NUL to its sector"); +} + int main(int argc, char **argv) { if (argc > 1 && !strcmp(argv[1], "-v")) @@ -504,6 +1023,23 @@ int main(int argc, char **argv) scenario_growing_window(); scenario_rexmit_after_shrink(); scenario_bad_l4_checksum(); + scenario_upload_reset_owner(); + scenario_fragmented_post_header(); + scenario_split_content_type(); + scenario_split_header_terminator(); + scenario_header_then_body(); + scenario_header_with_partial_body(); + scenario_post_header_timeout(); + scenario_oversized_post_header(); + scenario_fragmented_missing_content_length(); + scenario_fragmented_get_cookie(); + scenario_fragmented_get_cookie_value(); + scenario_split_get_header_terminator(); + scenario_fragmented_get_without_cookie(); + scenario_get_header_timeout(); + scenario_oversized_get_header(); + scenario_split_method_names(); + scenario_config_upload(); printf("\n%s (%d failure%s)\n", failures ? "BENCH: FAILURES" : "BENCH: ALL PASS", diff --git a/test/test_lacp.c b/test/test_lacp.c index dbadea04..160c773e 100644 --- a/test/test_lacp.c +++ b/test/test_lacp.c @@ -11,7 +11,7 @@ /* ---------- platform mocks ---------- */ -uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2]; +uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; uint16_t uip_len; struct uip_eth_addr uip_ethaddr = { .addr = {0x02,0x11,0x22,0x33,0x44,0x55} }; const struct machine machine = { .min_port = 0, .max_port = 7, diff --git a/test/test_nic_rx.c b/test/test_nic_rx.c new file mode 100644 index 00000000..4ad36310 --- /dev/null +++ b/test/test_nic_rx.c @@ -0,0 +1,277 @@ +#include +#include +#include +#include + +#include "rtl837x_common.h" +#include "rtl837x_regs.h" +#include "rtl837x_nic.h" + +uint8_t rx_headers[16]; + +/* Model the DMA behavior reported on SWTGW218AS: a transfer starting inside + * the RX ring wraps at its end. An initial address outside the ring instead + * reads flat ASIC memory, including stale TX bytes at 0x2800. */ +static uint8_t asic[0x8000]; +static struct { + uint8_t before[16]; + uint8_t data[UIP_CONF_BUFFER_ALLOC_SIZE]; + uint8_t after[16]; +} destination; + +struct dma_request { + uint8_t *buffer; + uint16_t ring; + uint8_t words; +}; +static struct dma_request requests[8]; +static unsigned request_count, fail_request; +static int failures; + +static void check(bool condition, const char *what) +{ + if (!condition) { + printf(" FAIL: %s\n", what); + failures++; + } +} + +bool nic_rx_dma(uint8_t *buffer, uint16_t ring, uint8_t words) +{ + size_t bytes = (size_t)words * 8; + unsigned call = ++request_count; + + if (call <= sizeof(requests) / sizeof(requests[0])) + requests[call - 1] = (struct dma_request){ buffer, ring, words }; + if (call == fail_request || !words || (size_t)ring + bytes > sizeof(asic)) + return false; + if (ring < RTL837X_NIC_RX_RING_BYTES) { + for (size_t i = 0; i < bytes; i++) + buffer[i] = asic[((size_t)ring + i) % RTL837X_NIC_RX_RING_BYTES]; + } else { + memcpy(buffer, asic + ring, bytes); + } + return true; +} + +static void fixture_reset(void) +{ + memset(asic, 0xd7, sizeof(asic)); + memset(&destination, 0xa5, sizeof(destination)); + memset(rx_headers, 0x6c, sizeof(rx_headers)); + memset(requests, 0, sizeof(requests)); + request_count = 0; + fail_request = 0; +} + +static bool filled(const uint8_t *data, size_t len, uint8_t value) +{ + while (len--) + if (*data++ != value) + return false; + return true; +} + +static bool guards_intact(void) +{ + return filled(destination.before, sizeof(destination.before), 0xa5) + && filled(destination.after, sizeof(destination.after), 0xa5); +} + +static bool requests_start_in_rx_ring(void) +{ + for (unsigned i = 0; i < request_count; i++) { + if (i >= sizeof(requests) / sizeof(requests[0]) || !requests[i].words + || (requests[i].ring & 7) + || requests[i].ring >= RTL837X_NIC_RX_RING_BYTES) + return false; + } + return true; +} + +static void ring_write(uint16_t offset, const uint8_t *data, size_t len) +{ + for (size_t i = 0; i < len; i++) + asic[((size_t)offset + i) % RTL837X_NIC_RX_RING_BYTES] = data[i]; +} + +static void put_descriptor(uint16_t offset, uint16_t len) +{ + uint8_t descriptor[8] = { 0x03, 0x00, 0xb0, 0xc8, len, len >> 8, 0, 0 }; + ring_write(offset, descriptor, sizeof(descriptor)); +} + +static void expect_descriptor(uint16_t len) +{ + uint8_t descriptor[8] = { 0x03, 0x00, 0xb0, 0xc8, len, len >> 8, 0, 0 }; + check(!memcmp(rx_headers, descriptor, sizeof(descriptor)), "the first eight descriptor bytes stay intact"); +} + +static void pattern(uint8_t *data, size_t len) +{ + for (size_t i = 0; i < len; i++) + data[i] = (uint8_t)(i * 37 + (i >> 8) + 0x13); +} + +static void t_last_descriptor(void) +{ + static const uint8_t root_bpdu[68] = { + 0x01, 0x80, 0xc2, 0, 0, 0, 0xd0, 0xea, 0x11, 0x12, 0x34, 0x56, + 0x88, 0x99, 0x04, 0, 0, 0, 0, 8, + 0, 0x27, 0x42, 0x42, 3, 0, 0, 2, 2, 0x3c, + 0x10, 0, 0xd0, 0xea, 0x11, 0x12, 0x34, 0x56, 0, 0, 0, 0, + 0x10, 0, 0xd0, 0xea, 0x11, 0x12, 0x34, 0x56, 0x80, 0x0a, + 0, 0, 0x14, 0, 2, 0, 0x0f, 0, 0 + }; + uint8_t stale_tx[72] = { 0 }; + uint16_t last = RTL837X_NIC_RX_RING_BYTES - 8; + + printf("[test] the last RX descriptor wraps its BPDU payload before DMA\n"); + fixture_reset(); + put_descriptor(last, sizeof(root_bpdu)); + ring_write(0, root_bpdu, sizeof(root_bpdu)); + memcpy(stale_tx, root_bpdu, sizeof(root_bpdu)); + stale_tx[17] = 0x20; + stale_tx[19] = 1; /* retained TX destination mask, not ingress port 8 */ + memcpy(asic + RTL837X_NIC_RX_RING_BYTES, stale_tx, sizeof(stale_tx)); + check(nic_rx_header(last), "the final descriptor is readable"); + expect_descriptor(sizeof(root_bpdu)); + check(nic_rx_packet(destination.data, last + 8), "a payload address at the RX ring limit wraps to zero"); + check(!memcmp(destination.data, root_bpdu, sizeof(root_bpdu)), "the complete upstream BPDU is read instead of stale TX bytes"); + check(destination.data[19] == 8, "the upstream ingress tag survives the ring boundary"); + check(request_count == 2 && requests[0].ring == last && requests[0].words == 1 + && requests[1].ring == 0 && requests[1].words == 9, + "descriptor and rounded payload DMA both start in the RX ring"); + check(requests_start_in_rx_ring() && guards_intact(), "DMA starts inside the RX ring and preserves destination guards"); + expect_descriptor(sizeof(root_bpdu)); +} + +static void t_payload_layouts(void) +{ + static const struct { + uint16_t descriptor, len; + } cases[] = { + { 0x0100, 8 }, { 0x0100, 16 }, { 0x0100, 64 }, + { 0x0100, 68 }, { 0x0100, 72 }, + { RTL837X_NIC_RX_RING_BYTES - 16, 8 }, + { RTL837X_NIC_RX_RING_BYTES - 16, 16 }, + { RTL837X_NIC_RX_RING_BYTES - 16, 68 }, + { RTL837X_NIC_RX_RING_BYTES - 72, 64 }, + { RTL837X_NIC_RX_RING_BYTES - 48, 68 } + }; + uint8_t frame[80]; + + printf("[test] payload DMA handles ordinary, exact-boundary, and crossing frames\n"); + pattern(frame, sizeof(frame)); + for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + size_t rounded = (cases[i].len + 7u) & ~7u; + fixture_reset(); + put_descriptor(cases[i].descriptor, cases[i].len); + ring_write(cases[i].descriptor + 8, frame, rounded); + check(nic_rx_header(cases[i].descriptor), "the descriptor transfer completes"); + check(nic_rx_packet(destination.data, cases[i].descriptor + 8), "the payload transfer completes"); + check(!memcmp(destination.data, frame, rounded), "every payload and permitted padding byte reaches the correct destination offset"); + check(filled(destination.data + rounded, sizeof(destination.data) - rounded, 0xa5), "DMA does not write beyond the rounded frame"); + check(request_count == 2, "the payload uses one DMA request even when crossing the ring end"); + check(requests_start_in_rx_ring() && guards_intact(), "crossing DMA starts inside the RX ring and preserves destination guards"); + expect_descriptor(cases[i].len); + } +} + +static void t_maximum_frames(void) +{ + uint8_t frame[(UIP_CONF_BUFFER_SIZE + 7u) & ~7u]; + static const uint16_t lengths[] = { 1, 7, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556 }; + + printf("[test] rounded maximum frames fit without overwriting their descriptor\n"); + pattern(frame, sizeof(frame)); + for (unsigned layout = 0; layout < 3; layout++) { + uint16_t descriptor = layout == 0 ? 0x0100 + : RTL837X_NIC_RX_RING_BYTES - (layout == 1 ? 16 : 8); + for (unsigned i = 0; i < sizeof(lengths) / sizeof(lengths[0]); i++) { + uint16_t len = lengths[i]; + size_t rounded = (len + 7u) & ~7u; + fixture_reset(); + put_descriptor(descriptor, len); + ring_write(descriptor + 8, frame, rounded); + check(nic_rx_header(descriptor), "the maximum-frame descriptor transfer completes"); + check(nic_rx_packet(destination.data, descriptor + 8), "all supported frame lengths fit the destination"); + check(!memcmp(destination.data, frame, rounded), "the full rounded frame is preserved"); + check(filled(destination.data + rounded, sizeof(destination.data) - rounded, 0xa5), "rounded DMA writes no bytes beyond the available destination"); + check(request_count == 2, "maximum frames use a single payload DMA request"); + check(requests_start_in_rx_ring() && guards_intact(), "rounded DMA starts inside the RX ring and preserves destination guards"); + expect_descriptor(len); + } + } +} + +static void t_invalid_frames(void) +{ + static const uint16_t invalid_lengths[] = { 0, UIP_CONF_BUFFER_SIZE + 1, 0xffff }; + static const uint16_t invalid_pointers[] = { 1, 7, RTL837X_NIC_RX_RING_BYTES + 8, 0xfff8 }; + + printf("[test] invalid lengths and DMA addresses are rejected before transfer\n"); + for (unsigned i = 0; i < sizeof(invalid_lengths) / sizeof(invalid_lengths[0]); i++) { + fixture_reset(); + rx_headers[4] = invalid_lengths[i]; + rx_headers[5] = invalid_lengths[i] >> 8; + check(!nic_rx_packet(destination.data, 0x0100), "unsupported or overflowing lengths are rejected"); + check(!request_count && filled(destination.data, sizeof(destination.data), 0xa5) && guards_intact(), + "invalid frame lengths cause no DMA or destination changes"); + } + for (unsigned i = 0; i < sizeof(invalid_pointers) / sizeof(invalid_pointers[0]); i++) { + fixture_reset(); + rx_headers[4] = 68; + rx_headers[5] = 0; + check(!nic_rx_header(invalid_pointers[i]), "an invalid descriptor address is rejected"); + check(!nic_rx_packet(destination.data, invalid_pointers[i]), "an invalid payload address is rejected"); + check(!request_count && guards_intact(), "invalid addresses never reach DMA"); + } + fixture_reset(); + check(!nic_rx_header(RTL837X_NIC_RX_RING_BYTES) && !request_count, + "a descriptor at the ring limit is rejected rather than wrapped"); +} + +static void t_dma_failure(void) +{ + uint8_t frame[UIP_CONF_BUFFER_ALLOC_SIZE]; + static const uint16_t lengths[] = { 68, UIP_CONF_BUFFER_SIZE }; + + printf("[test] failed descriptor and single-payload DMA transfers propagate failure\n"); + fixture_reset(); + fail_request = 1; + check(!nic_rx_header(0x0100) && request_count == 1, "descriptor DMA failure reaches the caller"); + pattern(frame, sizeof(frame)); + for (unsigned layout = 0; layout < 3; layout++) { + uint16_t descriptor = layout == 0 ? 0x0100 + : RTL837X_NIC_RX_RING_BYTES - (layout == 1 ? 16 : 8); + for (unsigned i = 0; i < sizeof(lengths) / sizeof(lengths[0]); i++) { + uint16_t len = lengths[i]; + fixture_reset(); + put_descriptor(descriptor, len); + ring_write(descriptor + 8, frame, (len + 7u) & ~7u); + check(nic_rx_header(descriptor), "the descriptor precedes the injected payload failure"); + fail_request = 2; + check(!nic_rx_packet(destination.data, descriptor + 8), "payload DMA failure reaches the caller"); + check(request_count == fail_request, "a failed payload DMA is not retried or split"); + check(filled(destination.data, sizeof(destination.data), 0xa5) && guards_intact(), + "an injected failure before DMA preserves the destination and guards"); + expect_descriptor(len); + } + } +} + +int main(void) +{ + t_last_descriptor(); + t_payload_layouts(); + t_maximum_frames(); + t_invalid_frames(); + t_dma_failure(); + if (failures) { + printf("%d NIC RX check(s) failed\n", failures); + return 1; + } + puts("all NIC RX checks passed"); + return 0; +} diff --git a/uip/uip-conf.h b/uip/uip-conf.h index 9e87fda2..f93e6bd7 100644 --- a/uip/uip-conf.h +++ b/uip/uip-conf.h @@ -132,6 +132,10 @@ typedef unsigned short uip_stats_t; */ #define UIP_CONF_BUFFER_SIZE 1556 +/* Backing storage includes padding for the NIC's eight-byte DMA transfers. + * Keep UIP_CONF_BUFFER_SIZE as the logical frame/MSS limit. */ +#define UIP_CONF_BUFFER_ALLOC_SIZE ((UIP_CONF_BUFFER_SIZE + 7U) & ~7U) + /** * Bytes of the buffer kept out of the advertised MSS. * diff --git a/uip/uip.c b/uip/uip.c index 774067da..c8d0f20b 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -136,7 +136,7 @@ static __code const uip_ipaddr_t all_zeroes_addr = #endif /* UIP_CONF_IPV6 */ #ifndef UIP_CONF_EXTERNAL_BUFFER -u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains +u8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; /* The packet buffer that contains incoming packets. */ #endif /* UIP_CONF_EXTERNAL_BUFFER */ diff --git a/uip/uipopt.h b/uip/uipopt.h index 620d6054..84ea318c 100644 --- a/uip/uipopt.h +++ b/uip/uipopt.h @@ -419,7 +419,7 @@ #endif /* UIP_CONF_BUFFER_EXTRA */ -extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; +extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_ALLOC_SIZE]; /** * Determines if statistics support should be compiled in.