Docbook revised.

This commit is contained in:
Frank A. Uepping 2005-01-25 18:13:37 +00:00
parent abff2ffe45
commit e749b19cdd
6 changed files with 299 additions and 256 deletions

View File

@ -21,8 +21,9 @@
<revhistory>
<revision>
<revnumber>$Revision$</revnumber>
<date>$Date$</date>
<revnumber></revnumber>
<date></date>
<revremark>Working Draft</revremark>
</revision>
</revhistory>
@ -42,10 +43,9 @@
</para>
<para>
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
</para>
<para>
@ -61,43 +61,44 @@
<title>Introduction</title>
<para>
<acronym>CAPI</> (COMMON-ISDN-API) is a message oriented and event
driven programming interface used by applications to access
<acronym>ISDN</> hardware equipment in a standardized and
straightforward way. Publisher of the <acronym>CAPI</> standard is the
<ulink url="http://www.capi.org">CAPI-Association</ulink>, a non-profit
<acronym>CAPI</> (COMMON-ISDN-API) is a message oriented and event driven
programming interface, used by applications to access <acronym>ISDN</>
hardware equipment in a standardized and straightforward way. Publisher
of the <acronym>CAPI</> standard is the <ulink
url="http://www.capi.org">CAPI-Association</ulink>, a non-profit
international consortium of hardware and software manufactures and
telecommunications institutions. The <acronym>CAPI</> standard is
freely available for download on their website.
telecommunications institutions; the <acronym>CAPI</> standard is freely
available for download on their website.
</para>
<para>
The <acronym>CAPI</> standard defines a set of messages,
protocols, and operations. While the messages and protocols are
interoperable, the interface to the operations is specific to
each supported operating-system. For Linux, the standard
defines <acronym>CAPI</> interfaces for user- and kernel-space.
The <acronym>CAPI</> standard defines a set of messages, protocols, and
operations. While the messages and protocols are interoperable, the
interface to the operations is specific to each supported
operating system. For Linux, the standard defines <acronym>CAPI</>
interfaces for user and kernel space.
</para>
<para>
<ulink url="http://www.capi4linux.org/ngc"><emphasis>Next
Generation CAPI</emphasis></ulink> (<acronym>NGC</>) is an
<emphasis>experimental</emphasis> implementation of the
<acronym>CAPI 2.0</> standard, and it started as a fork of <ulink
url="http://www.isdn4linux.org">CAPI4Linux</ulink>.
<ulink url="http://www.capi4linux.org/ngc"><emphasis>Next Generation
CAPI</emphasis></ulink> (<acronym>NGC</>) is an
<emphasis>experimental</emphasis> implementation of the <acronym>CAPI</>
2.0 standard and derived from <ulink
url="http://www.capi4linux.org">CAPI4Linux</ulink>.
</para>
<para>
The heart of the <acronym>NGC</> subsystem is the
<emphasis>capicore</emphasis> and, as such, it is crucial to the
performance and the stability of the whole subsystem. Basically, the
<emphasis>capicore</emphasis> provides an infrastructure for the
communication between applications and device-drivers. Applications are
interfaced with the <emphasis>capicore</emphasis> via <acronym>CAPI</>,
and device-drivers via an interface proprietary to Linux. This white
paper is related to these interfaces, and it is assumed that the reader
is familiar with the basic concepts and terms of the <acronym>CAPI</>
standard and with Linux kernel programming in general.
The heart of the <acronym>NGC</> subsystem is the capicore and, as such,
it is crucial to the performance and the stability of the whole
subsystem. Basically, the capicore provides an infrastructure for the
communication between applications and device drivers. Applications are
interfaced with the capicore via <acronym>CAPI</>, and device drivers via
a custom made interface proprietary to Linux. This white paper is
concerned with these interfaces, and describes them from the viewpoint of
a device driver and an application developer, respectively. Further, it
is assumed that the reader is familiar with the basic concepts and terms
of the <acronym>CAPI</> standard and with Linux kernel programming in
general.
</para>
</chapter>
@ -105,9 +106,9 @@
<title>Structures and Data Types</title>
<para>
The <emphasis>capicore</emphasis> provides a set of common structures
and data types, forming the basis of communication between the various
layers of the <acronym>CAPI</> subsystem.
The capicore provides a common set of structures and data types forming
the basis of communication between the various layers of the
<acronym>NGC</> subsystem.
</para>
!Iinclude/linux/isdn/capinfo.h
@ -120,64 +121,64 @@
<title>Device Driver Interface</title>
<para>
Device-drivers and applications communicate together via the
<emphasis>capicore</emphasis> in an asynchronous way by exchanging
messages according to the <acronym>CAPI</> standard. While the
implementation of a device-driver might be rather complex internally,
the interface with the <emphasis>capicore</emphasis> is simple. The
declarations to this interface can be found in <filename
class="headerfile">linux/isdn/capidevice.h</filename>.
Device drivers and applications communicate together, via the capicore,
in an asynchronous way by exchanging messages according to the
<acronym>CAPI</> standard. While the implementation of a device driver
might be rather complex internally, the interface with the capicore is
pretty simple. The declarations to this interface can be found in
<filename class="headerfile">linux/isdn/capidevice.h</filename>.
</para>
<sect1>
<title>Overview</title>
<para>
Devices are represented to the <emphasis>capicore</emphasis> by
objects of the generic <structname>capi_device</structname> structure.
This structure forms the basis of communication between the
<emphasis>capicore</emphasis> and device-drivers. Devices are
reference counted objects and need to be dynamically allocated by the
device-driver via the function <function>capi_device_alloc</function>.
When the device-driver is done with the device (i.e.: after removing
the device from the <emphasis>capicore</emphasis>), it should drop its
reference to it via the function <function>capi_device_put</function>.
Devices are represented to the capicore by objects of the generic
<structname>capi_device</structname> structure. This structure forms
the basis of communication between the capicore and device drivers.
Devices are reference counted objects and need to be dynamically
allocated by the device driver via the function
<function>capi_device_alloc</function>. Destroying a device is
done by releasing all references to it via the function
<function>capi_device_put</function>.
</para>
<para>
Once a generic <structname>capi_device</structname> object is
initialized, the device-driver can register it with the
<emphasis>capicore</emphasis> via the function
<function>capi_device_register</function>. Removing the device from
the <emphasis>capicore</emphasis> is done via the function
<function>capi_device_unregister</function>.
initialized, the device driver can register it with the capicore via
the function <function>capi_device_register</function>. Removing the
device from the capicore is done via the function
<function>capi_device_unregister</function>; subsequently, the
device driver can release the device via the function
<function>capi_device_put</function>.
</para>
<para>
The device-driver has to provide three functions for calling by the
<emphasis>capicore</emphasis> via the
<structname>capi_driver</structname> structure. This enables the
<emphasis>capicore</emphasis> to register and remove applications with
devices, and transfering messages to them.
The device driver has to provide three functions for calling by the
capicore via the <structname>capi_driver</structname> structure,
enabling the registration and removal of applications with the device
driver's devices and the transfer of messages to them.
</para>
<para>
Each application owns a message queue by which devices are
transferring messages to the application. Adding messages to the
application queue is done via the function
<function>capi_appl_enqueue_message</function>, and informing the
application about new messages via the function
<function>capi_appl_signal</function>. If the device-driver
encounters an error concerning the message exchange, it should inform
the corresponding application about this event via the function
<function>capi_appl_signal_error</function>.
Each application owns a message queue by which devices are transferring
messages to the application. Adding messages to the application queue
is done via the function
<function>capi_appl_enqueue_message</function>. Upon that, the device
driver should <emphasis>wakeup</emphasis> the application via the
function <function>capi_appl_signal</function>. If the device driver
encounters an error related to a message (i.e., in the context of an
application), it should inform the concerned application about that
condition via the function <function>capi_appl_signal_error</function>,
causing the application to release.
</para>
<para>
Besides that, since <acronym>CAPI</> devices are <emphasis>class
devices</emphasis>, they can easily export own attributes to the
<emphasis>sysfs</emphasis>. See <filename
class="headerfile">linux/device.h</filename> for more information.
devices</emphasis>, they can easily export own attributes to the sysfs,
enabling the device driver to offer device specific features to the
user. See <filename class="headerfile">linux/device.h</filename> for
more information.
</para>
</sect1>
@ -193,19 +194,19 @@
<title>Application Interface</title>
<para>
Applications and device-drivers communicate together via the
<emphasis>capicore</emphasis> in an asynchronous way by exchanging
messages according to the <acronym>CAPI</> standard. While the
implementation of an application might be rather complex internally, the
interface with the <emphasis>capicore</emphasis> is simple.
Applications and device drivers communicate together, via the capicore,
in an asynchronous way by exchanging messages according to the
<acronym>CAPI</> standard. While the implementation of an application
might be rather complex internally, the interface with the capicore is
pretty simple.
</para>
<para>
For Linux, the <acronym>CAPI</> standard defines interfaces for user-
and kernel-space applications. Unfortunately, the specification to the
kernel-space <acronym>CAPI</> is too unspecific. To give developers the
required backing in writing safe kernel-space applications, the
<emphasis>capicore</emphasis> introduces an alternative interface which
For Linux, the <acronym>CAPI</> standard defines <acronym>CAPI</>
interfaces for user and kernel space applications. Unfortunately, the
specification to the kernel space <acronym>CAPI</> is too unspecific. To
give developers the required backing in writing safe kernel space
applications, the capicore introduces an alternative interface which
we're going to describe here in detail. The declarations to this
interface can be found in <filename
class="headerfile">linux/isdn/capiappl.h</filename>.
@ -215,21 +216,23 @@
<title>Overview</title>
<para>
Applications are represented to the <emphasis>capicore</emphasis> by
objects of the generic <structname>capi_appl</structname> structure.
This structure forms the basis of communication between the
<emphasis>capicore</emphasis> and applications. Once a generic
<structname>capi_appl</structname> object is initialized, the
application can register it with the <emphasis>capicore</emphasis> via
the function <function>capi_register</function>. Removing
applications from the <emphasis>capicore</emphasis> is done via the
function <function>capi_release</function>.
Applications are represented to the capicore by objects of the generic
<structname>capi_appl</structname> structure. This structure forms the
basis of communication between the capicore and applications.
</para>
<para>
Applications need to register a signal-handler via the function
<function>capi_set_signal</function>. The signal-handler serves as a
notification mechanism for asynchronous events such as:
Once a generic <structname>capi_appl</structname> object is
initialized, the application can register it with the capicore via the
function <function>capi_register</function>. Removing an application
from the capicore is done via the function
<function>capi_release</function>.
</para>
<para>
Applications need to install a signal handler via the function
<function>capi_set_signal</function>. The signal handler serves as a
notification mechanism for asynchronous events, such as:
<itemizedlist mark=opencircle>
<listitem>
@ -239,19 +242,40 @@
<para>the clearance of queue-full/busy conditions</para>
</listitem>
<listitem>
<para>occurred message exchange errors</para>
<para>errors</para>
</listitem>
</itemizedlist>
The signal-handler is not meant to be a
<emphasis>workhorse</emphasis>, but a mechanism for waking-up and
Note that a signal handler is not meant to be a
<emphasis>workhorse</emphasis>, but just a mechanism for waking up and
scheduling applications.
</para>
<para>
Applications transfer messages via the function
<function>capi_put_message</function>, and fetch them via the function
<function>capi_get_message</function>.
<function>capi_get_message</function>. They can put back messages via
the function <function>capi_unget_message</function>, and check for
pending messages via the function
<function>capi_peek_message</function>.
</para>
<para>
Applications can retrieve informations from <acronym>CAPI</> devices
via the functions: <function>capi_get_manufacturer</function>,
<function>capi_get_serial_number</function>,
<function>capi_get_version</function>,
<function>capi_get_profile</function>, and
<function>capi_get_product</function>.
</para>
<para>
Since <acronym>CAPI</> devices are <emphasis>class devices</emphasis>,
applications can install a <emphasis>class interface</emphasis> with
the Linux device driver core to get informed when <acronym>CAPI</>
devices are being registered and removed with the capicore. See
<filename class="headerfile">linux/device.h</filename> for more
information.
</para>
</sect1>

