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

   digiasyn.h


Abstract:

	Serial (async) driver for DXB-based adapters, e.g. Houston or Hercules.  This 
	driver communicates with the S/DXB firmware module.

Author:

   Michael Zarns

--*/

#ifndef DIGIASYN_H
#define DIGIASYN_H

#define UNICODE
#include <ntddk.h>
#include <ntddser.h>                    // Serial port definitions.

// Standard defines required by firmware headers
#include "dxbtypes.h"

// firmware headers
#include "sdxb_prot.h"

#include "digilib.h"
#include "dsapi.h"
#include "dxbreg.h"
#include "asynlog.h"
#include "asynerror.h"
#include "asynrx.h"
#include "asynsdxb.h"

#include "isdn_proto.h"
#include "sdxbisdn.h"

typedef struct ASYN_WRITE *PASYN_WRITE;
typedef struct ASYN_SDXB *PASYN_SDXB;
typedef struct ASYN_PORT_EXT *PASYN_PORT_EXT;

#include "asyncreate.h"
#include "asyninit.h"
#include "asynioctl.h"
#include "asynpnp.h"
#include "asynread.h"
#include "asynrsp.h"
#include "asynwait.h"
#include "asynwrite.h"
#include "pnpmodem.h"
#include "digidga.h"

// Driver Global Data
extern PDRIVER_OBJECT gpDriverObject;
extern LIST_ENTRY     gDeviceExtList;
extern UNICODE_STRING gDriverRegPath;

// Default pool tag for ExAllocatePoolWithTag memory allocations
extern ULONG DefaultPoolTag;

// Debug flags
#define DIGIINIT			DEBUG_00000001
#define DIGIRXENGINE		DEBUG_00000002
#define DIGIFLOW			DEBUG_00000004
#define DIGIUNLOAD		DEBUG_00000008

#define DIGICREATE		DEBUG_00000010
#define DIGICLOSE			DEBUG_00000020
//#define DIGI			DEBUG_00000040
//#define DIGI			DEBUG_00000080

#define DIGISDXBRSP		DEBUG_00000100
//#define DIGI			DEBUG_00000200
//#define DIGI			DEBUG_00000400
//#define DIGI			DEBUG_00000800

#define DIGIPNP			DEBUG_00001000
#define DIGIPOWER			DEBUG_00002000
//#define DIGI			DEBUG_00004000
//#define DIGI			DEBUG_00008000

#define DIGIREAD			DEBUG_00010000
#define DIGIWRITE			DEBUG_00020000
#define DIGIIOCTL			DEBUG_00040000
#define DIGIWAIT			DEBUG_00080000

#define DIGITIMEOUT		DEBUG_00100000
#define DIGICANCEL		DEBUG_00200000
//#define DIGI			DEBUG_00400000
//#define DIGI			DEBUG_00800000

//#define DIGI			DEBUG_01000000
//#define DIGI			DEBUG_02000000
#define DIGIWARN		DEBUG_WARN
#define DIGIERROR		DEBUG_ERROR
#define DIGIBREAK		DEBUG_BREAK

#define					MILLISECOND  10000L

PDEVICE_OBJECT			GlobalDgaObject;


typedef enum 
{
	ASYN_TYPE_PORT_EXT = 0xAA000001,
	ASYN_TYPE_RXENGINE,
	ASYN_TYPE_ADAPTER_EXT,
	ASYN_TYPE_COUNT
} ASYN_OBJECT_TYPE;

/*
 * Port State variable State transition values.
 */
typedef enum
{
   IdleState = 0,
	OpenInProgressState,
	OpenState,
	CloseWaitTxDrainState,
	CloseInProgressState,
	CloseOnFinalSyncState,
   ShutdownState,
	OpenState_PowerD3,				// Device was open prior to request to transition to D3 power state
	OpeningState_PowerD3,			// Create IRP received while port was in D3 power state
	IdleState_PowerD3					// Device was idle prior to request to transition to D3 power state
} PORT_STATE;

