/**
 * @file daic_dispatch.h
 *
 * Daic-Dispatch - Module to dispatch all kinds of messages to their respective
 * context state machines.
 *
 * Copyright: 2003 Thomas Wintergerst. All rights reserved.
 *
 * $FreeBSD$
 * $Id: daic_dispatch.h,v 1.1.2.1 2006/02/28 21:35:12 thomas Exp $
 * $Project:    CAPI for BSD $
 * $Target:     daic - CAPI manager driver for Diehl active ISDN controllers $
 * @date        02.02.2003
 * @author      "Thomas Wintergerst" <twinterg@gmx.de>
 * <p>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * </p>
 */

#ifndef __DAIC_DISPATCH_H
#define __DAIC_DISPATCH_H

#ifndef __DAIC_GLOBAL_H
#  include <c4b/driver/daic/daic_var.h>
#endif
#ifndef __DAIC_HW_H
#  include <c4b/daic/daic_hw.h>
#endif





/* === Public declarations =============================================== */





/* === Prototypes of interface functions ================================= */





/* --- Functions to handle messages from the controller --- */

/**
 * Handle a return code from a controller.
 *
 * @param pPortData             I/O: The address of the port data for this
 *                                 operation.
 * @param pRcData               I: The return code data to evaluate.
 *
 * @return Nothing.
 */
extern void daicdisp_handle_rc
   (DaicPortData_t     *pPortData,
    const DaicRcData_t *pRcData);

/**
 * Handle an indication from a controller.
 *
 * @param pPortData             I/O: The address of the port data for this
 *                                 operation.
 * @param pmbIndData            I: The indication data to evaluate. The
 *                                 ownership of the mbuf changes to the called
 *                                 function.
 *
 * @return Nothing.
 */
extern void daicdisp_handle_ind
   (DaicPortData_t *pPortData,
    struct mbuf    *pmbIndData);



/* --- Miscellaneous convenience functions --- */

/**
 * Reset all state machines to Idle state.
 *
 * @param pPortData             I/O: The port data for this operation.
 *
 * @return Nothing.
 */
extern void daicdisp_reset_all
   (DaicPortData_t *pPortData);

/**
 * Start operation of all state machines of a controller.
 *
 * The only thing to do is to start the allocation of a global id for D-channel
 * access to be informed about incoming calls.
 *
 * @param pPortData             I/O: The port data for this operation.
 *
 * @return CAPI result value, CAPI_OK on success.
 */
extern unsigned daicdisp_start_all
   (DaicPortData_t *pPortData);

/**
 * Clear any pending calls for an application during kcapi_release().
 *
 * If there is still some connection running for the application id specified,
 * the application id in the corresponding state machines must be cleared. This
 * is necessary, because after the release operation the CAPI manager must not
 * receive any messages for this application any more. Without a valid
 * application id the state machines will not send out any CAPI message in the
 * application direction, but abort any connection.
 *
 * This should never happen, because the CAPI manager will perform a
 * Disconnect-Request before releasing the application. But maybe the PLCI state
 * machine only waits for the Disconnect-Response that will never arrive after a
 * release. In this case the state machine will remove any resources for this
 * call and return all allocated ids (signalling and network) to the board
 * firmware.
 *
 * @param pSc                   I/O: The device softc structure.
 * @param pPortData             I/O: The port for the desired operation.
 * @param uApplID               I: The application id to be released.
 * @param iApplIdx              I: The index into the application data array for
 *                                 the application id.
 *
 * @return Nothing.
 */
extern void daicdisp_release_appl
   (DaicSc_t       *pSc,
    DaicPortData_t *pPortData,
    unsigned        uApplID,
    int             iApplIdx);

/**
 * Handle a CAPI message for a controller.
 *
 * The mbuf for the message (and a possibly attached data block) is dispatched
 * to the PLCI or NCCI instance or to the global id handler, according to the
 * message content. If the message can be dispatched, the result is CAPI_OK and
 * the ownership of the message (and its data block) changes to the respective
 * handler. If the message cannot be enqueued or directly handled, the result is
 * some other value than CAPI_OK and the caller (in effect the CAPI manager) is
 * still responsible of releasing the mbuf if necessary.
 *
 * @param pSc                   I/O: The device softc structure.
 * @param pPortData             I/O: The port for the desired operation.
 * @param uApplID               I: The application id the CAPI message is from.
 * @param pmbMsg                I: The CAPI message to send. A Data-B3-Request
 *                                 contains the address of another mbuf in its
 *                                 pmbMsg->m_next member.
 *
 * @retval CAPI_OK              The CAPI message could be evaluated or enqueued
 *                              successfully. The mbuf(s) will be released by
 *                              the respective message handler.
 * @retval Else                 CAPI result value to indicate error in message
 *                              handling. The ownership of the message mbuf(s)
 *                              remains at the caller.
 */
extern unsigned daicdisp_put_message
   (DaicSc_t       *pSc,
    DaicPortData_t *pPortData,
    unsigned        uApplID,
    struct mbuf    *pmbMsg);

/**
 * Handle an Indicate-Indication from the global id state machine.
 *
 * This function is called by the global id state machine, when an incoming call
 * is signaled. First a new PLCI must be allocated and the reported signaling id
 * associated with it. The Indicate-Indication is then forwarded to this PLCI.
 * The later is not done by the general indication handling function, but with a
 * special one. So it is possible to direct rejection of the call back to the
 * global id state machine if no application is registered or no registeration
 * data entry matches the call.
 *
 * @param pPortData             I/O: The port data as the operation context.
 * @param bSigId                I: The signaling id of the global id state
 *                                 machine that received the new call.
 * @param pIndData              I: The data for the Indicate-Indication.
 *
 * @retval CAPI_OK              The new call is successfully transfered to the
 *                              PLCI state machine, the global id state machine
 *                              must allocate a new one.
 * @retval Else                 The new call cannot be handled, the global id
 *                              state machine must reject it itself.
 */
