/*++
*******************************************************************************
* Copyright (c) 1990-98 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:

   dxbiwan.c

Abstract:

   Iwan interface routines for the datafire PRIme adapter.

Author:

   Michael Zarns

--*/

#include "digidxb.h"
#pragma hdrstop // Stop precomiled header generation

// Header defines conflict between mgmthlc.h and t1_api.h.  Override them here:
enum
{
	HLC_FRAME_ESF          = FRAME_ESF,
	HLC_FRAME_D4           = FRAME_D4,
	HLC_FRAME_CEPT_CRC4    = FRAME_CEPT_CRC4,
	HLC_FRAME_CEPT_WO_CRC4 = FRAME_CEPT_WO_CRC4
};

#undef FRAME_ESF
#undef FRAME_D4
#undef FRAME_CEPT_CRC4
#undef FRAME_CEPT_WO_CRC4

enum
{
	HLC_JITTER_AUTO = JITTER_AUTO,
	HLC_JITTER_TX   = JITTER_TX,
	HLC_JITTER_RX   = JITTER_RX,
	HLC_JITTER_NONE = JITTER_NONE
};

#undef JITTER_AUTO
#undef JITTER_TX
#undef JITTER_RX
#undef JITTER_NONE

#include "t1_api.h"
#include "iwan_control.h"


NTSTATUS
dxbIwanSetSnid(
	IN HANDLE hStream,
	IN ULONG  Snid, 
	IN ULONG  Class,
	IN ULONG  ChanId )
/*++

Description:

	Send the adapter an IWAN_SET_SNID ioctl.

Parameters:

	hStream
		Handle to previously opened stream to IWAN device.

	iPort
		Zero-based index of port being configured

	Snid
		SubNetworkID identifying this port

Return Value:

	STATUS_SUCCESS, or failure status

--*/
{
	ULONG Error;
	NTSTATUS Status;
	iwan_snioc_t SetSnid = {0};
	SetSnid.w_type   = WAN_SNID;
	SetSnid.w_class  = (UCHAR)Class;
	SetSnid.w_chanid = ChanId;
	SetSnid.w_snid   = Snid;
	
	DigiDump( DIGICONFIG, ( "DXB!IwanSetSnid: w_type 0x%x, w_class 0x%x, w_chanid 0x%x, w_snid 0x%x\n", SetSnid.w_type, SetSnid.w_class, SetSnid.w_chanid, SetSnid.w_snid ) );
	Status = DsIoctl( hStream, N_SETSNID, &SetSnid, sizeof SetSnid, &Error );

	if ( NT_ERROR( Status ) )
	{
		DigiDump( DIGIWARN, ( "DXB!IwanSetSnid failed!  Status 0x%x, Error 0x%x\n", Status, Error ) );
	}

	return Status;
}


NTSTATUS
dxbT1Tune(
	IN PDXB_DEVICE_EXTENSION pExt, 
	IN HANDLE                hKeyPort,
	IN ULONG                 iPort,
	IN ULONG                 nBChannels )
