Thursday, April 12, 2007

Ide2cf timeout with Linux

In my MythTV frontend I use a compact flash card as boot device, making the frontend into a diskless, silent media player. To connect the CF card to the system I use an IDE2CF adapter.

One annoying problem is that during boot, I get a couple of seconds timeout and some error output on the console. I think this comes from the IDE2CF card not supporting DMA correctly. The output I get is:

hda:hda: dma_timer_expiry: dma status == 0x21
hda: DMA timeout error
hda: dma timeout error: status=0x58 { DriveReady SeekComplete DataRequest }
ide: failed opcode was: unknown

I have searched the Internet and the only solution I have found said to include the ide=nodma commmand line parameter to the kernel, in the GRUB menu.lst file. That did not work, I still got the timeout.

I when decided to look into the source code directly, to try to see if I could find the error message and maybe see why the ide=nodma option was not working. I studied the code and found one interesting function. In the file ide-probe.c the code probes the IDE disks, and one call is to a function called ide_dma_check that probes the DMA capabilities of the drive. It seems that this ide_dma_check does it job and ignores the nodma command line option. My simple solution was to remove the call to ide_check_dma completely. I don't want DMA in my setup.

To patch your kernel you need to download the kernel source and the tools needed to build the new kernel.
My whole MythTV system is built on debian, so your exact procedure may be different if you use a different distribution.


#>apt-get install linux-source-2.6.18 kernel-package libncurses5-dev libqt3-mt-dev

Unpack the source.

#>cd /usr/src/
#>tar -jxf linux-source-2.6.18.tar.bz2
#>ln -s linux-source-2.6.18 linux
#>cd linux

Patch the ide-probe.c file to disable the DMA probing by searching for the ide_dma_check function call.

#>nano drivers/ide/ide-probe.c

You should find:


hwif->ide_dma_off_quietly(drive);
#ifdef CONFIG_IDEDMA_ONLYDISK
if (drive->media == ide_disk)
#endif
hwif->ide_dma_check(drive);
}

Just comment the call to hwif->ide_dma_check(driver) and the error message and startup timeout should go away. I admit that maybe the right solution is to look at the noautodma global variable, but this patch fixed my problem.

// hwif->ide_dma_check(drive);

Now build your new kernel.

#>make oldconfig
#>make-kpkg --initrd --append-to-version=-nodma kernel_image kernel_headers

After a (long) while the compilation will be finished and you can pick up two new .deb packages under /usr/src. One package for the kernel image and one for kernel headers. These new packages can be installed onto the frontend with:

#>dpkg -i linux-image-2.6-18-nodma-10.00.Custom_i386.deb

Now it's just to reboot.
Good luck!