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

   digiisdn.h

Abstract:

   Common includes, defines, structs for the digiisdn driver.


Author:

   Michael Zarns

--*/

#ifndef DIGIISDN
#define DIGIISDN

#define UNICODE
#include <ntddk.h>
#include "digilib.h"	// Needed for NT5_BUILD definition and standard digi defs

#include <ndis.h>
#include <ndiswan.h>
#include <ndistapi.h>

#include "dsapi.h"
#include "dxbreg.h"

// Digi type definitions used by firmware headers
#include "dxbtypes.h"

#define DIGIINIT			DEBUG_00000001
#define DIGIMP				DEBUG_00000002
#define DIGICALL			DEBUG_00000004
#define DIGISTATE			DEBUG_00000008

#define DIGIQUEUE			DEBUG_00000010
#define DIGIRXENGINE 	DEBUG_00000020
#define DIGILISTEN		DEBUG_00000040

#define DIGITX				DEBUG_00000100
#define DIGITXDATA		DEBUG_00000200
#define DIGIRX				DEBUG_00000400
#define DIGIRXDATA		DEBUG_00000800

#define DIGITAPIOID		DEBUG_00001000
#define DIGIWANOID		DEBUG_00002000
#define DIGILANOID		DEBUG_00004000
#define DIGIOID			DEBUG_00008000

#define DIGITAPIEVENT	DEBUG_00010000
#define DIGIWANEVENT		DEBUG_00020000

#define DIGIV1				DEBUG_00100000
#define DIGIV2				DEBUG_00200000

#define DIGIWARN		DEBUG_WARN
#define DIGIERROR		DEBUG_ERROR
#define DIGIBREAK		DEBUG_BREAK


// Constants used for Wan and Tapi indications
#define ISDN_MAX_FRAME_SIZE	1524
#define ISDN_SEND_WINDOW 		4
#define ISDN_FRAMING_BITS 		(PPP_FRAMING|PPP_COMPRESS_PROTOCOL_FIELD|TAPI_PROVIDER|RAS_FRAMING)
#define ISDN_HEADER_PADDING 	0
#define ISDN_TAIL_PADDING		0
#define ISDN_COMP_BITS			0

// Used by Tapi and AddTapiDevices code.
#define ISDN_PROVIDER_MEDIA					"ISDN"
#define ISDN_PROVIDER_DEVICE					"DigiIsdn"

typedef enum ISDN_OBJECT_TYPE
{
	ISDN_TYPE_UNKNOWN,
	ISDN_TYPE_ADAPTER,
	ISDN_TYPE_CALL,
	ISDN_TYPE_QUEUE_ENTRY,
	ISDN_TYPE_RXENGINE,
	ISDN_TYPE_FREED,
	ISDN_TYPE_COUNT
} ISDN_OBJECT_TYPE;


typedef enum ISDN_CONN_TYPE
{
	ISDN_CONN_UNKNOWN,
	ISDN_CONN_TOLLSAVER,
	ISDN_CONN_D56,
	ISDN_CONN_D64,
	ISDN_CONN_COUNT
} ISDN_CONN_TYPE;



struct ISDN_CALL;
typedef struct ISDN_CALL ISDN_CALL, *PISDN_CALL;

struct ISDN_LINE;
typedef struct ISDN_LINE ISDN_LINE, *PISDN_LINE;

struct ISDN_EVENT_HANDLERS;
typedef struct ISDN_EVENT_HANDLERS ISDN_EVENT_HANDLERS, *PISDN_EVENT_HANDLERS;

//
// ISDN_CODEC is a table of function pointers to routines which write and read (hence 
// CODE and DECODE == CODEC) Spider ISDN messages.  To support PRIme and Dense adapters
// which have different versions of the API, we encapsulate the version specific code
// behind this dispatch table.
//
typedef NTSTATUS (*PISDN_XN_CONNECT)  ( IN PVOID   pOwner,
                                        IN HANDLE  hStream,
                                        IN ULONG   Snid,
                                        IN ULONG   MaxFrameSize,
                                        IN ULONG   ConnType,
                                        IN PSTRING pRemoteAddress );

typedef NTSTATUS (*PISDN_XN_CONNACK)  ( IN PVOID   pOwner,
                                        IN HANDLE  hStream,
                                        IN ULONG   ChanIndex,
                                        IN ULONG   Channel );

typedef NTSTATUS (*PISDN_XN_DISCONN)  ( IN PVOID   pOwner,
                                        IN HANDLE  hStream,
                                        IN ULONG   ChanIndex,
                                        IN ULONG   Channel );

