Setting up Fedora Core 2 for PCMCIA memory card reading

file: fedora2-pcmcia-setup.html
date: 30 Sep 2004


Beginning with RedHat 7, Linux kernel version 2.4 became the standard kernel in the RedHat distribution. Unfortunately, some of the lesser-used memory card drivers were not ported to the Linux 2.4 kernel drivers (see comments by David Hinds on 2.4 kernel issues with PCMCIA). Thus the default 2.4 kernels from RedHat (and others) will not handle "raw" memory cards directly. PCMCIA support is still available as part of the standalone PCMCIA package. But Redhat no longer supports their non-Enterprise versions, so unless you like paying per-machine subscription fees to maintain your Linux machines, Fedora now seems to be the "free" route.

It gets worse! Unfortunately, with the advent of Fedora 2, which uses the 2.6 kernel, not even standalone PCMCIA support is available. (I suppose you could pay Redhat Enterprise subscription fees, and stay with a supported package that uses a 2.4 kernel for the moment(!!) but eventually the 2.6 kernel will arrive for RHEL users too.) So, what to do.....

But wait! There is a slightly "bumpy" solution for the moment - not perfect, but workable. The 2.6 kernel includes modules for various non-standard FLASH formats, for which it depends on the "Memory Technology Device" drivers, one of which supports PCMCIA. This support is somewhat "BROKEN" at the moment, but will work well enough to read (only) PCMCIA FLASH cards. Well, hey, that's what we want! This requires "tweaking" the kernel and rebuilding it, installing some parts of the latest pcmcia-cs package from sourceforge.net, then a couple of minor setup changes to Fedora startup files. This document will outline that process.


Getting the new kernel and pcmcia-cs sources

The first step is to get the latest kernel sources for your machine as well as the pcmcia-cs source. Go to fedora.redhat.com and look for the most recent kernel RPM's in the download/updates section of the site (Fedora Updates). Find the i386 packages at: Download Server. Download the pre-built kernel for your machine, plus the kernel-source package - you want the kernel-sourcecode-[version].noarch.rpm; for example, on my Dell Inspiron 8100 notebook with Fedora Core 2 running (in Sept 2004), it's kernel source kernel-sourcecode-2.6.8-1.521.noarch.rpm and pre-compiled kernel kernel-2.6.8-1.521.i686.rpm

Follow the instructions for upgrading your running kernel - get this working before proceeding! Once you are happy that everything is running normally with the new kernel, you can update the kernel source package on your PC as well. If you have rebuilt your kernel before for any reason, backup any .config files you want to keep (the /usr/src/linux-2.6/ source tree will normally be replaced when you upgrade). Once you're happy about your backups, upgrade the kernel source.

Now that you have the latest kernel running, and the matching kernel source is on your machine, get the latest pcmcia-cs source package from pcmcia-cs.sourceforge.net at the downloads page. As of Sept 2004, the package is pcmcia-cs-3.2.8.tar.gz. Untar this in the /usr/src/ directory. An ls in the /usr/src/ directory (current as of Sept 2004) shows the following directories:

aragorn: /usr/src#  ls
kernelconfigs/    linux-2.6.8-1.521/    pcmcia-cs-3.2.8/    redhat/

kernelconfigs/ is where I backed up a couple of older .config files for the linux kernel, linux-2.6@ is the symlink to linux-2.6.8-1.521, and pcmcia-cs-3.2.8 is the new pcmcia-cs source tree.


Rebuilding the kernel for MTD PCMCIA support

To rebuild the kernel for use with Memory Technolgy Device (MTD) PCMCIA support, you need to fix a Kconfig file so that the "make xconfig" step will work correctly, run "make xconfig" to set some stuff, then recompile everything. Here's how:

  1. cd to the /usr/src/linux-2.6.8-1.521/drivers/mtd/maps/ directory
  2. Make a backup of the Kconfig file in this directory (cp -p Kconfig Kconfig.orig) then edit the Kconfig file as follows:
  3. cd to the /usr/src/linux-2.6.8-1.521/ directory (everything that follows is done in this directory)
  4. make mrproper
  5. copy the config file for your installed kernel from /usr/src/linux-2.6.8-1.521/configs/ (or from the backup of a special build you kept in /usr/src/kernelconfigs/ ) to .config in the current directory. In my case, kernel-2.6.8-i686.config is the config file that was originally used to build the stock kernel.
  6. make xconfig
    1. The qconf, the Linux kernel configuration utility, will pop up.
    2. On the left menu, highlight "Device Drivers", "Memory Technology Devices (MTD)", and be sure MTD support is ON in the right hand menu (a "dot" indicates modular - that's fine).
    3. Also in the right menu, be sure "direct char ..", "caching block .." and "readonly block device access to MTD devices" are all ON as well ("dot" for modular).
    4. Back to the left menu, go down a couple of lines to "Mapping drivers for chip access".
    5. On the right menu, turn ON "support for non-linear mappings of flash chips" ("check" mark)
    6. Now the menu on the right should list a bunch of stuff including a choice for "PCMCIA MTD driver" - be sure this choice is ON with a "dot" for modular.
    7. Next, in the left hand menu, go down to "File systems" and highlight it.
    8. Now, in the right hand menu, find "Ext3 journalling file system support" and chnage it from modular ("dot") to built-in ("check") to build ext3 support directly into the kernel. (This will prevent complaints at boot time (non-fatal) because there is no initrd containing modules used with this new kernel).
    9. Done - "Save and Quit" to finish configuration.
  7. The top-level Makefile includes the variable name EXTRAVERSION; typically it is set to the extra version number of the source tree with the word custom appended ( -1.521custom in my case). If it DOESN'T have that extension, be sure to add it so you don't overwrite all your current kernel and module directories in the following steps.
  8. make
  9. make modules_install
  10. cd to /usr/src/linux-2.6.8-1.521/arch/i386/boot/ and copy the new kernel, bzImage, to the /boot directory on your system.

Now that the kernel and modules have been rebuilt, it might be a good idea to be sure you have a boot floppy available to reboot your current system if anything goes wrong in the next several steps. If you don't have a working boot floppy, make one now, if possible. (If the kernel is too big, mkbootdisk won't be able to fit everything on the floppy; in that case, you can use your Fedora rescue CD to recover). See the man page for mkbootdisk for a handy way to make a boot floppy (example: if your current kernel is version 2.6.8-1.521, put a 1.4MB floppy in your drive and enter mkbootdisk 2.6.8-1.521 to create a boot disk for the running kernel).