typedef enum 
{
	PNPSTATE_OK				= 0x00,
	PNPSTATE_STOPPING		= 0x01,
	PNPSTATE_STOPPED 		= 0x02,
	PNPSTATE_REMOVING  	= 0x04,
	PNPSTATE_ADDED       = 0x08,
} ASYN_PNP_STATE;

typedef enum ASYN_POWER_STATE
{
  PWRSTATE_ON,            // power on, device in D0 state
  PWRSTATE_OFF_PENDING,   // power off operation is pending
  PWRSTATE_OFF,           // power off, device in D3 state
  PWRSTATE_OFF_IDLE,      // power off due to idle detection
} ASYN_POWER_STATE, *PASYN_POWER_STATE;

//
// S/DXB Defaults
//

// Adjust these defaults 
#define SDXB_RMAX_DEF           	128
#define SDXB_RTIME_DEF          	10        // MilliSeconds
#define SDXB_TMAX_DEF           	256
#define SDXB_TTIME_DEF          	256        // MilliSeconds
#define SDXB_ICDTIME_DEF			10

// Low latency defaults:
#define SDXB_RMAX_LOWLATENCY     1
#define SDXB_RTIME_LOWLATENCY    1         // MilliSeconds
#define SDXB_TMAX_LOWLATENCY     1
#define SDXB_TTIME_LOWLATENCY    1        // MilliSeconds
#define SDXB_ICDTIME_LOWLATENCY  1

#define SDXB_MAXLEN_DEF         	1024
#define ASYN_DEF_BAUDRATE  		9600
#define ASYN_DEF_XON       		0x11
#define ASYN_DEF_XOFF      		0x13

#define SDXB_LTIME_DEF         100            // Line Error Report time in mSec
#define SDXB_LTIME_OFF         0           // Line Error Report is off

typedef struct ASYN_SDXB
{
   //
   // Port Speed and Processing Flags
   //
	DIGI_SPINLOCK 	Lock;				  		// Spinlock to protect access 

	USHORT			SyncSeqNum;
	USHORT			SyncSeqAck;

	LIST_ENTRY    	PendingIrps;			// Queue of pending irps awaiting a SDXB sync response

	UCHAR				PortType;				// Reported in port capabilities response
	ULONG				PortCapabilities;		

	struct sdxb_param_command	
						PortParams;				// Structure used for SDXB port param requests 

   //
   // Event Reporting
   //
   USHORT      Estat;                  // Active Event conditions.

   //
   // Modem Control Variables
   //
   UCHAR       Mout;                   // Modem active signals.
	UCHAR			Mint;
   UCHAR       Mflow;                  // Modem flow control.
   UCHAR       Mctrl;                  // Modem flow control for out-of-band data.
   UCHAR       Mstat;                  // Current Modem status.

   //
   // Line Error Counters
   //
   USHORT      Ltime;                  // Line error report time (milliseconds)
   UCHAR       LerrFlags;              // SDXB_LERR flags
   ULONG       Norun;                  // Number of UART Overrun errors.
   ULONG       Noflow;                 // Number of buffer Overflow errors.
   ULONG       Nframe;                 // Number of Framing errors.
   ULONG       Nparity;                // Number of Parity errors.
   ULONG       Nbreak;                 // Number of Breaks received.

	ULONG			Rmax;							// Max inbound bytes in SDXB's buffer before data is sent to the host
	ULONG			Rtime;						// Receive trigger time
	ULONG			Icdtime;						// Max. inter-character delay

	ULONG			Tmax;							// Outbound trigger level of flow control
	ULONG			Ttime;						// Tout report time (msec)

   SERIAL_HANDFLOW  Handflow;          // Flow control.
	SERIALPERF_STATS PerfStats;
	
	ULONG			CommErr;					 	
					
	UCHAR			EofChar;						// Driver doesn't use, but keep for reporting
													//  on IOCTL_SERIAL_GET_CHARS request.

} ASYN_SDXB;

typedef struct WRITE_TIMER
{
	KTIMER			Timer;				// These are the varibles for the write time out 
	BOOLEAN			TimerOn;
	BOOLEAN			TimerInUse;
	KDPC			TimeOutDPC;
	LARGE_INTEGER	TimerLength;
	ULONG			TimeoutMultiplier;
	ULONG			TimeoutConstant;

} WRITE_TIMER;

