From e749b19cddb5bde06cf185e3852198e35b52415a Mon Sep 17 00:00:00 2001 From: "Frank A. Uepping" Date: Tue, 25 Jan 2005 18:13:37 +0000 Subject: [PATCH] Docbook revised. --- linux/Documentation/DocBook/ngc.tmpl | 224 ++++++++++++++------------ linux/drivers/isdn/capi/core.c | 128 ++++++++------- linux/include/linux/capi.h | 11 +- linux/include/linux/isdn/capiappl.h | 62 +++---- linux/include/linux/isdn/capidevice.h | 126 ++++++++------- linux/include/linux/isdn/capinfo.h | 4 +- 6 files changed, 299 insertions(+), 256 deletions(-) diff --git a/linux/Documentation/DocBook/ngc.tmpl b/linux/Documentation/DocBook/ngc.tmpl index 67dcf93..16217cc 100644 --- a/linux/Documentation/DocBook/ngc.tmpl +++ b/linux/Documentation/DocBook/ngc.tmpl @@ -21,8 +21,9 @@ - $Revision$ - $Date$ + + + Working Draft @@ -42,10 +43,9 @@ - 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 @@ -61,43 +61,44 @@ Introduction - CAPI (COMMON-ISDN-API) is a message oriented and event - driven programming interface used by applications to access - ISDN hardware equipment in a standardized and - straightforward way. Publisher of the CAPI standard is the - CAPI-Association, a non-profit + CAPI (COMMON-ISDN-API) is a message oriented and event driven + programming interface, used by applications to access ISDN + hardware equipment in a standardized and straightforward way. Publisher + of the CAPI standard is the CAPI-Association, a non-profit international consortium of hardware and software manufactures and - telecommunications institutions. The CAPI standard is - freely available for download on their website. + telecommunications institutions; the CAPI standard is freely + available for download on their website. - The 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 CAPI interfaces for user- and kernel-space. + The 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 CAPI + interfaces for user and kernel space. - Next - Generation CAPI (NGC) is an - experimental implementation of the - CAPI 2.0 standard, and it started as a fork of CAPI4Linux. + Next Generation + CAPI (NGC) is an + experimental implementation of the CAPI + 2.0 standard and derived from CAPI4Linux. - The heart of the 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 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 CAPI - standard and with Linux kernel programming in general. + The heart of the 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 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 CAPI standard and with Linux kernel programming in + general. @@ -105,9 +106,9 @@ Structures and Data Types - The capicore provides a set of common structures - and data types, forming the basis of communication between the various - layers of the CAPI subsystem. + The capicore provides a common set of structures and data types forming + the basis of communication between the various layers of the + NGC subsystem. !Iinclude/linux/isdn/capinfo.h @@ -120,64 +121,64 @@ Device Driver Interface - Device-drivers and applications communicate together via the - capicore in an asynchronous way by exchanging - messages according to the CAPI standard. While the - implementation of a device-driver might be rather complex internally, - the interface with the capicore is simple. The - declarations to this interface can be found in linux/isdn/capidevice.h. + Device drivers and applications communicate together, via the capicore, + in an asynchronous way by exchanging messages according to the + 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 + linux/isdn/capidevice.h. Overview - Devices are represented to the capicore by - objects of the generic capi_device 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 capi_device_alloc. - When the device-driver is done with the device (i.e.: after removing - the device from the capicore), it should drop its - reference to it via the function capi_device_put. + Devices are represented to the capicore by objects of the generic + capi_device 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 + capi_device_alloc. Destroying a device is + done by releasing all references to it via the function + capi_device_put. Once a generic capi_device object is - initialized, the device-driver can register it with the - capicore via the function - capi_device_register. Removing the device from - the capicore is done via the function - capi_device_unregister. + initialized, the device driver can register it with the capicore via + the function capi_device_register. Removing the + device from the capicore is done via the function + capi_device_unregister; subsequently, the + device driver can release the device via the function + capi_device_put. - The device-driver has to provide three functions for calling by the - capicore via the - capi_driver structure. This enables the - capicore 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 capi_driver structure, + enabling the registration and removal of applications with the device + driver's devices and the transfer of messages to them. - 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 - capi_appl_enqueue_message, and informing the - application about new messages via the function - capi_appl_signal. If the device-driver - encounters an error concerning the message exchange, it should inform - the corresponding application about this event via the function - capi_appl_signal_error. + 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 + capi_appl_enqueue_message. Upon that, the device + driver should wakeup the application via the + function capi_appl_signal. 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 capi_appl_signal_error, + causing the application to release. Besides that, since CAPI devices are class - devices, they can easily export own attributes to the - sysfs. See linux/device.h for more information. + devices, they can easily export own attributes to the sysfs, + enabling the device driver to offer device specific features to the + user. See linux/device.h for + more information. @@ -193,19 +194,19 @@ Application Interface - Applications and device-drivers communicate together via the - capicore in an asynchronous way by exchanging - messages according to the CAPI standard. While the - implementation of an application might be rather complex internally, the - interface with the capicore is simple. + Applications and device drivers communicate together, via the capicore, + in an asynchronous way by exchanging messages according to the + CAPI standard. While the implementation of an application + might be rather complex internally, the interface with the capicore is + pretty simple. - For Linux, the CAPI standard defines interfaces for user- - and kernel-space applications. Unfortunately, the specification to the - kernel-space CAPI is too unspecific. To give developers the - required backing in writing safe kernel-space applications, the - capicore introduces an alternative interface which + For Linux, the CAPI standard defines CAPI + interfaces for user and kernel space applications. Unfortunately, the + specification to the kernel space 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 linux/isdn/capiappl.h. @@ -215,21 +216,23 @@ Overview - Applications are represented to the capicore by - objects of the generic capi_appl structure. - This structure forms the basis of communication between the - capicore and applications. Once a generic - capi_appl object is initialized, the - application can register it with the capicore via - the function capi_register. Removing - applications from the capicore is done via the - function capi_release. + Applications are represented to the capicore by objects of the generic + capi_appl structure. This structure forms the + basis of communication between the capicore and applications. - Applications need to register a signal-handler via the function - capi_set_signal. The signal-handler serves as a - notification mechanism for asynchronous events such as: + Once a generic capi_appl object is + initialized, the application can register it with the capicore via the + function capi_register. Removing an application + from the capicore is done via the function + capi_release. + + + + Applications need to install a signal handler via the function + capi_set_signal. The signal handler serves as a + notification mechanism for asynchronous events, such as: @@ -239,19 +242,40 @@ the clearance of queue-full/busy conditions - occurred message exchange errors + errors - The signal-handler is not meant to be a - workhorse, but a mechanism for waking-up and + Note that a signal handler is not meant to be a + workhorse, but just a mechanism for waking up and scheduling applications. Applications transfer messages via the function capi_put_message, and fetch them via the function - capi_get_message. + capi_get_message. They can put back messages via + the function capi_unget_message, and check for + pending messages via the function + capi_peek_message. + + + + Applications can retrieve informations from CAPI devices + via the functions: capi_get_manufacturer, + capi_get_serial_number, + capi_get_version, + capi_get_profile, and + capi_get_product. + + + + Since CAPI devices are class devices, + applications can install a class interface with + the Linux device driver core to get informed when CAPI + devices are being registered and removed with the capicore. See + linux/device.h for more + information. diff --git a/linux/drivers/isdn/capi/core.c b/linux/drivers/isdn/capi/core.c index 34f7a6b..4bd408d 100644 --- a/linux/drivers/isdn/capi/core.c +++ b/linux/drivers/isdn/capi/core.c @@ -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]) diff --git a/linux/include/linux/capi.h b/linux/include/linux/capi.h index 7463e3d..557013c 100644 --- a/linux/include/linux/capi.h +++ b/linux/include/linux/capi.h @@ -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; diff --git a/linux/include/linux/isdn/capiappl.h b/linux/include/linux/isdn/capiappl.h index 48cc8f1..248a434 100644 --- a/linux/include/linux/isdn/capiappl.h +++ b/linux/include/linux/isdn/capiappl.h @@ -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) diff --git a/linux/include/linux/isdn/capidevice.h b/linux/include/linux/isdn/capidevice.h index 5a24fb1..249e3f5 100644 --- a/linux/include/linux/isdn/capidevice.h +++ b/linux/include/linux/isdn/capidevice.h @@ -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) diff --git a/linux/include/linux/isdn/capinfo.h b/linux/include/linux/isdn/capinfo.h index 6bec826..92c0165 100644 --- a/linux/include/linux/isdn/capinfo.h +++ b/linux/include/linux/isdn/capinfo.h @@ -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,