Case Study: va2000-amix¶
asokero/va2000-amix is a single-file character framebuffer driver that exposes the MNT VA2000 Zorro II RTG (ReTargetable Graphics) card to Amix as /dev/va2000, char major 68, minor 0 ✅. The kernel side discovers the board via the Amiga AUTOCONFIG mechanism, maps its 4 MB Zorro II window, and lets user space read/write/mmap the framebuffer; on top of it the companion Xrtg X11R5 server draws an actual desktop. This page is the worked, real-world counterpart to the conceptual Amix device-driver model and the parallel-port teaching driver.
Everything here is ✅ (from the repo's README and source) unless a claim carries another tag. The driver targets Amix 2.1p2a on an Amiga 3000 / 68030, Zorro II ✅, like the other modern Amix driver repos.
At a glance¶
| Property | Value | Tag |
|---|---|---|
| Repo | github.com/asokero/va2000-amix |
✅ |
| Device node | /dev/va2000 |
✅ |
| Class / major / minor | character, major 68, minor 0 | ✅ |
| Card | MNT VA2000 RTG, Zorro II | ✅ |
| AutoConfig manufacturer | 0x6D6E |
✅ |
| AutoConfig product | 0x01 |
✅ |
| Board window | 4 MB Zorro II | ✅ |
| Modes | 800×600 / 1024×768 / 1280×720 @ 16-bit | ✅ |
| Build | native cc va2000.c (single source file) |
✅ |
| Kernel files patched by installer | 6 (see below) | ✅ |
What the driver does¶
The VA2000 is treated as a generic linear-framebuffer RTG board, not as Amiga custom-chip graphics (Amix never touches Agnus/Denise/Paula — see the overview). The driver:
- Probes for the board at boot via
autocon()using the card's AutoConfig product id. - Maps the board's 4 MB Zorro II window and splits it into a register region and a framebuffer region (see Memory map).
- Supports three resolutions, all 16-bit colour: 800×600, 1024×768, and 1280×720 ✅.
- Lets user space access the framebuffer through standard character-device entry points (
read/writeviauiomove(), plus the user/kernel copy primitives) and a page-frame mapping formmap.
It is a character driver, which is the right class for a framebuffer: its core is read()/write() plus memory mapping, not the block layer's strategy() (compare the two classes in the driver model).
AutoConfig identity and discovery¶
The VA2000 announces itself on the Amiga expansion bus through AUTOCONFIG, the Zorro II protocol that assigns each board a base address at reset. The driver matches the board by its AutoConfig identity ✅:
| Field | Value |
|---|---|
| Manufacturer (mfr) | 0x6D6E |
| Product | 0x01 |
Amix exposes the AUTOCONFIG results to drivers through the Amix-specific autocon() call (Zorro II only — there is no Zorro III mapping in Amix ✅; see Quirks). The driver passes the product id to autocon() to obtain the board's assigned base address, then computes its register and framebuffer pointers as offsets from that base. The same AutoConfig fields are what a userspace scanner like lszorro would print for the card.
Note: the VA2000 is a register-only board (its 4 MB Zorro II window contains registers and a framebuffer, not RAM). It has a valid AutoConfig identity (
0x6D6E/0x01), but userspace scanners likelszorrodetect such boards by fingerprint rather than by reading a memory-mapped AutoConfig ROM body 🟡 — see the lszorro case study.
Memory map: the 4 MB window¶
The board presents a single 4 MB Zorro II window, split into registers and framebuffer ✅:
| Offset (from board base) | Region | Size |
|---|---|---|
0x000000–0x00FFFF |
registers | 64 KB |
0x010000–0x3FFFFF |
framebuffer | ~4 MB − 64 KB |
For mmap, the driver converts a framebuffer offset to a physical page-frame number with (base + off) >> 11 — the right-shift-by-11 "page frame" convention also used by the Piccolo RTG path ✅. (A right shift of 11 corresponds to the page granularity the HAT/MMU layer expects for this mapping; the value is taken verbatim from the repo, not re-derived here.)
Kernel APIs the driver uses¶
The driver draws on the standard SVR4 DDI/DKI surface plus the one Amix-specific call ✅. See the driver model's API table for the full list; the ones load-bearing here are:
| API | Role in this driver |
|---|---|
autocon(product_id, dev, &board, &dummy) |
Amix-specific Zorro II board discovery — finds the VA2000's assigned base address 🟡 (repo-confirmed) |
uiomove() |
move pixel data between the framebuffer and the user uio on read/write |
copyin() / copyout() |
move control data across the user/kernel boundary |
page frame (base + off) >> 11 |
translate a framebuffer offset to a page frame for mmap |
Building the driver¶
The driver is one C file and builds with the native AT&T SVR4 cc already on the system ✅ — a single cc call, where the multi-file Hydra STREAMS driver needs a make plus a full-kernel make force (both native, no cross-compiler):
Because it is plain native cc, there is no toolchain bootstrap problem here — and there is none for Hydra either; both build on-box (the m68k-amix-gcc cross-compiler has no public recipe 🔴 but is not needed — see the toolchain page). The object goes into the kernel source tree and is linked statically into the kernel — Amix has no loadable modules, so every driver is part of /unix (the kernel architecture explains why).
The six kernel files the installer patches¶
Adding a statically-linked driver means editing the kernel source tree under /usr/sys and relinking. The va2000 installer patches six files ✅:
| # | File | Change |
|---|---|---|
| 1 | amiga/driver/Makefile |
add va2000.o to the build |
| 2 | amiga/console/scrdev.c |
register the RTG screen type |
| 3 | amiga/console/c0.c |
register the RTG screen type |
| 4 | amiga/console/screen.c |
register the RTG screen type |
| 5 | master.d/kernel.c |
extern declarations + cdevsw[] slot 68 + va2000init added to io_init[] |
| 6 | (the mknod step, below) |
create the /dev/va2000 node |
The three amiga/console/ files (scrdev.c, c0.c, screen.c) teach the Amix console/screen subsystem about a new RTG screen type so the X server can open the VA2000 as a screen ✅. The heart of the wiring is in master.d/kernel.c, the in-source kernel config file:
- an
externdeclaration for each entry point, - a
cdevsw[]entry at major 68 (the index is the major number — see the switch-table model), - and
va2000initadded to the boot-time init array, which thiskernel.ccallsio_init[]✅.
Note: the Ditto paper calls the boot-time init array
init_tbl[]; this modernkernel.ccalls itio_init[]. Treat them as the same concept (a list of functions run once at boot). The full originalmaster.d/kernel.cis not publicly archived, so the exact array name is version-dependent 🔴 — see the driver model.
Install sequence¶
End to end, the installer does the following ✅ (the generic version of this cycle is in Building and installing a kernel):
# 1. Build the driver object (native cc, single file)
cc va2000.c
# 2. Patch the six kernel files (Makefile, three console files, kernel.c) — done by the installer
# (adds va2000.o, the RTG screen type, extern decls, cdevsw[68], va2000init in io_init[])
# 3. Create the device node: char, major 68, minor 0
mknod /dev/va2000 c 68 0
# 4. Relink the kernel
make install # -> produces relocunix
# 5. Write the new kernel into the boot partition
cp relocunix /stand
make bootpart KERNEL=relocunix
# 6. Reboot into the new kernel
shutdown -i6 # keep the old /unix as a fallback
The kernel image is relocunix on modern 2.1 systems (the 1990 Ditto paper called the equivalent image rdbunix — a historical rename 🟡). After reboot, /dev/va2000 is live and the Xrtg server can be started against it.
Gotchas worth stealing¶
These are the practical traps the repo documents — useful for anyone writing or installing any Amix driver, not just this one ✅:
- Amix
/bin/shis pre-POSIX. No$(...)command substitution (use backticks) and nogrep -q(redirect to/dev/nulland test$?). Install scripts that assume a modern shell will fail silently — this is a system-wide Amix quirk, not specific to va2000 (see Quirks and the userland notes) ✅. externdeclarations must precedeio_init[]inkernel.c. If you append yourextern va2000init();after the array that references it, the relink fails — order the patch so declarations come first ✅.- Always remove stale objects before relinking. Run
rm -f amiga/config/unix.o master.d/exp unixbeforemake, or the build can link against stale objects and produce a kernel that doesn't reflect your changes ✅.
See also¶
- The Amix device-driver model — major/minor numbers and the
cdevsw[]switch table this driver plugs into at slot 68. - Writing a character driver — the
parteaching driver; the same class of driver as va2000. - Building and installing a kernel — the relink /
make bootpart/ reboot cycle the installer automates. - Zorro II autoconfig for drivers — how
autocon()and AUTOCONFIG board discovery work. - X11 and RTG drivers and the
XrtgX11R5 server case study — the userspace graphics stack that consumes/dev/va2000. lszorrouserspace Zorro scanner — how the VA2000's AutoConfig identity looks from user space.- Device list reference — char major 68 and other known device numbers.
Sources¶
asokero/va2000-amixrepo (README +va2000.csource): https://github.com/asokero/va2000-amix — device node, char major 68, AutoConfig mfr0x6D6E/product0x01, 4 MB window split, modes, nativeccbuild, the six patched kernel files, install sequence,(base+off)>>11page frame, and the shell/extern/stale-object gotchas.sources/research-brief.md§6 (modern driver repos — va2000 entry), §5 (device-driver model,cdevsw[]/io_init[]/init_tbl[],autocon()/uiomove()/copyin/copyout), §4 (monolithic kernel, no loadable modules,kernel.cin source), §2 (Zorro II only), §11 (pre-POSIX/bin/sh).- Ditto, Writing Amix Device Drivers, 1990 European Amiga Developer's Conference — driver-add procedure and the
init_tbl[]vsio_init[]naming note (the full originalmaster.d/kernel.cis not publicly archived 🔴).