Commands may be thought of as synchronous calls to a driver function, that is after the command invocation returns, the action specified is completed. Example: mode setting, setting of attribute lookup tables, etc. Command implementations may have high performance penalties (e.g. user<->kernel transition).
Mappings of MMIO region resources give applications direct access to memory mapped I/O resources of the display hardware. Accessing these regions must not cause fatal errors (system lockup, etc.) in any case but may be undefined if other resources are used concurerently (e.g. if the accelerator is currently accessing the framebuffer). Examples are frame buffers, local buffers, texture memory, etc. Accelerator FIFOs or MMIO regions _may_ be exported, but usually are only to the session leader.
Several regions scattered in physcial address space may be presented to the application as a virtually continous region. However, all regions must have the same size and are guarantueed not to be accessed simultaneously.
MMIO regions have no application dependent state except the last/current offset of the region if several discontinous regions are part of this resource.
Accelerators are means to execute command buffers filled by the application. They have a driver/protocol dependent application context associated with each mapping. When establishing the mapping, the mapper allocates a number of buffers and a context buffer meeting the preferences of the driver (e.g. do the buffers/the context buffer have to be suited for DMA access?). It then maps one buffer exclusively into the applications address space and waits for the application to fill this buffer. Once this is done, the application will initiate "execution" of that buffer, whereby the application looses access to that buffer, eventually caches are flushed (all data is written to memory), and the buffer is handed to the driver. The driver may choose to execute the buffer synchronously (buffer is executed if the drivers execute() function returns) or asynchronously (the buffer may still 'belong' to the driver).
In any case, the driver has to be aware that executing a buffer may require a context switch and perform this one as neccessary. Also, if asynchronous execution is implemented, scheduling issues are left to the driver.
There may be up to 16 buffers of arbitrary but same size per mapping. The number of mappings is only limited by process limits.
Shared memory implements access to a common region of memory for both the application and the driver/hardware. The shared memory may be attached to a context of an accelerator mapping.
The current implementation of a mapper providing access to the resources via standard file operations can be found in file:kgi-0.9/kgi/Linux/linux/drivers/kgi/graphic.c.
For MMIO regions, the _no_page() function determines the offset of the physical region to be mapped, asks the hardware to prepare itself and invalidates mappings of another region and validates the mapping for the accessed region.
For accelerator mappings, the _no_page() function determines what part of the the buffer is to be executed (depending on the offset into the next buffer), invalidates the mapping and passes the buffer to the driver for execution. After the buffer is scheduled for execution or is executed, it determines the next buffer from a circular list of buffers, makes sure it is executed (by testing the buffer state, if it is not idle -- thus being or waiting to be executed -- it waits until the buffer is executed). Done that it validates the mapping into the application address space and waits until the application has filled that buffer.