debacle: a complete and ludicrous failure; a rout, as of an army; a great disaster; a fiasco The Mesa Anything I/O boards have FPGAs that need to be programmed with firmware (such as HostMot2) before they can do anything useful. The firmware is stored on the host computer. The host computer sends the firmware to the Anything I/O board at startup, using a communication mechanism very similar to the mechanism it uses to communicate with the firmware during normal operation later. Each board has several possible HostMot2 firmwares it can run, each providing different combinations of quadrature counters, PWM generators, step/dir generators, etc. The user must decide which firmware to run on which board. When emc2 is installed as a Debian package, the firmware files are installed in /lib/firmware/hm2. When emc2 is compiled from source and run-in-place (RIP), the firmware files are located in the user's sandbox, usually in a random user-chosen directory. The user may have several different sandboxes, each using RIP. There are two reasonable-seeming ways to send the firmware to the boards: via the normal kernel driver, or via a separate userspace utility. 1. kernel driver loads firmware The 2.6 kernel has a mechanism that allows a device driver to request a firmware file; udev fetches the file and delivers it to the driver. The mechanism is documented in the linux kernel source, in Documentation/firmware_class/README. It's widely used and well supported. The default solution would of course be to use this existing infrastructure to accomplish firmware loading. The driver would accept a modparam string where the user specified the firmware to load on each board. If the user did not specify a firmware name, the driver would not try to program the FPGA, or it might use a default one. A typical firmware name might be "hm2/7i43/SVST4_4S.BIT". udev would deliver the requested firmware and the driver would program the FPGA. There are several reasons this solution would be desirable: Having all the code that talks to the boards in one place (the device driver) is natural and simple. The kernel has full, unfettered access to the boards, whereas access to PCI and EPP devices from userspace is awkward. This solution avoids issues with userspace library availability, library version skew, etc, though at the expense of kernel version skew. The kernel firmware interface has been stable for a long time now, so this seems like a good trade. Unfortunately the kernel firmware interface has shortcomings that make it awkward to use with emc2. The standard kernel firmware loading userspace helper searches for firmware in a small set of standard system directories (/lib/firmware & friends). This would work great when emc2 is installed by .deb package, but wouldnt work out-of-the-box with RIP: the firmware helper doesnt know to look in the user's sandbox. RIP with the standard userspace helper would thus require that the user symlink their sandboxes' firmware directories into /lib/firmware. This would violate the system's integrity by placing files in the public part of the filesystem without going through the package manager. One way to avoid that problem would be to tweak udev to allow kernel drivers to specify absolute paths to the firmware they want. udev is flexible, and it's possible to provide alternate firmware helper scripts to handle loading firmwares from other places. Some documentation on how to do this is here: . This would require installing a custom udev rule in /etc/udev/rules.d (emc2 already does this, to tweak the permissions of the rtai fifos) and installing a custom firmware helper. The driver's firmware modparam would specify the absolute path to the firmware file to load on each board, and the custom userspace firmware helper would fetch the file and deliver it to the driver. This would work well, except... The kernel imposes a 30-character limit on the filename of the requested firmware (FIRMWARE_NAME_MAX in include/linux/firmware.h). Firmwares in sandboxes tend to be in deeply nested subdirectories, with paths much longer than this. So absolute firmware paths are basically infeasible. Custom udev firmware helpers can't help with this, it's a kernel limitation. The firmware name length limitation also affects the "symlink sandboxes into /lib/firmware" solution. The sample firmware name given above is 21 characters, leaving just 8 characters for the name of the sandbox-symlink. Tight but not impossible. Thus the only way to do in-kernel firmware loading (as of Linux 2.6.24) is to install emc2 via the .deb, or to symlink the user's active RIP sandboxes into /lib/firmware. 2. userspace utility (bfload) loads firmware This has the advantage that userspace has full access to the filesystem, so accessing firmware files in arbitrary sandbox directories is easy. However, it also has several drawbacks: It's clumsy to have two pieces of code driving the boards. I/O conflicts must be detected and avoided, and this is fraught with race conditions. I think this is not a huge problem in practice, but it smells bad. EPP I/O must be done "manually" with ins and outs, since the standard Linux parport driver is unsuitable for use with RTAI. Properly initializing the PCI boards requires access to both the PCI Config space and the board's normal BARs (both memory and IO). Userspace PCI access is via one of several libraries: upci (the current emc2 PCI access library) supports IO and Memory BAR access but lacks PCI Config space access libpci supports Config space access but lacks BAR access libpciaccess supports Config space and Memory BARs, but not IO BARs The cleanest way to handle the PCI access issue would be to have one PCI library that provided all the access methods needed. No such library currently exists to my knowledge, and certainly none is available on all our supported platforms. The PCI access issue can be fixed a couple of ways: Use upci and libpci together (gross). Merge upci into libpci or libpciaccess (clean) and fork the result into our tree to support old distros without the new upstream library (gross). Shell out to setpci where needed. This would only be sensible for very simple situations where no feedback is required (such as the current situation). This solution is slightly complicated by the fact that system(3) explicitly clears the setuid bit before running the shell. bfload would have to reimplement system() without this safety feature, calling fork and exec manually. So the implemented solution is firmware loading from kernel space. RIP users must symlink their sandboxes' firmware directories into /lib/firmware and everything works fine. This is documented in the hostmot2 man page.