typedef NTSTATUS (*PISDN_XN_CONNEND)  ( IN PVOID   pOwner,
                                        IN HANDLE  hStream,
                                        IN ULONG   ChanIndex,
                                        IN ULONG   Channel );

typedef NTSTATUS (*PISDN_XN_LISTEN)   ( IN PVOID   pOwner,
                                        IN HANDLE  hStream,
                                        IN ULONG   Snid );

typedef VOID (*PISDN_INTERPRETER) ( IN PVOID                pOwner,
                                    IN PISDN_EVENT_HANDLERS pDispatchTable,
                                    IN PVOID                pControl,
                                    IN ULONG                cbControl,
                                    IN PVOID                pData, 
                                    IN ULONG                cbData );

typedef struct ISDN_CODEC
{
	PISDN_XN_CONNECT  XnConnect;
	PISDN_XN_CONNACK  XnConnack;
	PISDN_XN_DISCONN  XnDisconn;
	PISDN_XN_CONNEND  XnConnend;
	PISDN_XN_LISTEN   XnListen;
	PISDN_INTERPRETER XnInterpreter;
	ULONG             XnCbControl;	// GetMsg Control buffer max size
	PCSTR             XnDeviceName;	// Firmware device to open for ISDN services
} ISDN_CODEC;


//
// ISDN_EVENT_HANDLERS is a table of function pointers to handlers for input (rx) 
// Spider ISDN message handlers.  We handle the messages differently depending on 
// whether they're received on a listen stream or a standard call stream.  
//

typedef VOID (*PISDN_ON_CONNECT) ( IN PVOID          pOwner, 
                                   IN ULONG          ChanIndex, 
                                   IN ULONG          Channel,
                                   IN ISDN_CONN_TYPE ConnType );

typedef VOID (*PISDN_ON_CONNACK) ( IN PVOID pOwner,
                                   IN ULONG ChanIndex, 
                                   IN ULONG Channel );

typedef VOID (*PISDN_ON_CACTIVE) ( IN PVOID pOwner );

typedef VOID (*PISDN_ON_DISCONN) ( IN PVOID pOwner,
                                   IN ULONG ChanIndex, 
                                   IN ULONG Channel );

typedef VOID (*PISDN_ON_CONNEND) ( IN PVOID pOwner,
                                   IN ULONG ChanIndex, 
                                   IN ULONG Channel );

typedef VOID (*PISDN_ON_LISTEN)  ( IN PVOID pOwner );

typedef VOID (*PISDN_ON_RXDATA)  ( IN PVOID pOwner,
                                   IN PVOID pData,
                                   IN ULONG cbData );

typedef struct ISDN_EVENT_HANDLERS
{
	PISDN_ON_CONNECT  OnConnect;
	PISDN_ON_CONNACK  OnConnack;
	PISDN_ON_CACTIVE  OnCActive;
	PISDN_ON_DISCONN  OnDisconn;
	PISDN_ON_CONNEND  OnConnend;
	PISDN_ON_LISTEN   OnListen;
	PISDN_ON_RXDATA   OnData;
} ISDN_EVENT_HANDLERS, *PISDN_EVENT_HANDLERS;


// An ISDN_RXENGINE struct is used by the RxEngine to keep it's state.

#define RXENGINE_GETMSG_COUNT 2

typedef struct ISDN_RXENGINE
{
	ISDN_OBJECT_TYPE     Type;
	HANDLE               hStream;
	HANDLE               hOwner;
	PISDN_EVENT_HANDLERS pDispatch;
	PISDN_INTERPRETER    Interpreter;
	ULONG                cbMaxControl;
	ULONG                cbMaxData;
	KDPC                 Dpc;
	KTIMER               Timer;
	KEVENT               Stopped;
	// Count of currently pended GetMsg requests.
	ULONG                nGetMsgPending;
	DIGI_SPINLOCK        Lock;

	BOOLEAN              fHalt;		// Halting?
	BOOLEAN              fStarted;	// Engine started?

} ISDN_RXENGINE, *PISDN_RXENGINE;


// An ISDN_ADAPTER represents a virtual adapter exposed to Ndis.  We expose a virtual
// ISDN adapter to Ndis for each line.  Thus, a two-line card exposes two adapters to
// Ndis, each associated with a single physical line.

