Skip to content

PlayStation 2 SMAP Ethernet driver - #2

Merged
hubix94 merged 2 commits into
ps2-dev9-power-upfrom
ps2-smap-driver
Sep 6, 2026
Merged

hubix94 merged 2 commits into
ps2-dev9-power-upfrom
ps2-smap-driver

Conversation

@hubix94

@hubix94 hubix94 commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Staging pull request inside my own fork - not aimed at frno7/linux. Opened here so the diff can be read without touching upstream.

Base is ps2-dev9-power-up, not ps2-main, and that is deliberate: the driver refuses to load on a kernel whose iop-dev9 does not power the expansion bay. Built on plain ps2-main it fails with

ps2-smap: expansion bay is not powered (DEV9 power 0000); this needs a kernel whose iop-dev9 initialises the bay

so this work sits on top of the two DEV9 fixes.

What it does

  • net: ps2: Add PlayStation 2 SMAP Ethernet driver - drivers/net/ethernet/ps2/ with its own Kconfig and Makefile, wired into drivers/net/ethernet/{Kconfig,Makefile}. EE-side port of Sony's linux-2.4.17/drivers/ps2/smap.c (GPL v2) onto 5.4: net_device_ops, NAPI, phylib with its own MDIO bus, MAC read from the EEPROM. Programmed I/O through a bounce buffer; the IOP-side DMA of the original is not ported.
  • MIPS: PS2: Register the SMAP Ethernet device - the platform device the driver binds to, plus CONFIG_PS2_SMAP=m in ps2_defconfig.

The chip window is shared with the ATA registers at IOP_PATA_BASE, so the device declares the two ranges SMAP actually uses rather than the whole window. Claiming all of it collides with the ATA device registered a few lines earlier, and the SMAP device then never registers at all. On hardware:

14000000-1400003f : speed
14000040-1400005f : PATA
14000100-14003fff : smap

Hardware results

SCPH-30004 (PAL, ROM 0150), adapter in the expansion bay, same driver source built out of tree:

Transmit 2.4 MB/s (~19 Mbit/s), sustained over 300 MB
Receive 1.4 MB/s (~11 Mbit/s)
Interrupts ~240k TXEND over the 300 MB run, no stall, no fallback to polling
Module reload works without a reboot
pata_ps2 loaded at the same time no interference, throughput unchanged

Known gaps

  • No DMA. That is what the throughput figures cost.
  • Only tested on SCPH-30004. Nothing in the driver is model-aware; SCPH-700xx is untested.
  • The in-tree wiring is being verified now. The driver code is the tested one; binding through platform resources is what this branch changes.
  • checkpatch reports 0 errors and 47 style warnings, mostly networking block-comment style and long lines.

🤖 Generated with Claude Code

Hubert Wyrzykiewicz and others added 2 commits September 6, 2026 19:54
The SMAP part of the SPEED chip in the PlayStation 2 expansion bay is an
IBM EMAC3 MAC with a National DP83846 PHY on MII address 1, a 4 KiB TX
FIFO, a 16 KiB RX FIFO and two rings of 64 buffer descriptors, all
memory-mapped at physical 0x14000000 on the EE side. The window answers
once the DEV9 expansion bay is powered; the driver checks that through
the IOP before it touches the window, because an unpowered bay turns
every EE access into a data bus error.

The register layout, the FIFO and buffer-descriptor protocol, the EMAC3
defaults and the EEPROM bit-bang sequence come from Sony's driver in the
PlayStation 2 Linux kit, linux-2.4.17/drivers/ps2/smap.c, GPL v2. The
driver structure is new for 5.4: net_device_ops, NAPI, and phylib with
its own MDIO bus instead of the original link-check thread.

Data moves by programmed I/O, 32-bit accesses through a bounce buffer
because skb data is only 2-byte aligned. The IOP-side DMA of the
original driver is not ported. Measured on an SCPH-30004 over TCP with
SSH on top: 2.4 MB/s transmit and 1.4 MB/s receive, sustained over
300 MB.

The three SPEED interrupts reach the EE through the IOP interrupt relay.
Because the SPEED interrupt mask register belongs to the IOP, the driver
never touches it and acknowledges its sources through SMAP_INTR_CLR, as
the original did. It also clears TXDNV and RXDNV, which the IOP side
does not acknowledge; left standing they keep the interrupt line
asserted and the interface stops receiving interrupts under load.

A poll parameter selects interrupt mode with a polling fallback
(default), interrupts only, or polling only. The fallback exists because
the interrupt relay for a bay device had never been exercised, and an
interrupt-only driver that stays silent says nothing about whether the
data path works.

Signed-off-by: Hubert Wyrzykiewicz <h.wyrzyk@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add the platform device the SMAP driver binds to: the 16 KiB SPEED
register window at physical 0x14000000, which holds the registers, both
FIFO data ports and the two buffer descriptor rings, and the three
interrupts relayed from the IOP, named rx, tx and emac3 so the driver
does not depend on their order.

Enable the driver as a module in ps2_defconfig.

Signed-off-by: Hubert Wyrzykiewicz <h.wyrzyk@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hubix94

hubix94 commented Sep 6, 2026

Copy link
Copy Markdown
Owner Author

Verified on hardware. Cold boot from this branch on an SCPH-30004:

dev9: Expansion device power on
dev9: Interface initialized
ps2-smap ps2-smap eth0: PlayStation 2 SMAP at 14000000, SPEED rev1 0011 rev3 0003, MAC 00:04:1f:2e:37:1c, irqs 115/114/116
ps2-smap ps2-smap eth0: Link is Up - 100Mbps/Full - flow control off

The module is in-tree - /proc/modules shows ps2_smap without the (O) taint - and the resources come out disjoint from the ATA window:

14000000-1400003f : speed
14000040-1400005f : PATA
14000100-14003fff : smap

30 MB transmit in 14.0 s (2.25 MB/s), matching the out-of-tree build, with no SPEED interrupts stopped and no fallback to polling. The console takes a DHCP lease and starts SSH about 20 s into the boot without any manual step.

Two things this branch got wrong before it worked, both worth recording:

  1. The first version declared the whole 16 KiB chip window as one resource, which collides with the ATA device registered earlier in devices.c. The SMAP platform device then never registers and platform_driver_probe() has nothing to bind to.
  2. It was based on ps2-main, where iop_dev9_init() returns before exp_dev_init(). The bay stays unpowered and the driver refuses to load - correctly, and with a message that says so. Hence the base branch here.

@hubix94
hubix94 merged commit 3b7a6e4 into ps2-dev9-power-up Sep 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant