/*++
*******************************************************************************
* 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 )
		PPPCallDestruct( pLine->pCall );

	RxEngineStop( &pLine->RxEngine );

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


NTSTATUS
PPPCircuitOnIncomingCall( 
	IN PDIGI_PPP_ADAPTER pAdapter,
	IN ULONG             iLine )
{
	NTSTATUS Status = STATUS_SUCCESS;


	return Status;
}


NTSTATUS
PPPCircuitOnTerminateCall(
	IN PDIGI_PPP_ADAPTER pAdapter,
	IN ULONG             iLine )
{
	NTSTATUS Status = STATUS_SUCCESS;
	// BUGBUG: shouldn't we spinlock access to pCall?
	PDIGI_PPP_CALL pCall = pAdapter->pLines[iLine].pCall;

	// 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;
	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 )
			Status = STATUS_UNSUCCESSFUL;
	}

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

	return Status;
}