typedef struct ISDN_ADAPTER
{
	ISDN_OBJECT_TYPE Type;

	// String defines name of the adapter, i.e. DigiIsdn1001.
	#define CB_ISDN_ADAPTER_NAME_MAX 32
	ANSI_STRING Name;
	CHAR        NameBuffer[CB_ISDN_ADAPTER_NAME_MAX];

	#define CB_ISDN_ADAPTER_NUMBER_MAX 8
	ANSI_STRING Number;
	CHAR        NumberBuffer[CB_ISDN_ADAPTER_NUMBER_MAX];

	LIST_ENTRY ListEntry;	// Entry on list of adapters.

	// Tapi and Ndis info
	HANDLE        hMiniport;	// Handle identifying this adapter for Ndis and Tapi.
	ULONG         TapiBaseId;	// Base DeviceId assigned by Tapi.  One DeviceId per line
	ULONG         nLines;		// Number of Lines == # DeviceIds == # Calls == # BChannels
	ISDN_LINE     *pLines;		// Array of size nLines
	DIGI_SPINLOCK Lock;

	// Dxb related info
	HANDLE hDevice;			// DsApi device handle represents the adapter
	ULONG  Snid;				// SubNetwork ID identifies the physical line on the adapter
	
	// Used because we need to "listen" for incoming calls.
	struct 
	{
		HANDLE        hStream;				// Dxb stream handle for listen stream
		ISDN_RXENGINE RxEngine;
		LIST_ENTRY    OfferingListHead;	// List of calls offering incoming connections to Tapi
	} Listen;

	// Call management
	struct
	{
		PKTHREAD   pThread;
		LIST_ENTRY Queue;
		KEVENT     WorkEvent;
		KEVENT     HaltEvent;
	} Mgr;

	// Adapter Context Queue and associated baggage
	struct 
	{
		NDIS_MINIPORT_TIMER Timer;
		DIGI_SPINLOCK       Lock;
		LIST_ENTRY          ListHead;
		BOOLEAN             Ready;		// Entries can only be inserted when "Ready"
	} Queue;

	// XN* Dispatch table.  Use function pointers here encapsulate reading/writing 
	// ISDN API version specific structs.
	ISDN_CODEC XnDispatch;

} ISDN_ADAPTER, *PISDN_ADAPTER;

#define AdapterAcquireLock( pAdapter ) DigiAcquireSpinLock( &(pAdapter)->Lock )
#define AdapterReleaseLock( pAdapter ) DigiReleaseSpinLock( &(pAdapter)->Lock )

// An ISDN_LINE represents a TAPI line.  Internally, there is a one-to-one mapping 
// between an ISDN_LINE and an ISDN_CALL.  
typedef struct ISDN_LINE
{
	HTAPI_LINE htLine;		// Tapi handle associated with this line.  Set on OID_TAPI_OPEN
	ISDN_CALL  *pCall;
	BOOLEAN    Listen;		// Set if Tapi is listening, via SetDefaultMediaDetection

} ISDN_LINE, *PISDN_LINE;


