/*++
*******************************************************************************
* 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:

        pppsync.c

Abstract:

        Init code for Sync Cards.  Firmware header overlap requires that this code be in 
        a separate file from CSU card init code.

Author:

        Michael Zarns

--*/
#include "digippp.h"
#include "wan_control.h"
#include "wan_proto.h"
#include "m32api.h"

NTSTATUS
PPPSyncInitCircuit( 
        IN PDIGI_PPP_ADAPTER pAdapter,
        IN PDIGI_PPP_LINE    pLine )
{
    NTSTATUS Status;
    // Send WAN_SID - ties a SNID to the WANx instance (e.g. to the physical line)
    {
        struct wan_sid sid = {0};
        sid.wan_type = WAN_SID;
        sid.wan_snid = pLine->Snid;

        DigiDump( DIGIINIT, ( "PPP!SyncInitCircuit: WAN_SID\n"
                              "   wan_type = 0x%x\n"
                              "   wan_snid = 0x%x\n",
                              sid.wan_type, sid.wan_snid ) );
        Status = DsPutMsg( pLine->hStream, &sid, sizeof (sid) , NULL, 0, DS_PRIORITY_LOW );
                
    }

    // Send SETTUNE - configure line properties
    if ( NT_SUCCESS(Status) )
    {
        ULONG Error;
        struct wan_tnioc Tune = {0};
        Tune.lli_type = LI_WANTUNE;
        Tune.lli_snid = pLine->Snid;
        Tune.wan_tune.WAN_options          = pAdapter->Sync.IsNrzi ? WAN_NRZI | WAN_HDLC : WAN_HDLC;
        Tune.wan_tune.WAN_hd.WAN_baud      = pAdapter->Sync.ExternalClocking ? 0 : pAdapter->Sync.LineSpeed;
        Tune.wan_tune.WAN_hd.WAN_maxframe  = pAdapter->MaxFrameSize;
        Tune.wan_tune.WAN_hd.WAN_cpdef.WAN_cptype = WAN_NONE;
        DigiDump( DIGIINIT, ( "PPP!SyncInitCircuit: W_SETTUNE\n"
                              "   lli_type     = 0x%x\n"
                              "   lli_snid     = 0x%x\n"
                              "   WAN_options  = 0x%x\n"
                              "   WAN_baud     = 0x%x\n"
                              "   WAN_maxframe = 0x%x\n"
                              "   WAN_cptype   = 0x%x\n",
                              Tune.lli_type, Tune.lli_snid, Tune.wan_tune.WAN_options, Tune.wan_tune.WAN_hd.WAN_baud, Tune.wan_tune.WAN_hd.WAN_maxframe, Tune.wan_tune.WAN_hd.WAN_cpdef.WAN_cptype) );
        Status = DsIoctl( pLine->hStream, W_SETTUNE, &Tune, sizeof Tune, &Error );
    }

    // Send WAN_REG
    if ( NT_SUCCESS(Status) )
    {
        ULONG Error;
        struct wan_reg Reg = {0};
        Reg.wan_type = WAN_REG;
        Reg.wan_snid = pLine->Snid;
        DigiDump( DIGIINIT, ( "PPP!SyncInitCircuit: WAN_REG\n"
                              "   wan_type = 0x%x\n"
                              "   wan_snid = 0x%x\n",
                              Reg.wan_type, Reg.wan_snid ) );
        Status = DsPutMsg( pLine->hStream, &Reg, sizeof Reg, NULL, 0, DS_PRIORITY_LOW );
    }

    // Send GetMsg - get a WC_CONNECT msg from firmware
    if ( NT_SUCCESS(Status) )
    {
        struct wan_ctl Ctrl;
        ULONG cbCtrl, cbData;
        Status = DsGetMsg( pLine->hStream, &Ctrl, sizeof Ctrl, &cbCtrl, NULL, 0, &cbData, DS_PRIORITY_LOW );
        if ( NT_ERROR(Status) )
        {
            DigiDump( DIGIERROR, ( "PPP!SyncInitCircuit: DsGetMsg failed, Status 0x%x\n", Status ) );
        }
        else
        {
            if ( Ctrl.wan_type    != WAN_CTL    ||
                 Ctrl.wan_command != WC_CONNECT 
// Will be fixed in firmware soon.  Currently this field is uninitialized by firmware
//                           || Ctrl.wan_status  != WAN_SUCCESS 
                )
            {
                DigiDump( DIGIWARN, ( "PPP!SyncInitCircuit: GetMsg error: type 0x%x, command 0x%x, status 0x%x\n", Ctrl.wan_type, Ctrl.wan_command, Ctrl.wan_status ) );
                Status = STATUS_UNSUCCESSFUL;
            }
        }
    }

    // Send WC_CONCNF - confirms the WC_CONNECT
    if ( NT_SUCCESS(Status) )
    {
        struct wan_ctl Ctrl = {0};
        Ctrl.wan_type    = WAN_CTL;
        Ctrl.wan_command = WC_CONCNF;
        Ctrl.wan_status  = WAN_SUCCESS;
        Status = DsPutMsg( pLine->hStream, &Ctrl, sizeof Ctrl, NULL, 0, DS_PRIORITY_HIGH );
    }

    if ( NT_SUCCESS(Status) )
        Status = RxEngineStart( &pLine->RxEngine, pAdapter->hMiniport, pLine->hStream, pLine, &CircuitEventHandlers, sizeof (union WAN_primitives), DIGI_PPP_MAX_FRAME_SIZE );

    return Status;
}

VOID
PPPMdmEngineStart( PDIGI_PPP_CALL pCall )
{
    NTSTATUS Status;
    PDIGI_PPP_ADAPTER pAdapter = pCall->pAdapter;
    PDIGI_PPP_LINE pLine = &pCall->pAdapter->pLines[pCall->hdLine];
    PDIGI_PPP_MDMENGINE pEngine = &pLine->MdmEngine;

    NdisZeroMemory( pEngine, sizeof *pEngine );
    pEngine->pAdapter = pAdapter;

    DigiDump( DIGIMDMENGINE, ( "PPPMdmEngineStart: pAdapter 0x%x\n", pAdapter ) );

    Status = MdmEngineStart( pEngine, pAdapter, pLine, pLine->hStream, &CircuitEventHandlers );

    if ( NT_ERROR( Status ) )
        MdmEngineStop( &pLine->MdmEngine );
}       

VOID
PPPMdmEngineStop( PDIGI_PPP_CALL pCall )
{
    PDIGI_PPP_LINE pLine = &pCall->pAdapter->pLines[pCall->hdLine];

    DigiDump( DIGIMDMENGINE, ( "PPPMdmEngineStop: pCall 0x%x\n", pCall ) );
    MdmEngineStop(&pLine->MdmEngine);

}
