From ff64b59fe09bd9bd02f29533c24bdbd2a79363ed Mon Sep 17 00:00:00 2001 From: flamingcow Date: Wed, 12 Aug 2026 18:33:10 -0700 Subject: [PATCH] Transcribe BCM PDFs to markdown visually (tables intact); catalog probe candidates: EEE advertised in reference bringup, EMI cmds are fast-retrain enables, 1588/loopback/ECD chapters missing --- docs/bcm84891l-mdio-commands.md | 215 ++++++++++++++++++++++++++++++++ docs/bcm84891l-sfp-registers.md | 79 ++++++++++++ docs/modules.md | 14 ++- docs/transports.md | 6 +- 4 files changed, 306 insertions(+), 8 deletions(-) create mode 100644 docs/bcm84891l-mdio-commands.md create mode 100644 docs/bcm84891l-sfp-registers.md diff --git a/docs/bcm84891l-mdio-commands.md b/docs/bcm84891l-mdio-commands.md new file mode 100644 index 0000000..f2a6d9d --- /dev/null +++ b/docs/bcm84891l-mdio-commands.md @@ -0,0 +1,215 @@ +# BCM84891L MDIO command handler — transcription + +Transcribed (visually, tables intact) from the FS-provided excerpt of the Broadcom +datasheet `84891L-DS101` (`BCM84891L-MDIO Command Descriptions-.pdf`). The excerpt +keeps the cover, TOC, and datasheet pages 41–59. Chapters the TOC lists but the +excerpt **omits** — each a potential follow-up ask to FS: + +- §1.17 EEE / AutogrEEEn (enable/disable, **monitoring EEE readiness**, fast retrain + modes: IEEE FR, Negotiated FR, BCM-proprietary FR) +- §1.18 Jumbo packets, §1.19 HiGig2 +- §1.20 Loopback operation — per-speed PCS loopbacks and **copper line loopback at + PMD/PCS** (§1.20.2) +- §1.21 Management interface, §1.22 TRD (MDI) pair swapping, §1.23 SPI +- **Chapter 2: Register Summary** (p62+) +- Not in the TOC at all: the ECD chapter and the 1588 operation chapter. + +Device headline features (cover page): IEEE 1588-2008 v2-compliant; IEEE fast retrain +and link monitoring; EEE with AutogrEEEn; enhanced cable diagnostics; detection and +correction of pair swaps (MDI crossover), pair skew, and pair polarity; line-side +loopback; jumbo to 18 KB; low-EMI; XFI/USXGMII/KR host interfaces. + +## Handler protocol (§1.24) + +Write the command code to CMD `1E.0x4005` with bit 15 set; firmware raises an +interrupt, services the command, and reports through STATUS `1E.0x4037` +(bidirectional — user-writable). Poll STATUS every ~100 ms. During the 2-second +10GBASE-T training phase STATUS freezes (returns SYSTEM_BUSY); only issue commands +after link-up. + +| Register | Address | +|---|---| +| CMD | 1E.0x4005 | +| STATUS | 1E.0x4037 | +| DATA1–DATA5 | 1E.0x4038–1E.0x403C | + +| STATUS code | Value | +|---|---| +| CMD_RECEIVED | 0x0001 | +| CMD_IN_PROGRESS | 0x0002 | +| CMD_COMPLETE_PASS / OPEN_FOR_CMDS | 0x0004 | +| CMD_COMPLETE_ERROR / OPEN_FOR_CMDS | 0x0008 | +| CMD_SYSTEM_BUSY | 0xBBBB | + +Procedure: poll STATUS until neither IN_PROGRESS nor BUSY → write params to DATAn → +write code\|0x8000 to CMD → poll STATUS for PASS/ERROR → read DATAn results. +Provisioning changes generally require an AN restart to take effect. + +**Field note (hardware-verified):** the handler does not clear DATA registers it +doesn't use — stale values persist across commands. GET_SNR must be invoked with +*no* DATA1 write (see its entry). + +## Table 5 — command codes (verified against hardware) + +| Command | Code | Notes | +|---|---|---| +| CMD_GET_PAIR_SWAP | 0x8000 | | +| CMD_SET_PAIR_SWAP | 0x8001 | needs AN restart | +| Reserved | 0x8002, 0x8003 | | +| CMD_GET_1588_ENABLE | 0x8004 | | +| CMD_SET_1588_ENABLE | 0x8005 | needs AN restart | +| GET_LIMITED_REACH_MODE_ENABLE | 0x8006 | | +| SET_LIMITED_REACH_MODE_ENABLE | 0x8007 | | +| CMD_GET_EEE_MODE | 0x8008 | | +| CMD_SET_EEE_MODE | 0x8009 | needs AN restart | +| CMD_GET_EMI_MODE_ENABLE | 0x800A | **description says: gets SW fast-retrain enable** | +| CMD_SET_EMI_MODE_ENABLE | 0x800B | **sets fast-retrain enables; needs AN restart** | +| CMD_GET_SUB_LF_RF_STATUS | 0x800D | | +| GET_KR_MODE_ENABLE | 0x800E | | +| SET_KR_MODE_ENABLE | 0x800F | | +| CMD_CLEAR_SUB_LF_RF | 0x8010 | | +| CMD_SET_SUB_LF_RF | 0x8011 | | +| GET_SYNC_E_ENABLE | 0x8012 | | +| SET_SYNC_E_ENABLE | 0x8013 | | +| GET_XFI_2P5G_5G_MODE | 0x8016 | | +| SET_XFI_2P5G_5G_MODE | 0x8017 | | +| SET_EEE_STATISTICS | 0x801A | arm counters; issue after link-up | +| GET_EEE_STATISTICS | 0x801B | | +| GET_JUMBO_PACKET | 0x801D | note: GET is 1D | +| SET_JUMBO_PACKET | 0x801C | note: SET is 1C | +| GET_PAUSE_FRAME_MODE | 0x801F | WAP/idle-stuffing niche only | +| SET_PAUSE_FRAME_MODE | 0x8020 | WAP/idle-stuffing niche only | +| GET_LED_TYPE | 0x8021 | | +| SET_LED_TYPE | 0x8022 | | +| GET_WAP_MODE_FRAME_TYPE | 0x8023 | | +| SET_WAP_MODE_FRAME_TYPE | 0x8024 | | +| SET_USXGMII | 0x8026 | | +| GET_USXGMII | 0x8027 | | +| GET_XFI_TX_FILTERS | 0x802B | | +| SET_XFI_TX_FILTERS | 0x802C | | +| GET_XFI_POLARITY | 0x802D | | +| SET_XFI_POLARITY | 0x802E | | +| GET_CURRENT_VOLTAGE | 0x802F | | +| CMD_GET_SNR | 0x8030 | | +| CMD_GET_CURRENT_TEMP | 0x8031 | | +| CMD_SET_UPPER_TEMP_WARNING_LEVEL | 0x8032 | | +| CMD_GET_UPPER_TEMP_WARNING_LEVEL | 0x8033 | | +| CMD_SET_LOWER_TEMP_WARNING_LEVEL | 0x8034 | | +| CMD_GET_LOWER_TEMP_WARNING_LEVEL | 0x8035 | | +| SET_WOL_ENABLE | 0x805A | | +| GET_WOL_ENABLE | 0x805B | | + +## Command semantics + +### CMD_GET_PAIR_SWAP (0x8000) / CMD_SET_PAIR_SWAP (0x8001) +GET: DATA1 = forced/requested swap value, DATA2 = current swap value. +SET: DATA2 = value to force; needs AN restart. +Encoding (Table 8): bits [7:6] PAIR_D_SEL, [5:4] PAIR_C_SEL, [3:2] PAIR_B_SEL, +[1:0] PAIR_A_SEL; each 2-bit field: 00=Pair A, 01=B, 10=C, 11=D. + +### CMD_GET/SET_1588_ENABLE (0x8004/0x8005) +DATA1: 0 = IEEE 1588 disabled, 1 = enabled. Set prior to link-up (or bounce the +link via AN restart). The 1588 engine's own registers are not documented in this +excerpt. + +### GET/SET_LIMITED_REACH_MODE_ENABLE (0x8006/0x8007) +DATA1: 0 = LR mode disabled, 1 = enabled. +DATA2 (when enabled): 0 = dynamically switch to LR power-saving level 2 **based on +cable length**; 1/2/3 = forced level 1 (most saving) / 2 / 3 (least). +GET-only DATA3: 1 = currently linked in limited-reach mode — the sole +handler-visible consequence of the DSP's internal length estimate. + +### CMD_GET_EEE_MODE (0x8008) / CMD_SET_EEE_MODE (0x8009) +Per-speed EEE mode fields in DATA1 — 10G in bits [1:0], 1G/100M in [3:2] +(interpreted per bits [11:10]), 2.5G in [5:4], 5G in [7:6]: +0 = EEE disabled, 1 = native EEE, 2 = AutogrEEEn fixed latency, +3 = AutogrEEEn variable latency. +DATA2 = AutogrEEEn high threshold, DATA3 = low threshold (default 0x7A12), +DATA4 = AutogrEEEn latency (default 0x480); shared across 2.5/5/10G, ignored at 10G +native. SET needs AN restart. + +### CMD_GET/SET_EMI_MODE_ENABLE (0x800A/0x800B) +Datasheet titles say EMI; both descriptions read "SW Fast Retrain enable": +DATA1 = 10G fast retrain (0/1), DATA2 = 5G, DATA3 = 2.5G. SET needs AN restart. + +### CMD_GET_SUB_LF_RF_STATUS (0x800D), CLEAR (0x8010), SET (0x8011) +Substitution of local/remote fault codes with IDLE toward the line direction. +GET DATA1: 0 = copper-TX LF/RF passes through, 1 = LF/RF replaced with IDLE. +SET enables substitution, CLEAR disables it. + +### GET/SET_KR_MODE_ENABLE (0x800E/0x800F) +DATA1: KR mode on the host interface, 0/1. (KR unsupported when 2500X/5000X mode +is enabled.) + +### GET/SET_SYNC_E_ENABLE (0x8012/0x8013) +DATA1 SyncE enable; DATA2/DATA3 M0/M1 recovered-clock mux select (P0 10G, P1–P3 +10G/1G, or P0 1G); DATA4 FW-vs-user control; DATA5 bits [1:0] M0/M1 output +disable. + +### GET/SET_XFI_2P5G_5G_MODE (0x8016/0x8017) +Rate adaptation for 2.5G/5G on the host side: 0 = 10G idle-stuffing, 1 = X mode, +2 = R mode (per speed in DATA1/DATA2). + +### SET_EEE_STATISTICS (0x801A) / GET_EEE_STATISTICS (0x801B) +SET arms the statistics (no params; issue after link-up). GET input selector: +0 = event counters, 1 = time durations. Returns TX(LOC) counter/time in +DATA2 (low 16) / DATA3 (high 16) and RX(REM) in DATA4/DATA5. PHY picks the +10G or 1G counter bank from current link speed. + +### GET/SET_JUMBO_PACKET (0x801D/0x801C) +DATA1 enable; DATA2 size option 0 = 10K, 1 = 18K, 2 = 9K. + +### GET/SET_PAUSE_FRAME_MODE (0x801F/0x8020) +DATA1: 0 = no pause frame, 1 = enabled. **Only valid for 2.5/5G idle-stuffing in +10G XFI WAP mode** — inert in plain 10G operation. + +### GET/SET_LED_TYPE (0x8021/0x8022) +DATA1: 0 = firmware control, 1 = user control. + +### GET/SET_WAP_MODE_FRAME_TYPE (0x8023/0x8024) +GET: DATA1 = 1 when priority protocol is IEEE 802.3bz; DATA2 current link frame +type (1 = 802.3bz, 2 = NBASE-T). SET: DATA1 frame-type priority. + +### SET/GET_USXGMII (0x8026/0x8027) +DATA1 enable; DATA2 USXGMII autoneg; DATA3 [2:0] single_max_speed (1 = 2.5G, +2 = 5G, 4 = 10G); DATA5: 1 = MAC/PHY frequency unlocked, 0 = locked. + +### GET/SET_XFI_TX_FILTERS (0x802B/0x802C) +Host-side XFI TX FIR taps. GET (for the current link speed; invalid if link +down): DATA2 [7:0] pre tap / [15:8] main tap; DATA3 [7:0] post1 / [15:8] post2; +DATA4 [15:8] TX HPF. SET adds DATA1 [15:8] speed selector (0 = 10G +backward-compat, 1 = 100BT, 2 = 1G, 3 = 10G, 4 = 2.5G, 5 = 5G). + +### GET/SET_XFI_POLARITY (0x802D/0x802E) +DATA2 TX polarity, DATA3 RX polarity. + +### GET_CURRENT_VOLTAGE (0x802F) +DATA1/DATA2 = 0.8 V rail measurements, DATA3 = 1.88 V rail. (Observed: tenths of +mV — 0x1E47 ≈ 775.1 mV, 0x49BC ≈ 1887.6 mV.) + +### CMD_GET_SNR (0x8030) +Documented: DATA1 input 0/1 = display SNR in IEEE registers; returns DATA2–5 = +SNR for channels A–D in dB×10. **Hardware-verified behavior: write nothing to +DATA1** — writing the display flag (either value) makes this firmware return +zeros, and the IEEE registers 1.133–1.140 never populate (constant 0x8080) +regardless. Bare invocation returns live per-pair SNR (~27–32 dB on a bench +cable, 0.1–0.4 dB jitter per read). Values are absolute receiver SNR. + +### CMD_GET_CURRENT_TEMP (0x8031) +DATA1 = die temperature (°C; observed ~68–70 on bench). + +### Temp warning levels (0x8032–0x8035) +Upper/lower limit in °C (two's complement) in DATA1, margin in DATA2, enable in +DATA3. + +### SET/GET_WOL_ENABLE (0x805A/0x805B) +DATA1: 0/1. SET takes effect immediately; soft-reset the PHY afterward. Only +relevant at 2.5G and above. + +## LED programmability (§1.26) +LED control words live in top-level vendor registers **1.0xA83B (LED Control)** +and **1.0xA83C (LED Control Source)** — five programmable LEDs, per-LED source +masks, 2-bit mode fields (off / blink-on-source / on-on-source), activity +sources: bit 1 RX activity, bit 2 TX activity, with a stretch enable for +visibility. (First documented vendor registers outside the handler; the SMI +example in the registers reference writes another one, 1.0xA820.) diff --git a/docs/bcm84891l-sfp-registers.md b/docs/bcm84891l-sfp-registers.md new file mode 100644 index 0000000..157eb1d --- /dev/null +++ b/docs/bcm84891l-sfp-registers.md @@ -0,0 +1,79 @@ +# FS SFP-10G-T-100 transport reference — transcription + +Transcribed (visually, tables intact) from the FS-provided 4-page +`10GBase-T Coper SFP Registers Operation's Reference for BCM84891.pdf` +(an ODM document — PDF metadata titles it "ABCU-5710RZ / ABCU-5700RZ"). + +## 1. Serial ID memory (A0h) + +Standard SFP MSA serial ID at I2C A0h. Notable factory values (the module is +honest about copper — cf. hardware.md): + +| Addr | Field | Value | Meaning | +|---|---|---|---| +| 0 | Identifier | 03 | SFP | +| 1 | Ext. identifier | 04 | MOD4 | +| 2 | Connector | 21 | Copper pigtail (the shipped unit reads 22 = RJ45) | +| 3–10 | Transceiver | 02 00 00 00 00 08 00 00 | 10G Base-XFI to copper / SGMII to copper | +| 11 | Encoding | 00 | 64B/66B (or 8B/10B) | +| 12 | BR, nominal | 67 | 10.3125 GBd | +| 18 | Length (copper) | 64 | 100 m; 30 m minimum in-spec copper length | +| 20–35 | Vendor name | "OEM " | shipped unit reads "FS" | +| 40–55 | Vendor PN | "10GBase-T C100m" | shipped unit reads "SFP-10G-T-100" | +| 64–65 | Options | 00 12 | TX_DISABLE and RX_LOS implemented (shipped: 00 1A) | +| 92 | Diag monitoring | 00 | **no A2h DOM implemented** | +| 93 | Enhanced options | 00 | | +| 94 | SFF-8472 compliance | 00 | digital diagnostics not included | +| 96–127 | Vendor specific | all 00 | | + +## 2–3. SMI (I2C→MDIO) protocol for the PHY, with timing + +The PHY is a 2-wire device at 8-bit address **0xAC write / 0xAD read** +(`1010110x`). Clause-45 access frames: + +**Write (one I2C frame, 6 bytes):** +`S [0xAC] [000+DEVAD] [Reg_H] [Reg_L] [Data_H] [Data_L] P` + +**Read (two I2C frames):** +`S [0xAC] [001+DEVAD] [Reg_H] [Reg_L] P` → **delay > 1 ms** → +`S [0xAD] [Data_H] [Data_L] P` + +Bit-level example diagrams confirm: every byte is slave-ACKed except the final +read data byte, which the master **NAKs** before STOP. Worked examples: write +0x55AA to 1.0xA820; read 0x8542 from 1.0x0003. + +## 4. PHY MMD map + +Clause-45 MMDs behind the bridge: + +| DEVAD | Block | +|---|---| +| 1 | 10GBASE-T PMA/PMD | +| 3 | 10GBASE-T PCS; XFI_M (XGMII) block also on DEVAD 3 | +| 7 | AN; SGMII block and 10/100/1000BASE-T PCS/PMA/PMD at 7.0xFFE0–0xFFFF | +| 30 | Top level (user-defined) | + +Side blocks: JTAG, SPI, BSC, PLL/clock, LED controller. + +## 5. Reference access commands and 10G bring-up sequence + +The ODM's host-side primitives are exactly our `sff_i2c` ops: +`Write_XGPHY_Register 0xAC [000+DEVAD] RegH RegL DataH DataL` and +`Read_XGPHY_Register 0xAC [001+DEVAD] RegH RegL, >1 ms, 0xAD DataH DataL`. + +Reference sequence "set PHY to work in 10GBE rate" (write in order): + +| Frame | Register = value | Meaning | +|---|---|---| +| AC 01 00 00 20 40 | 1.0 = 0x2040 | PMA control: 10G speed select | +| AC 01 00 07 00 09 | 1.7 = 0x0009 | PMA control 2: 10GBASE-T type | +| AC 07 00 10 10 01 | 7.16 = 0x1001 | AN advertisement | +| AC 07 00 20 10 03 | 7.32 = 0x1003 | 10GBASE-T AN control | +| AC 07 00 3C 00 08 | 7.60 = 0x0008 | **EEE advertisement — advertises 10GBASE-T EEE** | +| AC 07 00 40 00 00 | 7.64 = 0x0000 | | +| AC 07 80 00 00 10 | 7.0x8000 = 0x0010 | vendor AN register | +| AC 07 00 00 B2 00 | 7.0 = 0xB200 | AN control: enable + restart | + +The EEE-advertisement line means the reference bring-up (and possibly the module +firmware's own defaults) leaves 10GBASE-T EEE negotiable — verify and disable +for measurement runs (see modules.md probe list). diff --git a/docs/modules.md b/docs/modules.md index 8f19d3a..4a418f8 100644 --- a/docs/modules.md +++ b/docs/modules.md @@ -34,13 +34,17 @@ All via the SMI bridge + command handler (transports.md carries the codes and th - **Standard PCS 3.32/3.33** — block lock, latched errored-block/BER counters, clear-on-read: the noise-stress error proxy. - **Retrain** — IEEE AN restart `7.0 |= bit9`, relinks in ~6 s. -Documented in the handler table, not yet exercised: -- **CMD_GET_PAIR_SWAP 0x8000** — MDI wiring/crossover/polarity report. +Documented in the handler table, not yet exercised (full transcription: `bcm84891l-mdio-commands.md`), in probe-priority order: +- **GET_EEE_MODE 0x8008** — per-speed EEE mode (disabled / native / AutogrEEEn fixed / variable; 10G in DATA1 bits [1:0]). Probe first: the ODM's reference bring-up *advertises 10GBASE-T EEE* (`7.60 = 0x0008`, see `bcm84891l-sfp-registers.md`), and module-to-module LPI would corrupt loss and latency numbers. `SET_EEE_MODE 0x8009` can force it off (AN restart to apply). +- **SET/GET_EEE_STATISTICS 0x801A/0x801B** — arm after link-up, then read TX(local)/RX(remote) LPI event counters or time durations. Direct evidence of whether EEE is actually happening on the wire, independent of what's advertised. +- **Fast-retrain enables 0x800A/0x800B** — the datasheet titles these EMI_MODE but both descriptions read "SW Fast Retrain enable" (per-speed, DATA1=10G/DATA2=5G/DATA3=2.5G). Fast retrains mask marginal-cable events as sub-ms hiccups; knowing (and possibly controlling) the enable state matters when attributing loss bursts. +- **CMD_GET_PAIR_SWAP 0x8000** — forced and current MDI pair mapping, 2 bits per pair: wiring/crossover verification. - **GET_LIMITED_REACH_MODE 0x8006** — DATA3 = "currently linked in limited-reach mode": the only handler-visible consequence of the DSP's internal cable-length estimate, a single short/long bit, and only meaningful when LR mode is enabled (a config change — measure-only by default). -- **GET_EEE_MODE 0x8008 / GET_EEE_STATISTICS 0x801B** — verify EEE is off before trusting loss numbers. -- **GET_SUB_LF_RF_STATUS 0x800D** — local/remote fault detail. +- **GET_SUB_LF_RF_STATUS 0x800D** — whether copper-TX local/remote fault codes pass through or are replaced with IDLE toward the line (SET/CLEAR 0x8011/0x8010): affects whether the far end can see faults at all. +- **Host-interface health**: GET_XFI_TX_FILTERS 0x802B (FIR taps for the current speed), GET_XFI_POLARITY 0x802D, GET_USXGMII 0x8027 (DATA5 = MAC/PHY frequency unlock flag). +- Pause-frame mode (0x801F/0x8020) turns out to be scoped to 2.5/5G idle-stuffing under 10G XFI WAP mode — inert in plain 10G operation. -**No cable length.** The handler catalog is complete (§1.25.1.1–45: pair swap through WOL) and contains no ECD, length, or skew command. Cable length, opens/shorts, pair skew, and polarity live in the separate ECD register mechanism whose chapter FS hasn't sent — still the one outstanding ask. Until it lands, FS-side length comes only from the NIC timestamp path — in contrast to the Aquantia oracle, whose `1E.C884` length register is fully documented. +**No cable length.** The handler catalog is complete (§1.25.1.1–45: pair swap through WOL) and contains no ECD, length, or skew command. Cable length, opens/shorts, pair skew, and polarity live in the separate ECD register mechanism whose chapter FS hasn't sent. The 1588 engine is the same story: the PHY is IEEE 1588-2008 v2-compliant with a one-command enable (0x8004/0x8005) but its operation registers are undocumented — in-PHY timestamping would measure path delay at the MDI, taking PHY-pipeline latency out of the length equation entirely (open-questions.md §2). Until either chapter lands, FS-side length comes only from the NIC timestamp path — in contrast to the Aquantia oracle, whose `1E.C884` length register is fully documented. ## Marvell cable-length register candidates (unverified, single-shot only) From kernel drivers for sibling parts — templates for a *future* single targeted probe on a sacrificial module, never a sweep, never near `*.0x??64`: diff --git a/docs/transports.md b/docs/transports.md index 8b988a9..41389e7 100644 --- a/docs/transports.md +++ b/docs/transports.md @@ -53,10 +53,10 @@ Docs are in this folder (`10GBase-T...BCM84891.pdf` transport, `BCM84891L-MDIO C - **CMD_GET_SNR = 0x8030** — invoke with **no DATA1 write**; writing the documented display flag makes this firmware return zeros. Bare invocation returns DATA2–5 = per-pair SNR (channels A–D) in tenths of dB. Bench: 27–32 dB absolute, ~0.1–0.4 dB read-to-read jitter. This is *absolute* receiver SNR, not margin (10GBASE-T operating point ≈ 26.5 dB). - The IEEE PMA SNR registers 1.133–1.140 read a constant 0x8080 on the BCM — never populated, display flag inert. **On FS modules SNR comes from the command handler, not standard registers.** - **CMD_GET_CURRENT_TEMP = 0x8031** (die runs ~70 °C on bench), **GET_CURRENT_VOLTAGE = 0x802F**. - - **Trap: 0x8020 is SET_PAUSE_FRAME_MODE** — a config *write*, and the handler executes whatever stale DATA1 holds as its argument. Module pause is explicitly set to 0 (off — the state cabletest requires); GET_PAUSE_FRAME_MODE (0x801F) returns junk on this firmware, so treat the setting as write-only. + - **Trap: SET commands execute stale DATA1.** The handler doesn't clear DATA registers between commands, so invoking any SET without writing its params applies leftover garbage (0x8020 SET_PAUSE_FRAME_MODE was hit this way under the old wrong GET_SNR constant — harmlessly, since pause mode is scoped to 2.5/5G idle-stuffing under XFI WAP mode and is inert at plain 10G). - The >1 ms SMI read delay: 3 ms works reliably. - - Also pair swap/skew/polarity, 1588. - - **Enhanced Cable Diagnostics** (shorts/opens/**cable length**) is a headline feature, but its invocation is NOT in the command-code table (0x8000–0x805B) — it's a separate ECD register mechanism whose chapter isn't in the docs FS sent. This is the one outstanding ask to FS. + - Full command catalog with semantics: `bcm84891l-mdio-commands.md`. Probe-priority list: modules.md "What the FS/BCM gives". + - **Enhanced Cable Diagnostics** (shorts/opens/**cable length**) is a headline feature, but its invocation is NOT in the command-code table (0x8000–0x805B) — it's a separate ECD register mechanism whose chapter isn't in the docs FS sent. The FS ask list, in value order: the ECD chapter, the 1588 operation chapter (in-PHY timestamping; enable exists at 0x8004/5), datasheet §1.20 loopback (copper line loopback) and §1.17 EEE/fast-retrain monitoring, and Chapter 2 register summary — the excerpt's TOC names them all. **Correct BCM SMI framing over the E810 topo-I2C** (recorded in case a write-capable multi-byte transport reappears): read = write `[001+devad,RegH,RegL]` offset_size=1, STOP, >1 ms, then read 2 B offset_size=0; write = offset_size=2, addr = devad<<8|RegH, data = `[RegL,DataH,DataL]`.