// An ISDN_CALL represents an active ISDN call.  Each call is exposed to Ndis as a 
// single "line".
typedef struct ISDN_CALL
{
	ISDN_OBJECT_TYPE Type;

	// On destruct, we set type to TYPE_FREED, keep TYPE_CALL here for post-mortem 
	// debugging.
	ISDN_OBJECT_TYPE TypeBeforeDestruct;

	ULONG State;	// Current state.
	
	// Keep state history for debugging.  Index 0 is most recent.
	ULONG StateHistory[8];

	// Dxb Stream handle used for all communication with the adapter for this call.
	HANDLE hStream;

	// List held by adapter of calls currently "offering" incoming connections to Tapi
	LIST_ENTRY OfferingListEntry;

	// Call Mgr Thread fields
	struct 
	{
		LIST_ENTRY ListEntry;	// Entry on list of calls with "work to do" by the thread
		ULONG      Action;		// The type of "work to do" for this call
	} Mgr;

	// Parent adapter and line
	PISDN_ADAPTER pAdapter;
	HDRV_LINE     hdLine;

	// String defines the address (phone number) of the remote endpoint
	#define ISDN_NUMBER_SIZE 32
//	STRING RemoteAddress;
//	CHAR RemoteAddressBuffer[ISDN_NUMBER_SIZE+1];	// Add 1 to force NULL termination

	STRING CallerID;
	CHAR CallerIDBuffer[ISDN_NUMBER_SIZE+1];	// Add 1 to force NULL termination

	STRING CalledID;
	CHAR CalledIDBuffer[ISDN_NUMBER_SIZE+1];	// Add 1 to force NULL termination

	STRING ConnectedID;
	CHAR ConnectedIDBuffer[ISDN_NUMBER_SIZE+1];	// Add 1 to force NULL termination


	// Tapi handle for this call.  Used when sending indications up to Tapi.
	HTAPI_CALL htCall;
	BOOLEAN fLineUpSent;	// Has WAN_LINE_UP indication been sent up to ndiswan yet?

	ULONG  TapiState;		// State last passed up to Tapi.

	// Ndis wan handle identifying this connection.  Returned from WanLineup, used to 
	// send indications up to Ndis.
	HANDLE hLink;

	// List used only by IsdnQueueTimer to keep track of links which need an
	// NdisMWanIndicateReceiveComplete indication sent up.
	LIST_ENTRY RxCompleteListEntry;

	// Required Tapi param.  Ignored, but passed back to Tapi on request.
	ULONG AppSpecific;

	// Bearer Mode current and mask requested in Tapi MakeCall request
	ULONG BearerModeMask;
	ULONG BearerMode;

	// Media Mode current and mask requested in Tapi MakeCall request
	ULONG MediaModeMask;
	ULONG MediaMode;

	// Min and Max rate from Tapi MakeCall request
	ULONG RateMin;
	ULONG RateMax;

	// Our own version of the connection speed, i.e. TollSaver (voice), Digital 56 or 64
	ISDN_CONN_TYPE ConnType;

	// WAN Get/Set Info baggage
	ULONG MaxSendFrameSize;
	ULONG MaxRecvFrameSize;
	ULONG HeaderPadding;
	ULONG TailPadding;
	ULONG SendFramingBits;
	ULONG RecvFramingBits;
	ULONG SendCompressionBits;
	ULONG RecvCompressionBits;
	ULONG SendACCM;
	ULONG RecvACCM;

	DIGI_SPINLOCK Lock;

	ISDN_RXENGINE RxEngine;

	struct 
	{
		ULONG  ChanIndex;
		ULONG  Channel;
	} Incoming;
	
} ISDN_CALL, *PISDN_CALL;


__inline NTSTATUS XnConnect( IN PISDN_ADAPTER  pAdapter,
                             IN PVOID          pOwner,
                             IN HANDLE         hStream,
                             IN ULONG          Snid,
                             IN ULONG          MaxFrameSize,
									  IN ULONG          ConnType,
                             IN PSTRING        pRemoteAddress )
{
	return pAdapter->XnDispatch.XnConnect( pOwner, hStream, Snid, MaxFrameSize, ConnType, pRemoteAddress );
}


__inline NTSTATUS XnConnack( IN PISDN_ADAPTER pAdapter,
                             IN PVOID         pOwner,
                             IN HANDLE        hStream,
                             IN ULONG         ChanIndex,
                             IN ULONG         Channel )
{
	return pAdapter->XnDispatch.XnConnack( pOwner, hStream, ChanIndex, Channel );
}


__inline NTSTATUS XnDisconn( IN PISDN_ADAPTER pAdapter,
                             IN PVOID         pOwner,
                             IN HANDLE        hStream,
                             IN ULONG         ChanIndex,
                             IN ULONG         Channel )
{
	return pAdapter->XnDispatch.XnDisconn( pOwner, hStream, ChanIndex, Channel );
}


__inline NTSTATUS XnConnend( IN PISDN_ADAPTER pAdapter,
                             IN PVOID         pOwner,
                             IN HANDLE        hStream,
                             IN ULONG         ChanIndex,
                             IN ULONG         Channel )
{
	return pAdapter->XnDispatch.XnConnend( pOwner, hStream, ChanIndex, Channel );
}


__inline NTSTATUS XnListen( IN PISDN_ADAPTER pAdapter,
                            IN PVOID         pOwner,
                            IN HANDLE        hStream,
                            IN ULONG         Snid )
{
	return pAdapter->XnDispatch.XnListen( pOwner, hStream, Snid );
}


__inline ULONG XnCbControl( IN PISDN_ADAPTER pAdapter )
{
	return pAdapter->XnDispatch.XnCbControl;
}

__inline PCSTR XnDeviceName( IN PISDN_ADAPTER pAdapter )
{
	return pAdapter->XnDispatch.XnDeviceName;
}


#include "isdncall.h"
#include "isdnlan.h"
#include "isdnlisten.h"
#include "isdnmp.h"
#include "isdnqueue.h"
#include "isdnrx.h"
#include "isdntapi.h"
#include "isdnv2.h"
#include "isdnv1.h"
#include "isdnwan.h"
#endif
