#ident "$Id: frsdrv.c,v 1.10 1997/10/21 20:48:07 gary Exp $"
/*****************************************************************************
 * Copyright (c) 1988-95 Digi International Inc., All Rights Reserved
 * 
 * This  software  contains  proprietary  and  confidential   information   of
 * Digi International  Inc.   By  accepting  transfer  of this copy, Recipient
 * agrees to retain this software in  confidence,  to  prevent  disclosure  to
 * others,  and  to make no  use of this software other than that for which it
 * was delivered.  This is an unpublished copyright work  Digi   International
 * Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is
 * strictly prohibited.
 * 
 * Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc.
 * Confidential  when   combined   with   the   aggregated  modules  for  this
 * product) OBJECT CODE ONLY SOURCE MATERIALS
 * 
 * (C) COPYRIGHT Digi International Inc. 1995
 * 
 * All Rights Reserved
 * 
 * US   Government   Users   Restricted   Rights   -   Use,   duplication   or
 * disclosure  restricted by GSA ADP Schedule Contract with Digi International
 * Inc.
 * 
 *****************************************************************************/

/*****************************************************************************
 *                                                                           *
 * (c) COPYRIGHT 1991, 1992 HARRIS & JEFFRIES, INC.                          *
 *                          888 WASHINGTON STREET                            *
 *                          SUITE 130                                        *
 *                          DEDHAM, MA  02026                                *
 * ALL RIGHTS RESERVED                                                       *
 *                                                                           *
 * This software is the property of Harris & Jeffries, Inc. and is furnished *
 * under license by Harris & Jeffries, Inc. and this software may be used    *
 * only in accordance with the terms of said license.  This copyright notice *
 * may not be removed, modified or obliterated without the prior written     *
 * permission of Harris & Jeffries, Inc.                                     *
 *                                                                           *
 * This software may not be copied, transmitted, provided to or otherwise    *
 * made available to any other person, company, corporation or other entiry  *
 * except as specified in the terms of said license.                         *
 *                                                                           *
 * No right, title, ownership or other interest in the software is hereby    *
 * granted or transferred.                                                   *
 *                                                                           *
 * The information contained herein is subject to change without notice and  *
 * should not be construed as a commitment by Harris & Jeffries, Inc.        *
 *                                                                           *
 *****************************************************************************

 MODULE NAME:


            @@@@@@  @@@@@    @@@@   @@@@@   @@@@@   @    @           @@@@
            @       @    @  @       @    @  @    @  @    @          @    @
            @@@@@   @    @   @@@@   @    @  @    @  @    @          @
            @       @@@@@        @  @    @  @@@@@   @    @   @@@    @
            @       @   @   @    @  @    @  @   @    @  @    @@@    @    @
            @       @    @   @@@@   @@@@@   @    @    @@     @@@     @@@@


    ORIGINAL AUTHOR:  Deepak Shahane
    SUBJECT MATTER 
            SPECIALIST:   Deepak Shahane

    REVISION HISTORY:

    Date     Version  Name          Description
    -------- -------  ------------  --------------------------------------------
    01-16-92 1.10A    H&J (DJ)      Original
    06-08-92 1.20A    H&J (DS)      Multiple events to Frame Relay driver
                                    changed to a single event
 
    $Log: frsdrv.c,v $
    Revision 1.10  1997/10/21 20:48:07  gary
    Modifications made to accomodate the SOH (Streams-on-host) folks.

    Revision 1.9  1997/09/23 16:38:13  gary
    The Frame Relay and X.25 API's consist of 32-bit fields only.  This is
    to simplify structure alignment considerations, and make endian issues
    less cumbersome.

    In addition, the Frame Relay API now uses SNID's instead of links, thereby
    making it more compatible with the X.25 and ISDN API's.

    These changes span a large number of files.

    Revision 1.8  1996/10/22 21:18:52  gary
    A bit of rearranging was required in order to move the FRF9_Stats_t
    structure over to fr_cont.h. (needed by host drivers)

    Revision 1.7  1996/06/21 21:37:31  gary
    Backflowing now implemented on the Frame Relay stack!
    This minimizes the amount of loss encountered under
    Forced and Buffered injection.

    Revision 1.6  1996/06/19 16:33:23  gary
    General cleanup and modifications so that the source files may be
    compiled using makefile v2.x.  References to the compiler flag
    "JUPITER" were replaced with "PCI".  #include <xxx> lines were
    replaced with #includ "xxx".

    Revision 1.5  1996/04/26 19:57:37  gary
    First rev of changes: Frame Relay on PRI card.
    Bug fix: sequence number on segmented frames was wrong.

    Revision 1.4  1995/04/10 16:31:50  garyp
    remove strm.h

 * Revision 1.3  1994/07/27  20:27:41  stavrosm
 * Release 2.2
 *
 * Revision 1.2  1993/11/02  11:13:35  stavrosm
 * Release 2.1
 *    
..............................................................................

    DESCRIPTION:

    FRSReceive:
    ----------

    This module is the H&J Frame Relay Stack Low-Level Driver Interface.

..............................................................................

  REF DOCUMENTS:

  (a) U.S Sprint Frame Relay Service Interface Specification Doc #: 5136.02
  (b) Frame Relay Interface Specification, Stratacom Inc., Doc #: 001-207460
  (c) Frame Relay Stack Functional Specification Rel 1.2 Harris & Jeffries Inc.
  (d) Frame Relay Stack External Specification Rel 1.2 Harris & Jeffries Inc.
  (e) MIB for Frame Relay DTEs - RFC Draft from Internet Engr Task Force (IETF).
  (f) Multiprotocol Interconnect over Frame Relay Networks - T. Bradley, C.Brown
      Wellfleet Communications, Inc. A. Malis BBN Communications Oct 14, 1991.


..............................................................................

    SPECIAL COMPILE/LINK INSTRUCTIONS:

        see notes/instructions in frs.h

..............................................................................

    FUNCTIONS INCLUDED in this module:

  (*) FRSDRV_InitLink       --- Initialise hardware et al
  (*) FRSDRV_LinkControl    --- Exercise link for diagnostic information
      FRSDRV_LinkUpEvent    --- Send a link up event to frame relay driver
      FRSDRV_LinkDownEvent  --- Send a link down event to frame relay driver
      FRSDRV_FrameRcvdEvent --- Send a frame rcvd event to frame relay driver
  (*) FRSDRV_SendData       --- Start transmitting data
      FRSDRV_TxDone         --- Transmit Done notification
      FRSDRV_AddRcvBfr      --- Add a receive buffer driver's pool


    (*) To be filled during portation

..............................................................................
*/


 /****************************************************************************
 * This software contains proprietary and confidential information of Digi  *
 * International Inc.  By accepting transfer of this copy, Recipient agrees *
 * to retain this software in confidence, to prevent disclosure to others,  *
 * and to make no use of this software other than that for which it was     *
 * delivered.  This is an unpublished copyright work of Digi International  *
 * Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly*
 * prohibited.                                                              *
 * Copyright 1994, Digi International Inc.                                  *
 * All rights reserved.                                                     *
 *       $Id: frsdrv.c,v 1.10 1997/10/21 20:48:07 gary Exp $I
 ****************************************************************************/


#define FRSRX_C

/*
 * Includes
 */

#define STATIC static

#define BUFP_T 	bufp_t
#define DBDIAG(MP, BYTE)    (MP)->b_datap->db_diag=BYTE;

#include "types.h"
#include "errno.h"
#include "stream.h"
#include "strlog.h"
#include "system.h"
#if EPC
#include "wan_proto.h"
#else
#include "iwan_proto.h"
#endif
#include "timer.h"
#include "x25trace.h"
#include "fr_cont.h"
#include "fr.h"
#include "frs.h"
#include "cnt_arry.h"

extern fr_t	    fr_wtab[] ;
extern mblk_t *allocb();

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_InitLink

    DESCRIPTION:

    This function will attempt to initialise a frame relay port and return
    the appropriate return code.

    PARAMETERS:

    struct lcb * --- Pointer to a link ctrl block

    RETURNS:

    FRS_SUCCESS if successful.
    Else, refer API codes in frs.h.

    NOTES:

    To be filled during portation.

*****************************************************************************/
u_short 
FRSDRV_InitLink( pLinkCfg)
struct frs_link_cfg *pLinkCfg;
{
    /** ------------------ TARGET SYSTEM CODE -------------------------**/
    /** ------------------ TARGET SYSTEM CODE -------------------------**/

    return FRS_SUCCESS;
}

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_LinkControl

    DESCRIPTION:

    PARAMETERS:

    struct lcb * --- Pointer to a link ctrl block
    u_short      --- A code identifying what action needs to be performed.
                     Set of { FRS_LINK_SDT, FRS_LINK_EDT,
                              FRS_LINK_LOCAL_LOOP, FRS_LINK_REM_LOOP }
             
    RETURNS:

    FRS_SUCCESS if successful.
    Else, refer API codes in frs.h.

    NOTES:

    ~ To be filled during portation.
    ~ For loopback tests, after a predetermined number of packets have been
        successfully looped, return with FRS_SUCCESS.
    ~ FRS_LINK_REMOTE_LOOP may be used optionally depending upon modem
        availability.
    ~ This procedure must reset the hardware after the loopback test completes.
        It NEED not re-initialise the hardware to a Start_Data_Traffic condition
        because a separate call will be made to reach that state.

