/*++
*******************************************************************************
* Copyright (c) 1999-2000 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 copyrighted work of Digi International   *
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly   *
* prohibited.                                                                 *
*                                                                             *
* Restricted Rights Legend                                                    *
*                                                                             *
* Use, duplication, or disclosure by the Government is subject to             *
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in         *
* Technical Data and Computer Software clause at DFARS 252.227-7031 or        *
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -          *
* Restricted Rights at 48 CFR 52.227-19, as applicable.                       *
*                                                                             *
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343          *
*                                                                             *
*******************************************************************************

Module Name:

        pppcircuit.c

Abstract:

        This module initializes and cleans up DIGI_PPP_LINE instances.  A "Circuit" or 
        "Line" is directly associated with a TAPI Line object and is a logical circuit in 
        our context.  It represents a circuit on which calls may be placed.  In this 
        driver, a Line always represents a logical circuit, and contains one and only one 
        call object.  Depending on the card, a logical ciruit may mean the entire line, or 
        a single timeslot on the line, or a group of n timeslots on the card.

                Sync Card (EIA-232, V.35, etc)
                        Line == Circuit == Entire line.  Sync cards are not channelized and thus 
                        cannot use timeslots.

                CSU/DSU Card
                        Line == Timeslot(s) == Logical circuit.  Any number of timeslots could be
                        mux'd together to form a single logical circuit.  Where one timeslot gives
                        64000 BPS, 2 gives 128000, etc.

Author:

        Michael Zarns

--*/
#include "digippp.h"


VOID
PPPCircuitDestruct( 
        IN PDIGI_PPP_LINE pLine )
{
    if ( pLine->pCall )
    {
        // Stop MdmEngine for call
        PPPMdmEngineStop(pLine->pCall);
        // and shutdown call
        PPPCallDestruct( pLine->pCall );
    }

    RxEngineStop( &pLine->RxEngine );

    if ( pLine->hStream )
    {
        DsClose( pLine->hStream );
        pLine->hStream = NULL;
    }
}


NTSTATUS
PPPCircuitOnIncomingCall( 
    IN PVOID pAdapter,
    IN ULONG Line
    )
{
    NTSTATUS Status = STATUS_SUCCESS;


    return Status;
}


NTSTATUS
PPPCircuitOnTerminateCall(
    IN PVOID pOwner
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    PDIGI_PPP_LINE pLine = pOwner;
    PDIGI_PPP_CALL pCall = pLine? pLine->pCall : NULL;

    // Notify call that line has gone down
    if ( pCall )
        PPPCallOnConnend( pCall );

    return Status;
}


NTSTATUS
PPPCircuitOnData( 
        IN PVOID pOwner,
        IN PVOID pData,
        IN ULONG cbData )
{
    NTSTATUS Status = STATUS_SUCCESS;
    PDIGI_PPP_LINE pLine = pOwner;

    PDIGI_PPP_CALL pCall = pLine->pCall;
    if ( pCall )
    {
        PPPCallOnData( pCall, pData, cbData );
    }
    return Status;
}


DIGI_PPP_EVENT_HANDLERS CircuitEventHandlers = 
{
    PPPCircuitOnIncomingCall,
    PPPCircuitOnTerminateCall,
    PPPCircuitOnData
};


NTSTATUS
PPPCircuitConstruct( 
        IN PDIGI_PPP_ADAPTER pAdapter,
        IN ULONG             iCircuit,
        IN ULONG             TimeslotMask,
        IN ULONG             Speed )
{
    NTSTATUS Status = STATUS_SUCCESS;
    BOOLEAN IsCsuLine = pAdapter->IsCsuLine;
    PDIGI_PPP_LINE pLine = &pAdapter->pLines[iCircuit];

    DigiDump( DIGIERROR, ( "PPP!CircuitConstruct, pAdapter 0x%x, iCircuit 0x%x\n", pAdapter, iCircuit ) );

    NdisZeroMemory( pLine, sizeof *pLine );
    pLine->pAdapter = pAdapter;
    pLine->Snid     = pAdapter->Snid;
    pLine->iLine    = iCircuit;
    pLine->Speed    = Speed;

    // Open firmware WAN/IWAN module
    {
        ULONG Error;
        Status = DsOpen( pAdapter->hDevice, pAdapter->LineName, pAdapter, NULL, 0, &pLine->hStream, &Error );
        if ( NT_ERROR( Status ) )
        {
            DigiDump( DIGIWARN, ( "PPP!CircuitConstruct: DsOpen failed, status 0x%x, error 0x%x\n", Status, Error ) );
            goto Exit;
        }
    }

    // Initialization sequence is different for CSU and Sync circuits.
    if ( IsCsuLine )
    {
        Status = PPPCsuInitCircuit( pAdapter, pLine, iCircuit, TimeslotMask, Speed );
    }
    else
    {
        Status = PPPSyncInitCircuit( pAdapter, pLine );

        if ( NT_SUCCESS(Status) )
            Status = MdmRaiseDtrRts( pLine );
    }

    if ( NT_SUCCESS(Status) )
    {
        PDIGI_PPP_CALL pCall = PPPCallConstruct( pAdapter, iCircuit );
        if ( pCall )
        {
            // Everything setup correctly - start MdmEngine
            PPPMdmEngineStart(pCall);
        }
        else
            Status = STATUS_UNSUCCESSFUL;
    }

 Exit:
    if ( NT_ERROR(Status) )
    {
        DigiDump( DIGIERROR, ( "PPP!CircuitConstruct: Error status 0x%x\n", Status ) );
        PPPCircuitDestruct(pLine);
    }

    return Status;
}
