GitHub - jflitton/daynaport-scsilink-linux-driver: Linux kernel drivers for the DaynaPORT SCSI/Link network adaper

3 min read Original article ↗

A loadable Ethernet driver for the DaynaPORT SCSI/Link SCSI-to-Ethernet adapter, as emulated by ZuluSCSI, BlueSCSI V2, and PiSCSI.

It binds to the SCSI processor device the adapter presents and exposes it as a standard Ethernet interface (e.g. eth0). Each driver builds out-of-tree as a loadable module against its kernel's source.

The Linux SCSI and networking subsystems were rewritten many times across the 2.0 → 7.x span, so a single source file can't span them. Instead the repo holds one self-contained driver per kernel era, each in its own directory, sharing only what is genuinely version-independent (the DaynaPORT protocol logic).

How it works

The adapter presents on the SCSI bus as a processor device. The driver binds to it and moves Ethernet frames over ordinary SCSI commands — WRITE(6) to send, READ(6) to receive — exposing a normal eth0-style interface to the network stack. A handful of device traits shape every version of the driver:

  • No receive interrupt. Nothing on the bus signals an inbound frame, so receive has to poll with READ(6) commands. Transmit never polls — the stack hands the driver a frame only when there is one to send.
  • One command at a time. The adapter has a single command slot and cannot transmit and receive at once, and its RX FIFO is small — so the driver must arbitrate the bus between sending and polling. Lean too hard either way and the other side stalls (upload throughput vs. draining inbound before the FIFO overflows).
  • Productive reads run back-to-back. A READ that returns frames is followed immediately by the next, so a live download runs at the speed of the SCSI round-trip; only empty polling — probing when nothing is waiting — needs pacing. The receive ceiling is set by the per-READ round-trip and the adapter, not by how fast the host polls.
  • Two-frame batch cap on SCSI2SD targets. ZuluSCSI and BlueSCSI are both based on SCSI2SD, whose firmware caps a batch at 2 frames; requesting more per READ gains nothing on those targets.

How each driver tunes this — poll-cadence knobs, the TX/RX arbitration limit, and whether parameters are writable at runtime — lives in the per-kernel README, since it depends on what each era's kernel allows.

Supported kernels

Kernel target Directory
Linux 2.0.x linux-2.0/
Linux 2.4.x linux-2.4/
Linux 7.x linux-7.0/

Repository layout

.
├── README.md          # this file
├── COPYING            # GPLv2 — shared, vendored into each release tarball
├── lib/               # shared, version-independent C
│   └── daynaport.h    # protocol constants + callback-based RX frame parser
├── reference/         # protocol documentation (version-independent)
│   ├── daynaport.md   # DaynaPORT opcode / framing reference
│   └── SLINKCMD.TXT   # Dayna's original SCSI/Link command set
├── make-release.sh    # package one target into a self-contained tarball
├── linux-2.0/         # the Linux 2.0.x driver
│   ├── scsilink.c
│   ├── Makefile
│   ├── install.sh
│   ├── README.md
│   └── CHANGES
├── linux-2.4/         # the Linux 2.4.x driver
│   ├── scsilink.c
│   ├── Makefile
│   ├── install.sh
│   ├── README.md
│   └── CHANGES
└── linux-7.0/         # the Linux 7.x driver
    ├── scsilink.c
    ├── Makefile
    ├── install.sh
    ├── README.md
    └── CHANGES

The protocol logic — opcode/framing constants and the RX record parser — lives once in lib/daynaport.h. It is kernel-API-free and C89-clean, so the same header compiles under gcc 2.7.x for the 2.0 driver and a modern toolchain for later ports; each driver supplies its own per-frame delivery callback that hands packets up the era's network stack.

License

GPLv2 — see COPYING.