View File

@ -40,19 +40,20 @@ atomic_t nr_capi_devs = ATOMIC_INIT(0);
/**
* capi_device_alloc - allocate a device structure
* capi_device_alloc - allocate a device control structure
*
* Context: !in_interrupt()
*
* Allocate a device structure and initialize the reference counter
* to one.
* Allocate a new device control structure and initialize its reference
* counter to one.
*
* Upon successful allocation, the pointer to the new device structure
* is returned. Otherwise, NULL is returned.
* Upon successful allocation, a pointer to the new device control
* structure is returned. Otherwise, NULL is returned.
*
* Note: The device structure must not be freed by simply calling
* kfree(), but by a call to capi_device_put(). This will cause the
* device structure to be freed if the reference counter reaches zero.
* Note: The device control structure must not be freed by simply calling
* kfree(), but by a call to capi_device_put(), which will cause the
* device control structure to be freed when the reference counter reaches
* zero.
*/
struct capi_device*
capi_device_alloc(void)
@ -155,10 +156,12 @@ unregister_capi_device(struct capi_device* dev)
*
* Context: !in_interrupt()
*
* The device is assigned a unique device number, and all applications
* will be registered with the device in turn. If the device fails to
* register an application, the device is marked as erroneous for that
* application.
* @dev is assigned a unique device number, and all applications are
* registered with @dev in turn. If the device driver fails to register
* an application with @dev, @dev is marked as erroneous on that
* application. Finally, @dev is registered with the sysfs, which in
* turn could result in applications issuing messages, from installed
* class interfaces, to @dev.
*
* Upon successful registration, 0 is returned. Otherwise, a negative
* error code is returned.
@ -197,16 +200,20 @@ capi_device_register(struct capi_device* dev)
*
* Context: !in_interrupt()
*
* The device-driver must ensure that by the time it is calling this
* function for @dev, no thread will be executing in a call to any
* of the functions capi_appl_enqueue_message(), capi_appl_signal(),
* or capi_appl_signal_error() in the name of @dev.
* The device driver must ensure that by the time it is calling this
* function for @dev, no thread is and will be executing, in the context
* of @dev, in a call to any of these functions capi_appl_signal_error(),
* capi_appl_enqueue_message(), or capi_appl_signal().
*
* Furthermore, the capicore ensures that by the time this function
* returns for @dev, no thread will be executing in a call from the
* capicore to that device-driver's device operations for @dev.
* Furthermore, the capicore ensures that by the time the call to this
* function returns for @dev, no thread is and will be executing in a call
* from the capicore to any of @dev's device driver operations for @dev.
*
* capi_device_put() should be called afterwards for @dev.
* By the time the device driver calls this function, applications could
* be in a passive state (e.g., listen state L-1) waiting for events from
* CAPI. The device driver should leave those applications as-is, even if
* they would wait forever; it is the responsibility of the user to deal
* with such situations.
*/
void
capi_device_unregister(struct capi_device* dev)
@ -264,10 +271,9 @@ bind_capi_appl(struct capi_appl* appl)
*
* Context: !in_interrupt()
*
* The application is assigned a unique application number, and is
* registered with each device in turn. If a device fails to register
* the application, the device is marked as erroneous for that
* application.
* @appl is assigned a unique application number, and is registered with
* each device in turn. If a device fails to register @appl, that device
* is marked as erroneous on @appl.
*
* Upon successful registration, %CAPINFO_0X10_NOERR is returned.
* Otherwise, a value indicting an error is returned.
@ -309,18 +315,17 @@ capi_device_listed(struct capi_device* dev)
*
* Context: !in_interrupt()
*
* The @appl is removed from each device registered with.
*
* The application must ensure that by the time it is calling this
* function for @appl, no thread will be executing in a call from the
* application to the function capi_put_message() for @appl.
* function for @appl, no thread is and will be executing in a call to
* any of these functions capi_put_message(), capi_get_message(),
* capi_unget_message(), or capi_peek_message() for @appl.
*
* Furthermore, the capicore ensures that by the time this function
* returns for @appl, no thread will be executing in a call from the
* capicore to that application's signal-handler.
* Furthermore, the capicore ensures that by the time a call to this
* function returns for @appl, no thread is and will be executing in a
* call from the capicore to the signal handler installed with @appl.
*
* Upon successful removal, %CAPINFO_0X11_NOERR is returned. Otherwise,
* an error is returned.
* a value indicating an error is returned.
*/
capinfo_0x11_t
capi_release(struct capi_appl* appl)
@ -357,19 +362,22 @@ capi_release(struct capi_appl* appl)
*
* Context: !in_irq()
*
* In the case of a data transfer message (DATA_B3_REQ), the data must be
* appended to the message (this is contrary to the CAPI standard which
* intends a shared buffer scheme) and the Data field will be ignored.
*
* %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY is returned if the
* message could not be accepted, but this does not imply that messages
* cannot be accepted directed to another device, PLCI or NCCI. This is
* a temporary condition and the application should retry sometime later
* after being signaled. Care must be taken by the application to
* implement the retransmit logic in race-free manner.
* %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY is returned if @msg
* could not be accepted, but this does not imply that messages cannot be
* accepted directed to another application, device, PLCI, or NCCI. This
* is a temporary condition and the application of @appl should retry
* sometime later after being signaled by the signal handler installed
* with @appl.
*
* If the message was accepted, %CAPINFO_0X11_NOERR is returned.
* Otherwise, a value indicating an error is returned.
*
* In the case of a data transfer message (DATA_B3_REQ), the data must be
* appended to the message (this is contrary to the CAPI standard which
* intends a shared buffer scheme), and the Data field will be ignored.
*
* The application should adhere to the CAPI data window protocol.
*
*/
capinfo_0x11_t
capi_put_message(struct capi_appl* appl, struct sk_buff* msg)
@ -401,11 +409,11 @@ capi_put_message(struct capi_appl* appl, struct sk_buff* msg)
/**
* capi_isinstalled - determine whether a device is available
* capi_isinstalled - check whether any device is installed
*
* Context: in_irq()
*
* If a device is available, %CAPINFO_0X11_NOERR is returned.
* If any device is installed, %CAPINFO_0X11_NOERR is returned.
* Otherwise, %CAPINFO_0X11_NOTINSTALLED is returned.
*/
capinfo_0x11_t
@ -442,12 +450,12 @@ try_get_capi_device_by_id(int id)
*
* Context: !in_irq()
*
* Copy the manufacturer string of the device denoted by @id, to the
* Copy the manufacturer string of the device, denoted by @id, to the
* target buffer. If @id is 0, copy the manufacturer string of the
* capicore.
*
* @manufacturer is returned if the device was available. Otherwise,
* NULL is returned.
* NULL is returned if there is no such device with @id. Otherwise,
* @manufacturer is returned.
*/
u8*
capi_get_manufacturer(int id, u8 manufacturer[CAPI_MANUFACTURER_LEN])
@ -473,12 +481,12 @@ capi_get_manufacturer(int id, u8 manufacturer[CAPI_MANUFACTURER_LEN])
*
* Context: !in_irq()
*
* Copy the serial number string of the device denoted by @id, to the
* Copy the serial number string of the device, denoted by @id, to the
* target buffer. If @id is 0, copy the serial number string of the
* capicore.
*
* @serial is returned if the device was available. Otherwise,
* NULL is returned.
* NULL is returned if there is no such device with @id. Otherwise,
* @serial is returned.
*/
u8*
capi_get_serial_number(int id, u8 serial[CAPI_SERIAL_LEN])
@ -504,12 +512,12 @@ capi_get_serial_number(int id, u8 serial[CAPI_SERIAL_LEN])
*
* Context: !in_irq()
*
* Copy the version structure of the device denoted by @id, to the
* Copy the version structure of the device, denoted by @id, to the
* target buffer. If @id is 0, copy the version structure of the
* capicore.
*
* @version is returned if the device was available. Otherwise,
* NULL is returned.
* NULL is returned if there is no such device with @id. Otherwise,
* @version is returned.
*/
struct capi_version*
capi_get_version(int id, struct capi_version* version)
@ -537,11 +545,11 @@ capi_get_version(int id, struct capi_version* version)
*
* Context: !in_irq()
*
* Copy the capabilities of the device denoted by @id, to the target
* buffer. If @id is 0, copy just the the number of installed devices.
* Copy the capabilities of the device, denoted by @id, to the target
* buffer. If @id is 0, copy just the number of installed devices.
*
* @profile is returned if the device was available. Otherwise,
* NULL is returned.
* CAPINFO_0X11_OSRESERR is returned if there is no such device with @id.
* Otherwise, CAPINFO_0X11_NOERR is returned.
*/
capinfo_0x11_t
capi_get_profile(int id, struct capi_profile* profile)
@ -568,10 +576,10 @@ capi_get_profile(int id, struct capi_profile* profile)
*
* Context: !in_irq()
*
* Copy the name of the device denoted by @id, to the target buffer.
* Copy the name of the device, denoted by @id, to the target buffer.
*
* @product is returned if the device was available. Otherwise,
* NULL is returned.
* NULL is returned if there is no such device with @id. Otherwise,
* @product is returned.
*/
u8*
capi_get_product(int id, u8 product[CAPI_PRODUCT_LEN])