extern unsigned daicdisp_handle_indicate_ind
   (DaicPortData_t      *pPortData,
    u_int8_t             bSigId,
    const DaicIndData_t *pIndData);

/**
 * Enter the qualification of a network id into the translation table.
 *
 * First the qualification of the id is checked if it is really a network id.
 * If true the NCCI data array is searched to find a free entry for the
 * specified channel id / NCCI association. If the channel id is found to
 * already exist in the array, its entry is simply overwritten (of course with
 * an error message).
 *
 * @param pPortData             I/O: The port data as the operation context.
 * @param uNetId                I: The network id for that the association is to
 *                                 be added.
 * @param uChId                 I: The channel id to enter.
 * @param uNcci                 I: The NCCI value to enter.
 *
 * @retval 0                    The association was successfully entered into
 *                              the table.
 * @retval -1                   The id is not a network id or the array of
 *                              channel id / NCCI associations is full.
 */
extern int daicdisp_idtrans_enter_channel_and_ncci
   (DaicPortData_t *pPortData,
    unsigned        uNetId,
    unsigned        uChId,
    unsigned        uNcci);

/**
 * Handle the removal of a controller id (network or signaling).
 *
 * @param pPortData             I/O: The port data as the operation context.
 * @param bId                   I: The controller id to mark as removed.
 *
 * @return Nothing.
 */
extern void daicdisp_id_removed
   (DaicPortData_t *pPortData,
    u_int8_t        bId);

/**
 * Register a received Hangup-Indication for a signaling id.
 *
 * A Hangup-Indication is normally entered into the message queue for a PLCI.
 * There may be some other messages before it is handled. But we must not send
 * any message but a Remove-Request for the now hung up signaling id to the
 * port. So this fact is registered through a flag for the PLCI. The hardware
 * layer will simply ignore any request other than a Remove-Request for this
 * signaling id.
 *
 * Here we first check if the id specified is really a signaling id assigned to
 * a PLCI. If so, the flag for a received Hangup-Indication is set. Otherwise
 * nothing is done.
 *
 * @param pPortData             I/O: The port data as the operation context.
 * @param bSigId                I: The signaling for which the Hangup-Indication
 *                                 is received.
 *
 * @return Nothing.
 */
extern void daicdisp_register_hangup_for_sig_id
   (DaicPortData_t *pPortData,
    u_int8_t        bSigId);

/**
 * Check if a signaling id already received a Hangup-Indication.
 *
 * If the id specified is really a signalind id assigned to a PLCI, this
 * function returns, if the flag for a Hangup-Indication is set for the related
 * PLCI. See also daicdisp_register_hangup_for_sig_id().
 *
 * @param pPortData             I/O: The port data as the operation context.
 * @param bSigId                I: The signaling that is to be checked for an
 *                                 already received Hangup-Indication.
 *
 * @retval 1                    A Hangup-Indication was already received for
 *                              this signaling id.
 * @retval 0                    The id specified is either not a signaling id
 *                              associated with a PLCI or a Hangup-Indication
 *                              was not received, yet.
 */
extern int daicdisp_got_hangup_for_sig_id
   (DaicPortData_t *pPortData,
    u_int8_t        bSigId);

/**
 * Register a received Disconnect-Indication for a network channel.
 *
 * A Disconnect-Indication is normally entered into the message queue for the
 * NCCI. There may be some other messages before it is handled. But we must not
 * send any more message to this channel, because it does not exist any more.
 * So the received Disconnect-Indication is registered through a flag for the
 * NCCI. The hardware layer will simply ignore any request for this channel id.
 *
 * Here we first check if the id specified is really a network id and the
 * channel id is really registered for an NCCI. If so, the flag for a received
 * Disconnect-Indication is set. Otherwise nothing is done.
 *
 * @param pPortData             I/O: The port data as the operation context.
 * @param bNetId                I: The network id for the channel id that
 *                                 received the Disconnect-Indication.
 * @param bNetCh                I: The channel id belonging to bNetId that
 *                                 received the Disconnect-Indication.
 *
 * @return Nothing.
 */
extern void daicdisp_register_disconnect_for_net_channel
   (DaicPortData_t *pPortData,
    u_int8_t        bNetId,
    u_int8_t        bNetCh);

/**
 * Check if a network channel already received a Disconnect-Indication.
 *
 * If the id specified is really a network id and the channel id is associated
 * with an NCCI, this function returns, if the flag for a Disconnect-Indication
 * is set for the related NCCI. See also
 * daicdisp_register_disconnect_for_net_channel().
 *
 * @param pPortData             I/O: The port data as the operation context.
 * @param bNetId                I: The network id for the context to theck the
 *                                 channel id for.
 * @param bNetCh                I: The channel id for which to check for a
 *                                 received Disconnect-Indication.
 *
 * @retval 1                    The network channel specified already received
 *                              a Disconnect-Indication.
 * @retval 0                    The network channel specified either is not
 *                              associated with an NCCI or it did not receive a
 *                              Disconnect-Indication, yet.
 */
extern int daicdisp_got_disconnect_for_net_channel
   (DaicPortData_t *pPortData,
    u_int8_t        bNetId,
    u_int8_t        bNetCh);





#endif /* __DAIC_DISPATCH_H */
