Stuart Schmitt, 3 January 2021
While PCMCIA linear flash is an obsolete technology, numerous devices using these cards remain in service. In the Linux world, linear flash cards are a type of Memory Technology Device, or MTD. Wonderfully, MTDs are still fully supported.
The Linux MTD implementation is an excellent alternative to Windows options. Many people resort to using antiquated laptop computers from the early 2000s running Windows 2000 or XP. There, one can use an abandoned program called Memory Card Explorer. Obtaining and maintaining such old hardware is burdensome, and the unsupported operating system poses a security threat.
Disclaimer: I am not an expert in MTDs or PCI bridges. I likely cannot provide any support for your efforts. I wrote this document because I have found no other guides that were either up-to-date or comprehensive.
mtd-utils
and pcmciautils
packages are required.sudo apt install mtd-utils pcmciautils
.lspci -v
to identify the PCMCIA adapter's memory window and I/O base addresses. For example, the relevant snippet of output on my system was the following:
08:00.0 CardBus bridge: Texas Instruments PCI1410 PC card Cardbus Controller (rev 01) Subsystem: SCM Microsystems PCI1410 PC card Cardbus Controller Flags: bus master, medium devsel, latency 168, IRQ 19 Memory at a4000000 (32-bit, non-prefetchable) [size=4K] Bus: primary=08, secondary=09, subordinate=09, sec-latency=176 Memory window 0: a2000000-a3ffffff (prefetchable) Memory window 1: a4080000-a40fffff I/O window 0: 00003000-000030ff I/O window 1: 00003400-000034ff 16-bit legacy interface ports at 0001 Capabilities: [a0] Power Management version 1 Kernel driver in use: yenta_cardbus Kernel modules: yenta_socket
Memory window
and I/O window
entries, and add them to /etc/pcmcia/config.opts
with 0x
prefixes:
include memory 0xa2000000-0xa3ffffff include memory 0xa4000000-0xa40fffff include port 0x3000-0x30ff include port 0x3400-0x34ffYou probably only need those lines in
/etc/pcmcia/config.opts
and nothing else. You do not need device
, module
, or card
directives; those were used in pre-2.6.13 Linux PCMCIA implementations.include
directive, do not do it. It will not work, and I don't know why.
/dev/mtd0
. That's your card!sudo pccardctl status
:
Socket 0: 3.3V 16-bit PC Card Subdevice 0 (function 0) bound to driver "pcmciamtd"In my example, the card is recognized as a 3.3 V device. However, I know that all of my cards are 5 V cards. Writing (“programming”) may be unsuccessful at 3.3 V. This is apparently a common issue; the programming voltage can be overridden with options supplied to the
pcmciamtd
kernel device. Since I don't anticipate ever using 3.3 V cards, I hard-coded the option into my system configuration:
sudo bash -c 'echo "options pcmciamtd vpp=50 setvpp=1" > /etc/modprobe.d/pcmciamtd.conf'Caution: Only do this if you are sure it is the right thing to do. 5 V will damage cards that are designed for 3.3 V.
The next three steps are optional, for convenience of using MTD cards without root privileges.
addgroup
or edit /etc/group
.udev
rule to set permissions for members of “flash”:
SUBSYSTEM=="mtd", MODE="0660", GROUP="flash"For example,
sudo bash -c 'echo "SUBSYSTEM==\"mtd\", MODE=\"0660\", GROUP=\"flash\"" > /etc/udev/rules.d/99-pcmciamtd.rules'
sudo visudo
) to give permission to members of “flash” to use pccardctl
:
%flash ALL=(ALL) NOPASSWD: /sbin/pccardctl
If things are not working, I'm sorry. Best of luck figuring it out. Possibly the syslog
output below will be helpful.
mtd_debug info /dev/mtd0
:
schmitt@electra:~/card_bin$ mtd_debug info /dev/mtd0
mtd.type = MTD_NORFLASH
mtd.flags = MTD_CAP_NORFLASH
mtd.size = 33554432 (32M)
mtd.erasesize = 262144 (256K)
mtd.writesize = 1
mtd.oobsize = 0
regions = 1
region[0].offset = 0x00000000
region[0].erasesize = 262144 (256K)
region[0].numblocks = 128
region[0].regionindex = 0
Note the mtd.size
value. You may find that useful for reading and writing.
pv -s [size] < /dev/mtd0 > [output filename]
dd status=progress if=/dev/mtd0 of=[output filename]
mtd_debug read /dev/mtd0 0 [size] [output filename]
cat /dev/mtd0 > [output filename]
pv
because it has a status bar:
schmitt@electra:~/card_bin$ pv -s 33554432 < /dev/mtd0 > read.bin 10.6MiB 0:00:09 [1.19MiB/s] [====================> ] 33% ETA 0:00:18
flashcp -v [input filename] /dev/mtd0
mtd_debug erase /dev/mtd0 0 [size]
followed by mtd_debug write /dev/mtd0 0 [size] [input filename]
schmitt@electra:~/card_bin$ flashcp -v new_image.bin /dev/mtd0 Erasing blocks: 128/128 (100%) Writing data: 32768k/32768k (100%) Verifying data: 32768k/32768k (100%)Direct tools such as
dd
, pv
, and cat
will corrupt the data due to the flash chip's NOR operation, and the card will be unusable until erased.
schmitt@electra:~/card_bin$ sudo pccardctl ejectYou are now able to remove the card and insert another. The
udev
system should detect the card insertion. This also means that you can insert a card at any time after system boot.Successful startup of the PCMCIA and MTD systems:
Jan 1 15:42:30 electra kernel: [ 4.943633] yenta_cardbus 0000:08:00.0: CardBus bridge found [133f:3000] Jan 1 15:42:30 electra kernel: [ 4.943663] yenta_cardbus 0000:08:00.0: can't claim BAR 16 [mem 0xa0000000-0xa1ffffff]: no compatible bridge window Jan 1 15:42:30 electra kernel: [ 4.943663] yenta_cardbus 0000:08:00.0: Preassigned resource 3 busy or not available, reconfiguring... Jan 1 15:42:30 electra kernel: [ 4.943665] yenta_cardbus 0000:08:00.0: CardBus bridge to [bus 09] Jan 1 15:42:30 electra kernel: [ 4.943666] yenta_cardbus 0000:08:00.0: bridge window [io 0x3000-0x30ff] Jan 1 15:42:30 electra kernel: [ 4.943670] yenta_cardbus 0000:08:00.0: bridge window [io 0x3400-0x34ff] Jan 1 15:42:30 electra kernel: [ 4.943675] yenta_cardbus 0000:08:00.0: bridge window [mem 0xa2000000-0xa3ffffff pref] Jan 1 15:42:30 electra kernel: [ 4.943679] yenta_cardbus 0000:08:00.0: bridge window [mem size 0x00080000] Jan 1 15:42:30 electra kernel: [ 4.943688] yenta_cardbus 0000:08:00.0: Enabling burst memory read transactions Jan 1 15:42:30 electra kernel: [ 4.943693] yenta_cardbus 0000:08:00.0: Using CSCINT to route CSC interrupts to PCI Jan 1 15:42:30 electra kernel: [ 4.943693] yenta_cardbus 0000:08:00.0: Routing CardBus interrupts to PCI Jan 1 15:42:30 electra kernel: [ 4.943698] yenta_cardbus 0000:08:00.0: TI: mfunc 0x00001d92, devctl 0x02 Jan 1 15:42:30 electra kernel: [ 5.189184] yenta_cardbus 0000:08:00.0: ISA IRQ mask 0x0000, PCI irq 19 Jan 1 15:42:30 electra kernel: [ 5.189187] yenta_cardbus 0000:08:00.0: Socket status: 10000051 Jan 1 15:42:30 electra kernel: [ 5.189189] yenta_cardbus 0000:08:00.0: pcmcia: parent PCI bridge window: [io 0x3000-0x4fff] Jan 1 15:42:30 electra kernel: [ 5.189190] yenta_cardbus 0000:08:00.0: pcmcia: parent PCI bridge window: [mem 0xa2000000-0xa40fffff] Jan 1 15:42:30 electra kernel: [ 5.189191] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa2000000-0xa40fffff: Jan 1 15:42:30 electra kernel: [ 5.189193] excluding 0xa2000000-0xa40fffff Jan 1 15:42:30 electra kernel: [ 5.189195] yenta_cardbus 0000:08:00.0: pcmcia: parent PCI bridge window: [mem 0xa0000000-0xa1ffffff 64bit pref Jan 1 15:42:30 electra kernel: [ 5.189195] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa0000000-0xa1ffffff: Jan 1 15:42:30 electra kernel: [ 5.189197] excluding 0xa0000000-0xa1ffffff Jan 1 15:42:30 electra kernel: [ 5.204854] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa2000000-0xa3ffffff: Jan 1 15:42:30 electra kernel: [ 5.204857] excluding 0xa2000000-0xa3ffffff Jan 1 15:42:30 electra kernel: [ 5.204865] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa4000000-0xa40fffff: Jan 1 15:42:30 electra kernel: [ 5.204865] excluding 0xa4000000-0xa400ffff 0xa4080000-0xa40fffff Jan 1 15:42:30 electra kernel: [ 6.104489] pcmcia_socket pcmcia_socket0: pccard: PCMCIA card inserted into slot 0 Jan 1 15:42:30 electra kernel: [ 6.104490] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa4010000-0xa407ffff: Jan 1 15:42:30 electra kernel: [ 6.118285] excluding 0xa407c000-0xa4081fff Jan 1 15:42:30 electra kernel: [ 6.118708] pcmcia 0.0: pcmcia: registering new device pcmcia0.0 (IRQ: 19) Jan 1 15:42:30 electra kernel: [ 6.130737] pcmciamtd 0.0: pcmcia: could not parse base and rmask0 of CIS Jan 1 15:42:30 electra kernel: [ 6.135487] MR032FLF14PCG 32MB FLASH CARD SERIES SV+ : Found 2 x16 devices at 0x0 in 16-bit bank. Manufacture Jan 1 15:42:30 electra kernel: [ 6.136850] Intel/Sharp Extended Query Table at 0x0031 Jan 1 15:42:30 electra kernel: [ 6.136912] Intel/Sharp Extended Query Table at 0x0031 Jan 1 15:42:30 electra kernel: [ 6.136977] Using buffer write method Jan 1 15:42:30 electra kernel: [ 6.136978] cfi_cmdset_0001: Erase suspend on write enabled Jan 1 15:42:30 electra kernel: [ 6.136978] erase region 0: offset=0x0,size=0x40000,blocks=128 Jan 1 15:42:30 electra kernel: [ 6.138560] pcmciamtd 0.0: mtd0: MR032FLF14PCG 32MB FLASH CARD SERIES SV+
Unsuccessful startup due to use of an ASM1083 bridge:
Jan 1 11:16:42 electra kernel: [ 71.465297] yenta_cardbus 0000:03:00.0: CardBus bridge found [123f:3000] Jan 1 11:16:42 electra kernel: [ 71.465340] yenta_cardbus 0000:03:00.0: Using INTVAL to route CSC interrupts to PCI Jan 1 11:16:42 electra kernel: [ 71.465340] yenta_cardbus 0000:03:00.0: Routing CardBus interrupts to ISA Jan 1 11:16:42 electra kernel: [ 71.465344] yenta_cardbus 0000:03:00.0: TI: mfunc 0x00001c92, devctl 0x02 Jan 1 11:16:42 electra kernel: [ 71.465346] yenta_cardbus 0000:03:00.0: Yenta TI: no PCI interrupts. Fish. Please report. Jan 1 11:16:42 electra kernel: [ 71.465349] yenta_cardbus 0000:03:00.0: no PCI IRQ, CardBus support disabled for this socket. Jan 1 11:16:42 electra kernel: [ 71.465349] yenta_cardbus 0000:03:00.0: check your BIOS CardBus, BIOS IRQ or ACPI settings. Jan 1 11:16:43 electra kernel: [ 71.601137] yenta_cardbus 0000:03:00.0: ISA IRQ mask 0x0000, PCI irq 0 Jan 1 11:16:43 electra kernel: [ 71.601147] yenta_cardbus 0000:03:00.0: Socket status: 10000051 Jan 1 11:16:43 electra kernel: [ 71.601158] yenta_cardbus 0000:03:00.0: pcmcia: parent PCI bridge window: [io 0x3000-0x4fff] Jan 1 11:16:43 electra kernel: [ 71.601161] yenta_cardbus 0000:03:00.0: pcmcia: parent PCI bridge window: [mem 0xa2000000-0xa40fffff] Jan 1 11:16:43 electra kernel: [ 71.601166] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa2000000-0xa40fffff: Jan 1 11:16:43 electra kernel: [ 71.601176] excluding 0xa2000000-0xa40fffff Jan 1 11:16:43 electra kernel: [ 71.601182] yenta_cardbus 0000:03:00.0: pcmcia: parent PCI bridge window: [mem 0xa0000000-0xa1ffffff 64bit pref Jan 1 11:16:43 electra kernel: [ 71.601185] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa0000000-0xa1ffffff: Jan 1 11:16:43 electra kernel: [ 71.601193] excluding 0xa0000000-0xa1ffffff Jan 1 11:16:43 electra kernel: [ 71.610999] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa2000000-0xa3ffffff: Jan 1 11:16:43 electra kernel: [ 71.611010] excluding 0xa2000000-0xa3ffffff Jan 1 11:16:43 electra kernel: [ 71.611047] pcmcia_socket pcmcia_socket0: cs: memory probe 0xa4000000-0xa40fffff: Jan 1 11:16:43 electra kernel: [ 71.611050] excluding 0xa4000000-0xa400ffff 0xa4080000-0xa40fffff