compactflash.device is an AmigaOS driver for CompactFlash cards in PCMCIA slots. Fork of the original driver by Torsten Jager (Aminet: disk/misc/cfd.lha, disk/misc/CFD133.lha).
Download: at GitHub Releases
Purpose
Access digital photos, MP3 files, and other media directly from CompactFlash cards. The AmigaOS-supplied carddisk.device cannot properly handle CF cards, this driver provides a reliable alternative.
Personal Note
This driver is maintained and improved in my free time. If you'd like to support ongoing maintenance and experimentation, you can do so on Ko-fi. You can also follow project planning and updates here: Planning for 2026.
Community Links
- English Amiga Forum Thread: Discussion Thread for user questions and troubleshooting.
- Aminet CFD Advanced Search: CFD releases (m68k, AmigaOS) shows all CFD packages, including v1.34+.
See docs/changes.md for release news and history.
- docs/automount.md - autoboot, automount, and ENV:cfd.prefs configuration.
- docs/changes.md - release notes and original CFD history.
- docs/CFInfo.md - CFInfo card information utility documentation.
- docs/pcmciaspeed.md - PCMCIA timing benchmark documentation.
- docs/pcmciacheck.md - PCMCIA compatibility checker documentation.
- Amiga 1200 or 600 (A1200 tested)
- AmigaOS 2.0+ (tested with 3.2.3)
- CF-to-PCMCIA adapter or SD-to-CF adapter (see Hardware Notes)
- Works with fat95 filesystem for FAT32 support (disk/misc/fat95.lha) or native (FFS, SFS, PFS) filesystems if RDB partition table is used
The archive ships two flavours (full / small) and two CPU tiers (68020+ / 68000), each as a partial sysroot ready to drop onto SYS:. The flavour is encoded in the path:
| Flavour | CPU Tier | File | Size |
|---|---|---|---|
| full | 68020+ | full/68020/devs/compactflash.device | ~11.2 KB |
| small | 68020+ | small/68020/devs/compactflash.device | ~7.9 KB |
| full | 68000+ | full/68000/devs/compactflash.device | ~11.3 KB |
| small | 68000+ | small/68000/devs/compactflash.device | ~8.0 KB |
Companion libraries live next to the device in the same flavour/CPU tree under <flavour>/<cpu>/libs/: ptable.library (partition scan/mount) and the optional compactflash.automount (boot/automount bringup, only needed for autoboot or automount).
Pick the tier that matches your CPU, then pick the full or small flavour:
- Use the full version if you want serial debug output (
Flags = 8) - Use the small version for minimal memory footprint
# A1200 (68020+) full flavour
Copy from cfd/full/68020/ to SYS: ALL
# A600 (68000) full flavour
Copy from cfd/full/68000/ to SYS: ALL
# Plus the shared tools
Copy cfd/c/CFInfo to C:
The inner devs/ and libs/ drawers map directly onto SYS:Devs/ and SYS:Libs/, so a single Copy ALL of <flavour>/<cpu>/ installs both the device and ptable.library at once.
Have fat95 installed on your system. Mount the drive by double-clicking Storage/DOSDrivers/CF0.
Inserted cards automount by default (with the optional compactflash.automount module active). To tune it, or disable it with AUTOMOUNT 0, copy the example config to ENVARC: (and ENV:):
Copy cfd/ENVARC/cfd.prefs to ENVARC:cfd.prefs
Copy cfd/ENVARC/cfd.prefs to ENV:cfd.prefs
See docs/automount.md for all keys and the optional compactflash.automount module.
For OS 3.5+:
Copy def_CF0.info sys:prefs/env-archive/sys
Copy def_CF0.info env:sys
compactflash.device can boot straight from an RDB-partitioned CF card (ROM-resident only) and automount inserted cards at DOS time (RDB, MBR, GPT, and flat whole-disk FAT). Both are driven by ptable.library plus the optional compactflash.automount module; without them the device still works as a plain mount-only device.
Automount is on by default everywhere (ROM-resident and file-based alike); disable it with AUTOMOUNT 0 in ENV:cfd.prefs (see the example config above). Removing a card fully unmounts all supported filesystems by default; UNMOUNT <names> restricts it and UNMOUNT NONE keeps the handlers. The resident driver re-reads that file on every card insert and removal.
The per-filesystem config keys (UNMOUNT, FLAGS_<fs>, CONTROL_<fs>) recognise exactly five filesystem names and no others: DOS, FFS, SFS, PFS, FAT. Any other name is silently ignored. See docs/automount.md for the full config reference.
compactflash.automount provides the boot/automount bringup: in a ROM it gives cold-boot autoboot and opens the device after DOS so the automount agent runs; on disk you get the same run-time automount (hot-swap) by adding it to your startup-sequence with:
LoadModule LIBS:compactflash.automount LIBS:ptable.library DEVS:compactflash.device
The full reference (the ENV:cfd.prefs keys, deployment matrix, removable-media model, cold-boot details and serial-debug output) lives in docs/automount.md (automount.guide).
To build a Kickstart ROM with compactflash.device + ptable.library embedded, see the companion amigaos-kickstart-builder repo.
You will need a special adapter card labelled "CompactFlash to PCMCIA", "PC Card" or "ATA". It looks like a normal 5mm PCMCIA card with a smaller slot for CF cards at the front side. There are two types of such adapters:
- CF Type 1 - for standard thickness CF cards (see images/cf-type-1.jpg)
- CF Type 2 - also supports thicker cards like MicroDrive (see images/cf-type-2.jpg)
Alternatively, you can use an SD-to-CF adapter with SD cards (see images/sd-cf-adapter.jpg).
Tested with CompactFlash cards (16MB, 4GB, 8GB, 16GB, 32GB, 64GB) and SD cards via SD-to-CF adapter (SanDisk, Samsung MicroSD).
Note: Commodore introduced the Amiga PCMCIA port before the official PCMCIA standard was released. Your results may vary depending on your hardware combination. Your adapter MUST support old 16bit PC-CARD mode. 32bit CARDBUS-only adapters won't work.
In conjunction with fat95 v3.09+, cfd can use CF card's built-in erase function if available.
Set in CF0 mountlist. Flags can be combined (e.g., Flags = 9 for cfd first + serial debug).
| Flag | Value | Description |
|---|---|---|
cfd first |
1 | Enable "cfd first" hack for PCMCIA conflicts with other drivers |
skip signature |
2 | unused (v1.37+) - was "skip invalid PCMCIA signature" - as fallback happens automatically |
compatibility |
4 | Use CardResource OS API instead of direct chipset access |
serial debug |
8 | Output initialization messages to serial port at 9600 baud (v1.35+ full build) |
enforce multi mode |
16 | Force 256 sector transfers regardless of card's reported capability (v1.35+) |
skip override auto-detect |
32 | Skip multi-sector override auto-detection, use firmware value (v1.37+) |
The driver can use your Amiga's serial port to report debug messages to a remote computer when serial debug output is enabled with Flags = 8.
You can monitor these messages on your laptop/PC via an RS232-to-USB converter. These converters typically use either a DB-9 Male or DB-9 Female connector. Since the Amiga uses a DB-25 Male connector for RS232 serial communication, you'll need an adapter to convert from DB-25 Female to DB-9 (either Male or Female, depending on your USB-to-RS232 converter type), as follows:
Option 1: DB-9 M(ale) RS232 to USB Converter
Use a adapter DB-25 Female to DB-9 Female, the adapter uses NULL MODEM connections between pins (7 wires):
| DB-25 Female (to Amiga side) | DB-9 Female (to USB Converter side) |
|---|---|
| n/a | Pin 1 (DCD) + Pin 6 (DSR) |
| Pin 2 (TXD) | Pin 2 (RXD) |
| Pin 3 (RXD) | Pin 3 (TXD) |
| Pin 4 (RTS) | Pin 8 (CTS) |
| Pin 5 (CTS) | Pin 7 (RTS) |
| Pin 6 (DSR) | Pin 4 (DTR) |
| Pin 7 (GND) | Pin 5 (GND) |
| Pin 8 (DCD) + Pin 6 (DSR) | n/a |
| Pin 20 (DTR) | Pin 6 (DSR) |
Option 2: DB-9 F(emale) RS232 to USB Converter
Use a adapter DB-25 Female to DB-9 Male, the adapter uses Straight-Through connections between pins (9 wires):
| DB-25 Female (to Amiga side) | DB-9 Male (to USB Converter side) |
|---|---|
| Pin 2 (TXD) | Pin 3 (TXD) |
| Pin 3 (RXD) | Pin 2 (RXD) |
| Pin 4 (RTS) | Pin 7 (RTS) |
| Pin 5 (CTS) | Pin 8 (CTS) |
| Pin 6 (DSR) | Pin 6 (DSR) |
| Pin 7 (GND) | Pin 5 (GND) |
| Pin 8 (DCD) | Pin 1 (DCD) |
| Pin 20 (DTR) | Pin 4 (DTR) |
| Pin 22 (RI) | Pin 9 (RI) |
Once the hardware is connected, monitor the serial port (e.g., screen /dev/ttyUSB0 9600, minicom -b 9600 -o -D /dev/ttyUSB0, putty) on remote computer to see online initialization process.
Cold boot (ROM-resident compactflash.automount + ptable.library, RDB-partitioned card). The [CFD] boot: lines come from compactflash.automount, the [PT] lines from ptable.library:
[CFD] boot: open ptable.library ...
[CFD] boot: ptable.library not preloaded, InitResident()...
[CFD] boot: BootScanPartitions(compactflash.device,0)
[PT] cold boot: scanning for partitions
[PT] RDB partition table
[PT] + filesystem handler PFS v20.0
[PT] + boot SDH0
[PT] + mount SDH1
[PT] cold boot done, partitions registered: 2
Card identification (hot-plug):
[CFD] compactflash.device 2.0-dev (10.07.2026) [68020]
[CFD] Card inserted
[CFD] Identifying card...
[CFD] Reset
[CFD] Configuring HBA
[CFD] ..done
[CFD] Setting voltage
[CFD] Voltage: 5V
[CFD] CIS gate
[CFD] ..DEVICE: type=0x0D speed=400ns size=0x00000800
[CFD] ..FUNCEXT: link=0x02, type=0x01, ifc=0x01
[CFD] ..RESULT: accept
[CFD] ..CONFIG: addr=0x00000200
(or: [CFD] ..CONFIG: default (0x200))
[CFD] RW test
[CFD] ..done, transfer mode: WORD
[CFD] Getting IDE ID ... done (ATA)
Model: TS4GCF133...............................
Serial: G68120052383AC0700C7
FW: 20110407
Max Multi (W47): 8001
Capabilities (W49): 0200
Multi Setting (W59): 0100
LBA Sectors (W60-61): 00777E70
DMA Modes (W63): 0000
PIO Modes (W64): 0003
UDMA Modes (W88): 0000
[CFD] IDENTIFY (raw):
W0: 848A 1E59 0000 0010 0000 0240 003F 0077
W8: 7E70 0000 4736 3831 3230 3035 3233 3833
W16: 4143 3037 3030 4337 0002 0002 0004 3230
W24: 3131 3034 3037 5453 3447 4346 3133 3320
W32: 2020 2020 2020 2020 2020 2020 2020 2020
W40: 2020 2020 2020 2020 2020 2020 2020 8001
...
W248: 0000 0000 0000 0000 0000 0000 0000 0000
[CFD] Init multi mode
[CFD] ..max multi: 1
[CFD] ..set multi: 1, OK
[CFD] ..override test: OK
[CFD] ..done, multi RW: 256
[CFD] Card identified OK
[CFD] Notify clients
[MW] config: read=-1 auto=1 flags=0
[MW] scanning compactflash.device:0 for partitions
[PT] scanning for partitions
[PT] MBR partition table
[PT] partitions found: 1
[MW] scan done, partitions known: 1
[MW] mounting new partitions
[PT] mounting partitions
[PT] mounted CFa0
[MW] mounted volumes: 1
[CFD] Card removed
[MW] config: read=-1 auto=1 flags=0
[MW] card removed
[PT] card removed, media absent
[PT] unmounting partitions
[PT] unmounted CFa0
[MW] entries detached: 1
The [MW] lines come from the automount mount worker (they appear when compactflash.automount is active), the [PT] lines from ptable.library. read=-1 means no ENV:cfd.prefs is set, so the defaults apply (auto=1).
If you don't have a null-modem cable, you can capture serial debug output on the Amiga itself using Sashimi. This works at DOS time, not during cold boot.
- Download Sashimi from Aminet, extract it, and copy the binary to
C:Sashimi. - Make sure your CF0 mountlist contains
Flags = 8(enables serial debug output). - From CLI, start Sashim, optionally redirecting its output to a log file:
Or just run it interactively (output goes to the current CLI window):
run sashimi >SYS:cf.logsashimi - Mount the CF card:
mount cf0:. You can also attach/detach the PCMCIA card and observe the output. - Stop Sashimi with
CTRL+Cwhen done.
Read and Write IO path will use 256 sectors for single IO regardless of what the card supports in Multiple Sector Mode if this flag is set (same behaviour as v1.33). The IO sector count can be limited by MaxTransfer (0x200 = 1 sector per IO) value in CF0 file.
Warning: Verify your card is capable before using for real data. Set the flag and read any text file from CF card (e.g., type CF0:cfd.s). The content should not contain repeating 32-byte pattern after first 512 bytes. See images/multimode-issue.jpg for an example of what broken output looks like on unsupported cards.
Note: As of v1.37, the driver uses a simple initialization test to automatically detect multi-sector operation and enables it when test pass. This flag is now only needed as a manual override if auto-detection fails for your specific card. Set Flags = 32 if detection does not work correctly with your card to disable auto-detection entirely.
Flags = 16
Combine with serial debug for testing:
Flags = 24
Flags = 16
MaxTransfer = 0x10000 /* 128 sectors per IO (64 KB) */
Flags = 24
MaxTransfer = 0x10000 /* debug + enforce mode, 128 sectors per IO */
Tested configurations (author's experience - your results may vary):
| Card Type | Capacity | Enforce Multi Mode |
|---|---|---|
| SD-to-CF adapter | SD card independent | ✓ Works with tested adapters |
| CF cards | Firmware before ~2014 | ✓ More likely to work |
| CF cards | Firmware from ~2014 onward | ✗ More likely not to work |
Specific card examples:
| Card Model | Firmware | Multisector Override |
|---|---|---|
| Transcend 4GB CF 133x (TS4GCF133) | 20110407 | ✓ Works |
| Transcend 4GB CF 133x (TS4GCF133) | 20140121 | ✗ Does not work |
When a card is inserted, the driver inspects the card's CIS (Card Information Structure) and decides whether to handle the card itself or release it back to the system so another PCMCIA driver can claim it. The decision is reported in serial debug right after the [CFD] CIS gate line as [CFD] ..RESULT: accept or [CFD] ..RESULT: reject.
Decision flow:
Stage 1 - CIS gate, using CIS attribute-memory only (no IDE/CCR access yet):
flowchart TD
Start["Card reset<br/>voltage"] --> Ident["CISTPL_DEVICE type 0x0D/0x05?<br/>(else CISTPL_FUNCID 0x04)"]
Ident -->|no| Reject["REJECT<br/>ReleaseCard"]
Ident --> FuncExt["CISTPL_FUNCEXT<br/>Disk Interface = IDE?<br/>10x retry"]
FuncExt -->|no| Reject
FuncExt --> CfgAddr["CISTPL_CONFIG addr<br/>10x retry<br/>fallback 0x200"]
CfgAddr -->|out of range| Reject
CfgAddr --> Identify["IDENTIFY DEVICE"]
Stage 2 - classification, after IDE / CCR registers are modified:
flowchart TD
Identify["IDENTIFY DEVICE"] --> AtaResult["ATA result?"]
AtaResult -->|yes| Accept["ACCEPT"]
AtaResult -->|no| AtapiResult["ATAPI result?"]
AtapiResult -->|no| RejectTimeout["REJECT<br/>timeout"]
AtapiResult -->|yes| AtapiBranch["ATAPI build flag?"]
AtapiBranch -->|yes| Iatapi["_t_iatapi handler"]
AtapiBranch -->|no| RejectAtapi["REJECT"]
The CIS gate is the primary disk-vs-not-disk filter; an ATAPI signature returned by IDENTIFY DEVICE after CIS accept is handled by the ATAPI build flag (default 0 releases the card so a dedicated ATAPI driver can claim it; ATAPI=1 routes ATAPI cards through _t_iatapi). See ATAPI status for details.
CISTPL_DEVICE type values shown in [CFD] ..DEVICE: type=0x..:
| Value | Meaning | CIS gate |
|---|---|---|
| 0x0 | NULL (no device) | reject |
| 0x1 | ROM | reject |
| 0x2 | OTPROM | reject |
| 0x3 | EPROM | reject |
| 0x4 | EEPROM | reject |
| 0x5 | FLASH | accept |
| 0x6 | SRAM | reject |
| 0x7 | DRAM | reject |
| 0xD | FUNCSPEC (function-specific memory) | accept |
| 0xE | EXTEND (extended type follows) | reject |
CompactFlash cards normally report 0x0D or 0x05.
CISTPL_FUNCID is only consulted when CISTPL_DEVICE is unavailable (some adapters/cards do not provide it). Shown in [CFD] ..FUNCID: 0x..:
| FUNCID | Meaning | CIS gate |
|---|---|---|
| missing/unreadable | (no positive ATA evidence) | reject |
| 0x04 | Fixed Disk | accept (subject to FUNCEXT confirmation below) |
| anything else | (e.g. WiFi/LAN, serial, ...) | reject |
CISTPL_FUNCEXT (function extension, code 0x22) is consulted after CISTPL_DEVICE / CISTPL_FUNCID have tentatively accepted the card. Only a well-formed Disk Interface extension declaring IDE keeps the accept; everything else - including missing or malformed FUNCEXT - rejects the card:
| FUNCEXT | Meaning | CIS gate |
|---|---|---|
| absent | tuple not in CIS | reject |
| short tuple (link < 2) | malformed | reject |
| TPLFE_TYPE != 1 | not a Disk Interface extension | reject |
| TPLFE_TYPE = 1, Interface != 1 | Disk Interface, non-IDE (e.g. ATAPI) | reject |
| TPLFE_TYPE = 1, Interface = 1 (IDE) | ATA disk confirmed | accept |
Rejected cards are released back to the system (ReleaseCard) so another PCMCIA driver can claim them. The driver touches no IDE or CCR registers before the gate accepts.
Debug builds (Flags = 8) log every gate decision so it is clear which branch fired and on what values. Sample lines per probe:
[CFD] CIS gate
[CFD] ..DEVICE: type=0x0D speed=250ns size=0x00004000
[CFD] ..FUNCEXT: link=0x02, type=0x01, ifc=0x01
[CFD] ..RESULT: accept
The [CFD] ..FUNCEXT: line appears once per probe and dumps the actual values read from the tuple. The five possible shapes - one accept and four reject reasons - are:
| FUNCEXT line | Meaning | RESULT |
|---|---|---|
..FUNCEXT: absent |
no tuple in CIS | reject |
..FUNCEXT: link=0x00, type=0x00, ifc=0x00 |
tuple present but empty (link=0) | reject |
..FUNCEXT: link=0x01, type=0xNN, ifc=0x00 |
short tuple, only sub-type byte | reject |
..FUNCEXT: link=0xNN, type=0xNN, ifc=0xNN (type != 0x01) |
wrong sub-type (not Disk Interface) | reject |
..FUNCEXT: link=0xNN, type=0x01, ifc=0xNN (ifc != 0x01) |
Disk Interface, non-IDE | reject |
..FUNCEXT: link=0xNN, type=0x01, ifc=0x01 |
Disk Interface, IDE | accept |
For cards rejected earlier in the gate (bad CISTPL_DEVICE type, non-disk FUNCID) the FUNCEXT line is not printed - the reject reason is the ..DEVICE: or ..FUNCID: line above.
compactflash.device does not support ATAPI devices (CD-ROM, DVD, Zip, etc.) in the default build. The gate that decides what cfd handles works in two stages:
- CIS gate (before any I/O):
CISTPL_DEVICE/CISTPL_FUNCID/CISTPL_FUNCEXTare read and validated. Cards without a well-formed Disk Interface FUNCEXT declaring IDE are rejected here, before any Card Configuration Register access. Each CIS read is retried up to 10 times to tolerate hardware whose attribute-memory reads are unstable (e.g. A1200 + ACA1234). Only after the gate accepts does the driver parseCISTPL_CONFIG(10x retry, fallback$200) to locate the CCR. See CIS gate decision above. - Post-IDENTIFY classification: if a card passes the CIS gate and
IDENTIFY DEVICEreturns the ATAPI signature (d0=2, or word-0 bit 15 set), the card is released so a dedicated ATAPI driver such astelmexatapi.device(from AminetIDEfix97) can claim it.
Serial debug builds log an ATA accept as:
[CFD] Setting voltage
[CFD] Voltage: 5V
[CFD] CIS gate
[CFD] ..DEVICE: type=0x0D speed=720ns size=0x00000000
[CFD] ..FUNCEXT: link=0x02, type=0x01, ifc=0x01
[CFD] ..RESULT: accept
[CFD] ..CONFIG: addr=0x00000200
[CFD] RW test
[CFD] ..done, transfer mode: WORD
[CFD] Getting IDE ID ... done (ATA)
A card without IDE FUNCEXT (e.g. Telmex ATAPI) rejects after the 10-retry exhausts. ..CONFIG: does not appear because the parser only runs on accepted cards:
[CFD] Voltage: 5V
[CFD] CIS gate
[CFD] ..DEVICE: type=0x0D ...
[CFD] ..FUNCEXT: absent
[CFD] ..RESULT: reject -> ReleaseCard
An ATAPI implementation has lived in compactflash.device since the early 2000s (see the v1.15 entry in the History table), but it has no real-world user and is untested. The code is preserved behind the make ATAPI=1 build flag for future refactoring. Since v1.44 the release default is ATAPI free. The handler (_t_iatapi, _Packet, _rb_scsi, _wb_scsi, _sc_atapi, ATAPIPoll, ATAPISize, _MediaStatus) is compiled in by make ATAPI=1, which routes ATAPI cards through _t_iatapi instead of releasing them. If an ATAPI device turns up that needs compactflash.device to handle it directly, the path can be brought back after proper testing and CIS gate refactoring.
Before v1.41 every block transfer paid a mode check and a small dispatch-table lookup. In v1.41 the dispatch is resolved once at probe time; the per-block path just jumps to the selected worker.
flowchart TD
Req["IO request"] --> WB["_WriteBlocks / _ReadBlocks"]
WB --> Chunk["per-chunk loop"]
Chunk --> Block["_rb_block / _wb_block"]
Block --> Mode["read CFU_ReceiveMode<br/>or CFU_SendMode<br/>every block"]
Mode -->|mode 0| Inline["inlined word-only loop<br/>(duplicated by ifnd COPYBURST)"]
Mode -->|mode 1-4| Tbl["pi_tab / po_tab lookup<br/>jmp every block"]
Tbl --> Workers["pi_mode1 / pi_mode2 / pi_mode3 / pi_mode4"]
Once at mode change:
flowchart TD
Evt["RWTest / _gid_end<br/>_wb_switch / _wb_bump"] --> Bind["_BindIOHandlers"]
Bind --> Slot1["CFU_ReadBlockFn = pi_modeN"]
Bind --> Slot2["CFU_WriteBlockFn = po_modeN"]
Per IO request:
flowchart TD
Req["IO request"] --> WB["_WriteBlocks / _ReadBlocks"]
WB --> Cache["load CFU_*BlockFn into a5<br/>once outside chunk loop"]
Cache --> Chunk["per-chunk loop"]
Chunk --> Block["_rb_block / _wb_block"]
Block --> Direct["jsr (a5)"]
Direct --> Worker["selected worker<br/>pi_modeN / po_modeN"]
- Per-block
move.b CFU_ReceiveMode(a3)+ branch. - Per-block
pi_tab/po_taboffset load +jmp(the tables are now used only by the cold_pio_in/_pio_outhelpers for IDENTIFY / config reads). - The four source copies of the word-only loop that the old
ifnd COPYBURST / elsewrapping produced.
_BindIOHandlers is called from:
- end of
RWTest(initial mode selection settles) _gid_end(covers_gid_switch's mode-4 fallback)_wb_switch(mid-write fallback to memory-mapped mode)_wb_bump(try next send mode on error)
Outside these four sites the hot path does not consult the mode at all.
Retaken from readme of version 1.32/1.33. Those versions behave as if Enforce Multi Mode is enabled.
| Card | Read | Write |
|---|---|---|
| 16MB Hitachi | 1.0 MB/s | 600 KB/s |
| 64MB PQI | 1.4 MB/s | 1.0 MB/s |
| 128MB Samsung | 2.1 MB/s | 1.4 MB/s |
| 2GB Sandisk | 2.1 MB/s | 1.7 MB/s |
| 4GB Kingston | 2.2 MB/s | 1.9 MB/s |
The driver auto-detects the transfer mode during card initialization by testing which PCMCIA access methods work reliably:
| Mode | Description |
|---|---|
| WORD | 16-bit word access to PCMCIA I/O register. Standard mode for most CF cards. |
| BYTE (data) | 8-bit byte access with high/low bytes at adjacent addresses. For cards that don't support 16-bit transfers. |
| BYTE (alt) | 8-bit byte access with high/low bytes at separate I/O addresses. For specific adapter configurations. |
| BYTE (alt2) | 8-bit byte access via alternate register. Rarely used fallback mode. |
| MMAP | Memory mapped word access. Direct memory transfer (requires PCMCIA memory mapping). |
Most CF cards work with WORD mode. The driver tests write/read patterns during initialization and falls back to BYTE modes if 16-bit access fails. The selected mode is shown in serial debug output as [CFD] ..done, transfer mode: WORD.
Displays card information (requires driver v1.36+). With driver v1.37+, it also shows the driver configuration. See CFInfo.md for a detailed field reference.
PCMCIA memory access timing benchmark. See pcmciaspeed.md for detailed documentation.
PCMCIA CompactFlash card compatibility testing tool. Tests the same read/write modes used by the driver to validate card compatibility. See pcmciacheck.md for detailed documentation.
Besides the usual AmigaOS error codes, there are some additional ones:
| Code | Description |
|---|---|
| 67 | Write or erase failed |
| 73 | Miscellaneous Error |
| 76, 120, 123, 124, 127 | Media format corrupt |
| 80, 84 | Sector ID not found |
| 81 | Uncorrectable checksum |
| 88 | Corrected read error |
| 95 | Data transfer error, command aborted |
| 96 | Invalid Command |
| 97 | Invalid CHS Address |
| 98 | Command needs more power than allowed |
| 103 | Media is write protected |
| 111 | Invalid LBA Address (too large) |
| 69, 112-116, 119, 126 | Self test or diagnosis failed |
| 117, 118 | Voltage out of tolerance |
| 122 | Spare sectors exhausted |
Report issues at: https://github.com/pulchart/cfd/issues
- Set
Flags = 8in CF0 mountlist to enable serial debug - Connect serial cable and monitor (9600 baud)
- Mount CF0:
- Insert the card
- Check serial output for
[CFD]messages - Report the serial log along with your hardware details (the accelerator can matter, e.g., ACA1234 behaves differently from ACA1240 / ACA1260 on the same card)
- Also attach the output of
pcmciacheck -cis(seedocs/pcmciacheck.md), which is helpful for PCMCIA card identification and CIS-related issues. Run it several times in succession without removing the card and confirm whether the dumps are identical. Differing dumps on repeated runs indicate unstable CIS attribute-memory reads, which is itself a diagnostic signal worth reporting.
- vasm - Portable 68k assembler (sun.hasenbraten.de/vasm)
- vbcc - C compiler for CFInfo tool (optional, compilers.de/vbcc)
- NDK - AmigaOS NDK headers for CFInfo (optional, aminet.net NDK3.2)
- lha - For creating release archives (optional)
Extract NDK to project directory:
mkdir NDK && cd NDK && lha x ~/Downloads/NDK3.2.lhaptable.library is not built from this repo. It lives in amigaos-ptable and is embedded as the extern/ptable submodule; make builds it there and copies the resulting binaries, lsptres and lsptres.guide into dist/, so a release always ships the ptable-built bytes.
git clone --recurse-submodules https://github.com/pulchart/cfd # fresh clone
git submodule update --init # existing clone
make ptable-sync # move to upstream tip + rebuild
make PTABLE=/path/to/amigaos-ptable # build against a local checkoutmake ptable-sync fetches origin in the submodule, checks out its master tip, and rebuilds everything that bundles it. It leaves the result uncommitted: review it, then commit the extern/ptable gitlink with the rebuilt dist/ artifacts. It follows the branch tip rather than the recorded pin, which is also the recovery path when an upstream history rewrite orphans the pinned commit.
# Build all (driver + CFInfo)
make
# Build with custom tool paths (prefix), the binaries are in prefix/bin/...
make VASM_HOME=/path/to/vasm VBCC_HOME=/path/to/vbcc
# Verbose output
make V=1| Option | Description |
|---|---|
V=1 |
Verbose output (show full compiler messages) |
GTIMING=1 |
Enable Gayle timing optimization (experimental) |
VASM_HOME= |
vasm installation path (default: /opt/vbcc) |
VBCC_HOME= |
vbcc installation path (default: /opt/vbcc) |
| Target | Description |
|---|---|
make |
Build all driver tiers + ptable.library variants + utilities |
make full |
68020+ full driver only (with debug support) |
make small |
68020+ small driver only (no debug) |
make full-000 |
68000 full driver only (stock A600) |
make small-000 |
68000 small driver only (stock A600) |
make library |
All ptable.library variants (68020+ and 68000, full + small) |
make library-full |
68020+ full ptable.library only |
make library-small |
68020+ small ptable.library only |
make library-full-000 |
68000 full ptable.library only |
make library-small-000 |
68000 small ptable.library only |
make tools |
Build utilities (requires vbcc + NDK) |
make ptable-sync |
Move extern/ptable to its upstream tip and rebuild (left uncommitted) |
make GTIMING=1 |
Build with Gayle timing optimization (experimental) |
make release |
Create Aminet LHA archive |
make checksums |
Show file sizes and checksums |
make clean |
Remove built files |
make help |
Show all available targets |
All targets write into
dist/<flavour>/<cpu>/{devs,libs}/<file>, e.g.makeproducesdist/full/68020/devs/compactflash.deviceanddist/full/68020/libs/ptable.library(and the same for thesmallflavour and the68000tier). Eachdist/<flavour>/<cpu>/drawer is a partial sysroot: drop its contents ontoSYS:to install both the device andptable.libraryat once.
The assembly source uses Motorola 68k syntax compatible with both ASMPro (Amiga) and vasm (Linux/cross).
# Manual vasm invocation
vasmm68k_mot -Fhunkexe -m68020 -nosym -DDEBUG=1 -o compactflash.device src/cfd.s
# Manual vbcc invocation (CFInfo)
vc +aos68k -O2 -c99 -INDK/Include_H -o CFInfo src/cfinfo.cGNU Lesser General Public License v2.1
"CompactFlash" is (TM) by CompactFlash Association