mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-09-02 15:02:51 +08:00
Review asked for this directly: the hardware layout above port_l2mc_set() would be better as documentation than as a comment, keeping only the two lines that say what the function does. doc/l2.md gains a section on static multicast entries, why delivery uses the forward action rather than the trap, and the SMI layout of the entry. doc/CpuPort.md gains the layout of the tag's flags and pmask words, with the byte order trap that cost an afternoon: writing the flags constant raw instead of through HTONS puts 0x0020 on the wire as 0x2000, which is EFID rather than LEARN_DIS, and the ASIC then leaves the 0x8899 header on the frame. The comments those paragraphs came from are replaced by a pointer to the file that now holds them.
97 lines
3.9 KiB
Markdown
97 lines
3.9 KiB
Markdown
# The CPU Port
|
|
|
|
The RTL827x provide a CPU Port for a NIC on the 8051 side of the SoC.
|
|
|
|
## Receiving packets
|
|
In order to receive packets on the ASIC side, bit 0 of RTL837X_REG_RX_CTRL
|
|
(0x785c) must be set. Further bits in the register enable reception of various
|
|
kinds of Ethernet frames. They should all be set in order for the firmware
|
|
to decide what to do with them. To drop packets with incorrect Ethernet frame CRC
|
|
already by the ASIC, clear bit 2 of this register.
|
|
|
|
Packets are received by either polling the RTL837X_REG_RX_AVAIL register
|
|
(0x7874), which will be > 0 if data is within a ring-buffer on the ASIC side
|
|
of the SoC. Alternatively, an interrupt can be triggered (EX1).
|
|
|
|
Data is transferred to the 8051 side by calling an SFR function. First, the
|
|
frame header of the received frame will be copied over. For this, provide
|
|
the destination memory location in xdata memory in SFRs B3 and B4 (little
|
|
endian), the source location on the ASIC-side in SFRs B5/B6 (also little
|
|
endian, found in RTL837X_REG_RX_RINGPTR, 0x787c) and execute the function
|
|
by setting SFR_NIC_CTRL (B7) to the length to be transferred divided by 8,
|
|
i.e. 1.
|
|
|
|
The frame header has the following format:
|
|
```
|
|
SS xx xx xP LL LH xx xx
|
|
SS: 8-bit sequence number
|
|
P: Port number
|
|
LHLL: Length of Ethernet frame (little endian)
|
|
xx: Unknown
|
|
```
|
|
|
|
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 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
|
|
starts. A documentation can be found here:
|
|
[TAG8899_COMMIT](https://github.com/torvalds/linux/commit/1521d5adfc2b557e15f97283c8b7ad688c3ebc40)
|
|
|
|
After copying over header and frame, the frame is marked read in the ring
|
|
buffer on the ASIC side by writing 0x1 to RTL837X_REG_RX_DONE (0x784c).
|
|
|
|
## Transmissing packets
|
|
Packets are transmitted by preparing a frame-header plus frame in xdata memory
|
|
and transferring both to the ASIC side via the SFRs. The ASIC will transmit
|
|
packets if bit 0 of RTL837X_REG_TX_CTRL (0x7860) is set.
|
|
|
|
```
|
|
SS 07 00 00 LL LH 00 00
|
|
SS: 8-bit sequence number
|
|
07: Enables header and TCP checksum offloading to ASIC
|
|
LHLL: Length of the Ethernet frame
|
|
```
|
|
The Ethernet frame data starts immediately after the frame header in xdata
|
|
memory. The frame is transferred to the ASIC side by setting SFRs B3 and B4
|
|
to the xdata source address of the frame header, and the ring pointer to the
|
|
free space indicated by register 0x7890 multiplied by 8 and the MSB set.
|
|
The length is given by the length of the frame plus 15, divided by 8.
|
|
|
|
Writing 0x1 to register 0x7850 will transmit the frame. The Ethernet frame
|
|
checksum and the TCP checksum are automatically calculated (offloaded) by the
|
|
ASIC before transmitting on the wire.
|
|
|
|
|
|
## The RTL tag words
|
|
|
|
The frame header uses the Realtek Remote Control Protocol (RRCP) format or
|
|
the like.
|
|
|
|
The `flags` word:
|
|
|
|
```
|
|
bit15 EFID_EN | 14:12 EFID | 11 PRI_EN | 10:8 PRI |
|
|
bit7 KEEP | 6 VSEL | 5 LEARN_DIS | 4:0 VIDX
|
|
```
|
|
|
|
All fields are in network byte order.
|
|
|
|
* `EFID_EN`, `EFID`: look the destination up under this filtering ID
|
|
instead of the port's own
|
|
* `PRI_EN`, `PRI`: force the given priority on the frame
|
|
* `KEEP`: keep the 802.1Q tagging of the frame exactly as injected,
|
|
bypassing the egress tagging rules of the port
|
|
* `VSEL`, `VIDX`: classify the frame into the VLAN at this index of the
|
|
VLAN table
|
|
* `LEARN_DIS`: do not learn the source address from this frame
|
|
|
|
The `pmask` word: bit 15 is `ALLOW`, bits 14 to 0 are a port mask.
|
|
|
|
* `ALLOW` clear: the mask is the egress set, the frame goes to exactly
|
|
the ports given
|
|
* `ALLOW` set: the ASIC looks the destination up as usual and the mask
|
|
only limits which ports the result may use
|