net: an RTL8139 driver, and the e1000 stops refusing the PCIe parts
Two NICs, and unlike the RTL8111 last commit, QEMU emulates both -- so both are tested rather than reasoned about. **RTL8139** is its own driver and not a mode of the 8169, because it is its own chip. No descriptor rings: the receiver is one circular buffer the chip writes packets into back to back behind four-byte headers, and the transmitter is four fixed slots. Putting both programming models behind one set of function pointers is how a mode flag ends up threaded through every path. Three details are the whole driver. CAPR runs sixteen bytes behind the true read position -- a quirk of the part, not an off-by-one. WRAP means the chip runs a packet past the end of the buffer rather than splitting it, so the 8 KB buffer is allocated as 8 KB + 16 + one maximum frame; getting that wrong is a chip writing past its allocation at line rate. And a length field of 0xFFF0 means "still writing this one", so treating it as a length copies a partial packet and loses the alignment for everything after it. **The e1000 now matches the PCIe 8257x parts.** Its header refused them, with a note saying they "differ in NVM access and initialisation, and claiming a device this driver has not been shown to initialise is worse than not claiming it". That was right, and the second half is answerable: QEMU emulates the 82574L, so it can be *shown* to initialise. What differs turned out to be one register. EERD moved its address field from bits 8-15 to bits 2-15 and its done bit from 4 to 1; the rings, RCTL, TCTL and ICR are identical. So there is a per-instance flag for the NVM layout and seven more ids -- not a second copy of four hundred lines of ring code. The wrong pair of constants fails silently, reading the wrong word or waiting for a bit that never sets, and the MAC comes out as zeroes; that is why it is named in the header rather than papered over. Still refused: the ICH/PCH parts (82562, 82577-82579, I217-I219), which put the PHY behind a MAC-PHY interconnect and need a different bring-up nothing here can test. Tested, each booted alone: rtl8139 (10ec:8139) and 82574L (8086:10d3) both bind, read a real MAC, complete DHCP and ping 4 of 4 with no loss. The classic 82540EM does the same, which is the regression that mattered for the NVM change. Both supported display configurations: one boot each, no traps, no panics, socktest and memfdtest green. Also recorded: the Chromebox CN62 carries an RTL8111, not an Intel part, so last commit's driver covers it too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4a723cfc0e
commit
0331d548c4
6 changed files with 530 additions and 8 deletions
|
|
@ -29,6 +29,55 @@ that completes a handshake and drops every byte.
|
|||
└────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Intel e1000, and the PCIe generation it used to refuse
|
||||
|
||||
`drivers/net/e1000/` matched the 8254x parts and deliberately refused the PCIe
|
||||
8257x, with a note saying they "differ in NVM access and initialisation, and
|
||||
claiming a device this driver has not been shown to initialise is worse than
|
||||
not claiming it".
|
||||
|
||||
That was right, and the second half of it is answerable: QEMU emulates the
|
||||
**82574L**, so the part can be shown to initialise rather than assumed to. What
|
||||
actually differs turned out to be **one register**. `EERD` moved its address
|
||||
field from bits 8-15 to bits 2-15 and its done bit from 4 to 1; the descriptor
|
||||
rings, `RCTL`, `TCTL` and the interrupt cause register are identical. So the
|
||||
8257x ids are matched now, with a per-instance flag for the NVM layout — not a
|
||||
second copy of four hundred lines of ring code.
|
||||
|
||||
Using the wrong pair of constants does not fail loudly, which is why it is
|
||||
named rather than papered over: it reads the wrong word or waits for a bit that
|
||||
will never be set, and the MAC comes out as zeroes.
|
||||
|
||||
Still refused: the ICH/PCH parts (82562, 82577-82579, I217-I219). Those put the
|
||||
PHY behind a MAC-PHY interconnect and need a genuinely different bring-up, and
|
||||
nothing here can test one.
|
||||
|
||||
|
||||
## Realtek RTL8139 — `drivers/net/rtl8139/`
|
||||
|
||||
A separate driver from the RTL8111 next door, despite the neighbouring name,
|
||||
because it is a different chip. The 8139 has **no descriptor rings**: the
|
||||
receiver is one circular buffer the chip writes packets into back to back, each
|
||||
behind a four-byte header, and the transmitter is four fixed slots used
|
||||
round-robin. Sharing a driver with the 8169 would put two programming models
|
||||
behind one set of function pointers, which is how a mode flag ends up threaded
|
||||
through every path.
|
||||
|
||||
Three details that are the whole driver:
|
||||
|
||||
- **`CAPR` runs sixteen bytes behind.** The register that tells the chip how
|
||||
far the driver has read is offset by 16 — a quirk of the part, not an
|
||||
off-by-one, and the buffer is allocated with that padding in mind.
|
||||
- **`WRAP` means the allocation is bigger than the buffer.** With it set the
|
||||
chip runs a packet past the end rather than splitting it, so the 8 KB buffer
|
||||
is allocated as 8 KB + 16 + one maximum frame. Getting that wrong is a chip
|
||||
writing past the allocation at line rate.
|
||||
- **A length of `0xFFF0` means "still writing"**, not a length. Copying on it
|
||||
gives a partial packet *and* loses the alignment for everything after.
|
||||
|
||||
It is also the one Realtek part QEMU emulates, so unlike the 8169 every line of
|
||||
it has run: DHCP completes and `ping` is 4 of 4.
|
||||
|
||||
## Realtek RTL8169/8168/8111 — `drivers/net/r8169/`
|
||||
|
||||
The NIC in a very large number of laptops and desktop boards. Every
|
||||
|
|
@ -60,6 +109,13 @@ The register layout is a *fact about the hardware*, taken the way
|
|||
[ldls.md](ldls.md) §3 says facts may be taken. The expression is this tree's:
|
||||
a descriptor-ring driver in the same shape as the e1000 beside it.
|
||||
|
||||
### The Chromebox has one of these
|
||||
|
||||
The Asus Chromebox CN62 "Guado" turns out to carry an RTL8111 rather than the
|
||||
Intel part its spec sheet suggests, so this driver covers it as well as the
|
||||
laptop that prompted it — which is the argument for the family match in one
|
||||
line rather than a device id per board.
|
||||
|
||||
### It has not run on hardware
|
||||
|
||||
**Stated plainly because it cannot be tested here.** QEMU emulates `rtl8139`
|
||||
|
|
|
|||
Loading…
Reference in a new issue