Asynchronous Request Architecture

Many of the drivers in this framework are accessed through an asynchronous request API built around a common data structure: The buffer. An asynchronous API is somewhat more complicated to use than a traditional synchronous API, where the function calls block until the request is done, but it offers several advantages:

Typical asynchronous request flow

The following sequence diagram describes the flow of a typical asynchronous request submitted by a Client to a Driver. When the request is being processed by hardware, the CPU may perform other tasks, or go to sleep if there's nothing to be done. The driver will call the callback associated with the request, if any, when the hardware signals that the request is complete.

Sometimes, the driver may need to perform multiple hardware operations in order to process a single request. This is completely hidden from the client. The driver may also keep a request queue, allowing multiple clients to submit any number of requests, which will often provide better utilization of the hardware.

inline_mscgraph_1

Asynchronous Request Buffers

While the definition of a request data structure may vary slightly from driver to driver, they all contain a linked list of buffer structures.

A buffer represents a memory region which is contiguous in physical and virtual memory. A request can have multiple buffers, allowing transfers to and from discontiguous memory regions.

Buffer Memory

The address of the memory region associated with a buffer is described using the type buffer_addr_t. This can be either a struct or a union with two members:

On some processors, for example the AVR32 UC3 family, the virtual address is always equal to the physical address, so the type is defined as a union to save space. Other processors, for example the AVR32 AP7 family, have integrated MMU hardware, so the software cannot assume that the virtual and physical addresses are identical. In this case, the type is defined as a struct in order to keep track of the addresses separately.

The size of the memory region in bytes is kept in the buffer::len field. This also indicates how many bytes that are to be transfered for one particular buffer segment.

Other Data Associated with a Buffer

The buffer::dma_desc field is for use by drivers that support DMA transfers to keep track of any descriptors used by the DMA hardware. It may become optional on some platforms that don't have any DMA hardware.

The buffer::node field is a list node primarily used for keeping the buffer on the request's buffer list. Drivers are free to move the buffers onto other lists while the request is being processed, but the original list must be restored before the request is handed back to the client.

Asynchronous Request Objects

The asynchronous request objects are subsystem-specific, but they usually have several fields in common:

Generated on Tue Sep 15 10:22:13 2009 for libavr32 by  doxygen 1.5.8