typedef struct SEQUENCE
{
	ULONG			WaitTillDone;
	ULONG			CurrentCountOut;
	ULONG			CurrentCountIn;
	ULONG			CurrentCountReference;			// This is user based, when the user wants to clear the stats.
	LIST_ENTRY		WaitTillCompleteQueue;
	DIGI_SPINLOCK	WaitLock;
	KEVENT			FlushEvent;
	LIST_ENTRY		FlushList;
	KEVENT			EmptyEvent;
	KEVENT			CancelEvent;
	BOOLEAN			WaitFlushEvent;
	BOOLEAN			WaitEmptyEvent;
	KEVENT			ClearEvent;
	BOOLEAN			WaitForWrite;

}SEQUENCE;

typedef struct ASYN_WRITE
{
	DIGI_SPINLOCK	Lock;					// Protects fields only in this struct

	BOOLEAN			fQueuing;				// Queue single-byte writes when done enmass

	ULONG			cbMaxPutMsg;			// Max number bytes to send in single PutMsg
	LIST_ENTRY		PendingQueue;			// Irps queued to be sent, not processed yet
	LIST_ENTRY		ActiveQueue;			// Irps in use, probably pending in dxb.

    PVOID           pWorkerThread;          // Object for the write worker thread
    KEVENT          WorkEvent;
    KEVENT          HaltEvent;
    
	WRITE_TIMER		WriteTimer;	
	SEQUENCE		Sequence;

	PIRP			ActiveIrp;
	BOOLEAN			TimeoutActive;



} ASYN_WRITE;

typedef struct ASYN_CLOSE
{
	KDPC		        DPC;                  // Close Timeout DPC
	KTIMER   		  Timer;			         // Close Timer
	ULONG            TxDrainTimeout;	
	USHORT           SyncSeq;              // Expected sequence number on sync response
} ASYN_CLOSE;

typedef struct ASYN_ADAPTER_EXT *PASYN_ADAPTER_EXT;

typedef struct _TRACE_IOCTL
{
	LIST_ENTRY		TraceQueue;
	DIGI_SPINLOCK	TraceLock;
	KTIMER			TraceTimer;
	KDPC			TraceDpc;
	LARGE_INTEGER	Timeout;

}TRACE_IOCTL, *PTRACE_IOCTL;

typedef struct ASYN_PORT_EXT
{
	ASYN_OBJECT_TYPE	Type;						// ASYN_TYPE_PORT_EXT
	DIGI_SPINLOCK		Lock;						// Spinlock to protect access 
	LIST_ENTRY			ListEntry;					// Entry on adapter's Portlist (NT4.0) or gDeviceExtList (Win2k)

	PASYN_ADAPTER_EXT	pParentExt;					// Device Extension of parent device
						  	
	PORT_STATE			State;						// Opening, Open, Closing, Idle.
    PDEVICE_OBJECT		pDevice;					// The Device Object for this Port.

	UNICODE_STRING		PortName;
	UNICODE_STRING		DeviceName;			
	ULONG				iSdxbPort;
    HANDLE				DsHandle;					// Handle to DStreams service provider.
    HANDLE				DsPortHandle;				// Handle returned from DsOpen

	PIRP				pPendingIrp;				// Used during Create and Close

	ASYN_CLOSE			Close;						// Structure for close specific data	
	ASYN_SDXB			SdxbValues;	

	HANDLE				hRxEngine_HighPriority;		// Self-contained engine which posts GetMsgs to Dxb
	HANDLE				hRxEngine_LowPriority;	

	ASYN_RXENGINE		RxEngine[DS_PRIORITY_COUNT];	

	ASYN_READ			Read;						// Structure for Read specific variables
	ASYN_WRITE			Write;						// Serial write specific data
	ASYN_WAIT			Wait;						// Wait event data

	TRACE_IOCTL			Trace;

#if NT5_BUILD
	PDEVICE_OBJECT		pPdo;						// Physical Device object created by PCI bus enumerator
	PDEVICE_OBJECT		pNextDeviceObject;	// Could be different than Pdo if filter 
	ASYN_PNP_STATE		PnpState;				
    ASYN_POWER_STATE    PowerState;         // current power state
    DEVICE_POWER_STATE  DevPower;           // current device power state
    SYSTEM_POWER_STATE  SysPower;           // current system power state
    SYSTEM_POWER_STATE  WakeSysPower;       // wakeup system power state
	UNICODE_STRING		DxbDevice;

	UNICODE_STRING		DeviceInterfaceSymbolicName; 
														// String returned by PnP manager when device is registered under comm class.
	ULONG					DeviceStateFlags;		// Used to respond to IRP_MN_QUERY_DEVICE_STATE 							

#endif

	// Used for Pnp Modem Detection.
	// TRUE signals that this port is actually a modem on an HLC adapter.
	// FALSE signals that it is a traditional serial port (i.e. AccelePort Xp )
	ULONG		        IsModem;
	HANDLE			    PnpModemDetectHandle;
	ULONG				AltPin;
	ULONG					fLowLatency;

} ASYN_PORT_EXT;