Next update your bootloader configuration file (grub.conf) to add the new kernel - DON'T remove the references to the current kernel. Add the lines for the new kernel so that you still default to the current kernel, and can choose the new kernel at boot time. Here's a typical example for grub.conf:

title Fedora Core (2.6.8-1.521)
        root (hd0,2)
        kernel /vmlinuz-2.6.8-1.521 ro root=LABEL=/ rhgb vga=791
        initrd /initrd-2.6.8-1.521.img
title Fedora Core (2.6.8-1.521custom)
        root (hd0,2)
        kernel /bzImage ro root=/dev/hda8 rhgb vga=791

If you use lilo.conf, the syntax is similar, but different; and don't forget to run /sbin/lilo after you save the new lilo.conf to actually update the boot record (there is no equivalent step for grub).

Now try rebooting to make sure everything is still working; if you kept your old kernel as default, everything should start up like always. Reboot again, and at the grub prompt, select the new kernel. Again, everything should start up normally. Fix any problems BEFORE proceeding. When you are sure everything is OK, modify your bootloader configuration file to make the new kernel the default.


Files from the PCMCIA-CS package

The normal Fedora Core 2 install to a laptop should include basic PCMCIA support, so the cardmgr, cardctl, and other utilities as well as a /etc/pcmcia/ directory are already present on the system. However, since the PCMCIA MTD support is NOT included, a couple of scripts need to copied from the pcmcia-cs package to /etc/pcmcia/.

  1. cd to the /usr/src/pcmcia-cs-3.2.8/etc/ directory
  2. cp -p the memory and memory.opts files to the /etc/pcmcia/ directory

Now, because PCMCIA MTD support is partially BROKEN, the /etc/pcmcia/memory file now needs to be modified slightly. Keep a backup of the original file, then edit /etc/pcmcia/memory as follows:

  1. find the line near the beginning of the file that gets device attributes: get_info $DEVICE
  2. insert 2 lines immediately after the get_info line:

    MAJOR=90
    MINOR=1

  3. save the file

Now modify the /etc/pcmcia/config file (keep a backup of the original) - this replaces some references to the old memory_cs module with pcmciamtd, the PCMCIA MTD module.

  1. find the device "memory" needs_mtd lines near the top of the file and and change these two lines to:

    device "pcmciamtd" needs_mtd
      class "memory" module "pcmciamtd"

  2. search thru the file for the section dealing with memory cards and find the stanzas with references to "Anonymous Memory" and "Memory Card".
  3. replace the references to "memory_cs" with "pcmciamtd"
  4. for other memory card stanzas that contain "memory_cs" references, either replace with "pcmciamtd" or remove each stanza not needed (I just removed all of them; since I made a backup of the original /etc/pcmcia/config file, I can restore them later if necessary).
  5. save the file

Testing PCMCIA MTD support

Now test the new PCMCIA MTD support; you should have a memory card with some data on it available for testing. An Intel Type2+ FLASH card should be recognized and all the correct modules will be insatlled.

  1. I assume you are running on the new kernel and modules - if not reboot to the new kernel now.
  2. next, do service pcmcia restart
  3. insert the PCMCIA FLASH card (for the moment, use an Intel Type2+ card if possible)
  4. ls /dev/mtd* should show several MTD devices present, as follows:

    /dev/mtd0a /dev/mtd0a0c /dev/mtd0c /dev/mtd0c0b /dev/mtd0c0c

Success! If you got these devices, you are in business! (Note that only the /dev/mtd0c0c devices actually works, but that's exactly the one we need). Otherwise, skip down to Uh-oh! below.

Copy the first 512kbytes of the card contents to a file as follows:

  dd bs=1024 count=512 if=/dev/mem0c0c of=test-file

then look at the file with:

  od -t x1 -A x test-file | less

See Linux FLASH Card Reading for more info.

Uh-oh! If you've got some other sort of FLASH card, like the "sort-of" Intel-compatible FLASH cards I have custom made from EDI, there is apparently something unusual in the card CIS structure. If you have both types of cards, try putting in the genuine Intel card first, which will cause the correct modules to load. Now swap for the non-standard card and see if you are reading it OK. If you are, the next steps will "hotwire" the PCMCIA MTD services so you can read these cards without any complications. (If this doesn't let you read the card successfully then you are out of luck at the moment. Please let me know if you come up with a solution; in fact, write it up like this document and send me the URL so I can link to it!)

To force the loading of the modules needed for reading PCMCIA FLASH cards, I added the following 2 lines to the end of the system startup /etc/rc.d/rc.local script. Keep a backup copy of the original rc.local file.

  1. save a backup copy of /etc/rc.d/rc.local
  2. edit /etc/rc.d/rc.local to add the following 2 lines at the end of the script:
      /sbin/modprobe pcmciamtd
      /sbin/modprobe cfi_cmdset_0001
  3. save the file
  4. Reboot should now cause a number of modules to be loaded automatically on startup - test by inserting a memory card as above.

Document any extra or special steps you took....NOW!!