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

   sohx25.c

Abstract:

   This module contains functions to set up the X25 Stack.

Author:

   Jeff Romatoski

Revision History:


--*/


////////////////////////////////////////////////////////////////////////////////

#include "digisoh.h"
#include "sohx25.h"
#pragma hdrstop
#include "ll_proto.h"
#include "x25_proto.h"
#include "x25_control.h"

#if !NT5_BUILD
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,SohX25SnIdent)
#pragma alloc_text(INIT,SohX25Tune)
#endif
#endif


NTSTATUS
SohX25SnIdent(
	IN HANDLE                hKeyLine,
	IN ULONG                 MuxId,
	IN ULONG                 Snid,
	IN HANDLE				 hStream )
/*++

Description:

	Configure (or Tune) X25 on the specified port.  Read line configuration from 
	registry and send it down to the adapter.  

Parameters:

	hKeyLine
		Handle to previously opened Line registry key

	MuxId
		Id returned from Link request

	Snid
		SubNetwork ID to be assigned to this port

Return Value:

	STATUS_SUCCESS or failure status.

--*/
{
	NTSTATUS Status;
	struct xll_reg SnIdent = {0};
	ULONG Error;
	HANDLE hKeyX25;


	DigiDump( DIGIINIT, ( "SOH!SohX25SnIdent: Snid 0x%x, MuxId 0x%x\n", Snid, MuxId ) );

	SnIdent.lmuxid               = MuxId;
	SnIdent.lreg.ll_type         = LL_REG;
	SnIdent.lreg.ll_snid         = Snid;
	SnIdent.lreg.ll_normalSAP    = 0x7E;
	SnIdent.lreg.ll_loopbackSAP  = 0x70;

	Status = DigiRegOpenSubkey( &hKeyX25, hKeyLine, DXB_REGKEY_X25 );
	if ( NT_SUCCESS( Status ) )
	{
		Status = DigiRegQueryDword( hKeyX25, DXB_REGVAL_X25_LLCLASS, &SnIdent.lreg.ll_class, DigiRegFlagRequired, 0 );
		DigiRegCloseKey( hKeyX25 );
	}

	if ( NT_SUCCESS( Status ) )
	{
		Status = DsIoctl( hStream, N_snident, &SnIdent, sizeof SnIdent, &Error );
		if ( NT_ERROR( Status ) )
		{
			DigiDump( DIGIERRORS, ( "Soh!SohX25SnIdent: DsIoctl failed, Status 0x%x, Error 0x%x\n", Status, Error ) );
		}
	}

	DigiDump( DIGIINIT, ( "SOH!SohX25SnIdent: Leave, Status 0x%x\n", Status ) );
	return Status;
}


NTSTATUS
SohX25Tune(
	IN HANDLE                hKeyLine,
	IN USHORT                iPort,
	IN ULONG                 Snid ,
	IN	HANDLE				 hStream)
