Repository navigation
DS2415+ (Avoton) and DX1215: how to control the hardware from plain Linux, and where it could fit in synodeb #1
Description
Offered as inspiration. Nothing here is expected to be merged as is: if it doesn't fit the
spirit or direction of synodeb, feel free to take only the findings, reshape them, or close
this.
Hi, and thanks for synodeb. It is what got us started: synodeb is the inspiration and the base
of our work on an older unit, a DS2415+ (Atom C2538, DSM platform avoton) with a DX1215
expansion unit. With the stage-1 boot chain proposed in the boot PRs, synodeb is also what
gets Unraid booting on this hardware; our separately hosted Unraid plugins then add the
hardware support (fans, LEDs, the expansion unit). Along the way we measured how the fans, LEDs and the expansion unit can be driven from a stock Linux kernel. This issue collects the findings so you can judge what is useful for synodeb, and asks how you would like them contributed.
Labels used below:
- measured: seen on our unit (one DS2415+, one DX1215).
- DSM-derived: read from DSM's own binaries/GPL source or logged from DSM's own tools; behaviour confirmed where marked measured.
- inferred: our interpretation, not tested.
Hardware-test status: everything marked measured was tested on Unraid 7.3.4 (kernel 6.18.58-Unraid) through two Unraid plugins, "Synology Hardware" (userspace MCU/fan daemon) and "Synology Expansion Unit Driver" (the out-of-tree kernel module synology_dx). Both are maintained and hosted by us in our own repository (https://github.com/luuvasara/unraid-synology-hardware and https://github.com/luuvasara/unraid-synology-expansion), are not proposed for synodeb, and are mentioned only as the field-tested reference. The libata quirk was measured on Debian 6.12.
Status of the synodeb port
The findings are implemented in synodeb's own format (kernel/patches + kernel/src driver, synohwd board support, a pkg/synology-ds2415p package), offered as PRs 07-11 below. Identifiers say ds2415p: Synology sells non-plus models in this family that are different hardware (DS1515 vs DS1515+), and DSM itself spells the model DS2415p; the DS923+ needs no suffix because there is no non-plus DS923. Facts below are therefore split into:
- hardware-tested on Unraid via the
synology_dxmodule / Synology Hardware plugin, and - build-tested only in synodeb form (nothing in synodeb form has been run on the unit yet, unless stated).
Implementation branches
| PR | content | status |
|---|---|---|
| 07 | kernel/patches/0009: libata API for PMP vendor registers from a quiet EH round (16-bit register numbers) |
build-tested (6.18.58, W=1); DS923+ drivers/ata objects byte-identical |
| 08 | kernel/src/drivers/ata/synology_ds2415p.c + patch 0010 + kernel/ds2415p.config (opt-in EXTRA_CONFIGS): 88SE9215 GPIO init, orange bay LEDs incl. PCH GPIO 49 as LED class, DX1215 hwmon (fan level, alarms), DX bay LEDs, switch |
build-tested only; the same register accesses hardware-tested through synology_dx |
| 09 | synohwd: DS2415PDaemon (MCU on ttyS1, allow-list, DSM fan tables, DX1215 policy) |
offline tests (138 checks, the old tests unchanged and green); the policy hardware-tested in the Unraid plugin |
| 10 | pkg/synology-ds2415p |
dpkg-deb --build only; not installed on the unit |
| 11 | docs/ds2415p-hardware.md design note |
— |
The boot-stall quirk is PR 02 (kernel/patches/0008).
1. DS2415+ microcontroller (MCU)
- Device: I/O 0x2F8, irq 3,
/dev/ttyS1, ASCII commands (measured). - Line settings: 9600 8N1 is assumed, taken from the DS923+ support in synodeb. It was not measured on this MCU. Writing without any
sttyworked from an initramfs, and the daemon opens the port 9600 8N1 raw. - Byte map: DSM's own
syno_microp_controlwas run with synobios logging on, and the bytes written to the port were recorded (measured).
| Function | Bytes |
|---|---|
| buzzer short | 2 |
| power LED on / blink / off | 4 / 5 / 6 |
| status LED off | 7 |
| status green on / blink | 8 / 9 |
| status orange on / blink | : / ; |
| USB LED on / blink / off | @ / A / B |
| alert LED on / blink / off | LA1 / LA2 / LA3 |
| eSATA LED on / blink / off | LE1 / LE2 / LE3 |
| fan duty, percent | V10 .. V99 |
| fan PWM frequency | W20 (DSM uses 20 Hz) |
| fan checker on / off | u / t |
| version query | O |
| Wake-on-LAN on / off | l / k |
| AC recovery on / off | q / p |
- Keepalive: DSM's
scemdsendsuabout every 10 s (measured). We keep sending it. What the MCU does if the stream stops was not measured (hypothesis: fan-fail beep or full speed). - DSM sends
tat shutdown (theSynoDisableFanCheckservice; inferred to bet). - Never-send list in our daemon (allow-list, everything else refused):
1(power off),C(reset),3(long buzzer, never seen on the wire), andVbelow 10 so that a bug cannot stop the fan.1andCare from third-party reports for other models and were not tested. - The MCU sends
3andKat about 4 Hz each; meaning unknown. Power-button and fan-fail event bytes are not decoded. - Fan policy: the DS2415+
scemd.xmltables (read from DSM, values only): disk 0/46/50/54 C to 20/40/70/99 %, alert at 58 C; CPU 0/65/85 C to 20/70/99 %, alert at 85 C.
DS2415+ fan sweep (measured; idle, duty held until no temperature moved more than 0.5 C in 600 s):
| Duty sent | CPU max (end) | Disk in DS bay 1 | Disk in DX1215 |
|---|---|---|---|
| 20 % | 33 C | 31 C | 28 C |
| 15 % | 35 C | 31 C | 28 C |
| 12 % | 36 C | 32 C | 28 C |
| 10 % | 37 C (max 38) | 33 C | 28 C |
| 20 % (again) | 34 C | 32 C | 28 C |
| 40 % | 30 C | 30 C | 28 C |
| 70 % | 28 C | 29 C | 28 C |
| 99 % | 27 C | 28 C | 28 C |
Every step settled; 10 % is safe at idle. The DX1215 disk did not move, so the DS2415+ fans do not cool the expansion unit.
2. DX1215 topology and its GPIO register file
- Topology (measured): the expansion port is a Marvell 88SE9235 (ata19-22). Behind each port is a Marvell 88SM9705 port multiplier (1b4b:9705) that mainline reports as 6 ports; DSM reports 5. Each PMP has an EMID (measured 0..3 for ata19..22 on our unit); the EMID-0 PMP is the master. Page 0 carries EMID in bits 7:5 and the unit id 0x13 (DX1215) in bits 4:0.
- Access (DSM-derived, then measured): PMP READ (0xE4) and WRITE (0xE8) on PMP port 15 (the control port), vendor registers
0x3a0(output data),0x3a4(output enable,0xffffffor a write) and0x3b0(input). The register number is 16 bits (high byte in the HOB feature field). DSM wraps this in a sysfs file in its patched kernel. A host-side write selects a "page" through address bits and pulses write/read strobe bits; the 8 data bits appear as GPO/GPI 1..8.
Pages (EMID-0 master; slaves read 0x3f on pages 2-4, not wired):
| Page | Bits | Meaning | Label |
|---|---|---|---|
| 0 | 4:0, 7:5 | unit id (0x13), EMID | measured |
| 1 | 0-2 | orange fault of the PMP's local disk 0-2 (1 = orange) | measured (DX bays 1, 2 lit) |
| 1 | 5 | PSU buzzer-mute pulse | DSM-derived, never set by us |
| 1 | 6 | 1 = all disk LEDs off | measured (0x40 at boot on all four) |
| 2 | 0 | fan 1 alarm | measured |
| 2 | 1 | fan 2 alarm | measured (DSM checks only bit 0) |
| 2 | 5 | power on | DSM-derived, not tested by cutting power |
| 2 | 6, 7 | PSU 1 / PSU 2 status | polarity unknown (one PSU fitted, both read 0) |
| 3 | 0 | DEFAULT/MANUAL switch, 1 = DEFAULT | measured at the box |
| 4 | 1:0 | fan code | measured |
| 4 | 3:2 | RAID-ready LED | DSM-derived |
| 4 | 4 | power-toggle pulse | DSM-derived; forced to 0 on every write |
| 4 | 5 | power-button disable | DSM-derived |
| 4 | 6 | alarm LED | DSM-derived |
- Fan code, page 4 low 2 bits, written only on the EMID-0 master, other bits written back as read: 00 FULL, 01 MIDDLE, 10 LOW, 11 STOP. Idle state with no host writes: LOW (10).
- Measured: MIDDLE, FULL and LOW writes each took about 0.05 s, read back as page 4 = 0x01, 0x00, 0x02 and were stable 30 s later with no fan alarm. A 30 s STOP test gave code 3, a fan alarm within 5 s and page 2 0x3c to 0x3f (both alarm bits). Reverting to LOW cleared it. So STOP really stops both fans, and nothing exists between LOW and STOP. The disk behind the DX1215 (28 C) was unaffected. No new libata reset lines in any step.
- The fans are two-wire alarm type: no tach, only the alarm lines and the commanded code can be read.
- DSM's DX1215 temperature table (values from
scemd.xml): disk temperature only, LOW at 0 C, MIDDLE at 48 C, FULL at 55 C, FULL plus shutdown at 61 C, period 300 s. Our daemon follows it, treats an alarm as FULL, an unreadable temperature as MIDDLE, and never sends STOP. - Caution (DSM-derived): never leave page-4 bit 4 set (it acts as a power-switch press) and never write page 4 without read-modify-write.
3. Bay LEDs
DS2415+ internal bays (three 88SE9215, measured on hardware):
- Green: the 9215 has its own GPIO block behind the AHCI vendor window (ABAR+0xA8 = index, +0xAC = data). DSM programs GPIO0-3 as link/activity of ports 0-3, and the chip then blinks the LED itself. Mainline ahci never touches this window, so the bays are dark. Init values (same as DSM's GPL ahci code): index
0x07071024(output enable) = 0,0x07071020(data out) = 0,0x07071058(pin function) =0x00B6D8D1. Before init they readoe=0xffffffff out=0 func=0x2db6c688. Green present/activity then works on both units. - Orange: GPIO4-7 are the fault LEDs of ports 0-3, data-out bit 4+port, 1 = orange. Setting only these bits does nothing (measured, 12 steps, no tray changed). The orange LEDs additionally need Avoton PCH GPIO 49 driven high, bit 17 of GPIOBASE+0x88 (SUS-well bank), as DSM's synobios does on the first disk-LED call and never undoes. With both set, the DS orange walk worked at the box. Role of GPIO 49 (enable for the LED buffer) is inferred.
DX1215 bays: page 1 of each 88SM9705 as in the table above: bits 0-2 orange fault, bit 6 = 1 turns all disk LEDs off (it is 1 at power-up, so the LEDs are dark until cleared). With bit 6 cleared the green LEDs work. Orange on DX bays 1 and 2 was seen at the box. Whether green comes purely from hardware is inferred.
Restore on unload: the module puts the load-time values back.
4. Bay maps (confirmed at the box by blink count)
- DS2415+: bay = DSM disk index + 1. The 88SE9215 at 03:00.0 gives bays 1-4, 05:00.0 gives bays 5-8, 06:00.0 gives bays 9-12, in controller port order. Front grid is 2 columns by 6 rows (1 2 / 3 4 / ... / 11 12).
- DX1215: bay = 3 x EMID + fan-out port + 1, three bays per PMP (confirmed for all 12). Our DX disk sits on EMID 2, port 1, which is bay 8.
5. Boot: the 88SM9705 SEMB link stall
- Symptom (measured, Debian 6.12): link 5 of each 88SM9705 is the SEMB (enclosure) device. It never answers SRST, so error handling loops (
softreset failed (1st FIS failed), "reset failed, giving up", "hard resetting link", repeat). With one internal and one DX1215 disk: internal disk attached at 200.6 s, DX1215 disk at 203.3 s, because the SCSI scan is serialised behind libata EH. libata.force=19.05:disable,...has no effect:disableis a device horkage applied after IDENTIFY, which link 5 never reaches.- Partial fix,
libata.force=19.05:norst,20.05:norst,21.05:norst,22.05:norst(measured, Unraid 6.18.58): last DX EH complete at 103 s instead of 200 s. The hard reset is still tried, so link 5 still showsfailed to resume link (SControl 0). - Full fix, a libata-pmp quirk setting
ATA_LFLAG_DISABLEDon link 5 of a 1b4b:9705, modelled on the existing Marvell 4140 SEMB quirk (measured, Debian 6.12): softreset failures from dozens to 0, EH complete in 8.6-18.5 s, internal disk at 18.6 s, DX1215 disk at 21.3 s (about 19 s overall versus 200 s). Onefailed to resume linkper PMP remains. The patch is tested on 6.12 only (build-tested on 6.18.58), offered askernel/patches/0008in PR 02; it could go to mainline later. - Unraid's kernel has libata built in, so the quirk cannot be shipped as a module there; that is why the module
synology_dxexists and why Unraid only gets thenorstworkaround.
6. What exists today
Two Unraid plugins, maintained and hosted by us (https://github.com/luuvasara/unraid-synology-hardware and https://github.com/luuvasara/unraid-synology-expansion), not proposed for synodeb, are the working, field-tested reference:
- Synology Hardware: MCU/fan daemon with the allow-list, DS2415+ fan tables and modes, MAC fix, DX1215 fan control, history graphs.
- Synology Expansion Unit Driver: the out-of-tree module
synology_dxwith a sysfs API under/sys/kernel/synology_dx/and a hwmon device (fan1_alarm,fan2_alarm,pwm1,pwm1_enable). Fan writes only on the EMID-0 master, STOP only as a time-limited test with a kernel-side revert, bay LEDs optional and off by default.
The same approach serves Debian in synodeb's own form in PRs 07-10 (in-tree, through libata's own EH context instead of the module's workaround for Unraid's built-in libata).
Questions for you
- Do you want DS2415+/DX1215 support inside synodeb at all (as PRs 07-10, or as a DKMS package), or would you prefer it in a fork / separate repository that synodeb references?
- How would you like other models' hardware support structured (per-model profile data, per-platform drivers, a common interface)? The MCU port, byte map and fan tables are clearly per-model.
- Is a driver in
kernel/src(with hwmon + LED class, PR 08) the right place for the DX1215 fan and LED code, or would you rather keep it in userspace? - Would you take the libata-pmp quirk through
kernel/patchesnow (PR 02), or wait until it is in mainline? - One published kernel for both models (the DS923+ drivers are DMI-gated, ours is DMI + PCI-topology gated), or a separate build for the DS2415+?
Open questions (ours)
- MCU baud rate on the DS2415+ is unmeasured (9600 assumed).
- What the MCU does when the
ukeepalive stops, and the meaning of the3andKbytes it sends. - Power-button and fan-fail event bytes; no clean shutdown on button press yet.
- DX1215 PSU bits (page 2 bits 6 and 7): polarity unknown; power-on bit not tested by cutting power.
- Role of PCH GPIO 49 (inferred as an LED buffer enable).
- Whether DX1215 green LEDs are purely hardware once page 1 bit 6 is 0.
- DS2415+ fan tach and fan-fail events are not read; no DX1215 fan sweep has been run (no tach).
- Remaining
failed to resume link (SControl 0)per PMP after the quirk was not investigated. - Other DX/RX units: only the DX1215 was tested; the unit id table (other 9705-class ids) is DSM-derived only.
Activity
rylos commentedon Oct 28, 2026
Thank you, this is a great write-up, and it's nice to see synodeb used as a base.
Short answers to your questions, with the details in the RFC (#6):
scales: platforms (
avotonfor the DS2415+), one board file per model, support tiers and amaintainer per platform. The DS2415+ would be the first community platform, with you as its
maintainer if you're up for it.
boards/ds2415plus.conf),common interfaces for the DOM, the boot entries and synohwd.
DX1215 fans and LEDs; the fan policy stays in synohwd.
series (longterm 6.18 as the default, stable 7.3); patches live in
kernel/patches/<x.y>.One request for everything that lands in this repository: hardware facts are fine, but please
leave out references to DSM binaries or Synology code, and include a boot log from the real
unit running the synodeb form (not only Unraid).
If you have a DX517 owner around: the port multiplier ID of a DX517 (from
dmesgunder DSM)would tell us whether #3/#5 also matter for DS923+ users.