typedef struct ASYN_ADAPTER_EXT
{
	ASYN_OBJECT_TYPE 	Type;						// ASYN_TYPE_ADAPTER_EXT
   DIGI_SPINLOCK  	Lock;	               // Covers all structures.
   HANDLE      		DsHandle;            // Handle to DStreams service provider.
	LIST_ENTRY       	ListEntry;				// Entry on gDeviceExtList

   PDEVICE_OBJECT		pDevice;					// The Device Object for this Adapter.

	UNICODE_STRING    InstanceName;			// Adapter instance name. NT4.0: DigiDxb#	
   LIST_ENTRY  		PortList;            // List of Ports on this adapter

} ASYN_ADAPTER_EXT;


VOID  AsynIoCompleteRequest(		IN PIRP				pIrp,
										IN NTSTATUS			Status,
										IN PASYN_PORT_EXT	pPortExt );


// Function for DGA Requests.

NTSTATUS		DigiDgaIoctl(			PDEVICE_OBJECT		DeviceObject,
										PIRP				Irp );

NTSTATUS		GetControllerData(		PDEVICE_OBJECT		DeviceObject,
										PIRP				Irp );

NTSTATUS		GetPortStatus(			PDEVICE_OBJECT		DeviceObject,
										PIRP				Irp );

PDEVICE_OBJECT	GetPortDeviceObject(	PDRIVER_OBJECT		DriverObject,
									    ULONG				ComPort);

void			AsynTraceWriteIrp(		PASYN_PORT_EXT		pPortExt,
										PIRP				pIrp );

void			AsynTraceIoctlIrp(		PASYN_PORT_EXT		pPortExt,
										PIRP				pIrp,
										BOOLEAN				In,
										BOOLEAN				Out);

void			AsynTraceReadIrp(		PASYN_PORT_EXT		pPortExt,
										PIRP				pIrp);

void			AsynTraceTimeout(		IN PKDPC			Dpc,
										IN PVOID			DeferredContext,
										IN PVOID			SystemContext1,
										IN PVOID			SystemContext2  );

void			AsynGetDeviceStatus(	PASYN_PORT_EXT		pPortExt,
										PPORT_STATUS		pPortStatus );

VOID			AsynDeleteGlobalCardExt();


STATIC __inline BOOLEAN
RemoveIrpFromQueue( 
	IN PLIST_ENTRY	pIrpQ, 	
   IN PIRP		  	pIrp
)
/*++

Description

	Called to remove the specified irp from the queue.
   
--*/
{   	
   PLIST_ENTRY ListEntry;
   BOOLEAN fIrpRemoved = FALSE;
   
   // Look for this Irp on the queue.
   for ( ListEntry = pIrpQ->Flink;
			ListEntry != pIrpQ; 
			ListEntry = ListEntry->Flink)
   {
      if ( pIrp == CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry ))
      {
         // Found it.
         RemoveEntryList( &pIrp->Tail.Overlay.ListEntry );
         fIrpRemoved = TRUE;
         break;
      }
   }
   return fIrpRemoved;
}

#include "asynpower.h"

#endif