/*++

Description:

	Configure (or Tune) X25 on the specified port.  Read line configuration from 
	registry and send it down to the adapter.  

Parameters:

	hKeyLine
		Handle to Port registry key containing configuration parameters

	iPort
		Zero-based index of the port being configured

	Snid
		SubNetwork ID identifies the port

Return Value:

	STATUS_SUCCESS or failure status.

--*/
{
	NTSTATUS Status;
	struct wlcfg Tune = {0};
	HANDLE hKeyX25;
	ULONG Error = 0;
//	HANDLE hStream;
	unsigned int i = 0;
	UNICODE_STRING	tempUnicode;
	USHORT	tempBuffer[10];

	DigiDump( DIGIINIT, ( "SOH!SohX25Tune: Enter, Port 0x%x\n", iPort ) );

	Tune.U_SN_ID = Snid;

	Status = DigiRegOpenSubkey( &hKeyX25, hKeyLine, DXB_REGKEY_X25 );
	if ( NT_SUCCESS( Status ) )
	{
		// TODO: Read all remaining x25 config params here!
		// See initx25.c, ReadX25Parameters for bad example.  Do not provide defaults.

		Status = DigiRegQueryDword( hKeyX25, L"Net_Mode", &Tune.NET_MODE, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"X25_VSN", &Tune.X25_VSN, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"L3PLPMODE", &Tune.L3PLPMODE, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LPC", &Tune.LPC, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"HPC", &Tune.HPC, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LIC", &Tune.LIC, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"HIC", &Tune.HIC, DigiRegFlagRequired, 0 );
		if (NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LTC", &Tune.LTC, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"HTC", &Tune.HTC, DigiRegFlagRequired, 0 );
			
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LOC", &Tune.LOC, DigiRegFlagRequired, 0 );
														
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"HOC", &Tune.HOC, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"THISGFI", &Tune.THISGFI, DigiRegFlagRequired, 0 );
			
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LOCMAXPKTSIZE", &Tune.LOCMAXPKTSIZE, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"REMMAXPKTSIZE", &Tune.REMMAXPKTSIZE, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LOCDEFPKTSIZE", &Tune.LOCDEFPKTSIZE, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"REMDEFPKTSIZE", &Tune.REMDEFPKTSIZE, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LOCMAXWSIZE", &Tune.LOCMAXWSIZE, DigiRegFlagRequired, 0 );
			
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"REMMAXWSIZE", &Tune.REMMAXWSIZE, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"LOCDEFWSIZE", &Tune.LOCDEFWSIZE, DigiRegFlagRequired, 0 );
												
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"REMDEFWSIZE", &Tune.REMDEFWSIZE, DigiRegFlagRequired, 0 );
																										
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"MAXNSDULEN", &Tune.MAXNSDULEN, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"ACKDELAY", &Tune.ACKDELAY, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"T20value", &Tune.T20value, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"T21value", &Tune.T21value, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"T22value", &Tune.T22value, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"T23value", &Tune.T23value, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"Tvalue", &Tune.Tvalue, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"T25value", &Tune.T25value, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"T26value", &Tune.T26value, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"idlevalue", &Tune.idlevalue, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"connectvalue", &Tune.connectvalue, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"R20value", &Tune.R20value, DigiRegFlagRequired, 0 );
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"R22value", &Tune.R22value, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"R23value", &Tune.R23value, DigiRegFlagRequired, 0 );


		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"localdelay", &Tune.localdelay, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"accessdelay", &Tune.accessdelay, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"locmaxthclass", &Tune.locmaxthclass, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"remmaxthclass", &Tune.remmaxthclass, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"locdefthclass", &Tune.locdefthclass, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"remdefthclass", &Tune.remdefthclass, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"locminthclass", &Tune.locminthclass, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"remminthclass", &Tune.remminthclass, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"CUG_CONTROL", &Tune.CUG_CONTROL, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"SUB_MODES", &Tune.SUB_MODES, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"SNMODES", &Tune.psdn_local.SNMODES, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"intl_addr_recogn", &Tune.psdn_local.intl_addr_recogn, DigiRegFlagRequired, 0 );

		
		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"intl_prioritised", &Tune.psdn_local.intl_prioritised, DigiRegFlagRequired, 0 );


		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"dnic1", &Tune.psdn_local.dnic1, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"dnic2", &Tune.psdn_local.dnic2, DigiRegFlagRequired, 0 );


		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"prty_encode_control", &Tune.psdn_local.prty_encode_control, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"prty_pkt_forced_value", &Tune.psdn_local.prty_pkt_forced_value, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"src_addr_control", &Tune.psdn_local.src_addr_control, DigiRegFlagRequired, 0 );


		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"dbit_control",  &Tune.psdn_local.dbit_control, DigiRegFlagRequired, 0 );


		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"thclass_neg_to_def", &Tune.psdn_local.thclass_neg_to_def, DigiRegFlagRequired, 0 );

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQueryDword( hKeyX25, L"thclass_type", &Tune.psdn_local.thclass_type, DigiRegFlagRequired, 0 );

		tempUnicode.Buffer = (USHORT *) tempBuffer;
		tempUnicode.Length = 0;
		tempUnicode.MaximumLength = sizeof(tempBuffer);

		if ( NT_SUCCESS( Status ) )
			Status = DigiRegQuerySz( hKeyX25, L"lsap_address", &tempUnicode, DigiRegFlagRequired, 0 );
		if (  NT_SUCCESS( Status ) )
		{
			
			PUCHAR lsapaddr		;
			ULONG len = tempUnicode.Length / sizeof (WCHAR) ;
			UCHAR digit;
			PWCHAR pwData = tempUnicode.Buffer;

			lsapaddr = Tune.local_address.lsap_add ;

			for(i=0; i<len; ++i)
			{
				digit = *pwData++ - '0' ;
				if (i & 1)
					*lsapaddr++ |= digit;
				else
					*lsapaddr = digit << 4;
			}

		   Tune.local_address.lsap_len = len;

         if ( tempUnicode.Buffer )
			   DigiRegFreeString( &tempUnicode );

		}					
			 		
		DigiRegCloseKey( hKeyX25 );
	}

	if 	 ( NT_SUCCESS( Status ) )

	{

		Tune.NPCchannels = Tune.HPC - Tune.LPC + 1;
		Tune.NICchannels = Tune.HIC - Tune.LIC + 1;
		Tune.NTCchannels = Tune.HTC - Tune.LTC + 1;
		Tune.NOCchannels = Tune.HOC - Tune.LOC + 1;

		Tune.Nochnls = Tune.NPCchannels + Tune.NICchannels +
                                 Tune.NTCchannels +
                                 Tune.NOCchannels;

	}




	if ( NT_SUCCESS( Status ) )
	{
	   DigiDump( DIGIINIT, ( "SOH!SohX25Tune: X25 line config, line %d:\n"
		                       "   U_SN_ID   = 0x%x\n"
		                       "   NET_MODE  = 0x%x\n"
		                       "   X25_VSN   = 0x%x\n"
		                       "   L3PLPMODE = 0x%x\n"
		                       "   LPC       = 0x%x\n"
									  // TODO: Dump the rest here!
								"   HPC = %u\n"
								"   LIC = %u\n"
								"   HIC = %u\n"
	                          "   LTC = %u\n"
    	                      "   HTC = %u\n"
        	                  "   LOC = %u\n"
            	              "   HOC = %u\n"
                	          "   NPCchannels = %u\n"
                    	      "   NICchannels = %u\n"
                        	  "   NTCchannels = %u\n"
	                          "   NOCchannels = %u\n"
    	                      "   Nochnls = %u\n",
        	                  
							  iPort,		
	                          Tune.U_SN_ID,
	                          Tune.NET_MODE,
	                          Tune.X25_VSN,
	                          Tune.L3PLPMODE,
	                          Tune.LPC,
							  Tune.HPC,
                          Tune.LIC,
                          Tune.HIC,
                          Tune.LTC,
                          Tune.HTC,
                          Tune.LOC,
                          Tune.HOC,
                          Tune.NPCchannels,
                          Tune.NICchannels,
                          Tune.NTCchannels,
                          Tune.NOCchannels,
                          Tune.Nochnls
                          

										// TODO: ...and here!
	                          ) );


		DigiDump( DIGIINIT, ( "SOH!SohX25Tune: X25 line config, line %d:\n"
		                      "   THISGFI = %u\n"
            	              "   LOCMAXPKTSIZE = %u\n"
                	          "   REMMAXPKTSIZE = %u\n"
                    	      "   LOCDEFPKTSIZE = %u\n"
                        	  "   REMDEFPKTSIZE = %u\n"
	                          "   LOCMAXWSIZE = %u\n"
    	                      "   REMMAXWSIZE = %u\n"
        	                  "   LOCDEFWSIZE = %u\n"
            	              "   REMDEFWSIZE = %u\n"
                	          "   MAXNSDULEN = %u\n"
                    	      "   ACKDELAY = %u\n",

						  iPort,	
                          Tune.THISGFI,
                          Tune.LOCMAXPKTSIZE,
                          Tune.REMMAXPKTSIZE,
                          Tune.LOCDEFPKTSIZE,
                          Tune.REMDEFPKTSIZE,
                          Tune.LOCMAXWSIZE,
                          Tune.REMMAXWSIZE,
                          Tune.LOCDEFWSIZE,
                          Tune.REMDEFWSIZE,
                          Tune.MAXNSDULEN,
                          Tune.ACKDELAY


										// TODO: ...and here!
	                          ) );





DigiDump( DIGIINIT, ("   T20value = %u\n"
                          "   T21value = %u\n"
                          "   T22value = %u\n"
                          "   T23value = %u\n"
                          "   Tvalue = %u\n"
                          "   T25value = %u\n"
                          "   T26value = %u\n"
                          "   idlevalue = %u\n"
                          "   connectvalue = %u\n"
                          "   R20value = %u\n"
                          "   R22value = %u\n"
                          "   R23value = %u\n"
                          "   localdelay = %u\n"
                          "   accessdelay = %u\n"
                          "   locmaxthclass = %u\n"
                          "   remmaxthclass = %u\n"
                          "   locdefthclass = %u\n"
                          "   remdefthclass = %u\n"
                          "   locminthclass = %u\n"
                          "   remminthclass = %u\n"
                          "   CUG_CONTROL = %u\n"
                          "   SUB_MODES = %u\n",
                          Tune.T20value,
                          Tune.T21value,
                          Tune.T22value,
                          Tune.T23value,
                          Tune.Tvalue,
                          Tune.T25value,
                          Tune.T26value,
                          Tune.idlevalue,
                          Tune.connectvalue,
                          Tune.R20value,
                          Tune.R22value,
                          Tune.R23value,
                          Tune.localdelay,
                          Tune.accessdelay,
                          Tune.locmaxthclass,
                          Tune.remmaxthclass,
                          Tune.locdefthclass,
                          Tune.remdefthclass,
                          Tune.locminthclass,
                          Tune.remminthclass,
                          Tune.CUG_CONTROL,
                          Tune.SUB_MODES) );
   DigiDump( DIGIINIT, ("   psdn_local.SNMODES = %u\n"
                          "   psdn_local.intl_addr_recogn = %u\n"
                          "   psdn_local.intl_prioritised = %u\n"
                          "   psdn_local.dnic1 = %u\n"
                          "   psdn_local.dnic2 = %u\n"
                          "   psdn_local.prty_encode_control = %u\n"
                          "   psdn_local.prty_pkt_forced_value = %u\n"
                          "   psdn_local.src_addr_control = %u\n"
                          "   psdn_local.dbit_control = %u\n"
                          "   psdn_local.thclass_neg_to_def = %u\n"
                          "   psdn_local.thclass_type = %u\n"
                          "   local_address.lsap_len = %u\n",
                          Tune.psdn_local.SNMODES,
                          Tune.psdn_local.intl_addr_recogn,
                          Tune.psdn_local.intl_prioritised,
                          Tune.psdn_local.dnic1,
                          Tune.psdn_local.dnic2,
                          Tune.psdn_local.prty_encode_control,
                          Tune.psdn_local.prty_pkt_forced_value,
                          Tune.psdn_local.src_addr_control,
                          Tune.psdn_local.dbit_control,
                          Tune.psdn_local.thclass_neg_to_def,
                          Tune.psdn_local.thclass_type,
                          Tune.local_address.lsap_len) );

	DigiDump( DIGIINIT, ("   local_address.lsap_add = ") );
	for( i = 0; (int)i < (Tune.local_address.lsap_len-1)/2; i++ )
	{
	   DigiDump( DIGIINIT, ("%c-", Tune.local_address.lsap_add[i]) );
	}
	DigiDump( DIGIINIT, ("%c", Tune.local_address.lsap_add[i]) );
	DigiDump( DIGIINIT, ("   (") );
	for( i = 0; (int)i < (Tune.local_address.lsap_len-1)/2; i++ )
	{
	   DigiDump( DIGIINIT, ("%x-", Tune.local_address.lsap_add[i]) );
	}
	DigiDump( DIGIINIT, ("%x)\n", Tune.local_address.lsap_add[i]) );


		
		Status = DsIoctl( hStream, N_snconfig, &Tune, sizeof Tune, &Error );
		if ( NT_ERROR( Status ) )
		{
			DigiDump( DIGIERRORS, ( "SOH!X25Tune: DsIoctl failed, Status 0x%x, Error 0x%x\n", Status, Error ) );
		}

//		(void)DsClose( hStream );
	}

	DigiDump( DIGIINIT, ( "SOH!SohX25Tune: Leave, Status 0x%x\n", Status ) );
	return Status;
}