/*++

Description:

	Send the adapter T1 configuration params

Return Value:

	STATUS_SUCCESS, or failure status

--*/
{
	NTSTATUS Status;
	HANDLE hStream = NULL;
	HANDLE hKey = NULL;
	IfaceMode_t Tune = {0};
	Tune.Header.Command = SET_IFACE_MODE;
	Tune.Header.Interface = iPort;
	Tune.Mode = DI_INACTIVE;

	Status = DigiRegOpenSubkey( &hKey, hKeyPort, DXB_REGKEY_DS1 );
	if ( NT_SUCCESS( Status ) )
	{
		ULONG Clocking;
		Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_CLOCKING, &Clocking, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			switch ( Clocking )
			{
				case TIMING_LOOP:  Tune.Mode |= CLOCK_LINE;  break;
				case TIMING_LOCAL: Tune.Mode |= CLOCK_LOCAL; break;
				default: Status = STATUS_UNSUCCESSFUL; break;
			}
	}

	if ( NT_SUCCESS( Status ) )
	{
		ULONG Framing;
		Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_FRAMING, &Framing, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			switch ( Framing )
			{
				case HLC_FRAME_D4:           Tune.Mode |= FRAME_D4;   break;
				case HLC_FRAME_ESF:          Tune.Mode |= FRAME_ESF;  break;
				case HLC_FRAME_CEPT_CRC4:    Tune.Mode |= FRAME_CEPT; break;
				case HLC_FRAME_CEPT_WO_CRC4: Tune.Mode |= FRAME_CEPT|FRAME_NOCRC;  break;
				default: Status = STATUS_UNSUCCESSFUL; break;
			}
	}

	if ( NT_SUCCESS( Status ) )
	{
		ULONG Coding;
		Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_CODING, &Coding, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			switch ( Coding )
			{
				case LINE_CODE_AMI:  Tune.Mode |= LINE_AMI;  break;
				case LINE_CODE_B8ZS: Tune.Mode |= LINE_B8ZS; break;
				case LINE_CODE_HDB3: Tune.Mode |= LINE_HDB3; break;
				default: Status = STATUS_UNSUCCESSFUL; break;
			}
	}

	if ( NT_SUCCESS( Status ) )
	{
		ULONG Jitter;
		Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_JITTER_ATTEN, &Jitter, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			switch ( Jitter )
			{
				case HLC_JITTER_AUTO: Tune.Mode |= JITTER_AUTO; break;
				case HLC_JITTER_TX:   Tune.Mode |= JITTER_TX;   break;
				case HLC_JITTER_RX:   Tune.Mode |= JITTER_RX;   break;
				case HLC_JITTER_NONE: Tune.Mode |= JITTER_NONE; break;
				default: Status = STATUS_UNSUCCESSFUL; break;
			}
	}

	if ( NT_SUCCESS( Status ) )
	{
		ULONG Span;
		Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_IF_TYPE, &Span, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			switch ( Span )
			{
				case LONG_HAUL:  Tune.Mode |= SPAN_LONG;  break;
				case SHORT_HAUL: Tune.Mode |= SPAN_SHORT; break;
				default: Status = STATUS_UNSUCCESSFUL; break;
			}
	}

	if ( NT_SUCCESS( Status ) )
	{
		switch ( nBChannels )
		{
			case 23:
				Tune.Mode |= SPAN_T1;
				switch ( SPAN_TYPE(Tune.Mode) )
				{
					case SPAN_LONG:
					{
						ULONG Lbo;
						Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_LONG_HAUL_LBO, &Lbo, DigiRegFlagRequired, 0 );
						if ( NT_SUCCESS( Status ) )
							switch ( Lbo )
							{
								case LBO_00_0_DB: Tune.Options = SPAN_LBO_0|RX_GAIN_LO;   break;
								case LBO_07_5_DB: Tune.Options = SPAN_LBO_075|RX_GAIN_LO; break;
								case LBO_15_0_DB: Tune.Options = SPAN_LBO_150|RX_GAIN_LO; break;
								case LBO_22_5_DB: Tune.Options = SPAN_LBO_225|RX_GAIN_LO; break;
								default: Status = STATUS_UNSUCCESSFUL; break;
							}

						if ( NT_SUCCESS( Status ) )
						{
							ULONG Gain;
							Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_EQ_GAIN_LIMIT, &Gain, DigiRegFlagRequired, 0 );
							if ( NT_SUCCESS( Status ) )
								switch ( Gain )
								{
									case EGL_LOW:  Tune.Options |= RX_GAIN_LO; break;
									case EGL_HIGH: Tune.Options |= RX_GAIN_HI; break;
									default: Status = STATUS_UNSUCCESSFUL; break;
								}
						}
						break;
					}

					case SPAN_SHORT:
					{
						ULONG Length;
						Status = DigiRegQueryDword( hKey, DXB_REGVAL_DS1_SHORT_HAUL_LEN, &Length, DigiRegFlagRequired, 0 );
						if ( NT_SUCCESS( Status ) )
							Tune.Options = Length * 133;
						break;
					}
					default:
						Status = STATUS_UNSUCCESSFUL;
						break;
				}
				break;

			case 30:
				Tune.Mode |= SPAN_E1;
				break;

			default:
				Status = STATUS_UNSUCCESSFUL;
				break;
		}
	}

	if ( NT_SUCCESS( Status ) )
	{
		// Look for optional PRIME overrides 
		Status = DigiRegQueryDword( hKey, L"Mode", &Tune.Mode, DigiRegFlagOptional, Tune.Mode );
		if ( NT_SUCCESS( Status ) )	
			Status = DigiRegQueryDword( hKey, L"Options", &Tune.Options, DigiRegFlagOptional, Tune.Options );
		Status = STATUS_SUCCESS;
	}

	// Send the params down!	
	if ( NT_SUCCESS( Status ) )
	{
		ULONG Error;
		Status = DsOpen( pExt->hDsDevice, "T1", NULL, NULL, 0, &hStream, &Error );
		if ( NT_SUCCESS( Status ) )
		{
			ULONG cbCtrl, cbData;
			DigiDump( DIGICONFIG, ( "DXB!T1Tune: Port %d, Mode 0x%x, Options 0x%x\n", iPort, Tune.Mode, Tune.Options ) );
			Status = DsPutMsg( hStream, &Tune, sizeof Tune, NULL, 0, DS_PRIORITY_LOW );
			if ( NT_SUCCESS( Status ) )
				Status = DsGetMsg( hStream, &Tune, sizeof Tune, &cbCtrl, NULL, 0, &cbData, DS_PRIORITY_LOW );
			DsClose( hStream );
		}
	}

	if ( hKey )
		DigiRegCloseKey( hKey );

	if ( hStream )
		DsClose( hStream );

	return Status;
}