*****************************************************************************/
u_short 
FRSDRV_LinkControl(pLCB, ActionCode)
struct lcb *pLCB;
u_short ActionCode;
{
    /** ------------------ TARGET SYSTEM CODE -------------------------**/
    /** ------------------ TARGET SYSTEM CODE -------------------------**/

    return FRS_SUCCESS;
}

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_LinkUpEvent

    DESCRIPTION:

    Generates a Link Up Event and dispatches it to the appropriate process.
    Event is generated only if the link is NOT in the link up state.

    PARAMETERS:

    struct lcb * --- Pointer to a link ctrl block

    RETURNS:

    FRS_SUCCESS if successful.
    Else, refer API codes in frs.h.

    NOTES:

    This function should be used by the low-level driver to signal the FRS
    of a link up situation.

*****************************************************************************/
u_short 
FRSDRV_LinkUpEvent(pLCB)
LCB *pLCB;
{
EVENT *pEvent;

    if( pLCB == LCBNULL )
        return( FRS_INVALID );

    /* One for XMit...
     */
     if (pLCB->State != FRS_LKUP)
        {
         if ((pEvent = FRSAllocEvent()) != (EVENT *)NULL)
            {
            pEvent->EventCode = FRS_LKUP;
            pEvent->Info = (void *)pLCB;

#if USE_TASKING
            os_queue_wakeup(&pLCB->RQTCB, pEvent);
#else
            FRSReceive(pLCB, pEvent);
#endif
            }
        else    
            return FRS_NO_BUFFERS;
        }

    return FRS_SUCCESS;
}

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_LinkDownEvent

    DESCRIPTION:

    Generates a Link Down Event and dispatches it to the appropriate
    process. Event is generated only if the link is NOT in the link down state.

    PARAMETERS:

    struct lcb * --- Pointer to a link ctrl block

    RETURNS:

    FRS_SUCCESS if successful.
    Else, refer API codes in frs.h.

    NOTES:

    This function should be used by the low-level driver to signal the FRS
    of a link down situation.
*****************************************************************************/
u_short 
FRSDRV_LinkDownEvent(pLCB)
LCB *pLCB;
{
    EVENT *pEvent;

    if( pLCB == LCBNULL )
        return( FRS_INVALID );

    /* Inform upper layers about change in status...
     */
    if (pLCB->State != FRS_LKDWN)
        {
        if ((pEvent = FRSAllocEvent()) != (EVENT *)NULL)
            {
            pEvent->EventCode = FRS_LKDWN;
            pEvent->Info = (void *)pLCB;

#if USE_TASKING
            os_queue_wakeup(&pLCB->RQTCB, pEvent);
#else
            FRSReceive(pLCB, pEvent);
#endif
            }
        else
            return FRS_NO_BUFFERS;
        }

    return FRS_SUCCESS;
}

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_FrameRcvdEvent

    DESCRIPTION:

    Generates a Frame Rcvd Event and dispatches it to the appropriate
    process.

    PARAMETERS:

    struct lcb *    -- Pointer to a link ctrl block
    struct usrbuf * -- Pointer to a chain of frames rcvd by the low-level driver

    RETURNS:

    FRS_SUCCESS if successful.
    Else, refer API codes in frs.h.

    NOTES:

    This function should be used by the low-level driver to forward a 
    frame contained in either a single buffer or chain of buffers to the
    FRS.

*****************************************************************************/
u_short 
FRSDRV_FrameRcvdEvent(pLCB, pUsrbuf)
LCB *pLCB;
USRBUF *pUsrbuf;
{
    EVENT *pEvent;

    if( pLCB == LCBNULL )
        return( FRS_INVALID );

    if ((pEvent = FRSAllocEvent()) != (EVENT *)NULL)
        {
        pEvent->EventCode = FRS_FRAME;
        pEvent->Info = (void *)pUsrbuf;

#if USE_TASKING
        os_queue_wakeup(&pLCB->RQTCB, pEvent);
#else
        FRSReceive(pLCB,pEvent);
#endif
        }
    else
        return FRS_NO_BUFFERS;

    return FRS_SUCCESS;
}

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_SendData

    DESCRIPTION:

    This function is used by the FRS to inform the low-level driver of data
    pending in the link injection queue. The low-level driver is expected
    to start transmitting frames queued in this queue.

    PARAMETERS:

    struct ccb * --- Pointer to a channel ctrl block
    struct usrbuf * --- Pointer to a user buffer structure

    RETURNS:

    FRS_SUCCESS if successful.
    Else, refer API codes in frs.h.

    NOTES:

    To be filled during portation.

