lkml.org 
[lkml]   [2011]   [Nov]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [RFC PATCH 1/7] Documentation: add docs for drivers/zio
On 11/26/2011 05:30 PM, Alessandro Rubini wrote:
> This is documentation for the beta3 release of zio.
> The files match commit 7d37663 in git://ohwr.org/misc/zio.git .
>
> We are aware the "modules.txt" file is not correct as it lists files
> that are not ready. We decided to avoid fixing it for this RFC
> submission, which won't go upstream anyways.
>
> Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
> Signed-off-by: Federico Vaga <federico.vaga@gmail.com>
> Acked-by: Juan David Gonzalez Cobas <dcobas@cern.ch>
> Acked-by: Samuel Iglesias Gonsalvez <siglesia@cern.ch>
> Acked-by: Manohar Vanga <manohar.vanga@cern.ch>
> ---
> Documentation/zio/00-INDEX | 10 +++
> Documentation/zio/buffer.txt | 114 ++++++++++++++++++++++++++++++++++++
> Documentation/zio/device.txt | 69 ++++++++++++++++++++++
> Documentation/zio/modules.txt | 45 ++++++++++++++
> Documentation/zio/trigger.txt | 128 +++++++++++++++++++++++++++++++++++++++++
> drivers/zio/README | 105 +++++++++++++++++++++++++++++++++
> 6 files changed, 471 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/zio/00-INDEX
> create mode 100644 Documentation/zio/buffer.txt
> create mode 100644 Documentation/zio/device.txt
> create mode 100644 Documentation/zio/modules.txt
> create mode 100644 Documentation/zio/trigger.txt
> create mode 100644 drivers/zio/README
>
> diff --git a/Documentation/zio/00-INDEX b/Documentation/zio/00-INDEX
> new file mode 100644
> index 0000000..093d9fb
> --- /dev/null
> +++ b/Documentation/zio/00-INDEX
> @@ -0,0 +1,10 @@
> +00-INDEX
> + - this file
> +device.txt
> + - description of what ZIO devices (and csets and channels) are.
> +buffer.txt
> + - description of the buffer, it's methods and how it is used.
> +trigger.txt
> + - what is a trigger and what's its role in ZIO.
> +modules.txt
> + - list of modules (and description) found in the first ZIO package
> diff --git a/Documentation/zio/buffer.txt b/Documentation/zio/buffer.txt
> new file mode 100644
> index 0000000..f80e63a
> --- /dev/null
> +++ b/Documentation/zio/buffer.txt
> @@ -0,0 +1,114 @@
> +
> +ZIO defines a "buffer" object type, so each device can exploit any
> +features it may offer to speed up data transfers.
> +
> +Each cset in a device can use a different buffer, which is specified
> +as an attribute of the cset. One instance of the buffer type exists
> +for each channel, and the char devices (control and data: see
> +device.txt) refer to the buffer.
> +
> +Please read <linux/zio-buffer.h> together with this file.
> +
> + Buffer Types
> + ============
> +
> +Buffers may be device-specific or generic. A generic buffer called
> +"kmalloc" is provided within zio-core; it uses kmalloc for allocation
> +data blocks. Such buffer is activated by default on all new csets
> +being registered but is not special in any other way, you can write
> +your own generic buffer (and if it's better than ours, we may use it
> +as default buffer in future releases).
> +
> +A device-specific buffer declares to be such within its attributes. A
> +device-specific buffer can only be used by csets that declare its name
> +as preferred buffer type. When such csets are registered, if the
> +buffer is already known to ZIO, it will be activated by default instead
> +of "kmalloc".
> +
> +Sometimes people write drivers for a set of similar devices, with
> +similar DMA capabilities. In this case, all of them may refer to the
> +same device-specific buffer type; the buffer type may be registered
> +as a standalone kernel module.
> +
> +The ZIO buffer data structures includes two sets of operations:
> +file_operations and buffer_operations.
> +
> +
> + Buffer Operations
> + =================
> +
> +Each buffer type must provide the following buffer operations. All
> +of them are implemented in zio-buf-kmalloc.c, which may be used as
> +reference to better understand the role of each method:
> +
> + struct zio_bi *(*create)(struct zio_buffer_type *zbuf,
> + struct zio_channel *ch,
> + fmode_t f_flags);
> + void (*destroy)(struct zio_bi *bi);
> +
> +The create() operation allocates and initializes an instance of the
> +buffer type. It is called by ZIO when a channel is opened for the
> +first time. The operation return a zio buffer instance (zio_bi),
> +which is the generic descriptor of a buffer instance. ZIO handles
> +only zio_bi, so complex buffer structures must contain the zio_bi
> +structure and use container_of() to access the private enclosing
> +structure.
> +
> +Destroy() deallocates a buffer instance. ZIO calls destroy when the
> +channel is unregistered from ZIO or when the user assigns a different
> +buffer type to the channel.
> +
> +When the control/data devices are closed, ZIO doesn't call destroy, so
> +incoming data can queue up while the application leaves it closed
> +(e.g., a shell script). Actually, the release file operation is not
> +handled by ZIO, so it couldn't call destroy on close even if it wanted
> +to.
> +
> + struct zio_block *(*alloc_block)(struct zio_bi *bi,
> + struct zio_control *ctrl,
> + size_t datalen, gfp_t gfp);
> + void (*free_block)(struct zio_bi *bi, struct zio_block *block);
> +
> +For input channels, a block is allocated before the trigger fires, and
> +it is freed when the user has read or explicitly ignored it. For
> +output, allocation happens on user write and free is called by the
> +trigger when it is done. Thus, the functions are sometimes called by
> +buffer code itself, and sometimes by the trigger. The generic
> +structure hosting a block is zio_block which contain both data
> +(samples) and control informations. If needed, buffers may use a more
> +complex structure, which will include zio_block, which is the only
> +structure that ZIO handles; by using container_of you can retrieve the
> +enclosing complex structure used in your buffer
> +
> + int (*store_block)(struct zio_bi *bi, struct zio_block *block);
> + struct zio_block (*retr_block) (struct zio_bi *bi);
> +
> +For input the trigger calls store_block() and the read system call issues
> +retr_block(). For output, the write system call runs store_block()
> +and the trigger may call retr_block() (although the buffer pushes to
> +the trigger when it receives the first data block).
> +
> +
> + File Operations
> + ===============
> +
> +This field hosts the file_operations used by the char devices (control and
> +data) for every channel using this buffer type. When char devices are
> +initially opened, the open method being run is within zio-code;
> +it kmallocs f->private_data before calling the buffer-specific open
> +method. The private data being used is:
> +
> + struct zio_f_priv {
> + struct zio_channel *chan;
> + enum zio_cdev_type type;
> + };
> +
> +All buffer file operations can thus refer to the current channel (and
> +its buffer and its trigger), and know if the current file is
> +ZIO_CDEV_CTRL or ZIO_CDEV_DATA. Every buffer is expected to
> +call zio_generic_release() at the end of its own release operation, or
> +used zio_generic_release() directly in the file operations.
> +
> +ZIO offers other generic file operations, that may be enough for your
> +buffer code or not. See zio-buf-kmalloc.c for a working example of
> +buffer file operations.
> diff --git a/Documentation/zio/device.txt b/Documentation/zio/device.txt
> new file mode 100644
> index 0000000..0c960e2
> --- /dev/null
> +++ b/Documentation/zio/device.txt
> @@ -0,0 +1,69 @@
> +
> + ZIO Device
> + ==========
> +
> +A device, registered through zio_register_device() is the description
> +of an I/O peripheral. It is made up of channel-sets, called csets
> +from now on. A device may represent a PCI board or an SPI integrated
> +circuit or whatever it makes sense to manage from a single device driver.
> +All I/O operations are performed on csets, so the device is just an
> +array of csets.
> +
> + Csets
> + =====
> +
> +A cset (channel-set) is an homogeneous set of I/O channels. All
> +channels in the set are feature the same physical characteristics;
> +moreover, a cset refers to a trigger object, so all channels in a set
> +are triggered by the same event. This is the typical use case for
> +logic analysers (digital input) or multi-probe scopes (analog input),
> +as well as multi-waveform output. If your device has several input
> +channels which are separately triggered, they should be defined as
> +several cset items, each featuring one channel only. Finally, all
> +channels in a cset use the same buffer object for in-kernel data
> +storage. Both the buffer and the trigger for a cset are set by
> +writing the proper name in sysfs. At device registration defaults
> +apply. If ZIO can't find the trigger/buffer name you wrote,
> +it will return EINVAL and leave the previous trigger/buffer in place.
> +
> + Channels
> + ========
> +
> +The channel is the lowest object in the ZIO hierarchy. It represents
> +the single physical connector of the device: analog or digital, input
> +or output. Time-to-digital and digital-to-time devices can be represented
> +as channels as well.
> +
> + Attributes
> + ==========
> +
> +Most configuration and information in ZIO happens through sysfs.
> +See sysfs.txt for information about attributes. (FIXME: sysfs.txt)
> +
> + Data Transfers
> + ==============
> +
> +Data transfer in ZIO uses two char devices for each channel offered by
> +the driver. One char device is used to describe data blocks (we call
> +it control device); the other is used to transfer the data blocks (we
> +call it data device). The control device returns (or accepts) a
> +fixed-size structure that describes the next data transfer, including
> +the trigger in use, data size, number of samples and various
> +attributes. Applications may choose to read the data device alone,
> +without retrieving control information: when any data of a new block
> +is transferred, the associated control information is discarded.
> +Similarly, data is discarded if you re-read the control device after
> +having retrieved the description of a data block you are not
> +interested in. For output, writing data without writing control uses
> +the default control information, or the one from the previous
> +transfer.
> +
> +The full set of rules for data and control transfers is described
> +elsewhere (FIXME: link to other docs) but it is pretty intuitive once
> +you get the idea.
> +
> +See the "zio-dump" host tool in the top-level zio dir for an example
> +of generic and simple input application that shows use of control and
> +data files.
> +
> +
> diff --git a/Documentation/zio/modules.txt b/Documentation/zio/modules.txt
> new file mode 100644
> index 0000000..b3df00a
> --- /dev/null
> +++ b/Documentation/zio/modules.txt
> @@ -0,0 +1,45 @@
> +
> +This is the list of ZIO modules, at the time of writing. It is there
> +to help new users understanding how the parts stick together.
> +
> + drivers/zio/zio-core.ko
> +
> +This module (which is linked from several source files) includes the
> +core sysfs and attribute management. It exports the register and
> +unregister functions for top-level objects. Moreover, it includes the
> +default buffer, called "kmalloc" and default trigger, called
> +"app-request".
> +
> + drivers/zio/trigger/trig-ktimer.ko
> + drivers/zio/trigger/trig-hrt.ko
> + drivers/zio/trigger/trig-irq.ko
> +
> +Three other generic triggers. Two of them are time-based, and the
> +third hooks to an external interrupt (or more than one) as source of
> +trigger that can be used be any zio cset).
> +
> + drivers/zio/dev/zio-null.ko
> + drivers/zio/dev/zio-parport.ko
> + drivers/zio/dev/zio-ad7888.ko
> + drivers/zio/dev/zio-uart.ko
> +
> +These modules are examples. "null" does nothing: it discards output
> +data and returns zeroes as input data. It can be used to experiment
> +with generic triggers and as a sandbox for local modifications and
> +testing.
> +
> +The parport driver registers two output csets and two input cset.
> +In each group one cset is byte-oriented and the other is bit-oriented.
> +
> +The ad7888 is an SPI ADC we mounted on an ARM board. It's a real
> +8-channel ADC we are using for internal development, and this is a
> +real driver for a real thing. Over time it will handle its own buffer
> +type (our SPI master uses DMA) and its own data-driven trigger (even
> +if the data will be scanned by the CPU, so it can only work at low
> +data rates).
> +
> +The uart driver is a line discpline that can receive data from a
> +serial port. The first implementation expects to receive an endless
> +stream of 16-bit data, big endian (we used this to run on-board ADC on
> +cortex-m3), but we plan to extend it as a serious test case. You can
> +drive it from a pty slave, for example.
> diff --git a/Documentation/zio/trigger.txt b/Documentation/zio/trigger.txt
> new file mode 100644
> index 0000000..95b426f
> --- /dev/null
> +++ b/Documentation/zio/trigger.txt
> @@ -0,0 +1,128 @@
> +
> +ZIO defines a "trigger" object type, and each cset is connected to
> +a trigger.
> +
> +Each cset in a device can use a different trigger, which is specified
> +as an attribute of the cset. When the trigger fires, it acts on all
> +the non-disabled channels of the cset. Only the "app-request" trigger
> +can act on a single channel at a time.
> +
> +Please read <linux/zio-trigger.h> together with this file.
> +
> + Trigger Types
> + =============
> +
> +Triggers may be device-specific or generic. A few generic triggers
> +are part of zio-core. The "app-request" trigger fires input when
> +the application calls read and fires output when the application calls
> +write (it acts on a single channel). The "ktimer" trigger uses a kernel
> +timer as trigger source. The "irq" trigger uses any interrupt (e.g.,
> +a GPIO interrupt, or pin 10 of the PC parallel port) as trigger event.
> +
> +A device-specific trigger declares to be such within its attributes. A
> +device-specific trigger can only be used by csets that declare its name
> +as preferred trigger type. When such csets are registered, if the
> +trigger is already known to ZIO, it will be activated by default instead
> +of "app-request".
> +
> + Trigger Operations
> + ==================
> +
> +Trigger operations are the following:
> +
> + struct zio_ti *(*create)(struct zio_trigger_type *trig,
> + struct zio_cset *cset,
> + struct zio_control *ctrl,
> + fmode_t flags);
> + void (*destroy)(struct zio_ti *ti);
> +
> +Create and destroy a trigger instance for a cset. ZIO calls create() when
> +attaching the trigger to a cset; it calls destroy() when the trigger is
> +replaced by a different one or the cset is being unregistered from ZIO.
> +The instance structure is trigger-specific, but it must include the
> +generic structure zio_ti. Every time this structure is passed over, trigger
> +code may use container_of if it needs to access the private enclosing
> +structure.
> +
> + int (*config)(struct zio_ti *ti, stuct zio_control *ctrl);
> +
> +The method is called by ZIO whenever the attributes for a trigger
> +instance are modified by the user (by writing to sysfs or otherwise).
> +
> + int (*push_block)(struct zio_ti *ti,
> + struct zio_channel *chan,
> + struct zio_control *ctrl);
> +
> +This is used for output channels: when a new data block is ready, it
> +must be sent to the trigger so it can be output when the event fires.
> +Buffer code, therefore, is expected to call this trigger method. The
> +function can return -EAGAIN if it has no space in the queue, or 0 on
> +success. If EAGAIN happens, the buffer should handle it (by storing
> +locally or notifying the user).
> +
> + void (*pull_block)(struct zio_ti *ti,
> + struct zio_channel *chan);
> +
> +The method asks the trigger for a new block. It may be called by
> +the buffer, if it wants a block immediately. The trigger that offers
> +this method (which may be NULL) is responsible of storing a block
> +when available. Since driver->input_cset completes asynchronously, this
> +method can't return a block directly. The block that will be stored
> +may be shorter than what the trigger would have stored in the buffer
> +by itself.
> +
> + void (*data_done)(struct zio_cset *cset);
> +
> +The function is called by the device, and signals the trigger that
> +the input or output operation on the cset is over. For input, the
> +trigger will push blocks to the buffer, for output it will release
> +the blocks. zio-core offers zio_generic_data_done() for triggers
> +that don't need special handling.
> +
> + File Operations
> + ===============
> +
> +The trigger may include a non-NULL f_ops pointer. Most triggers will
> +not need it, but for example "app-request" does, because it needs to
> +look at individual read and write calls performed by applications.
> +ZIO will use these file operations (instead of the buffer file operations)
> +when the open method of the char device detects that the active trigger
> +declares a non-NULL f_ops field. These operations will most
> +likely fall back to buffer->f_ops for most of their actual work.
> +
> +See zio-trig-app-request.c for details about how this is used.
> +
> + When the trigger fires
> + ======================
> +
> +The trigger event may happen for a variety of reasons. It can be
> +time-driven, data-driven or whatever else. In any case, there is
> +a time when the trigger fires, so input or output may happen.
> +(With most hardware-specific triggers, the actual input or output of
> +data has already happened when the trigger interrupt runs, but this
> +doesn't change the software flow).
> +
> +Hardware-driven triggers will need to make their own work by themselves,
> +but ZIO offers this help macro to loop over all non-disabled channels:
> +
> + cset_for_each(struct zio_cset *cset, struct zio_channel *ch)
> +
> +The macro works like "task_for_each" or "list_for_each" in the kernel
> +headers.
> +
> +For software-based triggers (where actual I/O happens when software
> +wants it to happen, even if it is in response to an interrupt), the
> +asynchronous code that runs the event will just need to call
> +
> + zio_fire_trigger(struct zio_ti *ti);
> +
> +This function, part of zio-core, calls the internal helpers
> +__zio_fire_input_trigger for input or __zio_fire_output_trigger for
> +output. For input, block allocation is performed for each
> +non-disabled channel, and drv->input_cset is called.
> +For output, drv->outoput_cset is called.
> +
> +You can refer to "zio-trig-timer" for an example of a multi-instance
> +generic timer and to "zio-trig-app-request" for a non-conventional
> +implementation based on trigger-local file_operations.
> +
> diff --git a/drivers/zio/README b/drivers/zio/README
> new file mode 100644
> index 0000000..d537353
> --- /dev/null
> +++ b/drivers/zio/README
> @@ -0,0 +1,105 @@
> +
> +Zio is "the ultimate I/O framework". Is being developed on the open
> +hardware repository at http://www.ohwr.org/projects/zio .
> +
> +This version is known to compile and run with kernels 2.6.34 onwards.
> +
> +This README refers to version "beta3", but work is ongoing towards
> +a stable package. See the TODO file on ohwr for details.
> +
> +To test zio you need to load the core modules (later, the default
> +trigger and default buffer will be part of zio-core):
> +
> + insmod zio-core.ko
> + insmod buffers/zio-buf-kmalloc.ko
> + insmod triggers/zio-trig-timer.ko
> +
> +Drivers can't live without a trigger and a buffer, so the modules above
> +must be loaded first.
> +
> +The kmalloc buffer is a simple buffer that hosts a list of data blocks,
> +for either input or output.
> +
> +The timer trigger is a kernel-timer based trigger, that fires a block
> +transfer on a timely basis. You can use the "ms" parameter to set the
> +inter-block time, in milliseconds (the default is two seconds). You
> +can also pass the "nsamples" parameter to say how many samples are
> +aquired at each trigger instance.
> +
> +With the core in place, you can load a driver:
> +
> + insmod drivers/zio-zero.ko
> +
> +zio-zero has a single channel-set (number 0) with three channels.
> +They simulate three analog inputs, 8-bit per sample.
> +
> + channel 0: returns zero forever
> + channel 1: returns random numbers
> + channel 2: returns a sawtooth signal (0 to 255 and back)
> +
> +The char devices are called using device-cset-channel:
> +
> + /dev/zzero-0-0-ctrl
> + /dev/zzero-0-0-data
> + /dev/zzero-0-1-ctrl
> + /dev/zzero-0-1-data
> + /dev/zzero-0-2-ctrl
> + /dev/zzero-0-2-data
> +
> +(later versions will use a /dev/zio/ directory for all zio files)
> +
> +To read data you can just cat, or "od -t x1" the data device.
> +To get control information meta-information) together with data, you
> +can use the "zio-dump" user-space utility, in this directory.
> +
> +For example:
> +
> + ./zio-dump /dev/zzero-0-2-ctrl /dev/zzero-0-2-data
> +
> +This is the result with a trigger that uses 2000 as msec and 32
> +as nsample:
> +
> + ./zio-dump /dev/zzero-0-2-ctrl /dev/zzero-0-2-data
> +
> + Ctrl: version 0.2, trigger timer, dev zzero, cset 0, chan 2
> + Ctrl: seq 1, n 32, size 1, bits 8, flags 01000001 (little-endian)
> + Ctrl: stamp 1320403540.084798370 (0)
> + Data: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
> + Data: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
> +
> + Ctrl: version 0.2, trigger timer, dev zzero, cset 0, chan 2
> + Ctrl: seq 2, n 32, size 1, bits 8, flags 01000001 (little-endian)
> + Ctrl: stamp 1320403542.091093781 (0)
> + Data: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
> + Data: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
> +
> + Ctrl: version 0.2, trigger timer, dev zzero, cset 0, chan 2
> + Ctrl: seq 3, n 32, size 1, bits 8, flags 01000001 (little-endian)
> + Ctrl: stamp 1320403544.084790274 (0)
> + Data: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
> + Data: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
> +
> +Zio dump is able to access several pairs of devices (control and data),
> +and you can change the trigger and buffer attributes for the cset.
> +
> +Example:
> +
> + echo 500 > /sys/zio/devices/zzero/cset0/trigger/ms-period
> + echo 4 > /sys/zio/devices/zzero/cset0/trigger/nsamples
> + echo 3 > /sys/zio/devices/zzero/cset0/chan0/buffer/max-buffer-len
> + ./zio-dump /dev/zzero-0-*
> +
> + Ctrl: version 0.2, trigger timer, dev zzero, cset 0, chan 0
> + Ctrl: seq 102, n 4, size 1, bits 8, flags 01000001 (little-endian)
> + Ctrl: stamp 4066.519285605 (0)
> + Data: 00 00 00 00
> +
> + Ctrl: version 0.2, trigger timer, dev zzero, cset 0, chan 1
> + Ctrl: seq 102, n 4, size 1, bits 8, flags 01000001 (little-endian)
> + Ctrl: stamp 4066.519285605 (0)
> + Data: 71 29 a6 53
> +
> + Ctrl: version 0.2, trigger timer, dev zzero, cset 0, chan 2
> + Ctrl: seq 102, n 4, size 1, bits 8, flags 01000001 (little-endian)
> + Ctrl: stamp 4066.519285605 (0)
> + Data: 60 61 62 63
Interesting approach to meta data handling. It's kind of 'partly' out
of band as it can apply to large chunks of data.

How does it map if you have triggers causing single captures from each
channel? I would imagine you will then store a whole meta data set per
sample? I know this isn't your use case, but I'm currious to see where
the overlap lies between this and IIO as you can imagine!


\
 
 \ /
  Last update: 2011-11-26 23:19    [from the cache]
©2003-2014 Jasper Spaans. Advertise on this site