Requirements for an I/O framework
What follows is a list of requirements for an I/O framework
to be used for most (all?) CERN drivers.
- Digital and analog, input and output. All the 4 combinations.
-
TDC and DTC devices. The former (time to digital converter) is
a
pure timestamp input, stamping a pulse. The latter (digital to time
converter) is outputting a pulse at a specified time. In most use
cases, the time is known to the peripheral device but not to the OS
kernel.
-
One-shot, burst, and streaming support (streaming being the
least interesting). We need to set a value in a DAC but also
send a stream of samples, to generate some waveform. Similarly,
acquisition may be immediately (at read time) or fired by
a trigger.
-
Layered structure. Most cards have arrays of identical channels,
so
the framework must support grouping them and acting on them all at the
same time. Input and output on the channels is synchronized, and the
framework must support this concept.
-
No hard limits on the number of bits or channels. Our systems
can be
very complex, like hundreds of devices and/or channels. We don't have
hundreds of PCI boards, but I/O device may be remote over a synchronized
network, so the host system may really to handle hundreds of them.
-
High-data rate, little storage overhead. On of the first devices
we
need to support is a 4-channel ADC, 100Msamples per second, and such
figures may only increase in the upcoming years. Our devices have
internal RAM, so the data is retrieved at a later time (no need for
continuous streaming of such data rates). However, we can't afford
per-sample storage overhead.
-
Easy and general configuration. Although there will surely be
device-specific I/O applications, generic application should be able
to make sense of the I/O zoo handled by each host system. We need
udev support, autodetection and all such features -- remember: we
have up to hundreds of such things in a single host.
-
Offset, gain, number of bits, ... . Most common attributes
should
be supported out of the box, with consistent naming for all devices.
-
Extensibility. New attributes may be needed in specific cases,
or
a new attribute may need to be promoted to be "common". The framework
must support special cases and the rare core extension with a minimal
effort from the programmer.
-
Little code overhead. Configuration should fit naturally in
the
device drivers, requiring just a few lines of code (mainly, data
structures). We can't afford long sysfs-specific code within each
low-level device.
-
Centralized semaphores. Low-level drivers should not deal with
semaphores, as much as possible. All the complexity must be dealt with
by the framework. The low-level driver should ideally only code the
specifics of the hardware.
-
Flexible buffer management. The framework must support both
standard kmalloc or circular buffers, to be used in simple situations,
and custom buffers. A fast ADC, for example, will need DMA-aware
buffering techniques, and support zero-copy acquisition to user space.
-
Device-driven data transfers. Data input or output may be
trigger
by data values (like a scope does), external pulses or whatever. Both
input and output operations may be fired by hardware, and the
framework must support this concept -- in addition to controlling
trasfers at software level.
-
Hardware time stamps. We need to either timestamp each sample,
or a whole batch of samples. In either case the time bits may be
provided by hardware, and the framework must make no assumption
on the format. The typical constraints (using timespec or a nanosecond
count) are not acceptable.