*****************************************************************************/
u_short
FRSDRV_SendData(pCCB, pBfr)
CCB *pCCB;
USRBUF *pBfr;
{
    struct wan_msg FAR *pp ;
    mblk_t	       *mp ;
    int			 i ;
    fr_t	       *lp ;

    /** ------------------ TARGET SYSTEM CODE -------------------------**/
    /** ------------------ TARGET SYSTEM CODE -------------------------**/

/** Before everything else, check to see if a frame is marked for
 ** dropping.  If so, call FRSDRV_TxDone to drop the frame.
 **
 ** if( POINTER TO A USRBUF IN THE QUEUE HAS FR_HDR == 0xFFFE )
 ** {
 **   FRSDRV_TxDone(pCCB->plcb, POINTER TO A USRBUF IN THE QUEUE);
 **   return (FRS_SUCCESS);
 ** }
 **/

	for(i = 0, lp = fr_wtab ; i < NLCBS; lp++, i++)
		if(lp->snid == pLCB_to_snid(pCCB->plcb))
			break ;

	if(i >= NLCBS)
	{
		/*
		* Mark this as an error
		*/
		return -1 ;
	}
#if POWERPC
	mp = pBfr ;
	if (lp->trace_active ) fr_trace(lp,mp,0);
#else
	if((mp = allocb(sizeof(struct wan_msg), BPRI_MED)) == (mblk_t *)0)
	{
		/*
		* Mark this as an error
		*/
		return -1 ;	
	}

	mp->b_datap->db_type = M_PROTO;
	mp->b_cont = pBfr ;
 
	pp = (struct wan_msg *)mp->b_wptr ;
	mp->b_wptr += sizeof(struct wan_msg);
	pp->wan_type = WAN_DAT;
#if EPC
	pp->wan_command = WC_TX;
#endif

	DBDIAG(mp, 0x6C)

	if (lp->trace_active ) fr_trace(lp,mp->b_cont,0);
#endif


/* With an appropriately chosen BcMax value, this becomes unnecessary */
#if 0
	if (!canput(lp->downq->q_next)) {
		freemsg(mp);
cnt_arry[FRAME_WDROP]++;
	}
	else {
		putnext(lp->downq, mp);
cnt_arry[FRAME_FINISH]++;
	}
#else
	putnext(lp->downq, mp);
cnt_arry[FRAME_FINISH]++;
#endif

    return FRS_SUCCESS;
}

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_TxDone

    DESCRIPTION:

    This function is called from the low level driver transmit done interrupt
    to dispose of the user buffer just transmitted.

    PARAMETERS:

    LCB *    --- Pointer to line control block
    USRBUF * --- Pointer to a user buffer

    RETURNS:

    FRS_SUCCESS if successful.
    Else, refer API codes in frs.h.

    NOTES:
      This function requires that the USRBUF.start field is set to
      the offset within the data of the frame relay header (dlci).

      During portation, code may be needed here to adjust the .start value
      before calling the user supplied TxDone function.

*****************************************************************************/
u_short 
FRSDRV_TxDone(pLCB, pBfr)
LCB *pLCB;
USRBUF *pBfr;
{
    EVENT *pEvent;

    if(pLCB == LCBNULL)
        return FRS_INVALID;

      if ((pEvent = FRSAllocEvent()) != (EVENT *)NULL)
          {
          pEvent->EventCode = FRS_TXDN;
          pEvent->Info = (void *)pBfr;

#if USE_TASKING
          os_queue_wakeup(&pLCB->TQTCB, pEvent);
#else
          FRSTransmit(pLCB,pEvent);
#endif
          }
    else    
         m_MMGR_FREE_BUFR(pBfr);

    return FRS_SUCCESS;
}

/**/
/*****************************************************************************

    PROCEDURE NAME:    FRSDRV_AddRcvBfr

    DESCRIPTION:

    This function is called from the target application to allocate
    a receive buffer for the low level driver to use.

    PARAMETERS:

    LCB *    --- Pointer to line control block

    RETURNS:

      Nothing

    NOTES:

      During portation, code may be added here to add a buffer to the
      queue or table of receive buffers for low level driver's use.

      This function would be called one or more times during initialization 
      to establish the low level driver's pool, and then again whenever
      received frame processing is completed and a buffer is freed.

      The net effect of this is the return of the buffer to the low level
      driver's receive pool.

*****************************************************************************/
void 
FRSDRV_AddRcvBfr(pLCB)
LCB *pLCB;
{
    /** ------------------ TARGET SYSTEM CODE -------------------------**/
    /** ------------------ TARGET SYSTEM CODE -------------------------**/

  /** add code here to add a receive buffer to the 
      low level driver's pool...
  **/

    return;
}