View File

@ -24,9 +24,9 @@
* struct capi_register_params - application parameters structure
* @level3cnt: maximum number of logical connections the application
* can concurrently maintain
* @datablkcnt: maximum number of received data blocks that can be
* reported to the application simultaneously for each
* logical connection
* @datablkcnt: maximum number of received data blocks (i.e., the
* receive data window) that can be reported to the
* application simultaneously for each logical connection
* @datablklen: maximum size of the application data block to be
* transmitted and received
*/
@ -79,7 +79,7 @@ typedef struct capi_version {
/**
* struct capi_profile - device capabilities structure
* @ncontroller: number of devices
* @ncontroller: number of installed devices
* @nbchannel: number of B-Channels
* @goptions: global options
* @support1: B1 protocols
@ -87,9 +87,6 @@ typedef struct capi_version {
* @support3: B3 protocols
* @reserved: reserved
* @manu: manufacturer specific information
*
* For more information about the individual bit-fields,
* see the CAPI standard.
*/
typedef struct capi_profile {
__u16 ncontroller;

View File

@ -59,14 +59,17 @@ typedef void (*capi_signal_handler_t) (struct capi_appl* appl, unsigned long par
/**
* struct capi_appl - structure representing an application instance
* @id: number
* struct capi_appl - application control structure
* @id: application number
* @stats: I/O statistics
* @params: parameters
* @data: private data
*
* The application is responsible for updating the application
* The application is responsible for updating the application's
* I/O statistics, and may freely use the @stats.lock.
*
* More fields are present, but not documented, since they are
* not part of the public interface.
*/
struct capi_appl {
u16 id;
@ -89,25 +92,24 @@ struct capi_appl {
/**
* capi_set_signal - register a signal handler
* capi_set_signal - install a signal handler
* @appl: application
* @signal: signal handler
* @signal: signal handler (in_irq() context)
* @param: parameter to signal handler
*
* The signal-handler informs the application about new messages, errors,
* or cleared queue-full/busy conditions. The signal-handler is not
* meant to be a workhorse, but a mechanism for waking-up and scheduling
* applications.
* The capicore ensures that by the time a call to the function
* capi_release() returns for @appl, no thread is and will be executing
* in a call from the capicore to @signal for @appl.
*
* The signal handler informs the application of @appl about new messages,
* errors, or cleared queue-full/busy conditions. The signal handler is
* not meant to be a workhorse, but just a mechanism for waking up and
* scheduling applications.
*
* The signal handler must be reentrant and will be called from in_irq()
* context. Consequently, it should be as lightweight and fast as
* possible.
* context; consequently, it should be as simple and fast as possible.
*
* The capicore ensures that by the time the function capi_release()
* returns for @appl, no thread will be executing in a call from the
* capicore to @signal for @appl.
*
* The application must provide a signal-handler, and must not
* The application must install a signal handler for @appl, and must not
* reset it once registered.
*/
static inline void
@ -122,19 +124,21 @@ capi_set_signal(struct capi_appl* appl, capi_signal_handler_t signal, unsigned l
/**
* capi_get_message - fetch message from an application queue
* capi_get_message - fetch a message from an application queue
* @appl: application
* @msg: message
*
* Context: !in_irq()
*
* Fetch a message from the message queue of @appl. Upon successfully
* fetching a message, %CAPINFO_0X11_NOERR is returned and a pointer to
* the message is passed via @msg. If there wasn't a message pending,
* return immediately passing %CAPINFO_0X11_QUEUEEMPTY as return value.
* Otherwise, a value indicating an error is returned.
*
* In the case of a data transfer message (DATA_B3_IND), the data is
* appended to the message (this is contrary to the CAPI standard which
* intends a shared buffer scheme) and the Data field is undefined.
*
* Upon fetching a message successfully, %CAPINFO_0X11_NOERR is returned.
* If there was no message available, %CAPINFO_0X11_QUEUEEMPTY is
* returned. Otherwise, a value indicating an error is returned.
* intends a shared buffer scheme), and the Data field is undefined.
*/
static inline capinfo_0x11_t
capi_get_message(struct capi_appl* appl, struct sk_buff** msg)
@ -149,14 +153,14 @@ capi_get_message(struct capi_appl* appl, struct sk_buff** msg)
/**
* capi_unget_message - reinsert the message to an application queue
* capi_unget_message - reinsert a message to an application queue
* @appl: application
* @msg: message
*
* Context: !in_irq()
*
* The message is placed at the head of the application queue, so that
* the message will be fetched next.
* @msg is placed at the head of the message queue of @appl, so that
* it will be fetched next.
*/
static inline void
capi_unget_message(struct capi_appl* appl, struct sk_buff* msg)
@ -166,14 +170,14 @@ capi_unget_message(struct capi_appl* appl, struct sk_buff* msg)
/**
* capi_peek_message - determine whether a message is available
* capi_peek_message - check whether a message is pending
* @appl: application
*
* Context: !in_irq()
*
* If a message is available, %CAPINFO_0X11_NOERR is returned.
* If there was no message, %CAPINFO_0X11_QUEUEEMPTY is returned.
* Otherwise, a value indicting an error is returned.
* If a message is pending on the message queue of @appl,
* %CAPINFO_0X11_NOERR is returned. If not, %CAPINFO_0X11_QUEUEEMPTY
* is returned. Otherwise, a value indicating an error is returned.
*/
static inline capinfo_0x11_t
capi_peek_message(struct capi_appl* appl)

View File

@ -41,28 +41,33 @@ struct capi_device;
/**
* struct capi_driver - device operations structure
* @capi_register: register an application
* @capi_release: remove an application
* @capi_put_message: transfer a message
* @capi_register: callback function registering an application
* @capi_release: callback function removing an application
* @capi_put_message: callback function transferring a message
*
* The device-driver must provide three functions for calling by the
* capicore. This enables the capicore to register and remove
* applications with devices, and transferring messages to them.
* The device driver must provide three functions for calling by the
* capicore via this structure, enabling the registration and removal of
* applications with the device driver's devices and the transfer of
* messages to them.
*
* The device-driver must ensure that by the time @capi_release returns
* for an application, no thread will be executing in a call from the
* device-driver to any of the functions capi_appl_enqueue_message(),
* capi_appl_signal(), or capi_appl_signal_error() for that application.
* The device driver must ensure that by the time a call to the callback
* function @capi_release returns, no thread is and will be executing,
* in the context of @dev, in a call to any of these functions
* capi_appl_signal_error(), capi_appl_enqueue_message(), or
* capi_appl_signal() for @appl.
*
* If @capi_put_message can not accept messages due to flow-control or
* busy reasons, it has the option of rejecting the message by either
* returning %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY, respectively.
* In this case, the device-driver should call capi_appl_signal() at a
* later time, when it can accept messages again.
* The device driver has the option of rejecting @msg by either returning
* %CAPINFO_0X11_QUEUEFULL or %CAPINFO_0X11_BUSY from the callback function
* @capi_put_message. In this case, @appl could block waiting for the
* clearance of the pending condition, and the device driver must call the
* function capi_appl_signal() for @appl either when the device driver can
* accept messages again for @dev or when the device driver has enqueued
* any message for @appl, whichever happens first.
*
* While @capi_register and @capi_release are called from process context
* and may block, @capi_put_message is called from bottom-half context and
* may not block. All three functions must be reentrant.
* While the callback functions @capi_register and @capi_release are called
* from process context and may block (but mustn't be slow, i.e., blocking
* indefinitely), @capi_put_message is called from bottom half context and
* must not block. All three callback functions must be reentrant.
*/
struct capi_driver {
capinfo_0x10_t (*capi_register) (struct capi_device* dev, struct capi_appl* appl);
@ -72,9 +77,9 @@ struct capi_driver {
/**
* struct capi_device - structure representing a device instance
* @id: number
* @product: name
* struct capi_device - device control structure
* @id: device number
* @product: device name
* @manufacturer: manufacturer
* @serial: serial number
* @version: version
@ -83,8 +88,11 @@ struct capi_driver {
* @stats: I/O statistics
* @class_dev: class device
*
* The device-driver is responsible for updating the device
* The device driver is responsible for updating the device's
* I/O statistics, and may freely use the @stats.lock.
*
* More fields are present, but not documented, since they are
* not part of the public interface.
*/
struct capi_device {
unsigned short id;
@ -112,10 +120,13 @@ void capi_device_unregister (struct capi_device* dev);
/**
* capi_device_get - increment the reference counter for a device
* capi_device_get - get another reference to a device
* @dev: device
*
* Context: !in_irq()
*
* Get another reference to @dev by incrementing its reference counter
* by one. Return @dev.
*/
static inline struct capi_device*
capi_device_get(struct capi_device* dev)
@ -130,13 +141,13 @@ capi_device_get(struct capi_device* dev)
/**
* capi_device_put - decrement the reference counter for a device
* capi_device_put - release a reference to a device
* @dev: device
*
* Context: !in_irq()
*
* Decrement the reference counter for device, and if zero, free the
* device structure.
* Release a reference to @dev by decrementing its reference counter
* by one and, if zero, free @dev.
*/
static inline void
capi_device_put(struct capi_device* dev)
@ -146,7 +157,7 @@ capi_device_put(struct capi_device* dev)
/**
* capi_device_set_devdata - set the private data pointer
* capi_device_set_devdata - set private data pointer
* @dev: device
* @data: private data
*/
@ -158,7 +169,7 @@ capi_device_set_devdata(struct capi_device* dev, void* data)
/**
* capi_device_get_devdata - return the private data pointer
* capi_device_get_devdata - return private data pointer
* @dev: device
*/
static inline void*
@ -169,7 +180,7 @@ capi_device_get_devdata(struct capi_device* dev)
/**
* capi_device_set_dev - set the device pointer
* capi_device_set_dev - set generic device pointer
* @capi_dev: device
* @dev: device
*/
@ -181,7 +192,7 @@ capi_device_set_dev(struct capi_device* capi_dev, struct device* dev)
/**
* capi_device_get_dev - return the device pointer
* capi_device_get_dev - return generic device pointer
* @capi_dev: device
*/
static inline struct device*
@ -192,7 +203,7 @@ capi_device_get_dev(const struct capi_device* capi_dev)
/**
* to_capi_device - cast to device structure
* to_capi_device - downcast to generic CAPI device control structure
* @cd: class device
*/
static inline struct capi_device*
@ -204,37 +215,22 @@ extern struct class capi_class;
/**
* capi_appl_signal - wakeup an application
* @appl: application
*
* Context: in_irq()
*
* The device-driver should wakeup the application after either
* enqueuing messages, or clearing a queue-fulf/busy condition.
* The device-driver may batch messages.
*/
static inline void
capi_appl_signal(struct capi_appl* appl)
{
appl->sig(appl, appl->sig_param);
}
/**
* capi_appl_enqueue_message - add a message to the application queue
* capi_appl_enqueue_message - add a message to an application queue
* @appl: application
* @msg: message
*
* Context: in_irq()
*
* The application queue has unbounded capacity, and the device-driver
* must adhere to the CAPI data window protocol in order to prevent the
* queue from growing immensely. If the device-driver needs to drop a
* messages, it should signal this event to the corresponding application.
* The message queue of @appl has unbounded capacity; hence the device
* driver must adhere to the CAPI data window protocol to prevent that
* queue from growing immensely. A full data window should cause the
* device driver to trigger flow control on the line, if supported by
* the line protocol; otherwise, the device driver should drop @msg and
* notify @appl about that condition.
*
* In the case of a data transfer message (DATA_B3_IND), the data must be
* appended to the message (this is contrary to the CAPI standard which
* intends a shared buffer scheme) and the Data field will be ignored.
* intends a shared buffer scheme), and the Data field will be ignored.
*/
static inline void
capi_appl_enqueue_message(struct capi_appl* appl, struct sk_buff* msg)
@ -244,15 +240,29 @@ capi_appl_enqueue_message(struct capi_appl* appl, struct sk_buff* msg)
/**
* capi_appl_signal_error - inform an application about an error
* capi_appl_signal - wakeup an application
* @appl: application
*
* Context: in_irq()
*
* @appl should be woken up either after enqueuing messages or clearing a
* queue-full/busy condition on @appl, respectively.
*/
static inline void
capi_appl_signal(struct capi_appl* appl)
{
appl->sig(appl, appl->sig_param);
}
/**
* capi_appl_signal_error - signal an error to an application
* @appl: application
* @info: error
*
* Context: in_irq()
*
* Signal a non-recoverable message exchange error to the application.
* This usually implies that messages have been lost, and the only recovery
* for the application is to do a release.
* The only recovery for @appl, from this condition, is to do a release.
*/
static inline void
capi_appl_signal_error(struct capi_appl* appl, capinfo_0x11_t info)

View File

@ -33,7 +33,7 @@
/**
* typedef capinfo_0x10_t - info class 0x10xx
*
* Represents application registration errors.
* Enumeration representing application registration errors.
*/
typedef enum {
CAPINFO_0X10_NOERR = 0x0000,
@ -54,7 +54,7 @@ typedef enum {
/**
* typedef capinfo_0x11_t - info class 0x11xx
*
* Represents message exchange errors.
* Enumeration representing message exchange errors.
*/
typedef enum {
CAPINFO_0X11_NOERR = 0x0000,