Christian Werner 914c92bdea
Some checks failed
Build kernel module / build (1:6.12.93-1+rpt1, bookworm) (pull_request) Successful in 8m4s
Build kernel module / build (1:6.18.34-1+rpt1, trixie) (pull_request) Failing after 2m31s
Build kernel module / release (pull_request) Has been skipped
feat(kernel): Add support for Debian suite configuration
Introduce `DEBIAN_SUITE` as a configurable argument in the Dockerfile, build
script, and CI workflow to align kernel builds with the target Raspberry Pi
OS release. Updated documentation to clarify the relationship between
suite versions and kernel compatibility.
2026-06-19 20:45:15 +02:00
..
2026-06-18 22:25:42 +02:00
2026-06-18 22:25:42 +02:00
2026-06-18 22:25:42 +02:00
2026-06-18 22:25:42 +02:00
2026-06-18 22:25:42 +02:00
2026-06-18 22:25:42 +02:00

iec_listener kernel module

Commodore IEC listener (printer, default address 4) for the Raspberry Pi Zero 2 W. The timing-critical IEC handshake runs in this kernel module; received bytes and bus events are pushed to userspace through /dev/iec0.

Build/deploy, pinning, GPIO-descriptor and timing details live in ../docs/kernel-notes.md. This README documents the self-test, which is the first thing to run after loading the module on real hardware.

Self-test

The module exposes a hardware self-test via the IEC_IOC_SELFTEST ioctl on /dev/iec0. It drives the DATA line (the only line the Pi asserts) low and reads it back, releases it, then samples ATN / CLK / RESET, returning a bitmask of line states. Run it with the C64 disconnected to check the wiring before connecting the real bus (see PLAN.md §10).

Running it

selftest.sh is non-persistent (nothing is installed into /lib/modules, no autoload): it checks vermagic, loads the module, runs the self-test, and always unloads it again.

sudo ./selftest.sh                                # auto-finds ./ or ~/iec_listener.ko, address 4
sudo ./selftest.sh ~/iec_listener.ko --address 5  # runs with ~/iec_listener.ko, address 5

It exits non-zero unless the result is a full pass (0x1F), so it is usable in scripts/CI.

Result bitmask

The ioctl returns a u32; a full pass is 0x1F (all five bits set).

Bit Value Meaning Source
DATA_ASSERT_OK 0x01 DATA read low while the module drives it low Pi drive + sense path
DATA_FLOAT_OK 0x02 DATA read high after release (Hi-Z) external pull-up on DATA
ATN_RELEASED 0x04 ATN high (idle) line state
CLK_RELEASED 0x08 CLK high (idle) line state
RESET_RELEASED 0x10 RESET high (idle) line state

Constants are defined in iec_listener.h; the ioctl number is _IOR('I', 3, __u32) = 0x80044903.

Interpreting failures

  • DATA_ASSERT_OK missing → driving DATA low doesn't read back low: level shifter wired backwards/inverting, wrong pin, or the sense path is broken. This is the only bit that is fully internal to the Pi — if it fails, suspect the module/build or the DATA wiring, not pull-ups.
  • DATA_FLOAT_OK missing → DATA stays low after release: missing/weak pull-up on DATA, or the pin didn't return to input.
  • CLK_RELEASED missing → CLK reads low at idle: no pull-up on CLK, short, or a swapped signal.
  • ATN_RELEASED / RESET_RELEASED missing → that line reads low at idle: short, missing pull-up, or swapped wiring.

⚠️ Bare-board caveat

With nothing connected, the expected result is 0x15, not a fault:

  • DATA_ASSERT_OK (0x01) passes — it's internal to the Pi.
  • ATN_RELEASED (0x04) and RESET_RELEASED (0x10) pass only because GPIO2/GPIO3 have fixed ~1.8 kΩ pull-ups built into the BCM2710 SoC (they are the I²C0 pins; the pull-ups can't be disabled). They read high even with nothing wired, so on a bare board these two bits prove nothing about your wiring.
  • DATA_FLOAT_OK (0x02) and CLK_RELEASED (0x08) read low because GPIO17/18 have no such built-in pull-up and nothing is attached.

So on a bare board the only meaningful signal is DATA_ASSERT_OK. A full 0x1F is only reachable once the level shifter (with its CLK/DATA pull-ups) is wired and powered. To make ATN/RESET meaningful, briefly ground each at the connector and confirm the corresponding bit drops.