From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/digi/digifile/dgatlas.c | 108 ++ private/ntos/ndis/digi/digifile/dgatlas.h | 194 ++ private/ntos/ndis/digi/digifile/digifile.c | 637 +++++++ private/ntos/ndis/digi/digifile/digifile.h | 105 ++ private/ntos/ndis/digi/digifile/makefile | 7 + private/ntos/ndis/digi/digifile/makefile.inc | 15 + private/ntos/ndis/digi/digifile/memprint.c | 922 ++++++++++ private/ntos/ndis/digi/digifile/memprint.h | 73 + private/ntos/ndis/digi/digifile/sources | 47 + private/ntos/ndis/digi/dirs | 27 + private/ntos/ndis/digi/images/adp.bin | Bin 0 -> 59288 bytes private/ntos/ndis/digi/images/idp_xfs.bin | Bin 0 -> 131072 bytes private/ntos/ndis/digi/pcimac/adapter.h | 223 +++ private/ntos/ndis/digi/pcimac/ansihelp.c | 487 +++++ private/ntos/ndis/digi/pcimac/ansihelp.h | 109 ++ private/ntos/ndis/digi/pcimac/cm.h | 162 ++ private/ntos/ndis/digi/pcimac/cm_chan.c | 106 ++ private/ntos/ndis/digi/pcimac/cm_conn.c | 323 ++++ private/ntos/ndis/digi/pcimac/cm_init.c | 488 +++++ private/ntos/ndis/digi/pcimac/cm_prof.c | 51 + private/ntos/ndis/digi/pcimac/cm_pub.h | 134 ++ private/ntos/ndis/digi/pcimac/cm_q931.c | 943 ++++++++++ private/ntos/ndis/digi/pcimac/cm_stat.c | 31 + private/ntos/ndis/digi/pcimac/cm_state.c | 757 ++++++++ private/ntos/ndis/digi/pcimac/cm_timer.c | 78 + private/ntos/ndis/digi/pcimac/cnf.h | 13 + private/ntos/ndis/digi/pcimac/dgbrip.h | 33 + private/ntos/ndis/digi/pcimac/disp.c | 105 ++ private/ntos/ndis/digi/pcimac/disp.h | 147 ++ private/ntos/ndis/digi/pcimac/event.h | 31 + private/ntos/ndis/digi/pcimac/frame.h | 196 ++ private/ntos/ndis/digi/pcimac/idd.h | 440 +++++ private/ntos/ndis/digi/pcimac/idd_init.c | 894 +++++++++ private/ntos/ndis/digi/pcimac/idd_io.c | 672 +++++++ private/ntos/ndis/digi/pcimac/idd_msg.c | 168 ++ private/ntos/ndis/digi/pcimac/idd_nv.c | 140 ++ private/ntos/ndis/digi/pcimac/idd_proc.c | 988 ++++++++++ private/ntos/ndis/digi/pcimac/idd_pub.h | 59 + private/ntos/ndis/digi/pcimac/idd_run.c | 868 +++++++++ private/ntos/ndis/digi/pcimac/io.h | 27 + private/ntos/ndis/digi/pcimac/io_core.c | 435 +++++ private/ntos/ndis/digi/pcimac/io_pub.h | 153 ++ private/ntos/ndis/digi/pcimac/lanoid.c | 240 +++ private/ntos/ndis/digi/pcimac/makefile | 6 + private/ntos/ndis/digi/pcimac/mtl.h | 306 ++++ private/ntos/ndis/digi/pcimac/mtl_init.c | 195 ++ private/ntos/ndis/digi/pcimac/mtl_rx.c | 840 +++++++++ private/ntos/ndis/digi/pcimac/mtl_set.c | 228 +++ private/ntos/ndis/digi/pcimac/mtl_tick.c | 47 + private/ntos/ndis/digi/pcimac/mtl_tx.c | 1092 +++++++++++ private/ntos/ndis/digi/pcimac/mydefs.h | 376 ++++ private/ntos/ndis/digi/pcimac/mytypes.h | 39 + private/ntos/ndis/digi/pcimac/opcodes.h | 152 ++ private/ntos/ndis/digi/pcimac/pcimac.c | 2385 ++++++++++++++++++++++++ private/ntos/ndis/digi/pcimac/pcimac.rc | 28 + private/ntos/ndis/digi/pcimac/res.h | 52 + private/ntos/ndis/digi/pcimac/res_core.c | 261 +++ private/ntos/ndis/digi/pcimac/sema.h | 8 + private/ntos/ndis/digi/pcimac/sources | 74 + private/ntos/ndis/digi/pcimac/tapioid.c | 2535 ++++++++++++++++++++++++++ private/ntos/ndis/digi/pcimac/tapioid.h | 440 +++++ private/ntos/ndis/digi/pcimac/trc.h | 71 + private/ntos/ndis/digi/pcimac/trc_core.c | 357 ++++ private/ntos/ndis/digi/pcimac/trc_pub.h | 49 + private/ntos/ndis/digi/pcimac/util.c | 146 ++ private/ntos/ndis/digi/pcimac/util.h | 27 + private/ntos/ndis/digi/pcimac/wan_conn.c | 122 ++ private/ntos/ndis/digi/pcimac/wanoid.c | 226 +++ 68 files changed, 21698 insertions(+) create mode 100644 private/ntos/ndis/digi/digifile/dgatlas.c create mode 100644 private/ntos/ndis/digi/digifile/dgatlas.h create mode 100644 private/ntos/ndis/digi/digifile/digifile.c create mode 100644 private/ntos/ndis/digi/digifile/digifile.h create mode 100644 private/ntos/ndis/digi/digifile/makefile create mode 100644 private/ntos/ndis/digi/digifile/makefile.inc create mode 100644 private/ntos/ndis/digi/digifile/memprint.c create mode 100644 private/ntos/ndis/digi/digifile/memprint.h create mode 100644 private/ntos/ndis/digi/digifile/sources create mode 100644 private/ntos/ndis/digi/dirs create mode 100644 private/ntos/ndis/digi/images/adp.bin create mode 100644 private/ntos/ndis/digi/images/idp_xfs.bin create mode 100644 private/ntos/ndis/digi/pcimac/adapter.h create mode 100644 private/ntos/ndis/digi/pcimac/ansihelp.c create mode 100644 private/ntos/ndis/digi/pcimac/ansihelp.h create mode 100644 private/ntos/ndis/digi/pcimac/cm.h create mode 100644 private/ntos/ndis/digi/pcimac/cm_chan.c create mode 100644 private/ntos/ndis/digi/pcimac/cm_conn.c create mode 100644 private/ntos/ndis/digi/pcimac/cm_init.c create mode 100644 private/ntos/ndis/digi/pcimac/cm_prof.c create mode 100644 private/ntos/ndis/digi/pcimac/cm_pub.h create mode 100644 private/ntos/ndis/digi/pcimac/cm_q931.c create mode 100644 private/ntos/ndis/digi/pcimac/cm_stat.c create mode 100644 private/ntos/ndis/digi/pcimac/cm_state.c create mode 100644 private/ntos/ndis/digi/pcimac/cm_timer.c create mode 100644 private/ntos/ndis/digi/pcimac/cnf.h create mode 100644 private/ntos/ndis/digi/pcimac/dgbrip.h create mode 100644 private/ntos/ndis/digi/pcimac/disp.c create mode 100644 private/ntos/ndis/digi/pcimac/disp.h create mode 100644 private/ntos/ndis/digi/pcimac/event.h create mode 100644 private/ntos/ndis/digi/pcimac/frame.h create mode 100644 private/ntos/ndis/digi/pcimac/idd.h create mode 100644 private/ntos/ndis/digi/pcimac/idd_init.c create mode 100644 private/ntos/ndis/digi/pcimac/idd_io.c create mode 100644 private/ntos/ndis/digi/pcimac/idd_msg.c create mode 100644 private/ntos/ndis/digi/pcimac/idd_nv.c create mode 100644 private/ntos/ndis/digi/pcimac/idd_proc.c create mode 100644 private/ntos/ndis/digi/pcimac/idd_pub.h create mode 100644 private/ntos/ndis/digi/pcimac/idd_run.c create mode 100644 private/ntos/ndis/digi/pcimac/io.h create mode 100644 private/ntos/ndis/digi/pcimac/io_core.c create mode 100644 private/ntos/ndis/digi/pcimac/io_pub.h create mode 100644 private/ntos/ndis/digi/pcimac/lanoid.c create mode 100644 private/ntos/ndis/digi/pcimac/makefile create mode 100644 private/ntos/ndis/digi/pcimac/mtl.h create mode 100644 private/ntos/ndis/digi/pcimac/mtl_init.c create mode 100644 private/ntos/ndis/digi/pcimac/mtl_rx.c create mode 100644 private/ntos/ndis/digi/pcimac/mtl_set.c create mode 100644 private/ntos/ndis/digi/pcimac/mtl_tick.c create mode 100644 private/ntos/ndis/digi/pcimac/mtl_tx.c create mode 100644 private/ntos/ndis/digi/pcimac/mydefs.h create mode 100644 private/ntos/ndis/digi/pcimac/mytypes.h create mode 100644 private/ntos/ndis/digi/pcimac/opcodes.h create mode 100644 private/ntos/ndis/digi/pcimac/pcimac.c create mode 100644 private/ntos/ndis/digi/pcimac/pcimac.rc create mode 100644 private/ntos/ndis/digi/pcimac/res.h create mode 100644 private/ntos/ndis/digi/pcimac/res_core.c create mode 100644 private/ntos/ndis/digi/pcimac/sema.h create mode 100644 private/ntos/ndis/digi/pcimac/sources create mode 100644 private/ntos/ndis/digi/pcimac/tapioid.c create mode 100644 private/ntos/ndis/digi/pcimac/tapioid.h create mode 100644 private/ntos/ndis/digi/pcimac/trc.h create mode 100644 private/ntos/ndis/digi/pcimac/trc_core.c create mode 100644 private/ntos/ndis/digi/pcimac/trc_pub.h create mode 100644 private/ntos/ndis/digi/pcimac/util.c create mode 100644 private/ntos/ndis/digi/pcimac/util.h create mode 100644 private/ntos/ndis/digi/pcimac/wan_conn.c create mode 100644 private/ntos/ndis/digi/pcimac/wanoid.c (limited to 'private/ntos/ndis/digi') diff --git a/private/ntos/ndis/digi/digifile/dgatlas.c b/private/ntos/ndis/digi/digifile/dgatlas.c new file mode 100644 index 000000000..2d846926c --- /dev/null +++ b/private/ntos/ndis/digi/digifile/dgatlas.c @@ -0,0 +1,108 @@ +/*++ + +***************************************************************************** +* * +* 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. * +* * +***************************************************************************** + +Module Name: + + dgatlas.c + +Abstract: + + This module is responsible for Atlas functionality common to all + drivers. + +--*/ + +#include + + +NTSTATUS DigiRegisterAtlasName( IN PUNICODE_STRING DeviceName, + IN PUNICODE_STRING ValueName, + IN PUNICODE_STRING ValueEntry ) +/*++ + +Routine Description: + + This routine will register the passed in value name and its associated + value for Atlas to find. In addition, we will create a symbolic + link to a name which is accessible for Atlas to open and exchange + information. + +Arguments: + + DeviceName - pointer to unicode string to use when creating a + symbolic link. It is assumed this device name is all ready + created and ready to have symbolic links created. + + ValueName - pointer to unicode string to be used as the registry + value name. + + Value - pointer to unicode string to be used as the value associated + with ValueName. + +Return Value: + + - STATUS_SUCCESS if successful + + - Error indicating problem + +--*/ +{ +#define DEFAULT_DIGI_ATLAS_DEVICEMAP L"DigiAtlas" + NTSTATUS Status; + UNICODE_STRING LinkName; + WCHAR LinkNameBuffer[32]; + + // + // First, we create the required link symbolic name from the passed + // in value name. + // + RtlInitUnicodeString( &LinkName, NULL ); + LinkName.Buffer = &LinkNameBuffer[0]; + LinkName.MaximumLength = sizeof(LinkNameBuffer); + LinkName.Length = 0; + + RtlAppendUnicodeToString( &LinkName, L"\\DosDevices\\" ); + RtlAppendUnicodeStringToString( &LinkName, ValueEntry ); + + // + // Create the symbolic link first. + // + + Status = IoCreateSymbolicLink( &LinkName, + DeviceName ); + + if( NT_ERROR(Status) ) + return( Status ); + + // + // We need to add a \\.\ to the beginning of ValueEntry. + // + LinkName.Length = 0; + RtlZeroMemory( LinkName.Buffer, LinkName.MaximumLength ); + RtlAppendUnicodeToString( &LinkName, L"\\\\.\\" ); + RtlAppendUnicodeStringToString( &LinkName, ValueEntry ); + + Status = RtlWriteRegistryValue( RTL_REGISTRY_DEVICEMAP, + DEFAULT_DIGI_ATLAS_DEVICEMAP, + ValueName->Buffer, + REG_SZ, + LinkName.Buffer, + LinkName.Length + sizeof(WCHAR) ); + + return( Status ); + +} // end DigiRegisterAtlasName diff --git a/private/ntos/ndis/digi/digifile/dgatlas.h b/private/ntos/ndis/digi/digifile/dgatlas.h new file mode 100644 index 000000000..1899ca354 --- /dev/null +++ b/private/ntos/ndis/digi/digifile/dgatlas.h @@ -0,0 +1,194 @@ +#ifndef DGATLAS_H +#define DGATLAS_H + +/*++ +***************************************************************************** +* * +* 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. * +* * +***************************************************************************** +++*/ + + +/////////////////////////////////////// Agent/Driver Commands section + +#pragma pack(4) + +#define MAX_DESCLEN 128 +#define GLOBAL_ATLAS_STRUCTURE_VERSION 1 + +#define DIGI_PERSONALITY_FR ((DWORD)' RF') // Frame Relay +#define DIGI_PERSONALITY_X25 ((DWORD)' 52X') // X.25 +#define DIGI_PERSONALITY_PRI ((DWORD)' IRP') // ISDN PRI +#define DIGI_PERSONALITY_BRI ((DWORD)' IRB') // ISDN BRI + +#define DIGI_ATLAS_IOCTL CTL_CODE(FILE_DEVICE_PARALLEL_PORT, 3072, METHOD_BUFFERED, FILE_ANY_ACCESS) + +typedef struct _DIGI_PERSONALITY_ +{ + DWORD dwVersion; + DWORD dwPersonalityTag; + DWORD dwId; // passed back by driver to uniquely + // id this adapter. + char szDesc[MAX_DESCLEN]; +} DIGI_PERSONALITY, *PDIGI_PERSONALITY; + +typedef enum _MAX_PERSONALITIES_ { MaxPersonalitiesPerAdapter = 4 } MAX_PERSONALITIES; + +//// payload for EnumAdapters command (was _DIGI_Personality_) +// +typedef struct _DIGI_ADAPTER_ +{ + DWORD dwVersion; + DWORD dwMemoryAddress; + DWORD dwMemoryRange; + + DWORD dwIOAddress; + DWORD dwIORange; + + DWORD dwInterruptNumber; // bitmask indicating which interrupt(s) are + // in use by this adapter instance. + + DWORD dwDMA; // bitmask indicating which DMA channels are + // in use by this adapter instance. + + DWORD dwPersonalities; // number of personality structs that follow + DIGI_PERSONALITY Personalities[MaxPersonalitiesPerAdapter]; +} DIGI_ADAPTER, *PDIGI_ADAPTER; + +typedef enum _MAX_ADAPTERS_ { MaxAdaptersInSystem = 8 } MAX_ADAPTERS; + +typedef struct _DIGI_SYSTEM_ +{ + DWORD dwVersion; + DWORD dwAdapters; // number of adapter structs that follow + DIGI_ADAPTER Adapters[MaxAdaptersInSystem]; +} DIGI_SYSTEM, *PDIGI_SYSTEM; + + +//////////////////////////////////////////////// Personality/Driver Section +// +// Internal Digi Command IDS; 0-1023 are agent/device driver +// 1024-8191 are personality/device driver + +typedef enum _DIGI_ATLAS_COMMAND_ +{ + EnumAdapters, // pdu = DIGI_ADAPTER + LastGeneralID = 1023 +} DIGI_ATLAS_COMMAND; + + + ///////////////////////// Header of payload in AS_Msg +// +typedef struct _ATLAS_PDU_HEADER_ +{ + DWORD dwHeaderSize; // offset to payload Buffer + DWORD dwPayloadSize; // size (in bytes) of Buffer following this header + DWORD dwVersion; // version of this PDU + DWORD dwFlags; // reserved for future use + DWORD dwCommand; // a value of type DIGI_ATLAS_COMMAND + DWORD dwAdapter; // identifies adapter to which command is targeted + DWORD dwClientContext; // reserved for client use + DWORD dwServerContext; // reserved for server use +} ATLAS_PDU_HEADER, *PATLAS_PDU_HEADER; + +///////////////////////// Macro to access header and payload of a buffer +// containing an Atlas command +// +#define GET_HEADER(X) ((ATLAS_PDU_HEADER*)X) +#define GET_PAYLOAD(X) ((BYTE*)((BYTE*)X+((ATLAS_PDU_HEADER*)X)->dwHeaderSize)) + +// +// MEMBERS +// +// dwHeaderSize is used to size the header independently from the size of +// the payload. This assures that entities will always be able to find +// the start of the buffer regardless of additional header fields that +// might be added in the future. +// +// dwPayloadSize indicates the length of the payload beyond this header, +// which follows immediately after the header. +// +// dwVersion is the version of the Atlas Agent to which the command is +// addressed. The client sending this command should use this as a hint +// of the oldest version of the agent capable of interpreting this command. +// The agent will return its version in the reply. +// +// Flags is reserved for future use and should be set to 0. +// +// dwCommand indicates the opcode of this command. Opcodes 0-1023 are +// reserved for commands in which the agent is an active participant. They +// are generic in the sense that they either are client/agent commands +// only or apply to all personalities/device drivers. See the enum, +// DIGI_ATLAS_COMMAND, for a list of currently supported opcodes in the +// range 0-1023. Opcodes 1024-8191 are personality specific and thus +// fall outside the scope of this header. +// +// dwAdapter identifies which adapter is the receiver of this command. +// This field is currently unused. The intent was to provide an unused +// header member should it become necessary to address adapters at +// the command protocol level rather than as part of an internal struct +// embedded in the payload. +// +// dwClientContext is a variable for exclusive use by the client sending +// this command. Any server, including the agent, promises both that +// it will ignore it and not alter it in subsequent replies. +// +// dwServerContext is a variable for exclusive use by the server replying +// to this command. Subsequent commands sent as part of the same +// transaction must preserve this value. +// +// REMARKS +// +// 1. An Atlas command pdu consists is a buffer the first part, the header, +// of which is formated according to the ATLAS_PDU_HEADER above and +// whose second part, the payload, is specified by the protocol between +// some personality and its associated driver. The payload may be +// accessed by using the macro defined above: +// +// // packing a buffer +// +// extern ATLAS_PDU_HEADER header; +// extern Payload myPayload; +// +// header.HeaderSize = sizeof(ATLAS_PDU_HEADER); +// header.PayloadSize = sizeof(Payload); +// +// BYTE* buffer = new BYTE [header.HeaderSize+header.PayloadSize]; +// memcpy(buffer, &header, header.HeaderSize); +// memcpy(GET_PAYLOAD(buffer), &myPayload, header.PayloadSize); +// +// // unpacking a buffer +// +// memcpy(&header, GetHeader(buffer), GetHeader(buffer)->HeaderSize); +// memcpy(&payload, GetPayload(buffer), GetHeader(buffer)->PayloadSize); +// +// Note that argument to either macro is any kind of pointer. +// +// 2. You add new members to ATLAS_PDU_HEADER with the following restrictions: +// +// 2.1 They must be added to the end of the current version +// 2.2 All instances of the new struct must set the Version member +// to a value > then the current version. +// 2.3 The new member must be a DWORD or a type whose size is a +// multiple of the size of a DWORD. +// +// 3. New versions of ATLAS_PDU_HEADER must not remove members from +// previous versions. +// + + +#pragma pack() + +#endif + + diff --git a/private/ntos/ndis/digi/digifile/digifile.c b/private/ntos/ndis/digi/digifile/digifile.c new file mode 100644 index 000000000..edf8dba75 --- /dev/null +++ b/private/ntos/ndis/digi/digifile/digifile.c @@ -0,0 +1,637 @@ +/*++ + +--*/ + +#include +#include +#include // Include to determine what version of NT + +// +// This is a fix for changes in DDK releases. +// +#ifdef VER_PRODUCTBUILD +#define rmm VER_PRODUCTBUILD +#endif + +#include "digifile.h" +#include "memprint.h" + +#ifdef ALLOC_PRAGMA + +#if rmm > 528 +#pragma message( "\n\\\\\n\\\\ Including PAGED CODE\n\\\\ \n" ) +#pragma alloc_text( PAGEDIGIFILE, DigiOpenFile ) +#pragma alloc_text( PAGEDIGIFILE, DigiCloseFile ) +#pragma alloc_text( PAGEDIGIFILE, DigiMapFile ) +#pragma alloc_text( PAGEDIGIFILE, DigiUnmapFile ) +#endif + +#endif + +VOID DigiCheckMem( VOID ); + +#if 0 +#define DigiCheckMem() \ +{ \ + PLIST_ENTRY _DigiQueue; \ + KIRQL _OldIrql, _CurrentIrql; \ + \ + _CurrentIrql = KeGetCurrentIrql(); \ + \ + _DigiQueue = &GlobalNonPagedMemQueue; \ + \ + KeAcquireSpinLock( &GlobalMemSpinLock, &_OldIrql ); \ + \ + while( _DigiQueue->Flink != &GlobalNonPagedMemQueue ) \ + { \ + PDIGI_MEM_DESCRIPTOR _MemDesc; \ + PUCHAR _Buf; \ + \ + _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, \ + DIGI_MEM_DESCRIPTOR, \ + ListEntry ); \ + \ + _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); \ + if( (_MemDesc->BeginTag != (ULONG)'lkir') || \ + (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) \ + { \ + DbgPrint( "DigiCheckMem corruption found (0x%x)!\n", _MemDesc ); \ + DbgBreakPoint(); \ + break; \ + } \ + \ + _DigiQueue = _DigiQueue->Flink; \ + } \ + \ + if( _CurrentIrql < DISPATCH_LEVEL ) \ + { \ + _DigiQueue = &GlobalPagedMemQueue; \ + while( _DigiQueue->Flink != &GlobalPagedMemQueue ) \ + { \ + PDIGI_MEM_DESCRIPTOR _MemDesc; \ + PUCHAR _Buf; \ + \ + _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, \ + DIGI_MEM_DESCRIPTOR, \ + ListEntry ); \ + \ + _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); \ + if( (_MemDesc->BeginTag != (ULONG)'lkir') || \ + (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) \ + { \ + DbgPrint( "DigiCheckMem corruption found (0x%x)!\n", _MemDesc ); \ + DbgBreakPoint(); \ + break; \ + } \ + \ + _DigiQueue = _DigiQueue->Flink; \ + } \ + } \ + \ + KeReleaseSpinLock( &GlobalMemSpinLock, _OldIrql ); \ +} +#endif + +// +// Describes an open DIGI file +// + +typedef struct _DIGI_FILE_DESCRIPTOR +{ + HANDLE NtFileHandle; + PVOID Data; + KSPIN_LOCK Lock; + BOOLEAN Mapped; +} DIGI_FILE_DESCRIPTOR, *PDIGI_FILE_DESCRIPTOR; + + +typedef struct _DIGI_MEM_DESCRIPTOR_ +{ + ULONG BeginTag; + ULONG Length; + LIST_ENTRY ListEntry; +} DIGI_MEM_DESCRIPTOR, *PDIGI_MEM_DESCRIPTOR; + +// +// Global Data +// +ULONG TotalMemAllocated=0L; +ULONG DefaultPoolTag=(ULONG)('igiD'); +LIST_ENTRY GlobalPagedMemQueue={&GlobalPagedMemQueue,&GlobalPagedMemQueue}; +LIST_ENTRY GlobalNonPagedMemQueue={&GlobalNonPagedMemQueue,&GlobalNonPagedMemQueue}; +KSPIN_LOCK GlobalMemSpinLock; + + +VOID DigiOpenFile( OUT PNTSTATUS Status, + OUT PHANDLE FileHandle, + OUT PULONG FileLength, + IN PUNICODE_STRING FileName, + IN PHYSICAL_ADDRESS HighestAcceptableAddress ) +/*++ + +Routine Description: + + This routine opens a file for future mapping and reads its contents + into allocated memory. + +Arguments: + + Status - The status of the operation + + FileHandle - A handle to be associated with this open + + FileLength - Returns the length of the file + + FileName - The name of the file + + HighestAcceptableAddress - The highest physical address at which + the memory for the file can be allocated. + +Return Value: + + None. + +--*/ +{ + NTSTATUS NtStatus; + IO_STATUS_BLOCK IoStatus; + HANDLE NtFileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG LengthOfFile; + WCHAR PathPrefix[] = L"\\SystemRoot\\system32\\drivers\\"; + UNICODE_STRING FullFileName; + ULONG FullFileNameLength; + PDIGI_FILE_DESCRIPTOR FileDescriptor; + PVOID FileImage; + + // + // This structure represents the data from the + // NtQueryInformationFile API with an information + // class of FileStandardInformation. + // + + FILE_STANDARD_INFORMATION StandardInfo; + + // + // Insert the correct path prefix. + // + + FullFileNameLength = sizeof(PathPrefix) + FileName->MaximumLength; + + FullFileName.Buffer = DigiAllocMem( NonPagedPool, + FullFileNameLength ); + + if (FullFileName.Buffer == NULL) { + *Status = STATUS_INSUFFICIENT_RESOURCES; + return; + } + + FullFileName.Length = sizeof (PathPrefix) - sizeof(WCHAR); + FullFileName.MaximumLength = (USHORT)FullFileNameLength; + RtlMoveMemory (FullFileName.Buffer, PathPrefix, sizeof(PathPrefix)); + + RtlAppendUnicodeStringToString (&FullFileName, FileName); + +#if DBG + DbgPrint ("DIGIFILE: Attempting to open %wZ\n", &FullFileName); +#endif + + InitializeObjectAttributes ( &ObjectAttributes, + &FullFileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + NtStatus = ZwCreateFile( &NtFileHandle, + SYNCHRONIZE | FILE_READ_DATA, + &ObjectAttributes, + &IoStatus, + NULL, // alloc size = none + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, // eabuffer + 0 ); // ealength + + if( !NT_SUCCESS(NtStatus) ) + { +#if DBG + DbgPrint ("Error opening file %x\n", NtStatus); +#endif + DigiFreeMem( FullFileName.Buffer ); + *Status = DIGI_STATUS_FILE_NOT_FOUND; + return; + } + + DigiFreeMem( FullFileName.Buffer ); + + // + // Query the object to determine its length. + // + + NtStatus = ZwQueryInformationFile( NtFileHandle, + &IoStatus, + &StandardInfo, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation ); + + if (!NT_SUCCESS(NtStatus)) { +#if DBG + DbgPrint ("Error querying info on file %x\n", NtStatus); +#endif + ZwClose( NtFileHandle ); + *Status = NtStatus; + return; + } + + LengthOfFile = StandardInfo.EndOfFile.LowPart; + +#if DBG + DbgPrint ("File length is %d\n", LengthOfFile); +#endif + + // + // Might be corrupted. + // + + if( LengthOfFile < 1 ) + { +#if DBG + DbgPrint ("Bad file length %d\n", LengthOfFile); +#endif + ZwClose( NtFileHandle ); + *Status = DIGI_STATUS_ERROR_READING_FILE; + return; + } + + // + // Allocate buffer for this file + // + + FileImage = DigiAllocMem( NonPagedPool, + LengthOfFile ); + + if( FileImage == NULL ) + { +#if DBG + DbgPrint ("Could not allocate buffer\n"); +#endif + ZwClose( NtFileHandle ); + *Status = DIGI_STATUS_ERROR_READING_FILE; + return; + } + + // + // Read the file into our buffer. + // + + NtStatus = ZwReadFile( NtFileHandle, + NULL, + NULL, + NULL, + &IoStatus, + FileImage, + LengthOfFile, + NULL, + NULL ); + + ZwClose( NtFileHandle ); + + if( (!NT_SUCCESS(NtStatus)) || (IoStatus.Information != LengthOfFile) ) + { +#if DBG + DbgPrint ("error reading file %x\n", NtStatus); +#endif + *Status = DIGI_STATUS_ERROR_READING_FILE; + DigiFreeMem( FileImage ); + return; + } + + // + // Allocate a structure to describe the file. + // + + FileDescriptor = DigiAllocMem( NonPagedPool, + sizeof(DIGI_FILE_DESCRIPTOR) ); + + if( FileDescriptor == NULL ) + { + *Status = STATUS_INSUFFICIENT_RESOURCES; + DigiFreeMem( FileImage ); + return; + } + + + FileDescriptor->NtFileHandle = NtFileHandle; + FileDescriptor->Data = FileImage; + KeInitializeSpinLock( &FileDescriptor->Lock ); + FileDescriptor->Mapped = FALSE; + + *FileHandle = (HANDLE)FileDescriptor; + *FileLength = LengthOfFile; + *Status = STATUS_SUCCESS; +} + + +VOID DigiCloseFile( IN HANDLE FileHandle ) +/*++ + +Routine Description: + + This routine closes a file previously opened with DigiOpenFile. + The file is unmapped if needed and the memory is freed. + +Arguments: + + FileHandle - The handle returned by DigiOpenFile + +Return Value: + + None. + +--*/ +{ + PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle; + + DigiFreeMem( FileDescriptor->Data ); + DigiFreeMem( FileDescriptor ); +} + + + +VOID DigiMapFile( OUT PNTSTATUS Status, + OUT PVOID * MappedBuffer, + IN HANDLE FileHandle ) +/*++ + +Routine Description: + + This routine maps an open file, so that the contents can be accessed. + Files can only have one active mapping at any time. + +Arguments: + + Status - The status of the operation + + MappedBuffer - Returns the virtual address of the mapping. + + FileHandle - The handle returned by DigiOpenFile. + +Return Value: + + None. + +--*/ +{ + PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle; + KIRQL oldirql; + + KeAcquireSpinLock (&FileDescriptor->Lock, &oldirql); + + if (FileDescriptor->Mapped == TRUE) { + *Status = DIGI_STATUS_ALREADY_MAPPED; + KeReleaseSpinLock (&FileDescriptor->Lock, oldirql); + return; + } + + FileDescriptor->Mapped = TRUE; + KeReleaseSpinLock (&FileDescriptor->Lock, oldirql); + + *MappedBuffer = FileDescriptor->Data; + *Status = STATUS_SUCCESS; +} + + +VOID DigiUnmapFile( IN HANDLE FileHandle ) +/*++ + +Routine Description: + + This routine unmaps a file previously mapped with DigiOpenFile. + The file is unmapped if needed and the memory is freed. + +Arguments: + + FileHandle - The handle returned by DigiOpenFile + +Return Value: + + None. + +--*/ +{ + PDIGI_FILE_DESCRIPTOR FileDescriptor = (PDIGI_FILE_DESCRIPTOR)FileHandle; + KIRQL oldirql; + + KeAcquireSpinLock (&FileDescriptor->Lock, &oldirql); + FileDescriptor->Mapped = FALSE; + KeReleaseSpinLock (&FileDescriptor->Lock, oldirql); +} + + + +PVOID DigiInitMem( IN ULONG PoolTag ) +/*++ + +Routine Description: + +Arguments: + + PoolTag - Tag to use when allocating memory. + +Return Value: + + None. + +--*/ +{ + + DefaultPoolTag = PoolTag; + InitializeListHead( &GlobalPagedMemQueue ); + InitializeListHead( &GlobalNonPagedMemQueue ); + KeInitializeSpinLock( &GlobalMemSpinLock ); + + return( NULL ); +} // end DigiInitMem + + + +#if DBG || DIGICHECKMEM + +PVOID DigiAllocMem( IN POOL_TYPE PoolType, IN ULONG Length ) +/*++ + +Routine Description: + +Arguments: + + + +Return Value: + + None. + +--*/ +{ + KIRQL OldIrql; + PDIGI_MEM_DESCRIPTOR buf; + ULONG Len = ((Length + (sizeof(ULONG)-1)) & ~(sizeof(ULONG)-1)); + + // + // Check memory consistency. + // + DigiCheckMem(); + + if( (buf = (PDIGI_MEM_DESCRIPTOR)ExAllocatePoolWithTag( PoolType, + Len + sizeof(DIGI_MEM_DESCRIPTOR) + sizeof(ULONG), + DefaultPoolTag)) == NULL ) + return(NULL); + + TotalMemAllocated += Len; + + buf->Length = Len; + buf->BeginTag = (ULONG)'lkir'; + + *(PULONG)((PUCHAR)buf + Len + sizeof(DIGI_MEM_DESCRIPTOR)) = (ULONG)'igid'; + + // + // Insert onto tail of global memory queue + // + + KeAcquireSpinLock( &GlobalMemSpinLock, &OldIrql ); + + if( PoolType == PagedPool ) + { + InsertTailList( &GlobalPagedMemQueue, + &(buf->ListEntry) ); + } + else + { + InsertTailList( &GlobalNonPagedMemQueue, + &(buf->ListEntry) ); + } + + KeReleaseSpinLock( &GlobalMemSpinLock, OldIrql ); + + return( (PUCHAR)buf + (sizeof(DIGI_MEM_DESCRIPTOR)) ); + +} // end DigiAllocMem + + + +VOID DigiFreeMem( IN PVOID Buf ) +/*++ + +Routine Description: + + Does consistency check on passed in memory block and free's the memory + block. + +Arguments: + + Buf - pointer to memory block which is to be freed. + +Return Value: + + None. + +--*/ +{ + PDIGI_MEM_DESCRIPTOR RealBuf; + KIRQL OldIrql; + ULONG Length; + + // + // Check memory consistency. + // + DigiCheckMem(); + + RealBuf = (PDIGI_MEM_DESCRIPTOR)((PUCHAR)Buf - sizeof(DIGI_MEM_DESCRIPTOR)); + Length = RealBuf->Length; + + if( RealBuf->BeginTag != (ULONG)'lkir' ) + { + DbgPrint( "Memory has been corrupted!\n" ); + DbgBreakPoint(); + } + + if( *(PULONG)((PUCHAR)Buf + Length) != (ULONG)'igid' ) + { + DbgPrint("Memory Overrun\n"); + DbgBreakPoint(); + } + + TotalMemAllocated -= Length; + + KeAcquireSpinLock( &GlobalMemSpinLock, &OldIrql ); + RemoveEntryList( &(RealBuf->ListEntry) ); + KeReleaseSpinLock( &GlobalMemSpinLock, OldIrql ); + + ExFreePool( RealBuf ); +} // end DigiFreeMem + + +VOID DigiCheckMem( VOID ) +{ + PLIST_ENTRY _DigiQueue; + KIRQL _OldIrql, _CurrentIrql; + + if( DigiPrintFlags & MEM_PRINT_FLAG_NOMEMCHECK ) + return; + + _DigiQueue = &GlobalNonPagedMemQueue; + + KeAcquireSpinLock( &GlobalMemSpinLock, &_OldIrql ); + + while( _DigiQueue->Flink != &GlobalNonPagedMemQueue ) + { + PDIGI_MEM_DESCRIPTOR _MemDesc; + PUCHAR _Buf; + + _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, + DIGI_MEM_DESCRIPTOR, + ListEntry ); + + _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); + if( (_MemDesc->BeginTag != (ULONG)'lkir') || + (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) + { + DbgPrint( "DigiCheckMem corruption found (0x%x)!n", _MemDesc ); + DbgBreakPoint(); + break; + } + + _DigiQueue = _DigiQueue->Flink; + } + + _DigiQueue = &GlobalPagedMemQueue; + _CurrentIrql = KeGetCurrentIrql(); + + while( (_CurrentIrql < DISPATCH_LEVEL) && + (_DigiQueue->Flink != &GlobalPagedMemQueue) ) + { + PDIGI_MEM_DESCRIPTOR _MemDesc; + PUCHAR _Buf; + + _MemDesc = CONTAINING_RECORD( _DigiQueue->Flink, + DIGI_MEM_DESCRIPTOR, + ListEntry ); + + _Buf = (PUCHAR)_MemDesc + sizeof(DIGI_MEM_DESCRIPTOR); + if( (_MemDesc->BeginTag != (ULONG)'lkir') || + (*(PULONG)(_Buf + _MemDesc->Length) != (ULONG)'igid') ) + { + DbgPrint( "DigiCheckMem corruption found (0x%x)!n", _MemDesc ); + DbgBreakPoint(); + break; + } + + _DigiQueue = _DigiQueue->Flink; + _CurrentIrql = KeGetCurrentIrql(); + } + + KeReleaseSpinLock( &GlobalMemSpinLock, _OldIrql ); +} + +#endif // end #if DBG || DIGICHECKMEM diff --git a/private/ntos/ndis/digi/digifile/digifile.h b/private/ntos/ndis/digi/digifile/digifile.h new file mode 100644 index 000000000..3f30774ba --- /dev/null +++ b/private/ntos/ndis/digi/digifile/digifile.h @@ -0,0 +1,105 @@ +#include + +#ifdef VER_PRODUCTBUILD +#define rmm VER_PRODUCTBUILD +#endif + + +#define DIGI_PHYSICAL_ADDRESS_CONST(_Low, _High) \ + { (ULONG)(_Low), (LONG)(_High) } + +#define DIGI_STATUS_FILE_NOT_FOUND ((NTSTATUS)0xC001001BL) +#define DIGI_STATUS_ERROR_READING_FILE ((NTSTATUS)0xC001001CL) +#define DIGI_STATUS_ALREADY_MAPPED ((NTSTATUS)0xC001001DL) + + +VOID DigiOpenFile( OUT PNTSTATUS Status, + OUT PHANDLE FileHandle, + OUT PULONG FileLength, + IN PUNICODE_STRING FileName, + IN PHYSICAL_ADDRESS HighestAcceptableAddress ); + +VOID DigiCloseFile( IN HANDLE FileHandle ); + +VOID DigiMapFile( OUT PNTSTATUS Status, + OUT PVOID * MappedBuffer, + IN HANDLE FileHandle ); + +VOID DigiUnmapFile( IN HANDLE FileHandle ); + +#ifndef POOL_TAGGING +#define ExAllocatePoolWithTag(a,b,c) ExAllocatePool(a,b) +#endif //POOL_TAGGING + +PVOID DigiInitMem( IN ULONG PoolTag ); +extern ULONG DefaultPoolTag; + +#if DBG || DIGICHECKMEM + +PVOID DigiAllocMem( IN POOL_TYPE PoolType, IN ULONG Length ); +VOID DigiFreeMem( IN PVOID Buf ); + +#else + +#define DigiAllocMem( PoolType, Length ) ExAllocatePoolWithTag( PoolType, \ + Length, \ + DefaultPoolTag ) +#define DigiFreeMem( Buffer ) ExFreePool( Buffer ) + +#endif + +// +// The following are prototypes for functions found in dgatlas.c +// +NTSTATUS DigiRegisterAtlasName( IN PUNICODE_STRING DeviceName, + IN PUNICODE_STRING ValueName, + IN PUNICODE_STRING ValueEntry ); + + +#if rmm <= 807 +#define MmLockPagableCodeSection( a ) MmLockPagableImageSection( a ) +#endif + +#if rmm <= 528 + +NTSTATUS +NTAPI +ZwCreateFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength + ); + +NTSTATUS +NTAPI +ZwQueryInformationFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); + +NTSTATUS +NTAPI +ZwReadFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN PLARGE_INTEGER ByteOffset OPTIONAL, + IN PULONG Key OPTIONAL + ); + +#endif diff --git a/private/ntos/ndis/digi/digifile/makefile b/private/ntos/ndis/digi/digifile/makefile new file mode 100644 index 000000000..58189757d --- /dev/null +++ b/private/ntos/ndis/digi/digifile/makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/digi/digifile/makefile.inc b/private/ntos/ndis/digi/digifile/makefile.inc new file mode 100644 index 000000000..bfd14171b --- /dev/null +++ b/private/ntos/ndis/digi/digifile/makefile.inc @@ -0,0 +1,15 @@ +..\lib\*: + mkdir ..\lib\* + +..\inc: + mkdir ..\inc + +..\inc\digifile.h: digifile.h + copy digifile.h ..\inc + +..\inc\memprint.h: memprint.h + copy memprint.h ..\inc + +..\inc\dgatlas.h: dgatlas.h + copy dgatlas.h ..\inc + diff --git a/private/ntos/ndis/digi/digifile/memprint.c b/private/ntos/ndis/digi/digifile/memprint.c new file mode 100644 index 000000000..e81189a7b --- /dev/null +++ b/private/ntos/ndis/digi/digifile/memprint.c @@ -0,0 +1,922 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + memprint.c + +Abstract: + + This module contains the routines to implement in-memory DbgPrint. + DbgPrint text is stored in a large circular buffer, and optionally + written to a file and/or the debug console. Output to file is + buffered to allow high performance by the file system. + +Author: + + David Treadwell (davidtr) 05-Oct-1990 + +Revision History: + +--*/ +// +// so it compiles when it includes ps.h +//typedef unsigned long LCID; /* locale ID */ + +#pragma message( "**** Including DEBUG functionality ****") + +#include "ntddk.h" + +#include // Include to determine what version of NT + +#ifdef VER_PRODUCTBUILD +#define rmm VER_PRODUCTBUILD +#endif + +#include "digifile.h" + +// The rest of the #includes are standard +#include +#include +#include "stdio.h" + +#include +#undef DbgPrint +#undef MemPrintPreInitSettings +#undef MemPrintInitialize +#undef MemPrintQuit +#undef MemPrint +#undef MemPrintFlush + + +#define MEM_PRINT_DEF_BUFFER_SIZE (65536 * 8) + +#define MEM_PRINT_LOG_FILE_NAME "\\SystemRoot\\DigiSer.log" + +// +// Forward declarations. +// + +VOID MemPrintWriteCompleteApc ( IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock ); + +VOID DigiPrintWriteThread ( IN PVOID Dummy ); + + +// +// Global data. It is all protected by MemPrintSpinLock. +// + +PVOID ThreadObjectPointer; +HANDLE fileHandle; +UCHAR TurnOffSniffer=1; + +CLONG MemPrintBufferSize = MEM_PRINT_DEF_BUFFER_SIZE; +PCHAR MemPrintBuffer; + +ULONG DigiPrintFlags = (MEM_PRINT_FLAG_CONSOLE | MEM_PRINT_FLAG_NOMEMCHECK); +ULONG AttemptedTempBufferAllocs=0; + +ULONG MemPrintFailures=0; + +CHAR DefaultLogFileName[1024]=MEM_PRINT_LOG_FILE_NAME; + +// +// Protect writing to the buffer +// +KSPIN_LOCK MemPrintSpinLock; + +BOOLEAN MemPrintInitialized = FALSE; +BOOLEAN UnloadingDriver = FALSE; + +KEVENT MemPrintQuitEvent; +KEVENT MemPrintWriteToLogEvent; + +LARGE_INTEGER totalBytesWritten; +LARGE_INTEGER fileAllocationSize; + +ULONG BufferInOffset, BufferOutOffset; + + +VOID MemPrintPreInitSettings( PCHAR NewLogFileName, + ULONG NewBufferSize ) +/*++ + +Routine Description: + + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + strcpy( DefaultLogFileName, NewLogFileName ); + MemPrintBufferSize = NewBufferSize; +} // end MemPrintPreInitSettings + + + +NTSTATUS MemPrintInitialize ( VOID ) +/*++ + +Routine Description: + + This is the initialization routine for the in-memory DbgPrint routine. + It should be called before the first call to MemPrint to set up the + various structures used and to start the log file write thread. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + NTSTATUS status; + HANDLE threadHandle; + KPRIORITY threadPriorityLevel; + + OBJECT_ATTRIBUTES objectAttributes; + PCHAR fileName; + ANSI_STRING fileNameString; + + UNICODE_STRING UnicodeFileName; + + LARGE_INTEGER delayInterval; + ULONG attempts = 0; + + IO_STATUS_BLOCK localIoStatusBlock; + + PETHREAD CurrentThread; + PEPROCESS CurrentProcess; + + if( MemPrintInitialized ) + { + // + // we have all ready been called. Just return. + // + return( STATUS_SUCCESS ); + } + + fileName = DefaultLogFileName; + UnloadingDriver = FALSE; + + // + // Initialize the total bytes written and write size variables. + // + + totalBytesWritten.QuadPart = 0; + fileAllocationSize.QuadPart = 0; + BufferInOffset = BufferOutOffset = 0; + + // + // Allocate memory for the circular buffer that will receive + // the text and data. If we can't do it, try again with a buffer + // half as large. If that fails, quit trying. + // + + MemPrintBuffer = (PCHAR)DigiAllocMem( NonPagedPool, MemPrintBufferSize ); + + if( MemPrintBuffer == NULL ) + { + MemPrintBufferSize /= 2; + DbgPrint( "Unable to allocate DbgPrint buffer--trying size = %ld\n", + MemPrintBufferSize ); + MemPrintBuffer = DigiAllocMem( NonPagedPool, MemPrintBufferSize ); + + if( MemPrintBuffer == NULL ) + { + DbgPrint( "Couldn't allocate DbgPrint buffer.\n" ); + return( STATUS_INSUFFICIENT_RESOURCES ); + } + } + + DbgPrint( "MemPrint buffer from %lx to %lx\n", + MemPrintBuffer, MemPrintBuffer + MemPrintBufferSize ); + + // + // Allocate the spin lock that protects access to the various + // pointers and the circular buffer. This ensures integrity of the + // buffer. + // + + KeInitializeSpinLock( &MemPrintSpinLock ); + + KeInitializeEvent( &MemPrintQuitEvent, + SynchronizationEvent, + (BOOLEAN)FALSE ); + + KeInitializeEvent( &MemPrintWriteToLogEvent, + SynchronizationEvent, + (BOOLEAN)FALSE ); + + // + // Initialize the string containing the file name and the object + // attributes structure that will describe the log file to open. + // + + RtlInitAnsiString( &fileNameString, + fileName ); + status = RtlAnsiStringToUnicodeString( &UnicodeFileName, + &fileNameString, + (BOOLEAN)TRUE ); + ASSERT(NT_SUCCESS(status)); + + InitializeObjectAttributes( &objectAttributes, + &UnicodeFileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + // + // Set the allocation size of the log file to be three times the + // size of the circular buffer. When it fills up, we'll extend + // it. + // + + fileAllocationSize.QuadPart += MemPrintBufferSize; + + // + // Open the log file. + // + // !!! The loop here is to help avoid a system initialization + // timing problem, and should be removed when the problem is + // fixed. + // + + while ( TRUE ) { + + status = ZwCreateFile( &fileHandle, + FILE_WRITE_DATA, + &objectAttributes, + &localIoStatusBlock, + &fileAllocationSize, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OVERWRITE_IF, + FILE_SEQUENTIAL_ONLY, + NULL, + 0L ); + + if( (status != STATUS_OBJECT_PATH_NOT_FOUND) || (++attempts >= 3) ) + { + RtlFreeUnicodeString( &UnicodeFileName ); + break; + } + + delayInterval.LowPart = (ULONG)(-5*10*1000*1000); // five second delay + delayInterval.HighPart = -1; + KeDelayExecutionThread( (KPROCESSOR_MODE)KernelMode, + (BOOLEAN)FALSE, + &delayInterval ); + } + + if( NT_ERROR(status) ) + { + DbgPrint( "NtCreateFile for log file failed: 0x%x\n", status ); + DigiFreeMem( MemPrintBuffer ); + return( status ); + } else + { + DbgPrint( "Successfully opened logfile %s\n", fileName ); + } + + // + // Set the priority of the write thread. + // + + threadPriorityLevel = LOW_REALTIME_PRIORITY + 1; + + CurrentThread = PsGetCurrentThread(); + CurrentProcess = PsGetCurrentProcess(); + + // + // Start the thread that writes subbuffers from the large circular + // buffer to disk. + // + + status = PsCreateSystemThread( &threadHandle, + THREAD_ALL_ACCESS, + NULL, + (HANDLE)0L, + NULL, + DigiPrintWriteThread, + NULL ); + + if( NT_ERROR(status) ) + { + DbgPrint( "MemPrintInitialize: PsCreateSystemThread failed: 0x%x\n", + status ); + // + // Cleanup + // + ZwClose( fileHandle ); + DigiFreeMem( MemPrintBuffer ); + + return( status ); + } + + status = ObReferenceObjectByHandle( threadHandle, + THREAD_ALL_ACCESS, + NULL, + KernelMode, + &ThreadObjectPointer, + NULL ); + + if( NT_ERROR(status) ) + { + ZwClose( fileHandle ); + DigiFreeMem( MemPrintBuffer ); + + return( status ); + } + + MemPrintInitialized = TRUE; + + return( STATUS_SUCCESS ); + +} // MemPrintInitialize + + + +VOID MemPrintQuit(VOID) +/*++ + +Routine Description: + + Called to cleanup. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + KIRQL oldIrql; + + KeAcquireSpinLock( &MemPrintSpinLock, &oldIrql ); + + UnloadingDriver = TRUE; + + if( !MemPrintInitialized ) + { + KeReleaseSpinLock( &MemPrintSpinLock, oldIrql ); + return; + } + + KeSetEvent( &MemPrintWriteToLogEvent, + 2, + (BOOLEAN)FALSE ); + + KeReleaseSpinLock( &MemPrintSpinLock, oldIrql ); + + KeWaitForSingleObject( ThreadObjectPointer, + Executive, + KernelMode, + FALSE, + NULL ); + + DigiFreeMem( MemPrintBuffer ); + + ZwClose( fileHandle ); + +} // MemPrintQuit + + + +VOID MemPrint ( CHAR *Format, ... ) +/*++ + +Routine Description: + + This routine is called in place of DbgPrint to process in-memory + printing. + +Arguments: + + Format - A format string in the style of DbgPrint. + + - formatting arguments. + +Return Value: + + None. + +--*/ +{ + va_list arglist; + KIRQL oldIrql; + ULONG CurrentOutOffset, CurrentInOffset; + ULONG BytesToMove; + PCHAR tempBuffer, CopyTempBuffer; + ULONG tempBufferLen; + + tempBuffer = DigiAllocMem( NonPagedPool, 1024 ); + + if( tempBuffer == NULL ) + { + // + // Only print out failure msg every ten times. + // + if( (AttemptedTempBufferAllocs % 10) == 0 ) + DbgPrint( "Unable to alloc temp buffer for MemPrint.\n" ); + + AttemptedTempBufferAllocs++; + return; + } + + CopyTempBuffer = tempBuffer; + + va_start( arglist, Format ); + +#if defined (_X86_) + _vsnprintf( tempBuffer, 1024, Format, arglist ); +#elif defined (_MIPS_) + _vsnprintf( tempBuffer, 1024, Format, arglist ); +#elif defined (_ALPHA_) + vsprintf( tempBuffer, Format, arglist ); +#else + vsprintf( tempBuffer, Format, arglist ); +#endif + + va_end( arglist ); + + // + // If memory DbgPrint has not been initialized, simply print to the + // console. + // + + if( !MemPrintInitialized || + UnloadingDriver ) + { + // + // Just dump to console and return. + // + + DbgPrint( "%s", tempBuffer ); + goto ExitMemPrintFree; + } + + if( DigiPrintFlags & MEM_PRINT_FLAG_CONSOLE ) + DbgPrint( "%s", tempBuffer ); + + tempBufferLen = strlen(tempBuffer); + BytesToMove = tempBufferLen; + + ASSERT( tempBufferLen+1 <= 1024 ); + + // + // Acquire the spin lock that synchronizes access to the pointers + // and circular buffer. + // + + KeAcquireSpinLock( &MemPrintSpinLock, &oldIrql ); + + CurrentOutOffset = BufferOutOffset; + CurrentInOffset = BufferInOffset; + + while( tempBufferLen ) + { + if( CurrentOutOffset > CurrentInOffset ) + { + // + // Take into account that we don't want to write one less + // so we don't put the CurrentInOffset equal to CurrentOutOffset. + // + BytesToMove = CurrentOutOffset - CurrentInOffset - 1; + } + else if( CurrentOutOffset < CurrentInOffset ) + { + BytesToMove = CurrentOutOffset + MemPrintBufferSize - CurrentInOffset; + } + else + { + // + // We have the full buffer, + // + BytesToMove = MemPrintBufferSize - 1; + } + + // + // We know how many bytes are available in the buffer. Now determine + // how many bytes we can actually write. + // + if( BytesToMove >= tempBufferLen ) + { + // + // We can put the whole thing into the memprint buffer. + // + BytesToMove = tempBufferLen; + } +// else +// { +// // +// // We can only put part of the print request into the memprint +// // buffer. +// // +// if( (MemPrintFailures % 1000) == 0 ) +// DbgPrint( "Unable to place entire print request into memprint buffer!\n" ); +// else +// DbgPrint( "^" ); +// +// MemPrintFailures++; +// } + + if( BytesToMove == 0 ) + { + // + // More than likely, we ran out of buffer space. + // + if( (MemPrintFailures % 1000) == 0 ) + DbgPrint( "Out of buffer space for MemPrint request, failures = %u!\n", + MemPrintFailures ); +// else +// DbgPrint( "." ); + + MemPrintFailures++; + break; + } + + // + // Okay, we know how many bytes we can potentially move. Now determine + // if we need to worry about wrapping the circular buffer. + // + if( (BytesToMove + CurrentInOffset) >= MemPrintBufferSize ) + { + // + // readjust so we only write the number of bytes to the end + // of the buffer. + // + BytesToMove = MemPrintBufferSize - CurrentInOffset; + } + + RtlMoveMemory( &MemPrintBuffer[CurrentInOffset], + tempBuffer, + BytesToMove ); + + tempBufferLen -= BytesToMove; + + tempBuffer += BytesToMove; + + CurrentInOffset += BytesToMove; + + // + // Adjust the CurrentInOffset for circular buffer wrapping. + // + ASSERT( CurrentInOffset <= MemPrintBufferSize ); + + if( CurrentInOffset == MemPrintBufferSize ) + CurrentInOffset = 0; + + } + + BufferInOffset = CurrentInOffset; + + KeReleaseSpinLock( &MemPrintSpinLock, oldIrql ); + + // + // Set the event that will wake up the thread writing subbuffers + // to disk. + // + + KeSetEvent( &MemPrintWriteToLogEvent, + 2, + (BOOLEAN)FALSE ); + +ExitMemPrintFree: + + DigiFreeMem( CopyTempBuffer ); + + return; + +} // MemPrint + + + +VOID MemPrintFlush ( VOID ) + +/*++ + +Routine Description: + + This is obsolete now since the write thread will try to write + as much of the circular buffer as possible. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + return; + +} // MemPrintFlush + + + +VOID DigiPrintWriteThread ( IN PVOID Dummy ) + +/*++ + +Routine Description: + + The log file write thread executes this routine. It sets up the + log file for writing, then waits for subbuffers to fill, writing + them to disk when they do. When the log file fills, new space + for it is allocated on disk to prevent the file system from + having to do it. + +Arguments: + + Dummy - Ignored. + +Return Value: + + None. + +--*/ + +{ + NTSTATUS status; + NTSTATUS waitStatus; + + IO_STATUS_BLOCK localIoStatusBlock; + + LARGE_INTEGER delayInterval; + ULONG NumberBytesToWrite; + + Dummy; + + // + // Delay for 20 seconds before we start executing. This will hopefully + // allow the system to get further along at boot time. + // + delayInterval.LowPart = (ULONG)(-20*10*1000*1000); // twenty second delay + delayInterval.HighPart = -1; + KeDelayExecutionThread( (KPROCESSOR_MODE)KernelMode, + (BOOLEAN)FALSE, + &delayInterval ); + + KeSetPriorityThread( KeGetCurrentThread(), + LOW_REALTIME_PRIORITY + 1 ); + + // + // Loop waiting for one of the subbuffer full events to be signaled. + // When one is signaled, wake up and write the subbuffer to the log + // file. + // + + if( UnloadingDriver ) + { + KeSetEvent( &MemPrintQuitEvent, + 2, + FALSE ); + PsTerminateSystemThread( STATUS_SUCCESS ); + } + + while( TRUE ) + { + PUCHAR tmpPtr; + ULONG CurrentOutOffset, CurrentInOffset; + KIRQL oldIrql; + + waitStatus = KeWaitForSingleObject( &MemPrintWriteToLogEvent, + Executive, + KernelMode, + TRUE, + NULL ); + + if( !NT_SUCCESS(waitStatus) ) + { + DbgPrint( "KeWaitForMultipleObjects failed: 0x%x\n", waitStatus ); + continue; + } + + // + // Check the DbgPrint flags to see if we really want to write + // this. + // + + if( !(DigiPrintFlags & MEM_PRINT_FLAG_FILE) ) + { + // + // There is nothing for us to do. + // + if( UnloadingDriver ) + { + KeSetEvent( &MemPrintQuitEvent, + 2, + FALSE ); + PsTerminateSystemThread( STATUS_SUCCESS ); + } + + continue; + } + + // + // Take a snap shoot of the in pointer. It is possible it will + // change on us. + // + KeAcquireSpinLock( &MemPrintSpinLock, &oldIrql ); + + CurrentInOffset = BufferInOffset; + CurrentOutOffset = BufferOutOffset; + + KeReleaseSpinLock( &MemPrintSpinLock, oldIrql ); + + while( CurrentInOffset != CurrentOutOffset ) + { + ASSERT( CurrentInOffset <= MemPrintBufferSize ); + ASSERT( CurrentOutOffset <= MemPrintBufferSize ); + + if( CurrentInOffset > CurrentOutOffset ) + { + // + // We only need to do one write to the log file. + // + NumberBytesToWrite = CurrentInOffset - CurrentOutOffset; + } + else + { + // + // We have a buffer wrap situation and as a result need + // to account by making two write's to the log file. + // + NumberBytesToWrite = MemPrintBufferSize - CurrentOutOffset; + } + + ASSERT( (CurrentOutOffset + NumberBytesToWrite) <= MemPrintBufferSize ); + + tmpPtr = MemPrintBuffer + CurrentOutOffset; + // + // Start the write operation. The APC routine will handle + // checking the return status from the write and updating + // BufferOutOffset. + // + + status = ZwWriteFile( fileHandle, + NULL, + (PIO_APC_ROUTINE)MemPrintWriteCompleteApc, + (PVOID)NumberBytesToWrite, + &localIoStatusBlock, + tmpPtr, + NumberBytesToWrite, + &totalBytesWritten, + NULL ); + + + if( !NT_SUCCESS(status) ) + { + DbgPrint( "ZwWriteFile for log file failed: 0x%x\n", status ); + } + + // + // Update the count of bytes written to the log file. + // + + CurrentOutOffset += NumberBytesToWrite; + ASSERT( CurrentOutOffset <= MemPrintBufferSize ); + + if( CurrentOutOffset >= MemPrintBufferSize ) + CurrentOutOffset = 0; + + totalBytesWritten.QuadPart += NumberBytesToWrite; + + // + // Extend the file if we have reached the end of what we have + // thus far allocated for the file. This increases performance + // by extending the file here rather than in the file system, + // which would have to extend it each time a write past end of + // file comes in. + // + + if( (totalBytesWritten.QuadPart >= fileAllocationSize.QuadPart) ) + { + fileAllocationSize.QuadPart = fileAllocationSize.QuadPart + MemPrintBufferSize; + + DbgPrint( "Enlarging logfile %s to %ld bytes.\n", + DefaultLogFileName, + fileAllocationSize.LowPart ); + + status = ZwSetInformationFile( fileHandle, + &localIoStatusBlock, + &fileAllocationSize, + sizeof(fileAllocationSize), + FileAllocationInformation ); + + if( !NT_SUCCESS(status) ) + { + DbgPrint( "Attempt to extend log file failed: 0x%x\n", status ); + fileAllocationSize.QuadPart = fileAllocationSize.QuadPart - MemPrintBufferSize; + } + } + + } + + if( UnloadingDriver ) + { + KeSetEvent( &MemPrintQuitEvent, + 2, + FALSE ); + PsTerminateSystemThread( STATUS_SUCCESS ); + } + } + + return; + +} // DigiPrintWriteThread + + + +VOID MemPrintWriteCompleteApc( IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock ) +/*++ + +Routine Description: + + This APC routine is called when the current write to disk complete. + It checks for success, printing a message if the write failed. + It also updates BufferOutOffset. + +Arguments: + + ApcContext - contains what the CurrentInOffset was when + ZwWriteFile was called. + + IoStatusBlock - the status block for the operation. + +Return Value: + + None. + +--*/ + +{ + KIRQL oldIrql; + ULONG NumberBytesWritten=(ULONG)ApcContext; + + if( !NT_SUCCESS(IoStatusBlock->Status) ) + { + DbgPrint( "ZwWriteFile for subbuffer %ld failed: 0x%x\n", + ApcContext, + IoStatusBlock->Status ); + return; + } + +// ASSERT( IoStatusBlock->Information == NumberBytesWritten ); + + // + // Acquire the spin lock that protects memory print global variables + // and set the subbuffer writing boolean to FALSE so that other + // threads can write to the subbuffer if necessary. + // + + KeAcquireSpinLock( &MemPrintSpinLock, &oldIrql ); + + if( BufferOutOffset + IoStatusBlock->Information > MemPrintBufferSize ) + { + BufferOutOffset = ( (BufferOutOffset + IoStatusBlock->Information) - + MemPrintBufferSize ); + } + else if( BufferOutOffset + IoStatusBlock->Information < MemPrintBufferSize ) + { + BufferOutOffset += IoStatusBlock->Information; + } + else + { + BufferOutOffset = 0; + } + +// BufferOutOffset += NumberBytesWritten; +// +// ASSERT( BufferOutOffset <= MemPrintBufferSize ); +// +// if( BufferOutOffset == MemPrintBufferSize ) +// BufferOutOffset = 0; + + KeReleaseSpinLock( &MemPrintSpinLock, oldIrql ); + + return; + +} // MemPrintWriteCompleteApc + + diff --git a/private/ntos/ndis/digi/digifile/memprint.h b/private/ntos/ndis/digi/digifile/memprint.h new file mode 100644 index 000000000..844b8a279 --- /dev/null +++ b/private/ntos/ndis/digi/digifile/memprint.h @@ -0,0 +1,73 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + memprint.h + +Abstract: + + Include file for in-memory DbgPrint function. Including this file + will change DbgPrints to a routine which puts the display text in a + circular buffer in memory. By default, the text is then sent to the + console via DbgPrint. By changing the value of the DigiPrintFlags + flag, however, the text may be routed to a file instead, thereby + significantly speeding up the DbgPrint operation. + +Author: + + David Treadwell (davidtr) 05-Oct-1990 + +Revision History: + +--*/ + +#ifndef _MEMPRINT_ +#define _MEMPRINT_ + +#define MEM_PRINT_FLAG_CONSOLE 0x00000001 +#define MEM_PRINT_FLAG_FILE 0x00000002 +#define MEM_PRINT_FLAG_HEADER 0x00000004 +#define MEM_PRINT_FLAG_QUIT 0x00000008 +#define MEM_PRINT_FLAG_NOMEMCHECK 0x80000000 + +extern ULONG DigiPrintFlags; +extern UCHAR TurnOffSniffer; + +// +// Exported routines. MemPrintInitialize sets up the circular buffer +// and other memory, MemPrint writes text to the console and/or a +// log file, and MemPrintFlush writes the current subbuffer to disk +// whether or not it is full. +// + +#if DBG +VOID MemPrintPreInitSettings( PCHAR NewLogFileName, + ULONG NewBufferSize ); + +NTSTATUS MemPrintInitialize ( VOID ); + +VOID MemPrintQuit ( VOID ); + +VOID MemPrint ( CHAR *Format, ... ); + +VOID MemPrintFlush ( VOID ); + +#define DbgPrint MemPrint + +#else + +#define MemPrintPreInitSettings( a, b ) + +#define MemPrintInitialize() + +#define MemPrintQuit() + +#define MemPrint() + +#define MemPrintFlush() +#endif + +#endif // def _MEMPRINT_ + diff --git a/private/ntos/ndis/digi/digifile/sources b/private/ntos/ndis/digi/digifile/sources new file mode 100644 index 000000000..36d4e3c03 --- /dev/null +++ b/private/ntos/ndis/digi/digifile/sources @@ -0,0 +1,47 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP= +MINORCOMP= + +TARGETNAME=digifile +TARGETPATH=..\lib +TARGETTYPE=LIBRARY + +INCLUDES=..\inc; \ + $(_NTBINDIR)\private\ntos\inc + +SOURCES= \ + memprint.c \ + digifile.c \ + dgatlas.c + +NTTARGETFILE0=\ + ..\lib\* \ + ..\inc \ + +NTTARGETFILE1= \ + ..\inc\digifile.h \ + ..\inc\memprint.h \ + ..\inc\dgatlas.h diff --git a/private/ntos/ndis/digi/dirs b/private/ntos/ndis/digi/dirs new file mode 100644 index 000000000..175b71bfe --- /dev/null +++ b/private/ntos/ndis/digi/dirs @@ -0,0 +1,27 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Steve Wood (stevewo) 17-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl + +!ENDIF + +DIRS=\ + digifile \ + pcimac + + diff --git a/private/ntos/ndis/digi/images/adp.bin b/private/ntos/ndis/digi/images/adp.bin new file mode 100644 index 000000000..ba3812fcf Binary files /dev/null and b/private/ntos/ndis/digi/images/adp.bin differ diff --git a/private/ntos/ndis/digi/images/idp_xfs.bin b/private/ntos/ndis/digi/images/idp_xfs.bin new file mode 100644 index 000000000..cae71d83e Binary files /dev/null and b/private/ntos/ndis/digi/images/idp_xfs.bin differ diff --git a/private/ntos/ndis/digi/pcimac/adapter.h b/private/ntos/ndis/digi/pcimac/adapter.h new file mode 100644 index 000000000..9a6f3b43e --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/adapter.h @@ -0,0 +1,223 @@ +/* + * ADAPTER.H - NDIS Adapter Interface, main include file + */ + + +#ifndef _ADAPTER_ +#define _ADAPTER_ + +#define PCIMAC_KEY_BOARDTYPE "BoardType" +#define PCIMAC_KEY_BASEIO "IOBaseAddress" +#define PCIMAC_KEY_BASEMEM "MemoryMappedBaseAddress" +#define PCIMAC_KEY_BOARDNAME "BoardName" +#define PCIMAC_KEY_LINENAME "LineName" +#define PCIMAC_KEY_NUMLINES "NumberOfLines" +#define PCIMAC_KEY_IDPFILENAME "IDPImageFileName" +#define PCIMAC_KEY_SWITCHSTYLE "SwitchStyle" +#define PCIMAC_KEY_TERMINALMANAGEMENT "TerminalManagement" +#define PCIMAC_KEY_NUMLTERMS "LogicalTerminals" +#define PCIMAC_KEY_TEI "TEI" +#define PCIMAC_KEY_SPID "SPID" +#define PCIMAC_KEY_ADDRESS "Address" +#define PCIMAC_KEY_LINE "Line" +#define PCIMAC_KEY_LTERM "LTerm" +#define PCIMAC_KEY_WAITFORL3 "WaitForL3" +#define PCIMAC_KEY_GENERICDEFINES "GenericDefines" + +/* global driver obect */ +typedef struct tagDRIVER_BLOCK +{ + NDIS_HANDLE NdisMacHandle; + NDIS_HANDLE NdisWrapperHandle; + struct _ADAPTER* AdapterTbl[MAX_ADAPTERS_IN_SYSTEM]; + ULONG InDriverFlag; + ULONG NumberOfAdaptersInSystem; + ULONG NextAdapterToPoll; + struct _ADAPTER* CurrentAdapter; + NDIS_SPIN_LOCK lock; +} DRIVER_BLOCK; + +typedef struct _ADAPTER +{ + NDIS_HANDLE Handle; +// ULONG InDriverFlag; +// NDIS_SPIN_LOCK InDriverLock; + CHAR Name[64]; + ULONG BaseIO; + PVOID VBaseIO; + ULONG BaseMem; + PVOID VBaseMem; + ULONG BoardType; + ULONG TapiBaseID; + ULONG NumberOfIddOnAdapter; + ULONG LastIddPolled; + VOID *TapiLineInfo[MAX_CM_PER_ADAPTER]; // 8 + VOID *IddTbl[MAX_IDD_PER_ADAPTER]; // 4 + VOID *CmTbl[MAX_CM_PER_ADAPTER]; // 8 + VOID *MtlTbl[MAX_MTL_PER_ADAPTER]; // 8 + NDIS_MINIPORT_TIMER IddPollTimer; // idd polling timer + NDIS_MINIPORT_TIMER MtlPollTimer; // mtl polling timer + NDIS_MINIPORT_TIMER CmPollTimer; // cm polling timer +}ADAPTER; + +typedef struct _CONFIGPARAM +{ + INT ParamType; + CHAR String[512]; + ULONG StringLen; + ULONG Value; + ULONG MustBePresent; + NDIS_HANDLE ConfigHandle; + NDIS_HANDLE AdapterHandle; +} CONFIGPARAM; + +VOID StopTimers(ADAPTER* Adapter); +VOID StartTimers(ADAPTER* Adapter); + +//VOID +//SetInDriverFlag( +// ADAPTER *Adapter +// ); +// +//VOID +//ClearInDriverFlag( +// ADAPTER *Adapter +// ); +// +//ULONG +//CheckInDriverFlag( +// ADAPTER *Adapter +// ); + +VOID +SetInDriverFlag( + ADAPTER *Adapter + ); + +VOID +ClearInDriverFlag( + ADAPTER *Adapter + ); + +ULONG +CheckInDriverFlag( + ADAPTER *Adapter + ); + +BOOLEAN +PcimacCheckForHang( + NDIS_HANDLE AdapterContext + ); + +VOID +PcimacHalt( + NDIS_HANDLE AdapterContext + ); + +NDIS_STATUS +PcimacInitialize( + PNDIS_STATUS OpenErrorStatus, + PUINT SelectMediumIndex, + PNDIS_MEDIUM MediumArray, + UINT MediumArraySize, + NDIS_HANDLE AdapterHandle, + NDIS_HANDLE WrapperConfigurationContext + ); + +NDIS_STATUS +PcimacSetQueryInfo( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesWritten, + PULONG BytesNeeded + ); + +NDIS_STATUS +PcimacReconfigure( + PNDIS_STATUS OpenErrorStatus, + NDIS_HANDLE AdapterContext, + NDIS_HANDLE WrapperConfigurationContext + ); + +NDIS_STATUS +PcimacReset( + PBOOLEAN AddressingReset, + NDIS_HANDLE AdapterContext + ); + +NDIS_STATUS +PcimacSend( + NDIS_HANDLE MacBindingHandle, + NDIS_HANDLE LinkContext, + PNDIS_WAN_PACKET WanPacket + ); + +INT +IoEnumAdapter( + VOID *cmd_1 + ); + +ADAPTER* +GetAdapterByIndex( + ULONG Index + ); + +ULONG +EnumAdaptersInSystem( + VOID + ); + +ADAPTER* +GetNextAdapter( + ADAPTER *Adapter + ); + +VOID +AdapterDestroy( + ADAPTER *Adapter + ); + +NDIS_STATUS +WanOidProc( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesReadWritten, + PULONG BytesNeeded + ); + +NDIS_STATUS +TapiOidProc( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesWritten, + PULONG BytesNeeded + ); + +NDIS_STATUS +LanOidProc( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesReadWritten, + PULONG BytesNeeded + ); + + +#if DIGIASSERT +#undef ASSERT +#define ASSERT( STRING ) \ + if( !(STRING) ) \ + { \ + DbgPrint( "ASSERT failed: " #STRING "\nfile: %s, line %d\n", __FILE__, __LINE__ ); \ + DbgBreakPoint(); \ + } +#endif + +#endif /* _ADAPTER_ */ diff --git a/private/ntos/ndis/digi/pcimac/ansihelp.c b/private/ntos/ndis/digi/pcimac/ansihelp.c new file mode 100644 index 000000000..1886e88d1 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/ansihelp.c @@ -0,0 +1,487 @@ + +#include +//#include + +#define _XA 0x200 +#define _XS 0x100 +#define _BB 0x80 +#define _CN 0x40 +#define _DI 0x20 +#define _LO 0x10 +#define _PU 0x08 +#define _SP 0x04 +#define _UP 0x02 +#define _XD 0x01 +#define XDI (_DI | _XD) +#define XLO (_LO | _XD) +#define XUP (_UP | _XD) + +static const SHORT CTypeTable[257] = { + 0, + _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, + _BB, _CN, _CN, _CN, _CN, _CN, _BB, _BB, + _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, + _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, + _SP, _PU, _PU, _PU, _PU, _PU, _PU, _PU, + _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, + XDI, XDI, XDI, XDI, XDI, XDI, XDI, XDI, + XDI, XDI, _PU, _PU, _PU, _PU, _PU, _PU, + _PU, XUP, XUP, XUP, XUP, XUP, XUP, _PU, + _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, + _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, + _UP, _UP, _UP, _PU, _PU, _PU, _PU, _PU, + _PU, XLO, XLO, XLO, XLO, XLO, XLO, _LO, + _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, + _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, + _LO, _LO, _LO, _PU, _PU, _PU, _PU, _BB, }; + +const SHORT *_Ctype = &CTypeTable[1]; + +#define BASE_MAX 36 +static const CHAR digits[] = {"0123456789abcdefghijklmnopqrstuvwxyz"}; +static const CHAR ndigs[BASE_MAX+1] = { + 0, 0, 33, 21, 17, 14, 13, 12, 11, 11, + 10, 10, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7 }; + +ULONG __Stoul (const CHAR *s, CHAR **endptr, INT base); + +/****************************************************************************** + + @doc INTERNAL + + @internal ULONG | __strlen | string length + + @parm PUCHAR | str | the string. + + @rdesc ULONG | the length of the string. + +******************************************************************************/ +ULONG +__strlen(PUCHAR str) +{ + ULONG len = 0; + + if (str == NULL) { + return(0); + } + + while (str[len] != '\0') { + len++; + } + + return(len); + +} // end of __strlen + + +/****************************************************************************** + + @doc INTERNAL + + @internal LONG | __strcmp | compare strings + + @parm PUCHAR | str1 | one string. + + @parm PUCHAR | str2 | another string. + + @rdesc ULONG | the comparison result. + +******************************************************************************/ +LONG +__strcmp(PUCHAR str1, PUCHAR str2) +{ + ULONG len = 0; + + if (str1 == str2) { + return(0); + } + if ((str1 == NULL) || (str2 == NULL)) { + return(-1); + } + + while ((str1[len] == str2[len]) && (str1[len] != '\0') && + (str2[len] != '\0')) { + len++; + } + + if (str1[len] == str2[len]) { + return(0); + } else if (str1[len] < str2[len]) { + return(-1); + } else { + return(1); + } + +} // end of __strcmp + + +/****************************************************************************** + + @doc INTERNAL + + @internal LONG | __strncmp | compare strings + + @parm PUCHAR | str1 | one string. + + @parm PUCHAR | str2 | another string. + + @parm ULONG | count | maximum characters to compare + + @rdesc ULONG | the comparison result. + +******************************************************************************/ +LONG +__strncmp(PUCHAR str1, PUCHAR str2, ULONG count) +{ + ULONG len = 0; + + if (str1 == str2) { + return(0); + } + if ((str1 == NULL) || (str2 == NULL)) { + return(-1); + } + + while (count-- && (str1[len] == str2[len]) && (str1[len] != '\0') && + (str2[len] != '\0')) { + len++; + } + + if (count == 0) { + len--; + } + if (str1[len] == str2[len]) { + return(0); + } else if (str1[len] < str2[len]) { + return(-1); + } else { + return(1); + } + +} // end of __strncmp + + +/****************************************************************************** + + @doc INTERNAL + + @internal LONG | __strnicmp | compare strings (case insensitive) + + @parm PUCHAR | str1 | one string. + + @parm PUCHAR | str2 | another string. + + @parm ULONG | count | maximum characters to compare + + @rdesc ULONG | the comparison result. + +******************************************************************************/ +LONG +__strnicmp(PUCHAR str1, PUCHAR str2, ULONG count) +{ + ULONG len = 0; + + if (str1 == str2) { + return(0); + } + if ((str1 == NULL) || (str2 == NULL)) { + return(-1); + } + + while (count-- && (str1[len] == str2[len]) && (str1[len] != '\0') && + (str2[len] != '\0')) { + len++; + } + + if (count == 0) { + len--; + } + if (str1[len] == str2[len]) { + return(0); + } else if (str1[len] < str2[len]) { + return(-1); + } else { + return(1); + } + +} // end of __strnicmp + + + + + +/****************************************************************************** + + @doc INTERNAL + + @internal PUCHAR | __strncpy | copy strings + + @parm PUCHAR | str1 | one string. + + @parm PUCHAR | str2 | another string. + + @parm ULONG | count | maximum characters to copy + + @rdesc ULONG | + +******************************************************************************/ +PUCHAR +__strncpy(PUCHAR str1, PUCHAR str2, ULONG count) +{ + PUCHAR tmp = str1; + + if (str1 && str2 && *str2 && count) { + while (count-- && (*str2 != '\0')) { + *str1++ = *str2++; + } + *str1 = '\0'; + } + + + return (tmp); +} // end of __strncpy + + + + +/****************************************************************************** + + @doc INTERNAL + + @internal PUCHAR | __strcpy | copy strings + + @parm PUCHAR | str1 | one string. + + @parm PUCHAR | str2 | another string. + + @rdesc PUCHAR | the comparison result. + +******************************************************************************/ +PUCHAR +__strcpy(PUCHAR str1, PUCHAR str2) +{ + PUCHAR tmp = str1; + + if (str1 && str2 && *str2) { + while (*str2 != '\0') { + *str1++ = *str2++; + } + *str1 = *str2; + } + + return (tmp); +} // end of __strcpy + + + +/****************************************************************************** + + @doc INTERNAL + + @internal PUCHAR | __strstr | search for substring with another string + + @parm PUCHAR | str1 | source string. + + @parm PUCHAR | str2 | substring string. + + @rdesc PUCHAR | + +******************************************************************************/ +PUCHAR +__strstr(PUCHAR str1, PUCHAR str2) +{ + return (NULL); +} // end of __strstr + + + +/****************************************************************************** + + @doc INTERNAL + + @internal PUCHAR | __memchr | search for char within buffer[0..count] + + @parm PUCHAR | buffer | starting address. + + @parm CHAR | chr | chr + + @parm ULONG | count | count + + @rdesc PUCHAR | + +******************************************************************************/ +PUCHAR +__memchr(PUCHAR buffer, CHAR chr, ULONG count) +{ + ULONG len = 0; + + if (buffer == NULL) { + return(NULL); + } + + while ((len +#include + +#define __strlen strlen +#define __strcmp strcmp +#define __strncmp strncmp +#define __strnicmp _strnicmp +#define __strncpy strncpy +#define __strcpy strcpy +#define __strstr strstr +#define __memchr memchr +#define __strchr strchr +#define __strrchr strrchr +#define __strlwr _strlwr +#define __strtoul strtoul +#define __isspace isspace + +#else +// Building for Windows + + +#undef tolower +#undef toupper +#undef isxdigit +#undef isdigit +#undef ctox + +#define _tolower(_c) ( (_c)-'A'+'a' ) +#define tolower(_c) ( ((_c) >= 'A' && (_c) <= 'Z') ? _tolower (_c) : (_c) ) +#define toupper(ch) (((ch >= 'a') && (ch <= 'z')) ? ch-'a'+'A':ch) +#define isxdigit(ch) (((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F')) || ((ch >= '0') && (ch <= '9'))) +#define isdigit(ch) ((ch >= '0') && (ch <= '9')) +#define ctox(ch) (((ch >='0') && (ch <= '9')) ? ch-'0': toupper(ch)-'A'+10) + +ULONG __strlen(PUCHAR str); + +LONG __strcmp(PUCHAR str1, PUCHAR str2); + +LONG __strncmp(PUCHAR str1, PUCHAR str2, ULONG count); + +LONG __strnicmp(PUCHAR str1, PUCHAR str2, ULONG count); + +PUCHAR __strncpy(PUCHAR str1, PUCHAR str2, ULONG count); + +PUCHAR __strcpy(PUCHAR str1, PUCHAR str2); + +PUCHAR __strstr(PUCHAR str1, PUCHAR str2); + +PUCHAR __memchr(PUCHAR buffer, CHAR chr, ULONG count); + +PUCHAR __strchr(PUCHAR str1, CHAR chr); + +PUCHAR __strrchr(PUCHAR str1, CHAR chr); + +PUCHAR __strlwr(PUCHAR str1); + +ULONG sprintf(PUCHAR str, PUCHAR format, ...); + +ULONG __strtoul (const CHAR *s, INT base); + +INT __isspace (INT c); + +PCHAR __vsprintf(); + +NTSTATUS +RtlAnsiStringToUnicodeString( + OUT PUNICODE_STRING DestinationString, + IN PANSI_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + + +NTSTATUS +RtlUnicodeStringToAnsiString( + OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +VOID +RtlFreeUnicodeString( + IN OUT PUNICODE_STRING UnicodeString + ); + +VOID +RtlFreeAnsiString( + IN OUT PANSI_STRING AnsiString + ); + + + +VOID +RtlInitAnsiString( + OUT PANSI_STRING DestinationString, + IN PUCHAR SourceString OPTIONAL + ); + + +VOID +RtlInitUnicodeString( + OUT PUNICODE_STRING DestinationString, + IN PWSTR SourceString OPTIONAL + ); + + +#endif diff --git a/private/ntos/ndis/digi/pcimac/cm.h b/private/ntos/ndis/digi/pcimac/cm.h new file mode 100644 index 000000000..4478d0b1e --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm.h @@ -0,0 +1,162 @@ +/* + * CM.H - definitions for connection manager + */ + +#ifndef _CM_ +#define _CM_ + +#include +#include + +/* error codes */ +#define CM_E_SUCC 0 /* success, ok */ +#define CM_E_NOSLOT 1 /* no slot available error */ +#define CM_E_BUSY 2 /* cm context is busy */ +#define CM_E_NOSUCH 3 /* no such object */ +#define CM_E_BADCHAN 4 /* bad channel argument */ +#define CM_E_IDD 5 /* idd command errored */ +#define CM_E_NOMEM 6 /* ran out of memory */ +#define CM_E_NOTIMPL 7 /* functionalit not implemented yet */ +#define CM_E_BADPARAM 8 /* bad parameter */ +#define CM_E_BADSTATE 9 /* bad state */ +#define CM_E_BADUUS 10 /* bad user-to-user signalling packet */ +#define CM_E_BADPORT 11 /* bad nai given */ + +// +// q931 switch styles +// +#define CM_SWITCHSTYLE_NONE 0 // no style +#define CM_SWITCHSTYLE_AUTO 1 // auto detect +#define CM_SWITCHSTYLE_NI1 2 // national isdn 1 +#define CM_SWITCHSTYLE_ATT 3 // at&t 5ess +#define CM_SWITCHSTYLE_NTI 4 // northern telecom dms100 +#define CM_SWITCHSTYLE_NET3 5 // net3 (europe) +#define CM_SWITCHSTYLE_1TR6 6 // 1tr6 (german) +#define CM_SWITCHSTYLE_VN3 7 // vn3 (france) +#define CM_SWITCHSTYLE_INS64 8 // ins64 (japan) + +// +// local cm def's +// +/* map a channel to signaling idd port */ +#define CM_PORT(_chan) ((_chan)->lterm + IDD_PORT_CM0_TX) + +/* user to user signaling structure (!must be byte alligned!) */ +#pragma pack(2) +typedef struct +{ + CHAR dst_addr[6]; /* destination address */ + CHAR src_addr[6]; /* source address */ + USHORT pkt_type; /* packet type field */ +#define CM_PKT_TYPE 0x5601 /* - private packet type */ + UCHAR prot_desc; /* protocol descriptor field */ +#define CM_PROT_DESC 0x78 /* - private protoocl descriptor */ + UCHAR opcode; /* opcode fields */ +#define CM_ASSOC_RQ 0x01 /* - request for chan/conn assoc */ +#define CM_ASSOC_ACK 0x02 /* - assoc ack'ed */ +#define CM_ASSOC_NACK 0x03 /* - assoc not ack'ed */ + UCHAR cause; /* cause value, to assist in diag */ +#define CM_NO_PROF 0x01 /* - no matching profile */ +#define CM_NO_CONN 0x02 /* - no connection slot avail */ +#define CM_NO_CHAN 0x03 /* - no channel slot avail */ +#define CM_DUP_CONN 0x04 /* - dup conn name */ + UCHAR conn; /* connection index */ + UCHAR channum; /* # of channels in connections */ + UCHAR chan; /* channel index */ + CHAR lname[24]; /* local profile name */ + ULONG option_0; // uus option fields +#define UUS_0_COMPRESSION 0x00004000 +#define COMP_TX_ENA 0x01 +#define COMP_RX_ENA 0x02 + ULONG option_1; + CHAR rname[24]; /* remote profile name */ + ULONG option_2; + ULONG option_3; + UCHAR chksum; /* zero checksum field */ +} CM_UUS; +#pragma pack() + +/* C compiler fails go generate odd sized structures!, must defined by self */ +#define CM_UUS_SIZE (sizeof(CM_UUS) - 1) + +/* special channel ustates */ +#define CM_US_UNDEF (USHORT)(-1) /* undefined, not known yet */ +#define CM_US_WAIT_CID (USHORT)(-2) /* waiting for a cid */ +#define CM_US_GAVE_UP (USHORT)(-4) /* gave up on this channel */ +#define CM_US_WAIT_CONN 50 /* connected, waiting on other */ +#define CM_US_UUS_SEND 51 /* sending uus now */ +#define CM_US_UUS_OKED 52 /* uus oked by side, wait on other */ +#define CM_US_CONN 53 /* connected */ + + +/* CM class operation prototypes */ +INT cm_init(VOID); +INT cm_term(VOID); +INT cm_register_idd(VOID* idd); +INT cm_deregister_idd(VOID* idd); + +/* CM object operation prototypes */ +INT cm_create(VOID** cm_1, NDIS_HANDLE AdapterHandle); +INT cm_destroy(VOID* cm_1); +INT cm_set_profile(VOID* cm_1, CM_PROF* prof); +INT cm_get_profile(VOID* cm_1, CM_PROF* prof); +INT cm_listen(VOID* cm_1); +INT cm_connect(VOID* cm_1); +INT cm_disconnect(VOID* cm_1); +INT cm_get_status(VOID* cm_1, CM_STATUS* stat); +INT cm_report_frame(VOID* cm_1, BOOL is_rx, CHAR* buf, ULONG len); + +/* prototypes for internal functions */ +VOID cm__q931_handler(IDD* idd, USHORT chan, ULONG Reserved, IDD_MSG* msg); +VOID cm__q931_bchan_handler(VOID* idd, USHORT chan, ULONG RxFrameType, IDD_XMSG* msg); +VOID cm__q931_cmpl_handler(VOID* idd, USHORT chan, IDD_MSG* msg); +INT cm__elem_rq(VOID* idd, USHORT port, CHAR* elem, USHORT elem_num); +INT cm__initiate_conn(CM* cm); +INT cm__disc_rq(CM_CHAN* chan); +INT cm__est_rq(CM_CHAN* chan); +INT cm__est_rsp(CM_CHAN* chan); +INT cm__est_ignore(PVOID idd, USHORT cid, USHORT lterm); +INT cm__deactivate_conn(CM* cm, BOOL by_idle_timer); +INT cm__activate_conn(CM* cm, ULONG CompressionFlag); +INT cm__bchan_ctrl(CM_CHAN* chan, BOOL turn_on); +INT cm__bchan_ctrl_comp(CM_CHAN *chan, ULONG CompressionFlag); +CM_CHAN* cm__map_chan(VOID* idd, USHORT lterm, USHORT cid); +CM_CHAN* cm__map_bchan_chan(VOID* idd, USHORT port); +INT cm__ans_est_ind(CM_CHAN* chan, IDD_MSG* msg, VOID* idd, USHORT lterm); +INT cm__org_cid_ind(CM_CHAN* chan, IDD_MSG* msg); +INT cm__org_state_ind(CM_CHAN* chan, IDD_MSG* msg); +INT cm__ans_state_ind(CM_CHAN* chan, IDD_MSG* msg); +INT cm__org_elem_ind(CM_CHAN* chan, IDD_MSG* msg); +INT cm__org_data_ind(CM_CHAN* chan, IDD_MSG* msg); +INT cm__ans_data_ind(CM_CHAN* chan, IDD_MSG* msg); +UCHAR cm__calc_chksum(VOID* buf_1, INT len); +CM* cm__get_conn(ULONG conn_index); +INT cm__get_next_chan(CM_CHAN* chan); +INT cm__tx_uus_pkt(CM_CHAN *chan, UCHAR opcode, UCHAR cause); +INT cm__get_bchan(IDD_MSG* msg, USHORT* bchan); +INT cm__get_type(IDD_MSG* msg, USHORT* type); +INT cm__get_addr(IDD_MSG* msg, CHAR addr[32]); +ULONG cm__type2speed(USHORT type); +UCHAR *cm__q931_elem(VOID* ptr_1, INT len, UCHAR elem); +INT cm__timer_tick(CM* cm); +CM_CHAN *cm__chan_alloc(VOID); +VOID cm__chan_free(CM_CHAN* chan); +BOOL cm__chan_foreach(BOOL (*func)(), VOID* a1, VOID* a2); +BOOL cm__inc_chan_num(CM_CHAN* chan, CM_CHAN* ref_chan, ULONG *chan_num); +BOOL cm__add_chan(CM_CHAN* chan, CM_CHAN* ref_chan, CM* cm); +CM* cm__find_listen_conn(CHAR* lname, CHAR* rname, CHAR* addr, VOID*); +VOID ChannelInit(VOID); +VOID ChannelTerm(VOID); +VOID cm__ppp_conn(VOID *idd, USHORT port); +INT WanLineup(VOID* cm_1, NDIS_HANDLE Endpoint); +INT WanLinedown(VOID* cm_1); +ULONG EnumCmInSystem(VOID); +ULONG EnumCmPerAdapter(ADAPTER*); +INT IoEnumCm(VOID* cmd_1); +VOID* CmGetMtl(VOID* cm_1); +UCHAR* GetDstAddr(VOID *cm_1); +UCHAR* GetSrcAddr(VOID *cm_1); +VOID CmPollFunction(VOID *a1, ADAPTER *Adapter, VOID *a3, VOID *a4); +VOID CmSetSwitchStyle(CHAR *SwitchStyle); + +#endif /* _CM_ */ diff --git a/private/ntos/ndis/digi/pcimac/cm_chan.c b/private/ntos/ndis/digi/pcimac/cm_chan.c new file mode 100644 index 000000000..b07b9a52d --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_chan.c @@ -0,0 +1,106 @@ +/* + * CM_CHAN.C - channel allocation (for incoming) code + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CM_CHAN *chan_tbl; +BOOL chan_used[MAX_CHAN_IN_SYSTEM]; + + +#pragma NDIS_INIT_FUNCTION(ChannelInit) + +// +// Allocate free channel pool +// +VOID +ChannelInit(VOID) +{ + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + + /* allocate memory object */ + NdisAllocateMemory((PVOID*)&chan_tbl, sizeof(CM_CHAN) * MAX_CHAN_IN_SYSTEM, 0, pa); + if ( chan_tbl == NULL ) + { + D_LOG(D_ALWAYS, ("ChannelInit: memory allocate failed!")); + return; + } + D_LOG(D_ALWAYS, ("ChannelInit: chan_tbl: 0x%x", chan_tbl)); + NdisZeroMemory (chan_tbl, sizeof(CM_CHAN) * MAX_CHAN_IN_SYSTEM); + NdisZeroMemory (chan_used, sizeof(chan_used)); +} + +VOID +ChannelTerm(VOID) +{ + /* free memory */ + NdisFreeMemory(chan_tbl, sizeof(CM_CHAN) * MAX_CHAN_IN_SYSTEM, 0); +} + +/* allocate a channel */ +CM_CHAN* +cm__chan_alloc(VOID) +{ + CM_CHAN *chan = NULL; + INT n; + + D_LOG(D_ENTRY, ("cm__chan_alloc: entry")); + + for ( n = 0 ; n < MAX_CHAN_IN_SYSTEM ; n++ ) + if ( !chan_used[n] ) + { + chan_used[n] = TRUE; + chan = chan_tbl + n; + break; + } + + D_LOG(D_EXIT, ("cm__alloc_chan: exit, chan: 0x%lx", chan)); + return(chan); +} + +/* free a channel */ +VOID +cm__chan_free(CM_CHAN *chan) +{ + D_LOG(D_ENTRY, ("cm__chan_free: entry, chan: 0x%lx", chan)); + + chan_used[chan - chan_tbl] = FALSE; +} + +/* call a callback function for each used channel */ +BOOL +cm__chan_foreach(BOOL (*func)(), VOID *a1, VOID *a2) +{ + INT n; + BOOL ret = TRUE; + + D_LOG(D_ENTRY, ("cm__chan_foreach: entry, func: %lx, a1: 0x%lx, a2: 0x%lx", \ + func, a1, a2)); + + for ( n = 0 ; n < MAX_CHAN_IN_SYSTEM ; n++ ) + if ( chan_used[n] ) + { + CM_CHAN *chan = chan_tbl + n; + + D_LOG(D_ALWAYS, ("cm__chan_foreach: calling for chan# %d, channel: %lx", n, chan)); + + ret = (*func)(chan, a1, a2); + + D_LOG(D_ALWAYS, ("cm__chan_foreach: returned %d", ret)); + + if ( !ret ) + break; + } + + return(ret); +} diff --git a/private/ntos/ndis/digi/pcimac/cm_conn.c b/private/ntos/ndis/digi/pcimac/cm_conn.c new file mode 100644 index 000000000..66bf2cd8d --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_conn.c @@ -0,0 +1,323 @@ +/* + * CM_CONN.C - connection managment code + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* mark connection as ready to accept calls (listening mode) */ +INT +cm_listen(VOID *cm_1) +{ + CM *cm = (CM*)cm_1; + D_LOG(D_ENTRY, ("cm_listen: entry, cm: 0x%lx", cm)); + + /* connection must be idle */ + if ( cm->state != CM_ST_IDLE ) + return(CM_E_BUSY); + + /* mark & return */ + cm->dprof = cm->oprof; + cm->state = CM_ST_LISTEN; + cm->StateChangeFlag = TRUE; + cm->PPPToDKF = 0; + return(CM_E_SUCC); +} + +/* initiate a connection */ +INT +cm_connect(VOID *cm_1) +{ +#define ABORT(_ret) { ret = _ret; goto aborting; } + CM *cm = (CM*)cm_1; + ULONG n; + INT ret = CM_E_SUCC; + + D_LOG(D_ENTRY, ("cm_connect: entry, cm: 0x%lx", cm)); + + /* connection must be idle or listening */ + if ( (cm->state != CM_ST_IDLE) && (cm->state != CM_ST_LISTEN) ) + return(CM_E_BUSY); + + /* switch connection state to waiting for activation for now */ + cm->state = CM_ST_WAIT_ACT; + cm->StateChangeFlag = TRUE; + + /* copy original profile to dynamic */ + cm->dprof = cm->oprof; + + + /* initialize other fields */ + cm->was_listen = 0; + cm->active_chan_num = 0; + cm->speed = 0; + cm->rx_last_frame_time = cm->tx_last_frame_time = ut_time_now(); + cm->timeout = cm->rx_last_frame_time; + cm->remote_conn_index = 0xff; + cm->CauseValue = 0x7F; + cm->SignalValue = 0xFF; + cm->NoActiveLine = 0; + cm->PPPToDKF = 0; + NdisZeroMemory(cm->DstAddr, sizeof(cm->DstAddr)); + NdisZeroMemory(cm->remote_name, sizeof(cm->remote_name)); + + /* init & check channel vector */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan = cm->dprof.chan_tbl + n; + + /* assign index */ + chan->num = (USHORT)n; + chan->cm = cm; + chan->ustate = 0; + chan->active = 0; + chan->gave_up = 0; + + /* if connection is nailed, channal must be explicit */ + if ( cm->dprof.nailed && !CM_BCHAN_ASSIGNED(chan->bchan) ) + ABORT(CM_E_BADCHAN); + } + + /* if connection is to be activated by frame, exit here */ + if ( cm->dprof.frame_activated ) + return(CM_E_SUCC); + + /* if here, connection has to be activated now! */ + cm->state = CM_ST_IN_ACT; + cm->StateChangeFlag = TRUE; + if ( (ret = cm__initiate_conn(cm)) == CM_E_SUCC ) + return(CM_E_SUCC); + + /* if here, aborting connection */ + aborting: + cm->state = CM_ST_IDLE; + cm->StateChangeFlag = TRUE; + return(ret); +} + +/* disconnect a connection, back to idle state */ +INT +cm_disconnect(VOID *cm_1) +{ + CM *cm = (CM*)cm_1; + ULONG n; + + D_LOG(D_ENTRY, ("cm_disconnect: entry, cm: 0x%lx", cm)); + + /* branch on connection state */ + switch ( cm->state ) + { + case CM_ST_IDLE : /* already idle, do nothing */ + default : + break; + + case CM_ST_LISTEN : /* waiting for a connection, cancel */ + case CM_ST_WAIT_ACT : /* waiting for activation, cancel */ + case CM_ST_DEACT : /* deactivated, cancel */ + cm->state = CM_ST_IDLE; + cm->StateChangeFlag = TRUE; + break; + + case CM_ST_IN_ACT : /* in activation */ + case CM_ST_IN_SYNC : /* syncronizing */ + case CM_ST_ACTIVE : /* is active */ + case CM_ST_IN_ANS : /* in answering process */ + + /* scan channel, issue a disconnect */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++) + { + CM_CHAN *chan = cm->dprof.chan_tbl + n; + + /* check is channel is used in this connection */ + if ( chan->gave_up || !chan->ustate ) + continue; + + /* disconnect it */ + cm__disc_rq(chan); + chan->cid = 0; + } + + /* deactivate connection (not by idle timer) */ + cm__deactivate_conn(cm, 0); + break; + } + + return(CM_E_SUCC); +} + +/* initiate a connection waiting for activation */ +INT +cm__initiate_conn(CM *cm) +{ + ULONG n; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__initiate_conn: entry, cm: 0x%lx\n", cm)); + + /* if connection is nailed, handle here */ + if ( cm->dprof.nailed ) + return(cm__activate_conn(cm, cm->dprof.HWCompression)); + + /* if here, connection is on demand, initate call setup on all chans */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++) + { + CM_CHAN *chan = cm->dprof.chan_tbl + n; + USHORT my_cid = MAKEWORD(chan->num, cm->local_conn_index); + + chan->cid = my_cid; + chan->ustate = CM_US_WAIT_CID; + chan->timeout = ut_time_now(); + + + cm__est_rq(chan); + + } + + return(CM_E_SUCC); +} + +/* activate a connection */ +INT +cm__activate_conn(CM *cm, ULONG CompressionFlag) +{ + ULONG n; + + D_LOG(D_ENTRY, ("cm__activate_conn: entry, cm: 0x%lx", cm)); + + /* mark change of state & time */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + cm->rx_last_frame_time = cm->tx_last_frame_time = cm->timeout = ut_time_now(); + + /* scan active channel, notify mtl, etc. */ + cm->active_chan_num = 0; + for ( n = 0 ; n < cm->dprof.chan_num ; n++) + { + CM_CHAN *chan = cm->dprof.chan_tbl + n; + + /* check is channel is used in this connection */ + if ( chan->gave_up ) + continue; + + // Give Compression command for this channel + cm__bchan_ctrl_comp(chan, CompressionFlag); + + /* turn channel on (may be redundant in demand connections */ + cm__bchan_ctrl(chan, 1); + + /* notify mtl of channel */ + mtl_add_chan(cm->mtl, + chan->idd, + chan->bchan, + chan->speed, + cm->ConnectionType); + + /* accumulate */ + cm->active_chan_num++; + } + + + /* get speed from mtl, tell mtl is connected now! */ + mtl_get_conn_speed(cm->mtl, &cm->speed); + + return(CM_E_SUCC); +} + +/* deactivate a connection */ +INT +cm__deactivate_conn(CM *cm, BOOL by_idle_timer) +{ + ULONG n; + + D_LOG(D_ENTRY, ("cm__deactivate_conn: entry, cm: 0x%lx", cm)); + +// DbgPrint ("DeactivateConn\n"); + /* mark change of state & time */ + cm->state = CM_ST_DEACT; + cm->StateChangeFlag = TRUE; + cm->rx_last_frame_time = cm->tx_last_frame_time = cm->timeout = ut_time_now(); + + /* tell mtl not connected now */ + mtl_set_conn_state(cm->mtl, cm->dprof.chan_num, 0); + + /* scan active channel, notify mtl, etc. */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++) + { + CM_CHAN *chan = cm->dprof.chan_tbl + n; + + /* check is channel is used in this connection */ + if ( chan->gave_up ) + continue; + + /* turn channel off */ + cm__bchan_ctrl(chan, 0); + + /* notify mtl of channel */ + mtl_del_chan(cm->mtl, chan->idd, chan->bchan); + + /* clear channel state */ + chan->ustate = 0; + chan->active = 0; + } + + /* if connection originated as listening, back to idle here */ + if ( cm->was_listen ) + { + make_idle: + cm->state = CM_ST_IDLE; + cm->StateChangeFlag = TRUE; + return(CM_E_SUCC); + } + + /* if connection is not persistant, back to idle */ + if ( !cm->dprof.persist ) + goto make_idle; + + /* if deactivate not by idle timer, back to idle */ + if ( !by_idle_timer ) + goto make_idle; + + /* if here, connection reverts to waiting for activation */ + cm->state = CM_ST_WAIT_ACT; + cm->StateChangeFlag = TRUE; + return(CM_E_SUCC); +} + +/* calc next channel, not implemented yet */ +INT +cm__get_next_chan(CM_CHAN *chan) +{ + CM *cm = (CM*)chan->cm; + + /* restore modified fields */ + chan->bchan = cm->oprof.chan_tbl[chan->num].bchan; + + /* step to next channel type */ + switch ( chan->type ) + { + case CM_CT_D64 : + chan->type = CM_CT_D56; + break; + + case CM_CT_D56 : + chan->type = CM_CT_VOICE; + break; + + case CM_CT_VOICE : + default: + return(CM_E_NOSUCH); + } + + /* if here, succ */ + return(CM_E_SUCC); +} + + diff --git a/private/ntos/ndis/digi/pcimac/cm_init.c b/private/ntos/ndis/digi/pcimac/cm_init.c new file mode 100644 index 000000000..57f2d5262 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_init.c @@ -0,0 +1,488 @@ +/* + * CM_INIT.C - initialization code for CM objects + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* local data structures */ +typedef struct +{ + VOID *idd; + USHORT lterm; + USHORT cid; + CM_CHAN *chan; +} CM_FIND_CHAN; + +typedef struct +{ + VOID *idd; + USHORT bchan; + CM_CHAN *chan; +} CM_FIND_BCHAN; + +/* local connection table */ +CM *cm_tbl[MAX_CM_IN_SYSTEM]; /* table of connection managers */ +BOOL cm_used[MAX_CM_IN_SYSTEM]; /* flags for used cm's */ +BOOL cm_terminated = FALSE; + +BOOL cm__find_chan(CM_CHAN* chan, CM_FIND_CHAN *fc, VOID* a2); +BOOL cm__find_bchan(CM_CHAN* chan, CM_FIND_BCHAN *fc, VOID* a2); +BOOL cm__match_str(CHAR* s1, CHAR* s2); + +/* driver global vars */ +extern DRIVER_BLOCK Pcimac; + +// +// added to support the new switch styles +// +ULONG SwitchStyle = CM_SWITCHSTYLE_NONE; + + +ULONG +EnumCmInSystem() +{ + ULONG n; + + for (n = 0; n < MAX_CM_IN_SYSTEM; n++) + { + if (cm_tbl[n] == NULL) + break; + } + return(n); +} + +ULONG +EnumCmPerAdapter( + ADAPTER *Adapter + ) +{ + ULONG n; + + for (n = 0; n < MAX_CM_PER_ADAPTER; n++) + { + if (Adapter->CmTbl[n] == NULL) + break; + } + return(n); +} + +INT +IoEnumCm(IO_CMD *cmd) +{ + ULONG n; + + cmd->val.enum_cm.num = (USHORT)EnumCmInSystem(); + + for (n = 0; n < cmd->val.enum_cm.num; n++) + { + CM *cm = cm_tbl[n]; + + strcpy(cmd->val.enum_cm.name[n], cm->name); + cmd->val.enum_cm.tbl[n] = cm; + } + + return(0); +} + +VOID* +CmGetMtl( + VOID *cm_1 + ) +{ + CM *cm = (CM*)cm_1; + + return(cm->mtl); +} + + +// +// added to support the new switch styles +// +VOID +CmSetSwitchStyle(CHAR *StyleName) +{ + if (!strcmp(StyleName, "ni1")) + SwitchStyle = CM_SWITCHSTYLE_NI1; + else if (!strcmp(StyleName, "att")) + SwitchStyle = CM_SWITCHSTYLE_ATT; + else if (!strcmp(StyleName, "nti")) + SwitchStyle = CM_SWITCHSTYLE_NTI; + else if (!strcmp(StyleName, "net3")) + SwitchStyle = CM_SWITCHSTYLE_NET3; + else if (!strcmp(StyleName, "1tr6")) + SwitchStyle = CM_SWITCHSTYLE_1TR6; + else if (!strcmp(StyleName, "vn3")) + SwitchStyle = CM_SWITCHSTYLE_VN3; + else if (!strcmp(StyleName, "ins64")) + SwitchStyle = CM_SWITCHSTYLE_INS64; + else + SwitchStyle = CM_SWITCHSTYLE_NONE; +} + +#pragma NDIS_INIT_FUNCTION(cm_init) + +/* initialize cm class */ +INT +cm_init(VOID) +{ + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + D_LOG(D_ENTRY, ("cm_init: entry\n")); + + NdisZeroMemory(cm_tbl, sizeof(cm_tbl)); + NdisZeroMemory(cm_used, sizeof(cm_used)); + + ChannelInit(); + + return(CM_E_SUCC); +} + +/* terminate cm class */ +cm_term() +{ + D_LOG(D_ENTRY, ("cm_term: entry\n")); + + cm_terminated = TRUE; + + // Release Channel Table + ChannelTerm(); + + return(CM_E_SUCC); +} + +/* register an available idd */ +cm_register_idd(VOID *idd) +{ + D_LOG(D_ENTRY, ("cm_register_idd: entry, idd: 0x%lx\n", idd)); + + /* add handles to idd cm/bchan receivers (cm1 may failed!) */ + idd_attach(idd, IDD_PORT_CM0_RX, (VOID*)cm__q931_handler, idd); + idd_attach(idd, IDD_PORT_CM1_RX, (VOID*)cm__q931_handler, idd); + idd_attach(idd, IDD_PORT_B1_RX, (VOID*)cm__q931_bchan_handler, idd); + idd_attach(idd, IDD_PORT_B2_RX, (VOID*)cm__q931_bchan_handler, idd); + + /* ask idp cm to deliver elements */ + cm__elem_rq(idd, IDD_PORT_CM0_TX, "\x08\x34\x18", 3); + cm__elem_rq(idd, IDD_PORT_CM1_TX, "\x08\x34\x18", 3); + + return(CM_E_SUCC); +} + +/* deregister an available idd */ +cm_deregister_idd(VOID *idd) +{ + D_LOG(D_ENTRY, ("cm_deregister_idd: entry, idd: 0x%lx\n", idd)); + + /* remove handle from idd cm receivers */ + idd_detach(idd, IDD_PORT_CM0_RX, (VOID*)cm__q931_handler, idd); + idd_detach(idd, IDD_PORT_CM1_RX, (VOID*)cm__q931_handler, idd); + idd_detach(idd, IDD_PORT_B1_RX, (VOID*)cm__q931_bchan_handler, idd); + idd_detach(idd, IDD_PORT_B2_RX, (VOID*)cm__q931_bchan_handler, idd); + + return(CM_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(cm_create) + +/* create a new cm object */ +cm_create(VOID **ret_cm, NDIS_HANDLE AdapterHandle) +{ + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + INT n; + + D_LOG(D_ENTRY, ("cm_create: entry, ret_cm: 0x%lx\n", ret_cm)); + + /* allocate memory object */ + NdisAllocateMemory((PVOID*)ret_cm, sizeof(CM), 0, pa); + if ( *ret_cm == NULL ) + { + D_LOG(D_ALWAYS, ("cm_create: memory allocate failed!\n")); + NdisWriteErrorLogEntry (AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 0); + return(CM_E_NOMEM); + } + D_LOG(D_ALWAYS, ("cm_create: cm: 0x%x\n", *ret_cm)); + NdisZeroMemory(*ret_cm, sizeof(CM)); + + /* allocate connection out of local table */ + for ( n = 0 ; n < MAX_CM_IN_SYSTEM ; n++ ) + if ( !cm_used[n] ) + break; + if ( n >= MAX_CM_IN_SYSTEM ) + { + /* free memory */ + NdisFreeMemory(*ret_cm, sizeof(CM), 0); + return(CM_E_NOSLOT); + } + + + /* initialize */ + cm_used[n] = 1; + cm_tbl[n] = *ret_cm; + ((CM*)*ret_cm)->local_conn_index = n; + + /* return */ + return(CM_E_SUCC); +} + +/* destory a cm object */ +cm_destroy(VOID *cm_1) +{ + CM* cm = (CM*)cm_1; + D_LOG(D_ENTRY, ("cm_destory: entry, cm: 0x%lx\n", cm)); + + cm_used[cm->local_conn_index] = 0; + cm_tbl[cm->local_conn_index] = NULL; + + // + // disconnect this connection object + // + cm_disconnect (cm); + +// added for dynamic allocation of cm + /* free memory */ + NdisFreeMemory(cm, sizeof(*cm), 0); + + return(CM_E_SUCC); +} + +/* find a channel from an */ +CM_CHAN* +cm__map_chan(VOID* idd, USHORT lterm, USHORT cid) +{ + CM *cm; + CM_CHAN *chan; + ULONG n, m; + CM_FIND_CHAN fc; + + D_LOG(D_ENTRY, ("cm__map_chan: entry: idd: 0x%lx, lterm: 0x%x, cid: 0x%lx\n", idd,lterm,cid)); + + /* scan incoming channel table first */ + fc.idd = idd; + fc.lterm = lterm; + fc.cid = cid; + fc.chan = NULL; + cm__chan_foreach(cm__find_chan, &fc, NULL); + if ( fc.chan ) + return(fc.chan); + + /* scan connection table */ + for ( n = 0; n < MAX_CM_IN_SYSTEM ; n++) + if ( cm_used[n] ) + { + cm = cm_tbl[n]; + switch ( cm->state ) + { + case CM_ST_IN_ACT : + case CM_ST_IN_SYNC : + case CM_ST_ACTIVE : + case CM_ST_IN_ANS : + for ( m = 0, chan = cm->dprof.chan_tbl ; + m < cm->dprof.chan_num ; m++, chan++ ) + if ( (idd == chan->idd) && + (lterm == chan->lterm) && + (cid == chan->cid) ) + return(chan); + break; + } + } + + /* if here, failed! */ + return(NULL); +} + +/* find a bchannel from an */ +CM_CHAN* +cm__map_bchan_chan(VOID *idd, USHORT bchan) +{ + CM *cm; + CM_CHAN *chan; + ULONG n, m; + CM_FIND_BCHAN fc; + + D_LOG(D_ENTRY, ("cm__map_bchan_chan: idd: 0x%lx, bchan: 0x%x\n", \ + idd,bchan)); + + /* scan incoming channel table first */ + fc.idd = idd; + fc.bchan = bchan; + fc.chan = NULL; + cm__chan_foreach(cm__find_bchan, &fc, NULL); + if ( fc.chan ) + return(fc.chan); + + /* scan connection table */ + for ( n = 0; n < MAX_CM_IN_SYSTEM ; n++) + if ( cm_used[n] ) + { + cm = cm_tbl[n]; + switch ( cm->state ) + { + case CM_ST_IN_ACT : + case CM_ST_IN_SYNC : + case CM_ST_ACTIVE : + case CM_ST_IN_ANS : + for ( m = 0, chan = cm->dprof.chan_tbl ; + m < cm->dprof.chan_num ; m++, chan++ ) + if ( (idd == chan->idd) && + (bchan == chan->bchan) && + (chan->ustate >= 10) ) + return(chan); + break; + } + } + + /* if here, failed! */ + return(NULL); +} + +/* return connection by index */ +CM* +cm__get_conn(ULONG index) +{ + /* check range */ + if ( index >= MAX_CM_IN_SYSTEM ) + return(NULL); + + /* check used */ + if ( !cm_used[index] ) + return(NULL); + + /* return it */ + return(cm_tbl[index]); +} + +/* find a matching listening connection */ +CM* +cm__find_listen_conn(CHAR *lname, CHAR *rname, CHAR *addr, VOID *Idd) +{ + CM *cm; + ULONG n; + + D_LOG(D_ENTRY, ("cm__find_listen_conn: entry, lname: [%s], rname: [%s], addr: [%s]\n", \ + lname, rname, addr)); + + /* scan connection table */ + for ( n = 0; n < MAX_CM_IN_SYSTEM ; n++) + { + cm = cm_tbl[n]; + if ( cm_used[n] && (cm->idd == Idd) && (cm->state == CM_ST_LISTEN) ) + { + D_LOG(D_ENTRY, ("cm__find_listen_conn: comparing to: name: [%s], remote_name: [%s]\n", \ + cm->dprof.name, cm->dprof.remote_name)); + if ( cm__match_str(cm->dprof.name, rname) && + cm__match_str(cm->dprof.remote_name, lname) ) + return(cm); + } + } + + return(NULL); +} + +/* 1 second timer tick, poll active cm's */ +VOID +CmPollFunction(VOID *a1, ADAPTER *Adapter, VOID *a3, VOID *a4) +{ + ULONG n; + + /* if terminated, ignore */ + if ( cm_terminated ) + return; + + /* poll active cm's */ + for ( n = 0; n < MAX_CM_PER_ADAPTER ; n++) + { + CM *cm = Adapter->CmTbl[n]; + + if (cm) + { + cm__timer_tick(cm); + if (cm->PrevState != cm->state || cm->StateChangeFlag == TRUE) + { + cm->PrevState = cm->state; + cm->StateChangeFlag = FALSE; + DoTapiStateCheck(cm); + } + } + } + + /* rearm timer */ + NdisMSetTimer(&Adapter->CmPollTimer, CM_POLL_T); +} + +/* assist routine for finding a channel. stop scan when found */ +BOOL +cm__find_chan(CM_CHAN *chan, CM_FIND_CHAN *fc, VOID *a2) +{ + if ( (chan->idd == fc->idd) && (chan->lterm == fc->lterm) && + (chan->cid == fc->cid) ) + { + fc->chan = chan; + return(FALSE); + } + + return(TRUE); +} + +/* assist routine for finding a channel by bchan. stop scan when found */ +BOOL +cm__find_bchan(CM_CHAN *chan, CM_FIND_BCHAN *fc, VOID *a2) +{ + if ( (chan->idd == fc->idd) && (chan->bchan == fc->bchan) ) + { + fc->chan = chan; + return(FALSE); + } + + return(TRUE); +} + +/* match two strings. allow for wild characters */ +BOOL +cm__match_str(CHAR *s1, CHAR *s2) +{ + /* march on strings, process wild characters '*' and '?' */ + for ( ; *s1 && *s2 ; s1++, s2++ ) + if ( (*s1 == '*') || (*s2 == '*') ) + return(TRUE); + else if ( (*s1 == '?') || (*s2 == '?') ) + continue; + else if ( *s1 != *s2 ) + return(FALSE); + + /* if here, atleast one string ended, other must end here */ + return( (*s1 | *s2) ? FALSE : TRUE ); +} + +UCHAR* +GetDstAddr( + VOID *cm_1 + ) +{ + CM *cm = (CM*)cm_1; + + return(&cm->DstAddr[0]); +} + +UCHAR* +GetSrcAddr( + VOID *cm_1 + ) +{ + CM *cm = (CM*)cm_1; + + return(&cm->SrcAddr[0]); +} diff --git a/private/ntos/ndis/digi/pcimac/cm_prof.c b/private/ntos/ndis/digi/pcimac/cm_prof.c new file mode 100644 index 000000000..be6376c65 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_prof.c @@ -0,0 +1,51 @@ +/* + * CM_PROF.C - profile related code + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* set profile in cm */ +INT +cm_set_profile(VOID *cm_1, CM_PROF *prof) +{ + CM *cm = (CM*)cm_1; + D_LOG(D_ENTRY, ("cm_set_prof: entry, cm: 0x%lx, prof: 0x%lx", cm, prof)); + + /* connection must be idle to change profile! */ + if ( cm->state != CM_ST_IDLE ) + return(CM_E_BUSY); + + /* set & return */ + cm->oprof = *prof; + + return(CM_E_SUCC); +} + +/* get profile from cm */ +INT +cm_get_profile(VOID *cm_1, CM_PROF *prof) +{ + CM *cm = (CM*)cm_1; + D_LOG(D_ENTRY, ("cm_get_prof: entry, cm: 0x%lx, prof: 0x%lx", cm, prof)); + + /* connection must has a profile */ + if ( !cm->oprof.name[0] ) + return(CM_E_NOSUCH); + + /* set & return */ + *prof = cm->dprof; + + return(CM_E_SUCC); +} + + diff --git a/private/ntos/ndis/digi/pcimac/cm_pub.h b/private/ntos/ndis/digi/pcimac/cm_pub.h new file mode 100644 index 000000000..a58af5eb0 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_pub.h @@ -0,0 +1,134 @@ +/* + * CM_PUB.H - definitions for connection manager + */ + +#ifndef _CM_PUB_ +#define _CM_PUB_ + +// +// global cm def's +// +/* a channel descriptor */ +typedef struct +{ + VOID* idd; /* related idd */ + USHORT lterm; /* logical terminal in idd */ + CHAR addr[32]; /* address to used - phone no. */ + + USHORT bchan; /* related b channel */ +#define CM_BCHAN_B1 0 /* - b1 */ +#define CM_BCHAN_B2 1 /* - b2 */ +#define CM_BCHAN_ANY 2 /* - any */ +#define CM_BCHAN_NONE 3 /* - no bchannel related */ +#define CM_BCHAN_ASSIGNED(_b) \ + ((_b) < 3) /* check for 'assigned' b channel */ + + USHORT type; /* channel type */ +#define CM_CT_D64 0 /* - digital 64 kbps */ +#define CM_CT_D56 1 /* - digital 56 kbps */ +#define CM_CT_VOICE 2 /* - digital voice/56 kbps */ + ULONG speed; /* channel speed, in bps */ + + USHORT ustate; /* ustate (q.931) of channel */ + USHORT cid; /* connection id, idp allocated */ + + USHORT num; /* channel number within connection */ + VOID *cm; /* related connection manager */ + + UCHAR DstAddr[6]; /* ethernet address of remote side */ + UCHAR remote_conn_index; /* connection # of remote connection */ + + ULONG timeout; /* used for dead-man timeouts */ + + BOOL active; /* channel is active? */ + BOOL gave_up; /* gave-up on channel? */ + + ULONG flag; /* general purpose flag */ +} CM_CHAN; + +/* a profile descriptor */ +typedef struct +{ + BOOL nailed; /* nailed/demand access */ + BOOL persist; /* connection persistance */ + BOOL permanent; /* connection is permanent? */ + BOOL frame_activated; /* connection activate by frame? */ + BOOL fallback; /* fallback on channels */ + BOOL HWCompression; // Compression negotiation on/off + + ULONG rx_idle_timer; /* idle timer for rx side */ + ULONG tx_idle_timer; /* idle timer for tx side */ + + USHORT chan_num; /* # of channels requested */ + CM_CHAN chan_tbl[MAX_CHAN_PER_CONN]; /* requested channel descriptor */ + + CHAR name[32]; /* name of this profile */ + CHAR remote_name[32]; /* name of remote profile */ +} CM_PROF; + +/* connection status descriptor */ +typedef struct _CM +{ + CHAR name[64]; /* name for this object */ + + CHAR LocalAddress[32]; /* address in format NetCard#-Line#-EndPoint */ + + USHORT state; /* connection state */ +#define CM_ST_IDLE 0 /* - idle */ +#define CM_ST_WAIT_ACT 1 /* - waiting for frame activation */ +#define CM_ST_IN_ACT 2 /* - in activation */ +#define CM_ST_IN_SYNC 3 /* - in syncronization */ +#define CM_ST_ACTIVE 4 /* - connection is active! */ +#define CM_ST_LISTEN 5 /* - is listening */ +#define CM_ST_IN_ANS 6 /* - in answering process */ +#define CM_ST_DEACT 7 /* - in deactivation process */ + + USHORT PrevState; /* used to track event signal states */ + USHORT StateChangeFlag; /* used to signal state changes */ + + CM_PROF dprof; /* related profile - dynamic copy */ + CM_PROF oprof; /* related profile - original copy */ + + BOOL was_listen; /* connection started as a listener? */ + ULONG active_chan_num; /* # of active channels */ + ULONG speed; /* connection speed, bps */ + ULONG ConnectionType; /* 0/1 - ppp/dkf */ + + ULONG rx_last_frame_time; /* last time rx frame recorded */ + ULONG tx_last_frame_time; /* last time tx frame recorded */ + + UCHAR local_conn_index; /* local connection # */ + UCHAR SrcAddr[6]; /* local side ethernet address */ + + UCHAR remote_conn_index; /* remote side connection # */ + UCHAR DstAddr[6]; /* remote side ethernet address */ + CHAR remote_name[32]; /* name of remote profile */ + + ULONG timeout; /* dead-man timeout */ + + VOID *mtl; /* related mtl, internal */ + VOID *idd; /* related idd */ + VOID *Adapter; /* related adapter, internal */ + + VOID *TapiLineInfo; // back pointer to owning line + + NDIS_HANDLE LinkHandle; // assigned during lineup + + ULONG htCall; // tapi's handle to the call + + ULONG TapiCallState; // tapi's call state + + ULONG CallState; // our call state + + ULONG AppSpecific; // app specific storage + + UCHAR CauseValue; // Cause Value in Disc or Rel Messages + UCHAR SignalValue; // Signal Value in CallProc or CallProg Messages + UCHAR CalledAddress[32]; // Address that was called + UCHAR CallingAddress[32]; // Address of caller + ULONG PPPToDKF; // Flag to signal a change from PPP to DKF + ULONG NoActiveLine; // Flag to indicate when no line is detected +} CM_STATUS, CM; + +#endif /* _CM_PUB_ */ + diff --git a/private/ntos/ndis/digi/pcimac/cm_q931.c b/private/ntos/ndis/digi/pcimac/cm_q931.c new file mode 100644 index 000000000..453fe3f84 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_q931.c @@ -0,0 +1,943 @@ +/* + * CM_Q931.C - q931 handling module. mainly outgoing side + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern ULONG SwitchStyle; + +/* local assist, copy data into buffer & advance pointer */ +#define adv_ptr(_p, _buf, _len) \ + { \ + NdisMoveMemory((_p), _buf, _len); \ + (_p) += _len; \ + } + +/* format an establish request */ +INT +cm__est_rq(CM_CHAN *chan) +{ + IDD_MSG msg; + UCHAR *p; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__est_rq: entry, chan: 0x%lx\n", chan)); + + /* clear outgoing message */ + NdisZeroMemory(&msg, sizeof(msg)); + + /* allocate a local buffer */ + if ( !(msg.bufptr = p = ut_get_buf()) ) + goto give_up; + + // + // added to support the new switch styles + // TB 03/14 + // + if (SwitchStyle != CM_SWITCHSTYLE_1TR6) + { + /* build bearer capabilities element */ + switch ( chan->type ) + { + case CM_CT_VOICE : + adv_ptr(p, ((SwitchStyle == CM_SWITCHSTYLE_NET3) ? + "\x04\x03\x80\x90\xA3" : + "\x04\x03\x80\x90\xA2"), 5); + chan->speed = 56000; + break; + + case CM_CT_D56 : + adv_ptr(p, "\x04\x04\x88\x90\x21\x8F", 6); + chan->speed = 56000; + break; + + default : + case CM_CT_D64 : + adv_ptr(p, "\x04\x02\x88\x90", 4); + chan->speed = 64000; + break; + } + } + + /* channel id element */ + switch ( chan->bchan ) + { + case CM_BCHAN_B1 : adv_ptr(p, "\x18\x01\x89", 3); + break; + case CM_BCHAN_B2 : adv_ptr(p, "\x18\x01\x8A", 3); + break; + default : + case CM_BCHAN_ANY : adv_ptr(p, "\x18\x01\x83", 3); + break; + } + + // + // added to support the new switch styles + // TB 03/14 + // + if (SwitchStyle != CM_SWITCHSTYLE_1TR6 + && SwitchStyle != CM_SWITCHSTYLE_NET3) + { + /* called number/address */ + *p++ = 0x2C; + *p++ = strlen(chan->addr); + adv_ptr(p, chan->addr, p[-1]); + } + else + { + // + // added to support the new switch styles + // TB 03/14 + // + *p++ = 0x70; + *p++ = strlen(chan->addr) + 1; + *p++ = (SwitchStyle == CM_SWITCHSTYLE_1TR6) ? 0x81 : 0x80; + adv_ptr(p, chan->addr, strlen(chan->addr)); + } + + // + // added for net3 fix + // TB 04/13 + // + if (SwitchStyle == CM_SWITCHSTYLE_NET3) + *p++ = 0xA1; // Sending Complete + + // + // added to support the new switch styles + // TB 03/14 + // + if (SwitchStyle == CM_SWITCHSTYLE_1TR6) + { + *p++ = 0x96; + *p++ = 0x01; + switch (chan->type) + { + case CM_CT_VOICE: + adv_ptr(p, "\x02\x01\x01", 3); + break; + + case CM_CT_D56: + case CM_CT_D64: + default: + adv_ptr(p, "\x02\x07\x00", 3); + break; + } + } + + /* fillin message structure */ + msg.opcode = Q931_EST_RQ; + msg.buflen = p - msg.bufptr; + msg.bufid = MAKELONG(chan->cid, 0); + chan->cid = 0; + + /* send to idd */ + if ( idd_send_msg(chan->idd, &msg, (USHORT)CM_PORT(chan), + (VOID*)cm__q931_cmpl_handler, chan) != IDD_E_SUCC ) + { + /* failed, give up on channel */ + give_up: + chan->gave_up = 1; + ut_free_buf(msg.bufptr); + return(CM_E_IDD); + } + + D_LOG(D_EXIT|DIGIQ931, ("cm__est_rq: exit\n")); + return(CM_E_SUCC); +} + +/* format an establish response */ +INT +cm__est_rsp(CM_CHAN *chan) +{ + IDD_MSG msg; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__est_rsp: entry, chan: 0x%lx\n", chan)); + + /* clear outgoing message */ + NdisZeroMemory(&msg, sizeof(msg)); + + /* fillin message structure */ + msg.opcode = Q931_EST_RSP; + msg.bufid = MAKELONG(0, chan->cid); + msg.bufptr = ut_get_buf(); + msg.buflen = 0; + + + /* send to idd */ + if (idd_send_msg(chan->idd, &msg, (USHORT)CM_PORT(chan), (VOID*)cm__q931_cmpl_handler, NULL) != IDD_E_SUCC) + ut_free_buf(msg.bufptr); + + return(CM_E_SUCC); +} + +/* format a call ignore response */ +INT +cm__est_ignore( + PVOID idd, + USHORT cid, + USHORT lterm) +{ + IDD_MSG msg; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__est_ignore: entry, idd: 0x%lx, cid: 0x%x, lterm: 0x%x\n", idd, cid, lterm)); + + /* clear outgoing message */ + NdisZeroMemory(&msg, sizeof(msg)); + + /* fillin message structure */ + msg.opcode = Q931_EST_IGNORE; + msg.bufid = MAKELONG(0, cid); + msg.bufptr = ut_get_buf(); + msg.buflen = 0; + + + /* send to idd */ + if (idd_send_msg(idd, &msg, (USHORT)(lterm + IDD_PORT_CM0_TX), (VOID*)cm__q931_cmpl_handler, NULL) != IDD_E_SUCC) + ut_free_buf(msg.bufptr); + + return(CM_E_SUCC); +} + +/* format a disconenct request */ +INT +cm__disc_rq(CM_CHAN *chan) +{ + IDD_MSG msg; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__disc_rq: entry, chan: 0x%lx\n", chan)); + + /* clear outgoing message */ + NdisZeroMemory(&msg, sizeof(msg)); + + /* fillin message structure */ + msg.opcode = Q931_REL_RQ; + msg.bufid = MAKELONG(0, chan->cid); + msg.bufptr = ut_get_buf(); + msg.buflen = 0; + + /* send to idd */ + if (idd_send_msg(chan->idd, &msg, (USHORT)CM_PORT(chan), (VOID*)cm__q931_cmpl_handler, NULL) != IDD_E_SUCC) + ut_free_buf(msg.bufptr); + + + /* turn off channel */ + cm__bchan_ctrl(chan, 0); + return(CM_E_SUCC); +} + +/* control data transfer on a bchannel */ +INT +cm__bchan_ctrl(CM_CHAN *chan, BOOL turn_on) +{ + USHORT is_ans, subchan, op; + IDD_MSG msg; + CM *cm = chan->cm; + ULONG IddFramingType = IDD_FRAME_DETECT; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__bchan_ctrl: entry, chan: 0x%lx, turn_on: %d, active: %d\n", \ + chan, + turn_on, + chan->active)); + + // + // check for a redundant operation + // + if ((!chan->active && !turn_on) || + (chan->active && turn_on)) + return(CM_E_SUCC); + + /* channel must be assigned */ + if ( !CM_BCHAN_ASSIGNED(chan->bchan) ) + return(CM_E_BADCHAN); + + cm__bchan_ctrl_comp( chan, 0 ); + + /* find out if on answering side */ + if ( cm ) + is_ans = cm->was_listen ? 0x0100 : 0x0000; + else + is_ans = 0x0100; + + /* map channel type to operation */ + if ( !turn_on ) + op = CMD_BCHAN_OFF; + else + { + switch ( chan->type ) + { + case CM_CT_VOICE : op = CMD_BCHAN_VOICE; break; + case CM_CT_D56 : op = CMD_BCHAN_56; break; + default : + case CM_CT_D64 : op = CMD_BCHAN_HDLC; break; + } + + chan->speed = cm__type2speed(chan->type); + } + + /* build subchannel descriptor */ + subchan = 0x1717; + + /* build msg */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = op; + msg.bufid = MAKELONG(is_ans | chan->bchan | (subchan << 1), 0); + + /* send it */ + idd_send_msg(chan->idd, &msg, IDD_PORT_CMD_TX, NULL, NULL); + + // + // Set rx framing mode + // + // if channel is being turned off + // + // channel off - rxmode = IDD_FRAME_DONTCARE + // + if (!turn_on) + IddFramingType = IDD_FRAME_DONTCARE; + + IddSetRxFraming(chan->idd, chan->bchan, IddFramingType); + + /* mark channel active state */ + chan->active = turn_on; + + return(CM_E_SUCC); +} + + +/* control data transfer on a bchannel */ +INT +cm__bchan_ctrl_comp(CM_CHAN *chan, ULONG CompressionFlag) +{ + IDD_MSG msg; + USHORT Enable = 0; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__bchan_ctrl_comp: entry, chan: 0x%lx, state: %d\n", \ + chan, CompressionFlag)); + + /* channel must be assigned */ + if ( !CM_BCHAN_ASSIGNED(chan->bchan) ) + return(CM_E_BADCHAN); + + /* map channel type to operation */ + if ( CompressionFlag ) + Enable = COMP_TX_ENA | COMP_RX_ENA; + + /* build msg */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = CMD_COMPRESS; + msg.bufid = MAKELONG( chan->bchan | ( Enable << 8 ), 0); + + /* send it */ + idd_send_msg(chan->idd, &msg, IDD_PORT_CMD_TX, NULL, NULL); + + return(CM_E_SUCC); +} + + +/* issue an element request to idp cm port */ +INT +cm__elem_rq(VOID *idd, USHORT port, CHAR *elem_buf, USHORT elem_len) +{ + IDD_MSG msg; + CHAR *p; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__elem_rq: entry, idd: 0x%lx, port: 0x%d, elem_buf: 0x%lx, elem_len: 0x%d\n", \ + idd, port, elem_buf, elem_len)); + + /* clear outgoing message */ + NdisZeroMemory(&msg, sizeof(msg)); + + /* allocate a local buffer */ + if ( !(msg.bufptr = p = ut_get_buf()) ) + return(CM_E_NOMEM); + + /* copy buffer */ + adv_ptr(p, elem_buf, (INT)elem_len); + + /* fillin message structure */ + msg.opcode = Q931_ELEM_RQ; + msg.buflen = p - msg.bufptr; + + /* send to idd */ + if ( idd_send_msg(idd, &msg, port, + (VOID*)cm__q931_cmpl_handler, NULL) != IDD_E_SUCC ) + { + ut_free_buf(msg.bufptr); + return(CM_E_IDD); + } + + return(CM_E_SUCC); +} + +/* completion handler for q931 command with attached local buffers */ +VOID +cm__q931_cmpl_handler(VOID *arg, USHORT port, IDD_MSG *msg) +{ + D_LOG(D_ENTRY|DIGIQ931, ("cm__q931_cmpl_handler: arg: 0x%lx, port: 0x%d, msg: 0x%lx\n", \ + arg, port, msg)); + + /* free attached buffer */ + ut_free_buf(msg->bufptr); +} + +/* handler for q931 events */ +VOID +cm__q931_handler(IDD *idd, USHORT port, ULONG Reserved, IDD_MSG *msg) +{ + USHORT lterm; + CM_CHAN *chan; + CM *cm; + extern BOOL cm_terminated; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__q931_handler: entry, idd: 0x%lx, port: %d, msg: 0x%lx\n", \ + idd, port, msg)); + D_LOG(DIGIQ931, ("cm_q931_handler: msg->opcode: 0x%x\n", msg->opcode)); + + /* ignore if already terminated */ + if ( cm_terminated ) + return; + + /* convert port to logical terminal */ + lterm = port - IDD_PORT_CM0_RX; + + /* try resolving idd/lterm/cid into a channel */ + if ( chan = cm__map_chan(idd, lterm, HIWORD(msg->bufid)) ) + cm = chan->cm; + else + cm = NULL; + + D_LOG(DIGIQ931, ("cm_q931_handler: chan: 0x%lx, cm: 0x%lx\n", chan, cm)); + + // + // since q.931 stuff touches this so much it is easier to + // copy locally then to keep track of adapter memory access + // + NdisZeroMemory(idd->RxBuffer, sizeof(idd->RxBuffer)); + IddGetDataFromAdapter(idd, + (PUCHAR)idd->RxBuffer, + (PUCHAR)msg->bufptr, + (USHORT)MIN(IDP_MAX_RX_BUFFER, msg->buflen)); + + msg->bufptr = idd->RxBuffer; + + D_LOG(DIGIQ931, ("cm_q931_handler: msg->opcode: 0x%x", msg->opcode)); + + /* switch to message handler */ + switch ( msg->opcode ) + { + case Q931_EST_IND : + D_LOG(DIGIQ931, (" (Q931_EST_IND)\n")); + cm__ans_est_ind(chan, (IDD_MSG*)msg, idd, lterm); + break; + + case Q931_CID_IND : + D_LOG(DIGIQ931, (" (Q931_CID_IND)\n")); + cm__org_cid_ind(chan, (IDD_MSG*)msg); + break; + + case Q931_P_STATE_IND: + D_LOG(DIGIQ931, (" (Q931_P_STATE_IND)\n")); + break; + + case Q931_STATE_IND : + D_LOG(DIGIQ931, (" (Q931_STATE_IND)\n")); + if ( !chan || cm ) + cm__org_state_ind(chan, (IDD_MSG*)msg); + else if ( chan ) + cm__ans_state_ind(chan, (IDD_MSG*)msg); + break; + + case Q931_ELEM_IND : + D_LOG(DIGIQ931, (" (Q931_ELEM_IND)\n")); + if ( cm && !cm->was_listen ) + cm__org_elem_ind(chan, (IDD_MSG*)msg); + break; + + default : + D_LOG(DIGIQ931, (" (Unknown)\n")); + break; + } +} + +VOID +cm__ppp_conn(VOID *idd, USHORT port) +{ + CM_CHAN *chan; + CM *cm; + ULONG n, CompressionFlag; + IDD_MSG msg1; + + /* try resolving idd/bchan into a channel */ + if ( !(chan = cm__map_bchan_chan(idd, port)) ) + return; + + // + // if this channel is already connected no need to do this stuff + // + if (chan->ustate == CM_US_CONN) + return; + + // + // kill dead man timer for this channel + // + NdisZeroMemory(&msg1, sizeof(IDD_MSG)); + msg1.opcode = Q931_CAN_TU10_RQ; + msg1.bufptr = ut_get_buf(); + msg1.buflen = 0; + msg1.bufid = MAKELONG(0, chan->cid); + + /* send to idd */ + if (idd_send_msg(chan->idd, &msg1, (USHORT)CM_PORT(chan), (VOID*)cm__q931_cmpl_handler, NULL) != IDD_E_SUCC) + ut_free_buf(msg1.bufptr); + + NdisZeroMemory(chan->DstAddr, sizeof(chan->DstAddr)); + + /* last channel, find matching connection/profile */ + if ( !(cm = cm__find_listen_conn("*", "*", "*", idd)) ) + { + /* none found, reject */ + D_LOG(DIGIQ931, ("cm__ppp_con: no listener found\n")); + return; + } + + /* matching connection found!, fillin */ + D_LOG(DIGIQ931, ("cm__ppp_conn: matching connection: chan: 0x%lx, cm: 0x%lx\n", + chan, + cm)); + + chan->remote_conn_index = 1; + + cm->state = CM_ST_IN_ANS; + cm->StateChangeFlag = TRUE; + cm->was_listen = TRUE; + cm->active_chan_num = 1; + cm->remote_conn_index = chan->remote_conn_index; + cm->ConnectionType = CM_PPP; + NdisMoveMemory(cm->DstAddr, chan->DstAddr, 6); + NdisZeroMemory(cm->remote_name, sizeof(cm->remote_name)); + + cm->timeout = cm->rx_last_frame_time = cm->tx_last_frame_time = + ut_time_now(); + + /* accept channel here */ + chan->ustate = CM_US_UUS_OKED; + chan->timeout = ut_time_now(); + chan->cm = cm; + + /* collect channels info local vector */ + cm->dprof.chan_num = 0; + cm__chan_foreach(cm__add_chan, chan, cm); + + /* init channel fields */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + chan1->ustate = CM_US_CONN; + chan1->timeout = ut_time_now(); + chan1->num = (USHORT)n; + chan1->cm = cm; + chan1->active = TRUE; + } + + /* make connection active */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + + // Set compression Flag + CompressionFlag = 0; + + cm__activate_conn(cm, CompressionFlag); + + return; +} + + +/* handler for bchannel data */ +VOID +cm__q931_bchan_handler( + IDD *idd, + USHORT port, + ULONG RxFrameType, + IDD_XMSG *msg + ) +{ + CM_CHAN *chan; + IDD_MSG msg1; + UCHAR DetectBytes[2]; + extern BOOL cm_terminated; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__q931_bchan_handler: entry, idd: 0x%lx, port: %d, msg: 0x%lx\n", \ + idd, port, msg)); + + /* ignore if terminated */ + if ( cm_terminated ) + return; + + // + // check to see if this port is servicing DKF or PPP + // + if (RxFrameType != IDD_FRAME_DKF) + return; + + // + // see if this is really uus or dror data + // if not uus we don't want to do all of the copying that we + // would do for uus + // + IddGetDataFromAdapter(idd, + (PUCHAR)&DetectBytes, + (PUCHAR)msg->bufptr, + 2); + +// NdisMoveMemory((PUCHAR)&DetectBytes, (PUCHAR)msg->bufptr, 2 * sizeof(UCHAR)); + + if ( (msg->buflen < 4) || DetectBytes[0] != DKF_UUS_SIG || DetectBytes[1]) + return; + + // + // since uus stuff touches this so much it is easier to + // copy locally then to keep track of adapter memory access + // + NdisZeroMemory(idd->RxBuffer, sizeof(idd->RxBuffer)); + IddGetDataFromAdapter(idd, + (PUCHAR)idd->RxBuffer, + (PUCHAR)msg->bufptr, + (USHORT)MIN(IDP_MAX_RX_BUFFER, msg->buflen)); + + msg->bufptr = idd->RxBuffer; + + D_LOG(DIGIQ931, ("cm__q931_bchan_handler: msg->buflen: 0x%x, DetectByte[0]: 0x%x\n", \ + msg->buflen, DetectBytes[0])); + + /* try resolving idd/bchan into a channel */ + if ( !(chan = cm__map_bchan_chan(idd, port)) ) + return; + + // + // make a copy of the message without the header or + // fragmentation flags + // + NdisMoveMemory(&msg1, msg, sizeof(IDD_MSG)); + msg1.bufptr += 4; + msg1.buflen -= 4; + + /* call handler */ + if ( chan->cm && !((CM*)(chan->cm))->was_listen ) + cm__org_data_ind(chan, &msg1); + else + cm__ans_data_ind(chan, &msg1); +} + +/* transmit a uus packet */ +INT +cm__tx_uus_pkt(CM_CHAN *chan, UCHAR opcode, UCHAR cause) +{ + CHAR *p; + IDD_MSG msg; + CM_UUS *uus; + CM *cm = chan->cm; + + /* must have a channel at this time */ + if ( !CM_BCHAN_ASSIGNED(chan->bchan) ) + return(CM_E_BADCHAN); + + /* allocate a buffer for uus */ + if ( !(p = ut_get_buf()) ) + return(CM_E_NOMEM); + + /* init messages structure */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.bufptr = p; + msg.buflen = 4 + CM_UUS_SIZE; + + /* build frame header */ + *p++ = 0x50; + *p++ = 0x00; + *p++ = 0x00; + *p++ = 0x00; + uus = (CM_UUS*)p; + + /* init uus */ + NdisZeroMemory(uus, sizeof(*uus)); + NdisMoveMemory(uus->dst_addr, "\xff\xff\xff\xff\xff\xff", 6); + + if ( cm ) + NdisMoveMemory(uus->src_addr, cm->SrcAddr, sizeof(uus->src_addr)); + uus->pkt_type = CM_PKT_TYPE; + uus->prot_desc = CM_PROT_DESC; + uus->opcode = opcode; + uus->cause = cause; + uus->option_0 = 0; + + if (cm) + if (cm->dprof.HWCompression) + uus->option_0 = UUS_0_COMPRESSION; + + /* install connection fields */ + uus->conn = cm ? cm->local_conn_index : 0; + uus->channum = cm ? (UCHAR)cm->dprof.chan_num : 0; + uus->chan = (UCHAR)chan->num; + if ( cm ) + { + NdisMoveMemory(uus->lname, cm->dprof.name, sizeof(uus->lname)); + NdisMoveMemory(uus->rname, cm->dprof.remote_name, sizeof(uus->rname)); + cm->tx_last_frame_time = ut_time_now(); + } + + /* calc chksum */ + uus->chksum = 256 - cm__calc_chksum(uus, CM_UUS_SIZE); + + /* send message to idd */ + if ( idd_send_msg(chan->idd, &msg, chan->bchan, (VOID*)cm__q931_cmpl_handler, chan) + != IDD_E_SUCC ) + ut_free_buf(msg.bufptr); + + return(CM_E_SUCC); +} + +/* get channel identification out of q931 element buffer */ +INT +cm__get_bchan(IDD_MSG *msg, USHORT *bchan) +{ + UCHAR *elem; + + + /* locate channel id element */ + if ( !(elem = cm__q931_elem(msg->bufptr, msg->buflen, 0x18)) ) + return(CM_E_NOSUCH); + else + elem++; + + /* verify length */ + if ( *elem++ != 0x1 ) + return(CM_E_NOSUCH); + + /* extract b channel */ + if ( *elem == 0x89 ) + *bchan = CM_BCHAN_B1; + else if ( *elem == 0x8A ) + *bchan = CM_BCHAN_B2; + else + return(CM_E_NOSUCH); + + /* if here, succ */ + return(CM_E_SUCC); +} + +/* get channel type out of q931 element buffer */ +INT +cm__get_type(IDD_MSG *msg, USHORT *type) +{ + UCHAR *elem, elem_len; + + /* locate type element */ + if ( !(elem = cm__q931_elem(msg->bufptr, msg->buflen, 0x04)) ) + return(CM_E_NOSUCH); + else + elem++; + elem_len = *elem++; + + // + // added to support the new switch styles + // TB 03/14 + // + if (SwitchStyle == CM_SWITCHSTYLE_1TR6) + { + switch (*elem) + { + case 0x01: + *type = CM_CT_VOICE; + return(CM_E_SUCC); + + case 0x07: + *type = CM_CT_D64; + return(CM_E_SUCC); + + default: + return(CM_E_BADPARAM); + } + } + + /* if information transfer type is speech, -> voice */ + if ( (*elem++ & 0x1F) == 0 ) + { + *type = CM_CT_VOICE; + return(CM_E_SUCC); + } + + /* trasnfer mode & type must be 64 */ + if ( (*elem++ & 0x7F) != 0x10 ) + return(CM_E_BADPARAM); + + /* if end of element here, must be 64 */ + if ( elem_len == 2 ) + { + *type = CM_CT_D64; + return(CM_E_SUCC); + } + + /* check for 56 */ + if ( (elem_len >= 4) && + ((*elem++ & 0x7F) == 0x21) && + ((*elem++ & 0x7F) == 0x0F) ) + { + *type = CM_CT_D56; + return(CM_E_SUCC); + } + + /* if here, unknown */ + return(CM_E_BADPARAM); +} + +/* get caller address out of q931 element buffer */ +INT +cm__get_addr(IDD_MSG *msg, CHAR addr[32]) +{ + UCHAR *elem, elem_len; + + /* locate type element */ + if ( !(elem = cm__q931_elem(msg->bufptr, msg->buflen, 0x6C)) ) + return(CM_E_NOSUCH); + else + elem++; + +// Subtracting 1 looks like a mistake +// TB 11.09.93 +// if ( (elem_len = *elem++ - 1) > 32 ) +// elem_len = 31; + if ( (elem_len = *elem++) > 32 ) + elem_len = 31; + + if (elem_len < 2) + return(CM_E_NOSUCH); + + elem += 2; + elem_len -= 2; + + /* copy in & terminate */ + NdisMoveMemory (addr, elem, elem_len); + addr[elem_len] = '\0'; + + return(CM_E_SUCC); +} + +/* scan q931 element buffer for a specific element */ +UCHAR* +cm__q931_elem(VOID *ptr_1, INT len, UCHAR elem) +{ + UCHAR *ptr = (UCHAR*)ptr_1; + CHAR codeset = 0; /* starting with code set 0 */ + CHAR prev_codeset; /* saving area for prev. codeset */ + CHAR locked = 1; /* locked/nonlocked codeset shift */ + + /* loop while length left */ + while ( len > 0 ) + { + /* handle shifting codesets */ + if ( (*ptr & 0xF0) == 0x90 /*Q931_IE0_SHIFT*/ ) + { + prev_codeset = codeset; /* save current code set */ + codeset = *ptr & 0x07; /* extract new codeset */ + locked = !(*ptr & 0x08); /* ... and locking status */ + ptr++; /* move past shift element */ + len--; + continue; + } + + /* check for codeset 0 */ + if ( codeset != 0 ) /* non codeset0 elements, just skip */ + { + if ( *ptr & 0x80 ) + { + ptr++; + len--; + } + // + // added to support the new switch styles + // TB 03/14 + // + else if (SwitchStyle == CM_SWITCHSTYLE_1TR6 && + elem == 0x04 && + *ptr == 0x01) + { + return(ptr); + } + else + { + len -= (2 + ptr[1]); + ptr += (ptr[1] + 2); + } + + if ( !locked ) + { + codeset = prev_codeset; + locked = 1; + } + + continue; /* move to next element */ + } + + /* try to match elem from codeset 0 */ + if ( *ptr & 0x80 ) /* single octet elem? */ + { /* yes */ + if ( (((elem & 0xF0) == 0xA0) && (elem == (UCHAR)*ptr)) || + (((elem & 0x80) == 0x80) && (elem == (UCHAR)(*ptr & 0xF0))) ) + { /* element found */ + return(ptr); + } + else + { + ptr++; /* skip this elem */ + len--; + } + } + else + { + if ( *ptr == elem ) + { /* multi byte elem match */ + return(ptr); + } + else + { + len -= (2 + ptr[1]); + ptr += (ptr[1] + 2); + } + } + + /* resert codeset if not locked */ + if ( !locked ) + { + codeset = prev_codeset; + locked = 1; + } + } + + /* if here, not found */ + return(NULL); +} + +/* convert channel type to speed */ +ULONG +cm__type2speed(USHORT type) +{ + switch ( type ) + { + case CM_CT_VOICE : + case CM_CT_D56 : + return(56000); + + case CM_CT_D64 : + default : + return(64000); + } +} diff --git a/private/ntos/ndis/digi/pcimac/cm_stat.c b/private/ntos/ndis/digi/pcimac/cm_stat.c new file mode 100644 index 000000000..87c11cd69 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_stat.c @@ -0,0 +1,31 @@ +/* + * CM_STAT.C - status related code + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* get status from cm (note that CM == CM_STATUS for now!) */ +INT +cm_get_status(VOID *cm_1, CM_STATUS *stat) +{ + CM* cm = (CM*)cm_1; + + D_LOG(D_ENTRY, ("cm_get_status: entry, cm: 0x%lx, stat: 0x%lx", cm, stat)); + + /* set & return */ + *stat = *cm; + return(CM_E_SUCC); +} + + + diff --git a/private/ntos/ndis/digi/pcimac/cm_state.c b/private/ntos/ndis/digi/pcimac/cm_state.c new file mode 100644 index 000000000..646feba1c --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_state.c @@ -0,0 +1,757 @@ +/* + * CM_STATE.C - q931 state managment code + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* (ans) process incoming connections */ +INT +cm__ans_est_ind(CM_CHAN *chan, IDD_MSG *msg, VOID *idd, USHORT lterm) +{ + USHORT bchan, type, cid; + INT RetCode; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__ans_est_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + cid = HIWORD(msg->bufid); + + /* must not have a channel at this time */ + if ( chan ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: on used channel, ignored!\n")); + + RetCode = CM_E_BADPARAM; + + // + // we need to let the adapter know that we are not processing + // this incoming call indication + // + ignored: + + /* answer channel */ + cm__est_ignore(idd, cid, lterm); + + return(RetCode); + } + + /* extract info out of message, must have bchan/type */ + if ( (cm__get_bchan(msg, &bchan) != CM_E_SUCC) || + (cm__get_type(msg, &type) != CM_E_SUCC) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: bchan or type missing, ignored!\n")); + + RetCode = CM_E_BADPARAM; + goto ignored; + } + + if ( !CM_BCHAN_ASSIGNED(bchan) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: bchan: %d, unassigned, ignored!\n",\ + bchan)); + RetCode = CM_E_BADPARAM; + goto ignored; + } + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: cid: 0x%x, bchan: %d, type: 0x%d\n",\ + cid, bchan, type)); + + /* channel will be answered only if a listening profile exists */ + if ( !cm__find_listen_conn("*", "*", "*", idd) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: not listening profile, ignored!\n")); + RetCode = CM_E_NOSUCH; + goto ignored; + } + + /* allocate a channel out of incoming channel poll */ + if ( !(chan = cm__chan_alloc()) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: no channel slot, ignored!\n")); + RetCode = CM_E_NOSLOT; + goto ignored; + } + + /* fillup channel structure */ + NdisZeroMemory(chan, sizeof(*chan)); + chan->idd = idd; + chan->lterm = lterm; + chan->bchan = bchan; + chan->type = type; + chan->speed = cm__type2speed(type); + chan->ustate = CM_US_UNDEF; + chan->cid = cid; + chan->timeout = ut_time_now(); + + /* extract caller address, if present */ + if ( cm__get_addr(msg, chan->addr) != CM_E_SUCC ) + __strcpy(chan->addr, ""); + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: caller address is: %s\n", \ + chan->addr)); + + /* answer channel */ + cm__est_rsp(chan); + + /* return succ */ + return(CM_E_SUCC); +} + +/* (ans) process state indications */ +INT +cm__ans_state_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + D_LOG(D_ENTRY|DIGIQ931, ("cm__ans_state_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* log state change */ + chan->ustate = LOWORD(msg->bufid); + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_state_ind: ustate: %d\n", chan->ustate)); + + /* if changed to U0, has been released */ + if ( !chan->ustate ) + { + cm__bchan_ctrl(chan, 0); + cm__chan_free(chan); + return(CM_E_SUCC); + } + + /* if changed to U10, just got connected, open data path */ + if ( chan->ustate == 10 ) + { + cm__bchan_ctrl(chan, 1); + chan->timeout = ut_time_now(); + return(CM_E_SUCC); + } + + /* else ignore */ + return(CM_E_SUCC); +} + +/* (ans) process data indications */ +INT +cm__ans_data_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM_UUS *uus; + ULONG chan_num, n; + UCHAR cause; + CM *cm; + ULONG CompressionFlag = 0; + IDD_MSG msg1; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__ans_data_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* assign UUS pointer & do some basic checks */ + uus = (CM_UUS*)msg->bufptr; + if ( msg->buflen < CM_UUS_SIZE ) + return(CM_E_BADUUS); + + if ( (uus->pkt_type != CM_PKT_TYPE) || + (uus->prot_desc != CM_PROT_DESC) || + (cm__calc_chksum(uus, CM_UUS_SIZE) != 0) ) + return(CM_E_BADUUS); + + /* channel must be atleast connected */ + if ( chan->ustate < 10 ) + return(CM_E_BADSTATE); + + /* if channel already accepted assoc, accept again (other side lost) */ + if ( chan->ustate == CM_US_UUS_OKED ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: chan_num->ustate: %d\n", chan->ustate)); + accept: + chan->ustate = CM_US_UUS_OKED; + chan->timeout = ut_time_now(); + cm__tx_uus_pkt(chan, CM_ASSOC_ACK, 0); + return(CM_E_SUCC); + } + + /* record information from uus */ + NdisMoveMemory (chan->DstAddr, uus->src_addr, 6); + + chan->remote_conn_index = uus->conn; + + // + // kill dead man timer for this channel + // + NdisZeroMemory(&msg1, sizeof(IDD_MSG)); + msg1.opcode = Q931_CAN_TU10_RQ; + msg1.bufptr = ut_get_buf(); + msg1.buflen = 0; + msg1.bufid = MAKELONG(0, chan->cid); + + /* send to idd */ + if (idd_send_msg(chan->idd, &msg1, (USHORT)CM_PORT(chan), (VOID*)cm__q931_cmpl_handler, NULL) != IDD_E_SUCC) + ut_free_buf(msg1.bufptr); + + + /* if not last channel, accept */ + chan_num = 0; + cm__chan_foreach(cm__inc_chan_num, chan, &chan_num); + if ( (UCHAR)chan_num < uus->channum ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: chan_num: %d, uus->channum: %d\n", chan_num, uus->channum)); + goto accept; + } + + + /* last channel, find matching connection/profile */ + if ( !(cm = cm__find_listen_conn(uus->lname, uus->rname, chan->addr, chan->idd)) ) + { + /* none found, reject */ + cause = CM_NO_PROF; + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: rejected, cause: %d\n", cause)); + cm__tx_uus_pkt(chan, CM_ASSOC_NACK, cause); + return(CM_E_NOSUCH); + } + + /* matching connection found!, fillin */ + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: matching connection: cm: 0x%lx\n", cm)); + + cm->state = CM_ST_IN_ANS; + cm->StateChangeFlag = TRUE; + cm->was_listen = TRUE; + cm->active_chan_num = chan_num; + cm->remote_conn_index = chan->remote_conn_index; + cm->ConnectionType = CM_DKF; + NdisMoveMemory(cm->DstAddr, chan->DstAddr, 6); + NdisMoveMemory (cm->remote_name, uus->rname, sizeof(cm->remote_name)); + + cm->timeout = cm->rx_last_frame_time = cm->tx_last_frame_time = + ut_time_now(); + + /* accept channel here */ + chan->ustate = CM_US_UUS_OKED; + chan->timeout = ut_time_now(); + chan->cm = cm; + cm__tx_uus_pkt(chan, CM_ASSOC_ACK, 0); + + + /* collect channels info local vector */ + cm->dprof.chan_num = 0; + cm__chan_foreach(cm__add_chan, chan, cm); + + /* init channel fields */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++) + { + CM_CHAN *chan = cm->dprof.chan_tbl + n; + + chan->ustate = CM_US_CONN; + chan->timeout = ut_time_now(); + chan->num = (USHORT)n; + chan->cm = cm; + chan->active = TRUE; + } + + /* make connection active */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + + // Set compression Flag + if (cm->dprof.HWCompression && (uus->option_0 & UUS_0_COMPRESSION)) + CompressionFlag = 1; + else + CompressionFlag = 0; + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: Activating connection for cm: 0x%lx\n", cm)); + return(cm__activate_conn(cm, CompressionFlag)); +} + +/* (org) new cid indicated on outgoing channel */ +INT +cm__org_cid_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM *cm; + USHORT conn_num, chan_num, cid; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_cid_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* extract conn_num/chan_num out of param 3, get cid */ + conn_num = HIBYTE(LOWORD(msg->bufid)); + chan_num = LOBYTE(LOWORD(msg->bufid)); + cid = HIWORD(msg->bufid); + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_cid_ind: conn_num: %d, chan_num: %d, cid: 0x%x\n", conn_num, chan_num, cid)); + +// DbgPrint("cid_ind: conn_num: %d, chan_num: %d, cid: 0x%x\n", +// conn_num, chan_num, cid); + + /* get related connection */ + if ( !(cm = cm__get_conn(conn_num)) ) + { +// DbgPrint("cid_ind: cm__get_conn failed!\n"); + return(CM_E_BADPARAM); + } + + /* get related channel */ + if ( chan_num >= cm->dprof.chan_num ) + { +// DbgPrint("cid_ind: invalid chan_num!\n"); + return(CM_E_BADPARAM); + } + else + chan = cm->dprof.chan_tbl + chan_num; + + /* check channel ustate */ + if ( chan->ustate != CM_US_WAIT_CID ) + { +// DbgPrint("cid_ind: invalid ustate (%d)!\n", chan->ustate); + return(CM_E_BADSTATE); + } + + /* cid == 0, no free slots at idp, simulate state change to 0 */ + if ( !cid ) + { + cm->NoActiveLine = 1; + return(cm__org_state_ind(chan, NULL)); + } + + /* assign params */ + chan->ustate = CM_US_UNDEF; + chan->cid = cid; +// DbgPrint("cid_ind: ustate: %d, cid: 0x%x assigned\n", chan->ustate, chan->cid); + + return(CM_E_SUCC); +} + +/* (org) process state indications */ +INT +cm__org_state_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM *cm; + ULONG n; + USHORT gave_up_num, chan_num; + ULONG CompressionFlag; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_state_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* check for change of state at protocol level */ + if ( !chan ) + { + /* not used for now */ + return(CM_E_NOTIMPL); + } + + /* log change */ + cm = chan->cm; + + chan->ustate = msg ? LOWORD(msg->bufid) : 0; + + D_LOG(DIGIQ931,("cm__org_state_ind: cm 0x%lx, ustate: 0x%x\n", \ + cm, chan->ustate)); + + /* if changed to U0, has been released, may retry connection here */ + if ( !chan->ustate ) + { + /* turn off bchannel */ + cm__bchan_ctrl(chan, 0); + + /* if not in activation, this is a fatal error, disconnect */ + if ( cm->state != CM_ST_IN_ACT ) + { + disc_all: + + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->ustate > 0 ) + cm__disc_rq(chan1); + } + + /* deactivate connection */ + cm__deactivate_conn(cm, 0); + + return(CM_E_SUCC); + } + + /* attampt to retry */ + if ( !cm->dprof.fallback || + (cm->CauseValue == 0x11 || cm->SignalValue == 0x04) || + (cm__get_next_chan(chan) != CM_E_SUCC) ) + { + chan->ustate = CM_US_GAVE_UP; + chan->gave_up = 1; + } + else + { + /* if here, retrying */ + chan->cid = MAKEWORD(chan->num, cm->local_conn_index); + chan->ustate = CM_US_WAIT_CID; + chan->timeout = ut_time_now(); + + cm__est_rq(chan); + } + + /* find out how many channels gave up (or connected) */ + check_chan: + for ( n = gave_up_num = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( cm->dprof.chan_tbl[n].gave_up ) + gave_up_num++; + else if ( cm->dprof.chan_tbl[n].ustate != CM_US_WAIT_CONN ) + break; + + /* if broke out of loop before hitting chan_num, some channels + are still in progress */ + if ( n < cm->dprof.chan_num ) + return(CM_E_SUCC); + + /* if all gave up, give up conn */ + if ( gave_up_num >= cm->dprof.chan_num ) + { + cm__deactivate_conn(cm, 0); + return(CM_E_SUCC); + } + + /* if here, some channels connected and some gave up, continue */ + chan_num = cm->dprof.chan_num - gave_up_num; + + /* if fallback set to no, must match */ + if ( !cm->dprof.fallback && (chan_num != cm->dprof.chan_num) ) + goto disc_all; + + /* connection enters in_sync state */ + cm->state = CM_ST_IN_SYNC; + cm->StateChangeFlag = TRUE; + cm->timeout = ut_time_now(); + + /* compact channel table & renumber */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->gave_up ) + { + NdisMoveMemory(cm->dprof.chan_tbl + n, + cm->dprof.chan_tbl + n + 1, + sizeof(CM_CHAN) * (cm->dprof.chan_num - n - 1)); + cm->dprof.chan_num--; + n--; + } + } + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + cm->dprof.chan_tbl[n].num = (USHORT)n; + + if (cm->ConnectionType == CM_DKF) + { + // + // if this is a uus connnection tx uus frames + // + /* send initial uus_rq on all active channels */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->gave_up ) + continue; + + chan1->timeout = ut_time_now(); + chan1->ustate = CM_US_UUS_SEND; + + cm__tx_uus_pkt(chan1, CM_ASSOC_RQ, 0); + } + } + else + { + // + // if this is a ppp connection mark channels + // as being connected and activate the connection + // + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->gave_up ) + continue; + + chan1->ustate = CM_US_CONN; + chan1->timeout = ut_time_now(); + chan1->remote_conn_index = 1; + } + NdisZeroMemory(cm->DstAddr, sizeof(cm->DstAddr)); + NdisZeroMemory(cm->remote_name, sizeof(cm->remote_name)); + + /* make connection active now */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + CompressionFlag = 0; + + return (cm__activate_conn(cm, CompressionFlag)); + } + + return(CM_E_SUCC); + } + + /* if change state to U10 just connected */ + if ( chan->ustate == 10 ) + { + /* start data transfer on channel */ + cm__bchan_ctrl(chan, 1); + chan->ustate = CM_US_WAIT_CONN; + chan->timeout = ut_time_now(); + + /* see if all channels are connected, continue as a change to U0 */ + goto check_chan; + } +} + +/* (org) process data indications */ +INT +cm__org_data_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM_UUS *uus; + CM *cm = chan->cm; + ULONG n, first; + ULONG CompressionFlag; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_data_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + + /* assign UUS pointer & do some basic checks */ + uus = (CM_UUS*)msg->bufptr; + if ( msg->buflen < CM_UUS_SIZE ) + return(CM_E_BADUUS); + if ( (uus->pkt_type != CM_PKT_TYPE) || + (uus->prot_desc != CM_PROT_DESC) || + (cm__calc_chksum(uus, CM_UUS_SIZE) != 0) ) + return(CM_E_BADUUS); + + /* channel must be atleast connected */ + if ( chan->ustate < 10 ) + return(CM_E_BADSTATE); + + /* if is a request, channel is part of a listening conn */ + if ( uus->opcode == CM_ASSOC_RQ ) + { + cm__tx_uus_pkt(chan, CM_ASSOC_ACK, 0); + return(CM_E_SUCC); + } + + /* if nack detected, connection is torn down */ + if ( uus->opcode == CM_ASSOC_NACK ) + { +// disc_all: + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->ustate > 0 ) + cm__disc_rq(chan1); + } + + /* deactivate connection */ + cm__deactivate_conn(cm, 0); + + return(CM_E_SUCC); + } + + /* if here must be an ack */ + if ( uus->opcode != CM_ASSOC_ACK ) + return(CM_E_BADUUS); + + /* if channel already connected and uus ack'ed - ignore */ + if ( chan->ustate > CM_US_UUS_OKED ) + return(CM_E_SUCC); + + // + // if this flag is set then we originally had a PPP connection + // this means that all of the connection stuff is taken care of and + // we just need to satisfy the remote ends uus requirements. + // there should be only one channel in this case! + // + if (cm->PPPToDKF) + { + chan->ustate = CM_US_CONN; + NdisMoveMemory (chan->DstAddr, uus->src_addr, 6); + NdisMoveMemory(cm->DstAddr, chan->DstAddr, 6); + cm->remote_conn_index = cm->dprof.chan_tbl[0].remote_conn_index; + NdisMoveMemory(cm->remote_name, uus->lname, sizeof(cm->remote_name)); + cm->PPPToDKF = 0; + return(CM_E_SUCC); + } + + /* if here, it is an ack */ + chan->ustate = CM_US_UUS_OKED; + chan->timeout = ut_time_now(); + + NdisMoveMemory (chan->DstAddr, uus->src_addr, 6); + + chan->remote_conn_index = uus->conn; + + /* proceed only if all channels ok'ed */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( !cm->dprof.chan_tbl[n].gave_up && + (cm->dprof.chan_tbl[n].ustate != CM_US_UUS_OKED) ) + return(CM_E_SUCC); + + /* verify all channel got connected to the same eaddr/conn */ + for ( first = 0 ; first < cm->dprof.chan_num ; first++ ) + if ( !cm->dprof.chan_tbl[n].gave_up ) + break; + + /* move all channels to connected state */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( !cm->dprof.chan_tbl[n].gave_up ) + { + cm->dprof.chan_tbl[n].ustate = CM_US_CONN; + cm->dprof.chan_tbl[n].timeout = ut_time_now(); + } + +// Hack to get around no cm for all channels < the last channel received + NdisMoveMemory(cm->DstAddr, chan->DstAddr, 6); + + /* store some values on a connection level */ + cm->remote_conn_index = cm->dprof.chan_tbl[first].remote_conn_index; + NdisMoveMemory(cm->remote_name, uus->lname, sizeof(cm->remote_name)); + + /* make connection active now */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + + // Set compression Flag + if (cm->dprof.HWCompression && (uus->option_0 & UUS_0_COMPRESSION)) + CompressionFlag = 1; + else + CompressionFlag = 0; + + return(cm__activate_conn(cm, CompressionFlag)); +} + +/* (org) process element indications */ +INT +cm__org_elem_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + USHORT bchan; + int auto_disc = 0; + CHAR *elem; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_elem_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* must have a valid channel to proceed */ + if ( !chan ) + return(CM_E_SUCC); + + /* check if bchannel reported */ + if ( cm__get_bchan(msg, &bchan) == CM_E_SUCC ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: bchan: %d\n", bchan)); + + if ( !CM_BCHAN_ASSIGNED(chan->bchan) ) + auto_disc |= 1; + else + chan->bchan = bchan; + } + + /* scan for cause */ + if ( (elem = cm__q931_elem(msg->bufptr, msg->buflen, 0x08)) && + (elem[1] >= 2) && !(elem[2] & 0x78) ) + { + static CHAR disc_vals[] = { 0x01, 0x11, 0x12 }; + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: cause: 0x%x\n", elem[3] & 0x7F)); + + if ( __memchr((PUCHAR)disc_vals,(CHAR) elem[3] & 0x7F, (ULONG) sizeof(disc_vals)) ) + { + CM *cm = (CM*)chan->cm; + + cm->CauseValue = elem[3] & 0x7F; + auto_disc |= 2; + } + } + + /* scan for signal */ + if ( (elem = cm__q931_elem(msg->bufptr, msg->buflen, 0x34)) && + (elem[1] == 1) ) + { +// static CHAR signal_vals[] = { 0x00, 0x03, 0x04, 0x0C }; + static CHAR signal_vals[] = { 0x03, 0x04, 0x0C }; + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: signal: 0x%x\n", elem[2])); + + if ( __memchr(signal_vals, elem[2], sizeof(signal_vals)) ) + { + CM *cm = (CM*)chan->cm; + + cm->SignalValue = elem[2]; + auto_disc |= 4; + } + } + + /* check if need to disconnect */ + if ( auto_disc ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: auto_disc: 0x%x\n", auto_disc)); + cm__disc_rq(chan); + } + + return(CM_E_SUCC); +} + +/* calc a checksum for a buffer */ +UCHAR +cm__calc_chksum(VOID *buf_1, INT len) +{ + UCHAR *buf = (UCHAR *)buf_1; + UCHAR sum; + + for ( sum = 0 ; len ; len-- ) + sum += *buf++; + + return(sum); +} + +/* increment a channel count */ +BOOL +cm__inc_chan_num(CM_CHAN *chan, CM_CHAN *ref_chan, ULONG *chan_num) +{ + /* find if this channel is part of same connection as ref_chan */ + if ( memcmp(chan->DstAddr, ref_chan->DstAddr, 6) || + (chan->remote_conn_index != ref_chan->remote_conn_index) ) + return(TRUE); + + /* inrement here */ + *chan_num += 1; + return(TRUE); +} + +/* add a channel to a connection */ +BOOL +cm__add_chan(CM_CHAN *chan, CM_CHAN *ref_chan, CM *cm) +{ + CM_CHAN *chan1; + + /* if connection already full, stop here */ + if ( cm->dprof.chan_num >= cm->active_chan_num ) + return(FALSE); + + /* find if this channel is part of same connection as ref_chan */ + if ( memcmp(chan->DstAddr, ref_chan->DstAddr, 6) || + (chan->remote_conn_index != ref_chan->remote_conn_index) ) + return(TRUE); + + /* add this channel */ + chan1 = &cm->dprof.chan_tbl[cm->dprof.chan_num++]; + *chan1 = *chan; + cm__chan_free(chan); + return(TRUE); +} + + + + diff --git a/private/ntos/ndis/digi/pcimac/cm_timer.c b/private/ntos/ndis/digi/pcimac/cm_timer.c new file mode 100644 index 000000000..20ce83bd0 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_timer.c @@ -0,0 +1,78 @@ +/* + * CM_TIMER.C - time code for cm module + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* timer values defined here */ +#define T1 30 /* 30 seconds to leave connection transient state */ +#define T2 4 /* 4 seconds to activate permanent connection */ + +/* timer tick entry point. called no faster then once a second! */ +INT +cm__timer_tick(CM *cm) +{ + ULONG n; + BOOL disc_by_idle_timer = FALSE; + + /* check for dead-man time in transient state */ + if ( (cm->state == CM_ST_IN_SYNC) || (cm->state == CM_ST_IN_ACT) ) + { + if ( (ut_time_now() - cm->timeout) > T1 ) + { + disc_all: + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( !cm->dprof.chan_tbl[n].gave_up ) + cm__disc_rq(cm->dprof.chan_tbl + n); + + return(cm__deactivate_conn(cm, disc_by_idle_timer)); + } + } + + /* if active now, check for idle timers */ + if ( cm->state == CM_ST_ACTIVE ) + { + if ( (cm->dprof.rx_idle_timer && + ((ut_time_now() - cm->rx_last_frame_time) > cm->dprof.rx_idle_timer)) || + (cm->dprof.tx_idle_timer && + ((ut_time_now() - cm->tx_last_frame_time) > cm->dprof.tx_idle_timer)) ) + { + disc_by_idle_timer = TRUE; + goto disc_all; + } + } + + /* check if connection has to activate as being permanent */ + if ( (cm->state == CM_ST_WAIT_ACT) && cm->dprof.permanent ) + { + if ( (ut_time_now() - cm->timeout) > T2 ) + { + cm->state = CM_ST_IN_ACT; + cm->timeout = ut_time_now(); + return(cm__initiate_conn(cm)); + } + } + + /* if in_sync, resend uus on channels requiring it */ + // + // if we are stuck in sync state the resend uus on all channels requiring it + // if we are in an ACTIVE state and the PPPToDKF Flag is set we need to send + // uus until they acknowledged + // + if ( cm->state == CM_ST_IN_SYNC || (cm->state == CM_ST_ACTIVE && cm->PPPToDKF)) + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( cm->dprof.chan_tbl[n].ustate == CM_US_UUS_SEND ) + cm__tx_uus_pkt(cm->dprof.chan_tbl + n, CM_ASSOC_RQ, 0); +} + + diff --git a/private/ntos/ndis/digi/pcimac/cnf.h b/private/ntos/ndis/digi/pcimac/cnf.h new file mode 100644 index 000000000..a897e0b22 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cnf.h @@ -0,0 +1,13 @@ +/* + * CNF_PUB.H - config module public defs + */ + +/* class operations */ +BOOL cnf_get_long(CHAR* path, CHAR* key, + ULONG* ret_val, ULONG def_val); +BOOL cnf_get_str(CHAR* path, CHAR* key, + CHAR* ret_val, ULONG maxlen, CHAR* def_val); +BOOL cnf_get_multi_str(CHAR* path, CHAR* key, + CHAR* store_buf, ULONG store_len, + CHAR** str_vec, ULONG str_max, ULONG* str_num, + CHAR** def_vec, ULONG def_num); diff --git a/private/ntos/ndis/digi/pcimac/dgbrip.h b/private/ntos/ndis/digi/pcimac/dgbrip.h new file mode 100644 index 000000000..0897fb1f3 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/dgbrip.h @@ -0,0 +1,33 @@ +#ifndef DGBRIP_H +#define DGBRIP_H + +/*++ +***************************************************************************** +* * +* 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. * +* * +***************************************************************************** +++*/ + + +typedef enum _DIGI_BRI_COMMAND_ +{ + BRIOldMethod = LastGeneralID + 1 +} DIGI_BRI_COMMAND; + +typedef struct _DIGI_OLD_METHOD_ +{ + IO_CMD ioCmd; +} DIGI_OLD_METHOD, *PDIGI_OLD_METHOD; + + +#endif diff --git a/private/ntos/ndis/digi/pcimac/disp.c b/private/ntos/ndis/digi/pcimac/disp.c new file mode 100644 index 000000000..8e80ca2bc --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/disp.c @@ -0,0 +1,105 @@ +/* + * DISP.C - debug display routines for NDIS environment + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if DBG +#define DISP_DEBUG 1 +#endif + +INT d_level = -1; /* current debug level */ +INT d_mode = 0; /* display mode: 0-dbg, 1-msg */ +INT d_cmplen = 0; /* lenght of filename string for compare */ +CHAR d_filestr[8]; /* filename string for compare */ +NDIS_SPIN_LOCK DebugLock; + +VOID +d_log_init (VOID) +{ + NdisAllocateSpinLock (&DebugLock); +} + +VOID +d_log_term (VOID) +{ + NdisFreeSpinLock (&DebugLock); +} + + +/* check if logging enabled on file,line,level (for now, always on) */ +INT +d_log_on(CHAR *file, INT line, INT level) +{ + CHAR *fname; + + if ( level > d_level ) + return(0); + + if ( fname = __strrchr(file, '\\') ) + fname++; + else + fname = file; + + if(d_cmplen && __strnicmp(fname,d_filestr,d_cmplen)) + return(0); + + NdisAcquireSpinLock(&DebugLock); + DbgPrint("PCIMAC.SYS: "); + + return(1); +} + +/* do output processing for logging */ +VOID +d_log_out(CHAR* fmt, ...) +{ + static CHAR buf[256]; + va_list marker; + + va_start (marker, fmt); +#if !BINARY_COMPATIBLE + vsprintf (buf, fmt, marker); +#endif + va_end (marker); + DbgPrint ("%s\n",buf); + + NdisReleaseSpinLock(&DebugLock); + +} + +VOID +InternalSetDebugLevel (INT DebugLevel) +{ + d_level = DebugLevel; +} + + +VOID +SetDebugLevel (VOID *cmd1) +{ + IO_CMD *cmd = (IO_CMD*)cmd1; + d_level = (INT)cmd->arg[0]; + d_cmplen = (INT)cmd->val.dbg_level.cmplen; + if(d_cmplen) + NdisMoveMemory(d_filestr,cmd->val.dbg_level.filestr,d_cmplen); + + if ( d_level != -1 ) + { + d_mode = d_level / 1000; + d_level = d_level % 1000; + } +} + diff --git a/private/ntos/ndis/digi/pcimac/disp.h b/private/ntos/ndis/digi/pcimac/disp.h new file mode 100644 index 000000000..b79bbf5fe --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/disp.h @@ -0,0 +1,147 @@ +/* + * DISP.H - debug display macro's under NDIS + */ + +#ifndef _DISP_ +#define _DISP_ + +#if !BINARY_COMPATIBLE +#include "digifile.h" +#include "memprint.h" +#else +#define DbgBreakPoint() {__asm { int 3 };} +#endif + +extern ULONG DigiDebugLevel; + +#define DIGIINIT ((ULONG)0x00000001) +#define DIGISETINFO ((ULONG)0x00000002) +#define DIGIGETINFO ((ULONG)0x00000004) +#define DIGIWANINFO ((ULONG)0x00000008) +#define DIGISXBINFO ((ULONG)0x00000010) +#define DIGITAPIINFO ((ULONG)0x00000020) +#define DIGIRECVDATA ((ULONG)0x00000040) +#define DIGITXDATA ((ULONG)0x00000080) +#define DIGIRARE ((ULONG)0x00000100) +#define DIGIWANERR ((ULONG)0x00000200) +#define DIGIWANERRDATA ((ULONG)0x00000400) +#define DIGIRXDATA ((ULONG)0x00000800) +#define DIGIWANOID ((ULONG)0x00010000) +#define DIGIQ931 ((ULONG)0x00020000) +#define DIGIIRP ((ULONG)0x00040000) +#define DIGIWAIT ((ULONG)0x00080000) +#define DIGITXFRAGDATA ((ULONG)0x00100000) +#define DIGIRXFRAGDATA ((ULONG)0x00200000) +#define DIGIIDD ((ULONG)0x00400000) +#define DIGINEVER ((ULONG)0x00800000) +#define DIGIATLASFLOW ((ULONG)0x01000000) +#define DIGIWINISDN ((ULONG)0x02000000) +#define DIGICALLSTATES ((ULONG)0x04000000) +#define DIGIMTL ((ULONG)0x08000000) +#define DIGIFLOW ((ULONG)0x10000000) +#define DIGIERRORS ((ULONG)0x20000000) +#define DIGINOTIMPLEMENTED ((ULONG)0x40000000) +#define DIGIBUGCHECK ((ULONG)0x80000000) +#define DIGIINFO (DIGIGETINFO | DIGISETINFO) + +#if DBG + +#define DigiAssert 1 +#if DigiAssert +#undef ASSERT +#define ASSERT( STRING ) \ + if( !(STRING) ) \ + { \ + DbgPrint( "ASSERT failed: " #STRING "\nfile: %s, line %d\n", __FILE__, __LINE__ ); \ + DbgBreakPoint(); \ + } +#endif + +#define DigiDump(LEVEL,STRING) \ + do { \ + ULONG _level = (LEVEL); \ + if ((DigiDebugLevel & _level) || (_level & DIGINOTIMPLEMENTED)) \ + { \ + DbgPrint STRING; \ + } \ + if (_level & DIGIBUGCHECK) \ + { \ + ASSERT(FALSE); \ + } \ + } while (0) + +#define DigiDumpData(LEVEL, DATA, LEN) \ + do \ + { \ + ULONG _DataLevel = (LEVEL); \ + ULONG _i, _k; \ + ULONG _len = (LEN); \ + PCHAR _data = (DATA); \ + \ + _k = 0; \ + while( _k <= _len ) \ + { \ + if( (_len - _k) > 16 ) \ + { \ + for( _i = 0; _i < 16; _i++ ) \ + { \ + DigiDump( _DataLevel, ( "%02x ", (_data[_i] & 0xFF)) ); \ + _k++; \ + } \ + \ + DigiDump( _DataLevel, ( " ") ); \ + \ + for( _i = 0; _i < 16; _i++ ) \ + { \ + if( _data[_i] >= 0x20 && _data[_i] <= 0x7E ) \ + DigiDump( _DataLevel, ( "%c",_data[_i]) ); \ + else \ + DigiDump( _DataLevel, ( ".") ); \ + } \ + DigiDump( _DataLevel, ( "\n") ); \ + _data += _i; \ + } \ + else \ + { \ + for( _i = 0; _i < (_len - _k); _i++ ) \ + { \ + DigiDump( _DataLevel, ( "%02x ",(_data[_i] & 0xFF)) ); \ + } \ + \ + for( _i = 0; _i < (16 - (_len - _k)); _i++ ) \ + DigiDump( _DataLevel, ( " ") ); \ + \ + DigiDump( _DataLevel, ( " ") ); \ + \ + for( _i = 0; _i < (_len - _k); _i++ ) \ + { \ + if(_data[_i] >= 0x20 && _data[_i] <= 0x7E) \ + DigiDump( _DataLevel, ( "%c",_data[_i]) ); \ + else \ + DigiDump( _DataLevel, ( ".") ); \ + } \ + DigiDump( _DataLevel, ( "\n") ); \ + break; \ + } \ + } \ + } while ( 0 ); + +#else +#define DigiDump(LEVEL,STRING) do {NOTHING;} while (0) +#define DigiDumpData(LEVEL,DATA,LEN) do {NOTHING;} while (0) +#endif + +/* main macro to be used for logging */ +#define D_LOG(level, args) DigiDump( level, args ) + +/* log levels */ +#define D_ALWAYS DIGIFLOW +#define D_ENTRY DIGIFLOW +#define D_EXIT DIGIFLOW +#define D_RARE DIGIRARE +#define D_NEVER DIGINEVER + + +#endif /* _DISP_ */ + + diff --git a/private/ntos/ndis/digi/pcimac/event.h b/private/ntos/ndis/digi/pcimac/event.h new file mode 100644 index 000000000..5f4b55387 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/event.h @@ -0,0 +1,31 @@ +/* + * EVENT.H - IDP Device Driver public header for PCIMAC/ISA + */ + +#ifndef _EVENT_ +#define _EVENT_ + +typedef struct +{ + ULONG Used; + struct _CM *cm; + ULONG Type; + ULONG State; + VOID (*Callback)(); + IRP *Irp; +} EVENTOBJECT; + +#define MAX_EVENTS 10 + + +ULONG EventInit (VOID); +VOID EventTerm (VOID); +UCHAR EventSet (CM *cm, CMD_EVENT *Event, IRP *Irp); +VOID EventComplete (IRP *Irp); +VOID EventCancel (DEVICE_OBJECT *DeviceObject, IRP *Irp); +VOID StateEventCheck (VOID *cm_1); + +#define EVENT_E_SUCC 0 + + +#endif /* _EVENT_ */ diff --git a/private/ntos/ndis/digi/pcimac/frame.h b/private/ntos/ndis/digi/pcimac/frame.h new file mode 100644 index 000000000..44c5cd04b --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/frame.h @@ -0,0 +1,196 @@ +// +// to build a version that does not support compression, commen out +// this define. +// +#define COMPRESSION 1 + +// when we pick up a frame, the coherency layer tells us +// about the frame... +// !!!!! NOTE: This is NOT an enumeration !!!!!! +// Look carefully at the code before you change these values. +#define FRAME_NOT_COMPRESSED 0 +#define FRAME_IS_FLUSH_FRAME 1 +#define FRAME_NEEDS_DECOMPRESSION 2 +#define FRAME_NEEDS_DECOMPRESSION_FLUSHING 3 + +// +// Set LSB if SW compression is ON +// +#define COMPRESSION_V1 1 + +typedef UCHAR FRAME_TYPE; +typedef UCHAR FRAME_TICKET; + +// +// ISDN pads to 60, so we need 60-14 worth of data +// before it is worth it to compress it! probably even more than that! +// +#define MINIMUM_COMPRESSED_PACKET_SIZE (60-14) + +#define COMPRESSED_HAS_REFERENCES 1 +#define COMPRESSED_NO_REFERENCES 2 +#define UNCOMPRESSED 3 +#define COMPRESSED 4 // generic compressed + +// BUG BUG should probably read this value from coherency code. +// we give one byte to coherency +#define COHERENCY_LENGTH 1 + +typedef ULONG FRAME_ID; + +// !!!! NOTE !!!! +// TransmittedUncompressed are the number of bytes that the compressor +// saw BEFORE attempting to compress the data (top end) +// TransmitCompressed is the bottom end of the compressor which +// is equal to the amount of bytes the compressor spat out (after compression) +// This only counts bytes that went THROUGH the compression mechanism +// Small frames and multi-cast frames (typically) do not get compressed. +typedef struct COMPRESSION_STATS COMPRESSION_STATS, *PCOMPRESSION_STATS; +struct COMPRESSION_STATS { + ULONG BytesTransmittedUncompressed; // Compression info only + ULONG BytesReceivedUncompressed; // Compression info only + ULONG BytesTransmittedCompressed; // Compression info only + ULONG BytesReceivedCompressed; // Compression info only +}; + +typedef struct ASYNC_CONNECTION ASYNC_CONNECTION, *PASYNC_CONNECTION; +typedef struct ASYNC_FRAME ASYNC_FRAME, *PASYNC_FRAME; + +typedef +VOID +(*PCOHERENT_DONE_FUNC) ( + IN PASYNC_CONNECTION pAsyncConnection, + IN PASYNC_FRAME pAsyncFrame); + + +struct ASYNC_CONNECTION { + // For me.. + PVOID pAsyncInfo; // Back ptr. + + // For compression + ULONG CompressionLength; // Length of Compression struct + PVOID CompressionContext; // Ptr to the Compression struct + + COMPRESSION_STATS CompressionStats; + + // For coherency + ULONG CoherencyLength; // Length of coherency struct + PVOID CoherencyContext; // Ptr to coherency struct + + NDIS_SPIN_LOCK CompMutex; // Non-paged pool mutex + + // These two values hold the size requested by the compression + // and coherent modules for their internal structures. + ULONG CompressStructSize; + ULONG CoherentStructSize; + + +}; + +struct ASYNC_FRAME { +//--------------------------------------------------------------------------- + // !!!!!!!! NOTE !!!!!!!! + // The FrameListEntry field must be first to + // dequeue things up properly so don't put anything + // in front of it or suffer severe crashes. + LIST_ENTRY FrameListEntry; // Used to queue up frames from + // the soon to be famous frame pool + // this frame's ID + FRAME_ID FrameID; + + // For Dougie + // Should Decompressed Frame can be non-paged?? + // i.e. Should I queue a worker thred to decompress?? + UINT DecompressedFrameLength;// Length of decompressed frame + PUCHAR DecompressedFrame; // Ptr to the decompressed 'frame' + // valid only after decompression + + // NOTE: If the frame is not compressed, the compressed fields + // are still valid when passed to Dave. + UINT CompressedFrameLength; // Length of compressed frame + PUCHAR CompressedFrame; // Ptr to the compressed 'frame' + // valid only after compression + // or just before decompression + + PNDIS_PACKET CompressionPacket; // Valid just before compression + // this is the packet passed down. + // Use NdisQueryPacket. + + PASYNC_CONNECTION Connection; // back ptr to connection struct + + // For Coherency + PUCHAR CoherencyFrame; // Ptr to coherency frame + PCOHERENT_DONE_FUNC CoherentDone; // function ptr to call when done + // sending frame + +}; + +// APIs to Compressor +VOID +CoherentDeliverFrame( + PASYNC_CONNECTION pConnection, + PASYNC_FRAME pFrame, + FRAME_TYPE FrameType); + +VOID +CoherentGetPipeline( + PASYNC_CONNECTION pConnection, + PULONG plUnsent); + + +// APIs to Transport/Network layer +VOID +CoherentSendFrame( + PASYNC_CONNECTION pConnection, + PASYNC_FRAME pFrame, + FRAME_TYPE FrameType); + + +ULONG +CoherentSizeOfStruct( ); + +VOID +CoherentInitStruct( + PVOID pCoherentStruct); + +// upcalls API's from Transport/Network layer +VOID +CoherentReceiveFrame( + PASYNC_CONNECTION pConnection, + PASYNC_FRAME pFrame); + +VOID +CoherentDeliverFrameDone( + PASYNC_CONNECTION pConnection, + PASYNC_FRAME pFrame); + + + +ULONG +CompressSizeOfStruct( + IN ULONG SendMode, // Compression + IN ULONG RecvMode, // Decompression + IN ULONG lfsz, // Largest frame size + OUT PULONG lcfsz); // Size of compression into buffer + +VOID +CompressInitStruct( + ULONG SendMode, // Compression + ULONG RecvMode, // Decompression + PUCHAR memptr, + PNDIS_SPIN_LOCK pMutex); // Must be in non-paged pool + +VOID +CompressFlush( + PASYNC_CONNECTION pAsyncConnection); + +VOID +CompressFrame( + PASYNC_FRAME pAsyncFrame); + +VOID +DecompressFrame( + PASYNC_CONNECTION pAsyncConnection, + PASYNC_FRAME pAsyncFrame, + BOOLEAN FlushBuffer); + diff --git a/private/ntos/ndis/digi/pcimac/idd.h b/private/ntos/ndis/digi/pcimac/idd.h new file mode 100644 index 000000000..592ee8270 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd.h @@ -0,0 +1,440 @@ +/* + * IDD.H - IDP Device Driver header + */ + +#ifndef _IDD_ +#define _IDD_ + +#include + + +/* idd error codes */ +#define IDD_E_SUCC 0 +#define IDD_E_NOMEM 1 +#define IDD_E_MEMERR 2 +#define IDD_E_NOSUCH 3 +#define IDD_E_NOROOM 4 +#define IDD_E_BADPORT 5 +#define IDD_E_IORERR 6 +#define IDD_E_IOWERR 7 +#define IDD_E_FMAPERR 8 +#define IDD_E_RUNERR 9 +#define IDD_E_PORTMAPERR 10 +#define IDD_E_PORTBINDERR 11 +#define IDD_E_PARTQINIT 12 +#define IDD_E_FAILINSTALL 13 +#define IDD_E_BUSY 14 +#define IDD_E_AREA 15 + +// +// Idd receive data framing types +// +#define DKF_UUS_SIG 0x50 +#define PPP_SIG_0 0xFF +#define PPP_SIG_1 0x03 + +/* IDD ports, rx/tx overlap! */ +#define IDD_PORT_B1_RX 0 /* recieve b1 data */ +#define IDD_PORT_B1_TX 0 /* trasmit b1 data */ +#define IDD_PORT_B2_RX 1 /* recieve b1 data */ +#define IDD_PORT_B2_TX 1 /* trasmit b1 data */ +#define IDD_PORT_U_RX 2 /* receive uart data */ +#define IDD_PORT_U_TX 2 /* trasmit uart data */ +#define IDD_PORT_CMD_RX 3 /* receive control messages */ +#define IDD_PORT_CMD_TX 3 /* trasmit control commands */ +#define IDD_PORT_CM0_RX 4 /* receive connection mgr events */ +#define IDD_PORT_CM0_TX 4 /* transmit connection mgr events */ +#define IDD_PORT_CM1_RX 5 /* ... on secondary tei (opt) */ +#define IDD_PORT_CM1_TX 5 /* ... on secondary tei (opt) */ + + +// +// local idd def's +// +/* some max values */ +#define IDD_FNAME_LEN 128 /* size of a filename (path) */ +#define IDD_DEF_SIZE 1000 /* size of definition database */ +#define IDD_MAX_SEND (6*32) /* max # of pending send allowed */ +#define IDD_MAX_RECEIVE (6*32) /* max # of pending receives on adapter*/ +#define IDD_MAX_HAND (6*6) /* max # of receive handles allowed */ +#define IDD_RX_PORTS 6 /* # of recieve ports defined */ +#define IDD_TX_PORTS 6 /* # of transmit ports defined */ +#define IDD_TX_PARTQ 4 /* # of (buffer) partition queues for tx */ +#define IDD_PAGE_NONE (UCHAR)0xFF /* no page arg for idd__cpage */ +#define IDP_MAX_RX_BUFFER 350 /* stupid double buffer buffer */ + +/* memory banks */ +#define IDD_BANK_BUF 0 +#define IDD_BANK_DATA 1 +#define IDD_BANK_CODE 2 + +/* representation of physical hardware */ +typedef struct +{ + ULONG base_io; /* base i/o address */ + ULONG base_mem; /* base memory address */ + CHAR idp_bin[IDD_FNAME_LEN]; /* binary image filename */ + NDIS_HANDLE fbin; /* idp bin file handle */ + UINT fbin_len; /* length in bytes of idp bin file */ +} IDD_PHW; + +/* virualization of hardware, in os (ndis) terms */ +typedef struct +{ + ULONG vbase_io; // virtual i/o base + CHAR *vmem; /* virtual address for memory */ +} IDD_VHW; + +/* descriptor for a message to be sent on a port */ +typedef struct +{ + IDD_MSG msg; /* copy of user's message */ + VOID (*handler)(); /* user's completion handler */ + VOID *handler_arg; /* handler's argument */ +} IDD_SMSG; + +/* a queue for messages waiting to be sent */ +typedef struct +{ + IDD_SMSG *tbl; /* send message table address */ + INT num; /* # of entries in queue */ + INT max; /* max # of entries allowed/alloc */ + INT put; /* put/insert index */ + INT get; /* get/remove index */ + NDIS_SPIN_LOCK lock; /* spin lock guarding access */ +} IDD_SENDQ; + +/* a descriptor for user's handler for a receiver port */ +typedef struct +{ + VOID (*handler)(); /* user's handler */ + VOID *handler_arg; /* handler's argument */ +} IDD_RHAND; + +/* a table of user's handlers on a reciever port */ +typedef struct +{ + IDD_RHAND *tbl; /* table of receiver handlers */ + ULONG RxFrameType; /* current receive framining mode */ + INT num; /* # of entries in table */ + INT max; /* max # of entries allowed/alloc */ + NDIS_SPIN_LOCK lock; /* spin lock guarding access */ +} IDD_RECIT; + +/* idp low level (shared memory) command interface structure */ +#pragma pack(2) +typedef struct +{ + UCHAR opcode; /* command opcode */ +#define IDP_L_MAP 0 /* - map a port name to id */ +#define IDP_L_READ 1 /* - read from a port */ +#define IDP_L_WRITE 2 /* - write to a port */ +#define IDP_L_BIND 3 /* - bind a port to a status bit */ +#define IDP_L_UNBIND 4 /* - unbind a port from a status bit */ +#define IDP_L_POLL 5 /* - poll a prot (check for read) */ +#define IDP_L_GET_WBUF 6 /* - get a write buffer */ +#define IDP_L_PUT_RBUF 7 /* - put (free) a read buffer */ + + UCHAR status; /* command status */ +#define IDP_S_PEND 0xFF /* - command pending */ +#define IDP_S_EXEC 0xFE /* - command is executing */ +#define IDP_S_OK 0x00 /* - command complted succ */ +#define IDP_S_NOPORT 0x01 /* - no such port error */ +#define IDP_S_NOMSG 0x02 /* - no messages error */ +#define IDP_S_NOBUF 0x03 /* - no local buffer error */ +#define IDP_S_NOBIT 0x04 /* - no status bit left error */ +#define IDP_S_BOUND 0x05 /* - port already bound error */ +#define IDP_S_NOTBOUND 0x06 /* - port not bound error */ +#define IDP_S_TIMEOUT 0x07 /* - command timed out error */ +#define IDP_S_DONE(s) (!(s & 0x80)) /* -command execution done (<0x80) */ + + USHORT port_id; /* related port identifier */ + CHAR port_name[16]; /* related port name */ + USHORT port_bitpatt; /* related port bit pattern */ + + UCHAR res[8]; /* 8 bytes of reserved area */ + + USHORT msg_opcode; /* message opcode (type) */ + USHORT msg_buflen; /* related buffer length */ + ULONG msg_bufptr; /* related buffer pointer (0=none) */ + ULONG msg_bufid; /* related buffer id */ + ULONG msg_param; /* parameter area */ +} IDP_CMD; +#pragma pack() + + +/* adp low level (shared memory) command interface structure */ +#pragma pack(2) +typedef struct +{ + UCHAR opcode; /* command opcode */ +#define ADP_L_MAP 0 /* - map a port name to id */ +#define ADP_L_READ 1 /* - read from a port */ +#define ADP_L_WRITE 2 /* - write to a port */ +#define ADP_L_BIND 3 /* - bind a port to a status bit */ +#define ADP_L_UNBIND 4 /* - unbind a port from a status bit */ +#define ADP_L_POLL 5 /* - poll a prot (check for read) */ +#define ADP_L_GET_WBUF 6 /* - get a write buffer */ +#define ADP_L_PUT_RBUF 7 /* - put (free) a read buffer */ + + UCHAR status; /* command status */ +#define ADP_S_PEND 0xFF /* - command pending */ +#define ADP_S_EXEC 0xFE /* - command is executing */ +#define ADP_S_OK 0x00 /* - command complted succ */ +#define ADP_S_NOPORT 0x01 /* - no such port error */ +#define ADP_S_NOMSG 0x02 /* - no messages error */ +#define ADP_S_NOBUF 0x03 /* - no local buffer error */ +#define ADP_S_NOBIT 0x04 /* - no status bit left error */ +#define ADP_S_BOUND 0x05 /* - port already bound error */ +#define ADP_S_NOTBOUND 0x06 /* - port not bound error */ +#define ADP_S_TIMEOUT 0x07 /* - command timed out error */ +#define ADP_S_DONE(s) (!(s & 0x80)) /* -command execution done (<0x80) */ + + USHORT port_id; /* related port identifier */ + CHAR port_name[8]; /* related port name */ + USHORT port_bitpatt; /* related port bit pattern */ + + USHORT msg_opcode; /* message opcode (type) */ + USHORT msg_buflen; /* related buffer length */ + CHAR *msg_bufptr; /* related buffer pointer (0=none) */ + ULONG msg_bufid; /* related buffer id */ + ULONG msg_param; /* parameter area */ +} ADP_CMD; +#pragma pack() + +typedef struct tagIDD_LINESTATE +{ + ULONG LineActive; /* is this idd's line active */ + ULONG L1TxState; /* Layer 1 Tx state */ + ULONG L1RxState; /* Layer 1 Rx state */ + ULONG L2State; /* Layer 2 State */ + ULONG L3State; /* Layer 3 State */ + ULONG L3ServiceState; /* Layer 3 Service State */ +}IDD_LINESTATE; + +typedef struct tagIDD_CALLINFO +{ + ULONG ChannelsUsed; /* # of bchans used on this idd */ + ULONG NumLTerms; /* # of lterms 1/2 */ + VOID* cm[2]; /* cm that is using an lterm */ +}IDD_CALLINFO; + +#ifdef DBG +typedef struct +{ + INT Count; + ULONG Put; + ULONG Get; + ULONG TxState; + ULONG FragsSinceBegin; + ULONG Buffer[32]; +}BUFFER_MANAGER; +#endif + +/* IDD object */ +typedef struct _IDD +{ + USHORT state; /* IDD object state */ +#define IDD_S_INIT 0 /* - initial state */ +#define IDD_S_CHECK 1 /* - in check hardware phase */ +#define IDD_S_STARTUP 2 /* - in startup */ +#define IDD_S_RUN 3 /* - now running */ +#define IDD_S_SHUTDOWN 4 /* - in shutdown */ + +#ifdef DBG + BUFFER_MANAGER BufferStuff[4]; +#endif + + ULONG WaitCounter; + ULONG MaxWaitCounter; + + USHORT AbortReason; + + NDIS_SPIN_LOCK lock; /* spin lock guarding access to obj */ + + NDIS_HANDLE adapter_handle; /* related adapter handle */ + + IDD_PHW phw; /* physical hardware */ + IDD_VHW vhw; /* virtualization of hardware */ + + IDD_SENDQ sendq[IDD_TX_PORTS]; /* send queues for tx ports */ + IDD_SMSG smsg_pool[IDD_MAX_SEND]; /* pool of smsgs for sendqs */ + + IDD_RECIT recit[IDD_RX_PORTS]; /* receive table for rx ports */ + IDD_RHAND rhand_pool[IDD_MAX_HAND]; /* pool or rhand for recit table */ + + USHORT rx_port[IDD_RX_PORTS]; /* port id's in idp terms for rx */ + USHORT tx_port[IDD_TX_PORTS]; /* ... for tx */ + ULONG rx_buf; /* id for last received (old) buffer from idp */ + ULONG tx_buf[IDD_TX_PARTQ]; /* (new) tx buffer as idp bufids */ + USHORT tx_partq[IDD_TX_PORTS]; /* related memory parition queues */ + + IDP_CMD volatile *IdpCmd; /* pointer to idp command struct */ + USHORT volatile *IdpStat; /* pointer to status register */ + UCHAR volatile *IdpEnv; /* pointer to status register */ + + ADP_CMD AdpCmd; /* pointer to adp command struct */ + USHORT AdpStat; /* pointer to status register */ + + SEMA proc_sema; /* processing sema */ + + CHAR name[64]; /* name (device name?) */ + USHORT btype; /* board type idd related to */ + USHORT bnumber; /* board number of this idd */ + USHORT bline; /* line index inside board */ + + IDD_CALLINFO CallInfo; /* information about active calls */ + + IDD_LINESTATE LineState; /* structure of idd state info */ + + VOID *res_mem; /* resource mgr handle for memory */ + VOID *res_io; /* resource mgr handle for i/o */ + + ULONG (*CheckIO)(); /* Check Base I/O */ + ULONG (*CheckMem)(); /* Check Base Mem */ + VOID (*SetBank)(); /* set memory bank */ + VOID (*SetPage)(); /* set memory page - or none */ + VOID (*SetBasemem)(); /* set base memory address */ + INT (*LoadCode)(); /* load the adapter */ + ULONG (*PollTx)(); /* poll the adapter for xmits*/ + ULONG (*PollRx)(); /* poll the adapter for recvs */ + UCHAR (*Execute)(); /* Execute a command */ + VOID (*OutToPort)(); /* Write Char to port*/ + UCHAR (*InFromPort)(); /* Read Char from port*/ + USHORT (*ApiGetPort)(); /* Get Port ID from adapter*/ + INT (*ApiBindPort)(); /* Bind a Port to a status bit*/ + ULONG (*ApiAllocBuffer)(); /* Get a buffer from the adapter*/ + VOID (*ResetAdapter)(); /* Reset the adapter*/ + USHORT (*NVRamRead)(); /* Read Adapters NVRam*/ + VOID (*ChangePage)(); /* Change Memory Page on Adapter*/ + + IDD_AREA Area; /* idd area storage */ + + VOID *trc; /* related trace object */ + + UCHAR DefinitionTable[IDD_DEF_SIZE]; /* init definition database */ + USHORT DefinitionTableLength; /* length of definition database */ + + UCHAR RxBuffer[IDP_MAX_RX_BUFFER]; /* receive storage */ +} IDD; + + +/* IDD object operation prototypes */ +INT idd_create(VOID** ret_idd, USHORT btype); +INT idd_destroy(VOID* idd_1); +INT idd_set_base_io(VOID* idd_1, USHORT base_io); +INT idd_set_base_mem(VOID* idd_1, ULONG base_mem, CHAR* vmem); +INT idd_set_idp_bin(VOID* idd_1, CHAR* idp_bin); +INT idd_add_def(IDD *idd, CHAR* name, CHAR* val); +INT idd_get_nvram(VOID *idd_1, USHORT addr, USHORT* val); +INT idd_check(VOID* idd_1); +INT idd_startup(VOID* idd_1); +INT idd_shutdown(VOID* idd_1); +ULONG idd_process(IDD* idd, UCHAR TxOnly); +INT idd_send_msg(VOID* idd_1, IDD_MSG *msg, USHORT port, + VOID (*handler)(), VOID* handler_arg); +INT idd_attach(VOID* idd_1, USHORT port, + VOID (*handler)(), VOID* handler_arg); +INT idd_detach(VOID* idd_1, USHORT port, + VOID (*handler)(), VOID* handler_arg); +CHAR* idd_get_name(VOID* idd_1); +ULONG idd_get_baseio(VOID* idd_1); +ULONG idd_get_basemem(VOID* idd_1); +USHORT idd_get_btype(VOID* idd_1); +USHORT idd_get_bline(VOID* idd_1); +VOID* idd_get_trc(VOID *idd_1); +VOID idd_set_trc(VOID *idd_1, VOID *Trace); +INT idd_install(NDIS_HANDLE adapter_handle); +INT idd_remove(NDIS_HANDLE adapter_handle); +VOID idd_start_timers(VOID* Adapter_1); +INT idd_reset_area(VOID* idd_1); +INT idd_get_area(VOID* idd_1, ULONG area_id, VOID(*handler)(), VOID*handler_arg); +INT idd_get_area_stat(VOID* idd_1, IDD_AREA *IddStat); +VOID IddSetRxFraming(VOID* idd_1, USHORT port, ULONG FrameType); + +VOID IddPollFunction(VOID* a1, VOID* Adapter_1, VOID* a3, VOID* a4); +VOID LineStateTimerTick(VOID* a1, VOID* Adapter_1, VOID* a3, VOID *a4); +VOID idd__cmd_handler(IDD *idd, USHORT chan, ULONG Reserved, IDD_MSG* msg); +VOID DetectFramingHandler(IDD *idd, USHORT chan, ULONG IddRxFrameType, IDD_XMSG *msg); + +ULONG EnumIddInSystem(VOID); +ULONG EnumIddPerAdapter(VOID *Adapter_1); +IDD* GetIddByIndex(ULONG); +INT IoEnumIdd(VOID *cmd); +ULONG idd_init(VOID); + +INT IdpLoadCode(IDD* idd); +INT AdpLoadCode(IDD* idd); +INT IdpBindPort(IDD* idd, USHORT port, USHORT bitpatt); +INT AdpBindPort(IDD* idd, USHORT port, USHORT bitpatt); +INT IdpResetBoard(IDD* idd); +INT AdpResetBoard(IDD* idd); +ULONG IdpAllocBuf(IDD*, INT); +ULONG AdpAllocBuf(IDD*, INT); +USHORT IdpGetPort(IDD *idd, CHAR name[8]); +USHORT AdpGetPort(IDD *idd, CHAR name[8]); +ULONG IdpCheckIO(IDD*); +ULONG AdpCheckIO(IDD*); +ULONG IdpCheckMem(IDD*); +ULONG AdpCheckMem(IDD*); + +/* board specific routines */ +VOID IdpPcSetBank(IDD* idd, UCHAR bank, UCHAR run); +VOID IdpPc4SetBank(IDD* idd, UCHAR bank, UCHAR run); +VOID IdpMcSetBank(IDD* idd, UCHAR bank, UCHAR run); +VOID AdpSetBank(IDD* idd, UCHAR bank, UCHAR run); +VOID IdpPcSetPage(IDD* idd, UCHAR page); +VOID IdpPc4SetPage(IDD* idd, UCHAR page); +VOID IdpMcSetPage(IDD* idd, UCHAR page); +VOID AdpSetPage(IDD* idd, UCHAR page); +VOID IdpPcSetBasemem(IDD* idd, ULONG basemem); +VOID IdpPc4SetBasemem(IDD* idd, ULONG basemem); +VOID IdpMcSetBasemem(IDD* idd, ULONG basemem); +VOID AdpSetBasemem(IDD* idd, ULONG basemem); + +UCHAR IdpInp(IDD* idd, USHORT port); +UCHAR AdpInp(IDD* idd, USHORT port); +VOID IdpOutp(IDD* idd, USHORT port, UCHAR val); +VOID AdpOutp(IDD* idd, USHORT port, UCHAR val); +ULONG IdpPollTx(IDD* idd); +ULONG AdpPollTx(IDD* idd); +ULONG IdpPollRx(IDD* idd); +ULONG AdpPollRx(IDD* idd); +UCHAR IdpExec(IDD *idd, UCHAR opcode); +UCHAR AdpExec(IDD *idd, UCHAR opcode); +VOID IdpCPage(IDD *idd, UCHAR page); +VOID AdpCPage(IDD *idd, UCHAR page); +USHORT IdpNVRead(IDD* idd, USHORT addr); +USHORT AdpNVRead(IDD* idd, USHORT addr); +VOID IdpNVWrite(IDD* idd, USHORT addr, USHORT val); +VOID AdpNVWrite(IDD* idd, USHORT addr, USHORT val); +VOID IdpNVErase(IDD* idd); +VOID AdpNVErase(IDD* idd); +VOID IdpMemset(UCHAR* dst, USHORT val, int size); +VOID AdpMemset(UCHAR* dst, USHORT val, int size); +VOID IdpMemcpy(UCHAR* dst, UCHAR* src, int size); +VOID AdpMemcpy(UCHAR* dst, UCHAR* src, int size); +USHORT IdpCopyin(IDD* idd, UCHAR* dst, UCHAR* src, USHORT src_len); +USHORT AdpCopyin(IDD* idd, UCHAR* src, USHORT src_len); + +VOID AdpWriteControlBit (IDD *idd, UCHAR Bit, UCHAR Value); +VOID AdpPutBuffer (IDD *idd, ULONG Destination, PUCHAR Source, USHORT Length); +VOID AdpGetBuffer (IDD *idd, PUCHAR Destination, ULONG Source, USHORT Length); +VOID AdpWriteCommandStatus(IDD *idd, UCHAR Value); +UCHAR AdpReadCommandStatus(IDD *idd); +VOID AdpSetAddress(IDD *idd, ULONG Address); +VOID AdpPutUByte(IDD *idd, ULONG Address, UCHAR Value); +VOID AdpPutUShort(IDD *idd, ULONG Address, USHORT Value); +VOID AdpPutULong(IDD *idd, ULONG Address, ULONG Value); +UCHAR AdpGetUByte(IDD *idd, ULONG Address); +USHORT AdpGetUShort(IDD *idd, ULONG Address); +ULONG AdpGetULong(IDD *idd, ULONG Address); +UCHAR AdpReadReceiveStatus(IDD *idd); +UCHAR IdpGetUByteIO(IDD* idd, USHORT port); +VOID IdpGetBuffer(IDD* idd, ULONG Bank, ULONG Page, ULONG Address, USHORT Length, PUCHAR Buffer); +VOID IdpPutUByteIO(IDD* idd, USHORT Port, UCHAR Value); +VOID IdpPutBuffer(IDD* idd, ULONG Bank, ULONG Page, ULONG Address, USHORT Length, PUCHAR Buffer); +VOID IddGetDataFromAdapter(VOID *idd_1, PUCHAR Destination, PUCHAR Source, USHORT Length); +VOID LineStateHandler(VOID* idd_1, ULONG AreaId, CHAR* AreaBuffer, ULONG BufferLen); + +#endif /* _IDD_ */ diff --git a/private/ntos/ndis/digi/pcimac/idd_init.c b/private/ntos/ndis/digi/pcimac/idd_init.c new file mode 100644 index 000000000..54cb548aa --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd_init.c @@ -0,0 +1,894 @@ +/* + * IDD_INIT.C - IDD initialization + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +typedef struct +{ + NDIS_SPIN_LOCK lock; + ULONG NumberOfIddsInSystem; + ULONG LastIddPolled; + ADAPTER *CurrentAdapter; + ADAPTER *LastAdapter; + IDD* Idd[MAX_IDD_IN_SYSTEM]; +}IDD_TABLE; + +IDD_TABLE GlobalIddTbl; + +BOOLEAN IsThisAdapterNext(ADAPTER *Adapter); + +/* driver global vars */ +extern DRIVER_BLOCK Pcimac; + +ULONG EnumIddInSystem() +{ + ULONG NumberOfIddsInSystem; + + NdisAcquireSpinLock(&GlobalIddTbl.lock); + + NumberOfIddsInSystem = GlobalIddTbl.NumberOfIddsInSystem; + + NdisReleaseSpinLock(&GlobalIddTbl.lock); + + return(NumberOfIddsInSystem); +} + +IDD* GetIddByIndex( ULONG Index ) +{ + IDD *idd; + + NdisAcquireSpinLock(&GlobalIddTbl.lock); + + idd = GlobalIddTbl.Idd[Index]; + + NdisReleaseSpinLock(&GlobalIddTbl.lock); + + return(idd); +} + +ULONG +EnumIddPerAdapter( + VOID *Adapter_1 + ) +{ + ADAPTER *Adapter = (ADAPTER*)Adapter_1; + + return(Adapter->NumberOfIddOnAdapter); +} + + +INT +IoEnumIdd(VOID *cmd_1) +{ + ULONG n; + IO_CMD *cmd = (IO_CMD*)cmd_1; + + NdisAcquireSpinLock(&GlobalIddTbl.lock); + + cmd->val.enum_idd.num = (USHORT)GlobalIddTbl.NumberOfIddsInSystem; + + for (n = 0; n < GlobalIddTbl.NumberOfIddsInSystem; n++) + { + IDD *idd; + + idd = cmd->val.enum_idd.tbl[n] = GlobalIddTbl.Idd[n]; + + NdisMoveMemory(&cmd->val.enum_idd.name[n], + idd->name, + sizeof(cmd->val.enum_idd.name[n])); + } + + NdisReleaseSpinLock(&GlobalIddTbl.lock); + + return(0); +} + +#pragma NDIS_INIT_FUNCTION(idd_init) + +ULONG +idd_init(VOID) +{ + // + // clear out idd table + // + NdisZeroMemory(&GlobalIddTbl, sizeof(IDD_TABLE)); + + NdisAllocateSpinLock(&GlobalIddTbl.lock); + + return(IDD_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(idd_create) + +/* allocate & initialize an idd object */ +INT +idd_create(VOID **ret_idd, USHORT btype) +{ + IDD *idd; + INT n; + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + + D_LOG(D_ENTRY, ("idd_create: BoardType: %d\n", btype)); + + /* allocate memory object */ + NdisAllocateMemory((PVOID*)&idd, sizeof(IDD), 0, pa); + if ( !idd ) + { + D_LOG(DIGIINIT, ("idd_create: memory allocate failed!\n")); + return(IDD_E_NOMEM); + } + + NdisAcquireSpinLock(&GlobalIddTbl.lock); + + // + // store idd in system idd table + // + for (n = 0; n < MAX_IDD_IN_SYSTEM; n++) + if (!GlobalIddTbl.Idd[n]) + break; + + if (n >= MAX_IDD_IN_SYSTEM) + { + // + // We are unable to find an empty slot for the IDD object. + // + /* free memory for idd */ + NdisFreeMemory(idd, sizeof(*idd), 0); + + NdisReleaseSpinLock(&GlobalIddTbl.lock); + + return(IDD_E_NOROOM); + } + + GlobalIddTbl.Idd[n] = idd; + GlobalIddTbl.NumberOfIddsInSystem++; + + NdisReleaseSpinLock(&GlobalIddTbl.lock); + + D_LOG(DIGIINIT, ("idd_create: idd: 0x%lx\n", idd)); + NdisZeroMemory(idd, sizeof(IDD)); + + /* setup init state, adapter handle */ + idd->state = IDD_S_INIT; + idd->trc = NULL; + + /* allocate root spinlock */ + NdisAllocateSpinLock(&idd->lock); + + /* initialize send queues */ + for( n = 0 ; n < IDD_TX_PORTS ; n++ ) + { + INT max; + + /* initialize queue */ + idd->sendq[n].max = max = IDD_MAX_SEND / IDD_TX_PORTS; + + idd->sendq[n].tbl = idd->smsg_pool + max * n; + + /* allocate spin lock */ + NdisAllocateSpinLock(&idd->sendq[n].lock); + } + + /* initialize receiver tables */ + for ( n = 0 ; n < IDD_RX_PORTS ; n++ ) + { + INT max; + + /* initialize table */ + idd->recit[n].max = max = IDD_MAX_HAND / IDD_RX_PORTS; + idd->recit[n].tbl = idd->rhand_pool + max * n; + + /* allocate spin lock */ + NdisAllocateSpinLock(&idd->recit[n].lock); + } + + /* initialize board specific functions */ + switch ( btype ) + { + case IDD_BT_PCIMAC : + idd->SetBank = (VOID*)IdpPcSetBank; + idd->SetPage = (VOID*)IdpPcSetPage; + idd->SetBasemem = (VOID*)IdpPcSetBasemem; + idd->CheckIO = (VOID*)IdpCheckIO; + idd->CheckMem = (VOID*)IdpCheckMem; + idd->LoadCode = (VOID*)IdpLoadCode; + idd->PollTx = (VOID*)IdpPollTx; + idd->PollRx = (VOID*)IdpPollRx; + idd->Execute = (VOID*)IdpExec; + idd->OutToPort = (VOID*)IdpOutp; + idd->InFromPort = (VOID*)IdpInp; + idd->ApiGetPort = (VOID*)IdpGetPort; + idd->ApiBindPort = (VOID*)IdpBindPort; + idd->ApiAllocBuffer = (VOID*)IdpAllocBuf; + idd->ResetAdapter = (VOID*)IdpResetBoard; + idd->NVRamRead = (VOID*)IdpNVRead; + idd->ChangePage = (VOID*)IdpCPage; + break; + + case IDD_BT_PCIMAC4 : + idd->SetBank = (VOID*)IdpPc4SetBank; + idd->SetPage = (VOID*)IdpPc4SetPage; + idd->SetBasemem = (VOID*)IdpPc4SetBasemem; + idd->CheckIO = (VOID*)IdpCheckIO; + idd->CheckMem = (VOID*)IdpCheckMem; + idd->LoadCode = (VOID*)IdpLoadCode; + idd->PollTx = (VOID*)IdpPollTx; + idd->PollRx = (VOID*)IdpPollRx; + idd->Execute = (VOID*)IdpExec; + idd->OutToPort = (VOID*)IdpOutp; + idd->InFromPort = (VOID*)IdpInp; + idd->ApiGetPort = (VOID*)IdpGetPort; + idd->ApiBindPort = (VOID*)IdpBindPort; + idd->ApiAllocBuffer = (VOID*)IdpAllocBuf; + idd->ResetAdapter = (VOID*)IdpResetBoard; + idd->NVRamRead = (VOID*)IdpNVRead; + idd->ChangePage = (VOID*)IdpCPage; + break; + + case IDD_BT_MCIMAC : + idd->SetBank = (VOID*)IdpMcSetBank; + idd->SetPage = (VOID*)IdpMcSetPage; + idd->SetBasemem = (VOID*)IdpMcSetBasemem; + idd->CheckIO = (VOID*)IdpCheckIO; + idd->CheckMem = (VOID*)IdpCheckMem; + idd->LoadCode = (VOID*)IdpLoadCode; + idd->PollTx = (VOID*)IdpPollTx; + idd->PollRx = (VOID*)IdpPollRx; + idd->Execute = (VOID*)IdpExec; + idd->OutToPort = (VOID*)IdpOutp; + idd->InFromPort = (VOID*)IdpInp; + idd->ApiGetPort = (VOID*)IdpGetPort; + idd->ApiBindPort = (VOID*)IdpBindPort; + idd->ApiAllocBuffer = (VOID*)IdpAllocBuf; + idd->ResetAdapter = (VOID*)IdpResetBoard; + idd->NVRamRead = (VOID*)IdpNVRead; + idd->ChangePage = (VOID*)IdpCPage; + break; + + case IDD_BT_DATAFIREU : + case IDD_BT_DATAFIREST: + case IDD_BT_DATAFIRE4ST: + idd->SetBank = (VOID*)AdpSetBank; + idd->SetPage = (VOID*)AdpSetPage; + idd->SetBasemem = (VOID*)AdpSetBasemem; + idd->CheckIO = (VOID*)AdpCheckIO; + idd->CheckMem = (VOID*)AdpCheckMem; + idd->LoadCode = (VOID*)AdpLoadCode; + idd->PollTx = (VOID*)AdpPollTx; + idd->PollRx = (VOID*)AdpPollRx; + idd->Execute = (VOID*)AdpExec; + idd->OutToPort = (VOID*)AdpOutp; + idd->InFromPort = (VOID*)AdpInp; + idd->ApiGetPort = (VOID*)AdpGetPort; + idd->ApiBindPort = (VOID*)AdpBindPort; + idd->ApiAllocBuffer = (VOID*)AdpAllocBuf; + idd->ResetAdapter = (VOID*)AdpResetBoard; + idd->NVRamRead = (VOID*)AdpNVRead; + idd->ChangePage = (VOID*)AdpCPage; + break; + } + + + /* init sema */ + sema_init(&idd->proc_sema); + + // + // attach idd frame detection handlers + // these must be attached 1st for all data handlers + // + idd_attach(idd, IDD_PORT_B1_RX, (VOID*)DetectFramingHandler, idd); + idd_attach(idd, IDD_PORT_B2_RX, (VOID*)DetectFramingHandler, idd); + + // attach a command handler to get area info from idp + idd_attach (idd, IDD_PORT_CMD_RX, (VOID*)idd__cmd_handler, idd); + + /* return address & success */ + *ret_idd = idd; + D_LOG(D_EXIT, ("idd_create: exit\n")); + return(IDD_E_SUCC); +} + +/* free idd object */ +INT +idd_destroy(VOID *idd_1) +{ + IDD *idd = (IDD*)idd_1; + INT n; + + D_LOG(D_ENTRY, ("idd_destroy: entry, idd: 0x%lx\n", idd)); + + // detach command handler from this idd + idd_detach (idd, IDD_PORT_CMD_RX, (VOID*)idd__cmd_handler, idd); + + /* perform a shutdown (maybe null) */ + idd_shutdown(idd); + + /* if file handle for binary file open, close it */ + if ( idd->phw.fbin ) + NdisCloseFile(idd->phw.fbin); + + /* free spin locks for send queue */ + for ( n = 0 ; n < IDD_TX_PORTS ; n++ ) + NdisFreeSpinLock(&idd->sendq[n].lock); + + /* free spin locks for reciever tables */ + for ( n = 0 ; n < IDD_RX_PORTS ; n++ ) + NdisFreeSpinLock(&idd->recit[n].lock); + + /* free resource handles */ + if ( idd->res_io != NULL) + res_destroy(idd->res_io); + + if ( idd->res_mem != NULL) + res_destroy(idd->res_mem); + + // free trc object + if (idd->trc != NULL) + { + trc_deregister_idd(idd); + trc_destroy (idd->trc); + } + + /* term sema */ + sema_term(&idd->proc_sema); + + /* free spinlock (while allocated!) */ + NdisFreeSpinLock(&idd->lock); + + NdisAcquireSpinLock(&GlobalIddTbl.lock); + + // + // store idd in system idd table + // + for (n = 0; n < MAX_IDD_IN_SYSTEM; n++) + if (GlobalIddTbl.Idd[n] == idd) + break; + + if (n < MAX_IDD_IN_SYSTEM) + GlobalIddTbl.Idd[n] = NULL; + + GlobalIddTbl.NumberOfIddsInSystem--; + + NdisReleaseSpinLock(&GlobalIddTbl.lock); + + /* free memory for idd */ + NdisFreeMemory(idd, sizeof(*idd), 0); + + + /* return success */ + D_LOG(D_EXIT, ("idd_destroy: exit\n")); + return(IDD_E_SUCC); +} + + +//#ifdef PERADAPTER + +VOID +IddPollFunction( + VOID *a1, + VOID *Adapter_1, + VOID *a3, + VOID *a4 + ) +{ +#define MAX_EVENTS 1000 + ULONG i, j, EventNum, TotalEventNum = 0; + ULONG FirstIdd, NumberOfIddOnAdapter; + ADAPTER *Adapter = (ADAPTER*)Adapter_1; + IDD *idd; + + // + // check to see if there is someone else already polling + // an adapter that has the same shared memory window + // as this adapter. if someone is then get out so that we + // don't burn up this processor waiting for the other to complete + // if this adapter is supposed to be the next adapter to be polled + // only send him away for awhile, else send him away for normal polling + // time + // + if (CheckInDriverFlag(Adapter)) + { + if (IsThisAdapterNext(Adapter)) + { + // + // we want to come back asap + // + NdisMSetTimer(&Adapter->IddPollTimer, 0); + } + else + { + // + // we want to come back at our regular time + // + NdisMSetTimer(&Adapter->IddPollTimer, IDD_POLL_T); + } + return; + } + + SetInDriverFlag(Adapter); + + // + // this will be the first idd that we will poll + // + FirstIdd = Adapter->LastIddPolled; + + // + // this will be the number of idds that we will poll + // + NumberOfIddOnAdapter = Adapter->NumberOfIddOnAdapter; + + do + { + EventNum = 0; + + // + // we will service all of the idd's in the system + // first lets do some receives + // + + for (i = FirstIdd, j = FirstIdd + NumberOfIddOnAdapter; i < j; i++) + { + idd = Adapter->IddTbl[i % NumberOfIddOnAdapter]; + + if (idd && (idd->state == IDD_S_RUN)) + EventNum += idd->PollRx(idd); + } + + + // + // we will service all of the idd's in the system + // now lets do the send queue + // + for (i = FirstIdd, j = FirstIdd + NumberOfIddOnAdapter; i < j; i++) + { + idd = Adapter->IddTbl[i % NumberOfIddOnAdapter]; + + if (idd && (idd->state == IDD_S_RUN)) + { + EventNum += idd->PollTx(idd); + EventNum += idd->PollRx(idd); + } + } + + TotalEventNum += EventNum; + + } while (EventNum && (TotalEventNum < MAX_EVENTS) ); + + // + // bump so we start at next idd next time + // + Adapter->LastIddPolled++; + + if (Adapter->LastIddPolled == NumberOfIddOnAdapter) + Adapter->LastIddPolled = 0; + + ClearInDriverFlag(Adapter); + + NdisMSetTimer(&Adapter->IddPollTimer, IDD_POLL_T); + + // + // lets go ahead and give some of this data up to the wrapper + // hopefully this will keep us from running out of room in our + // assembly descriptor table + // + TryToIndicateMtlReceives(Adapter); +} + +//#endif + +BOOLEAN +IsThisAdapterNext( + ADAPTER *Adapter + ) +{ + BOOLEAN ThisIsIt = FALSE; + + NdisAcquireSpinLock(&Pcimac.lock); + + if (Adapter == Pcimac.AdapterTbl[Pcimac.NextAdapterToPoll]) + ThisIsIt = TRUE; + + NdisReleaseSpinLock(&Pcimac.lock); + + return(ThisIsIt); +} + + +#ifdef ALLADAPTERS +VOID +IddPollFunction( + VOID *a1, + VOID *Adapter_1, + VOID *a3, + VOID *a4 + ) +{ +#define MAX_EVENTS 1000 + ULONG i, j, EventNum, TotalEventNum = 0; + ULONG FirstIdd, NumberOfIddsInSystem; + ADAPTER *Adapter = (ADAPTER*)Adapter_1; + IDD *idd; + + + NdisAcquireSpinLock(&GlobalIddTbl.lock); + + GlobalIddTbl.LastAdapter = GlobalIddTbl.CurrentAdapter; + + GlobalIddTbl.CurrentAdapter = Adapter; + + // + // this will be the first idd that we will poll + // + FirstIdd = GlobalIddTbl.LastIddPolled; + + // + // this will be the number of idds that we will poll + // + NumberOfIddsInSystem = GlobalIddTbl.NumberOfIddsInSystem; + + do + { + EventNum = 0; + + // + // we will service all of the idd's in the system + // first lets do some receives + // + for (i = FirstIdd, j = FirstIdd + NumberOfIddsInSystem; i < j; i++) + { + idd = GlobalIddTbl.Idd[i % NumberOfIddsInSystem]; + + if (idd->state == IDD_S_RUN) + EventNum += idd->PollRx(idd); + } + + // + // we will service all of the idd's in the system + // now lets do the send queue + // + for (i = FirstIdd, j = FirstIdd + NumberOfIddsInSystem; i < j; i++) + { + idd = GlobalIddTbl.Idd[i % NumberOfIddsInSystem]; + + if (idd->state == IDD_S_RUN) + { + EventNum += idd->PollTx(idd); + EventNum += idd->PollRx(idd); + } + } + + TotalEventNum += EventNum; + + } while (EventNum && (TotalEventNum < MAX_EVENTS) ); + + GlobalIddTbl.LastIddPolled++; + + if (GlobalIddTbl.LastIddPolled == NumberOfIddsInSystem) + GlobalIddTbl.LastIddPolled = 0; + + NdisReleaseSpinLock(&GlobalIddTbl.lock); + + // + // lets go ahead and give some of this data up to the wrapper + // hopefully this will keep us from running out of room in our + // assembly descriptor table + // +// TryToIndicateMtlReceives(Adapter); + + NdisMSetTimer(&Adapter->IddPollTimer, IDD_POLL_T); +} + +#endif + +#ifdef OLD +VOID +IddPollFunction( + VOID *a1, + VOID *Adapter_1, + VOID *a3, + VOID *a4 + ) +{ +#define MAX_EVENTS 1000 + ULONG n, EventNum, TotalEventNum = 0; + + ADAPTER *Adapter = (ADAPTER*)Adapter_1; + + do + { + EventNum = 0; + + // + // we will service all of the idd's in the system + // first lets do some receives + // + for (n = 0; n < MAX_IDD_IN_SYSTEM; n++) + { + IDD *idd = GlobalIddTbl[n]; + + if (idd && (idd->state == IDD_S_RUN)) + EventNum += idd->PollRx(idd); + } + + // + // we will service all of the idd's in the system + // now lets do the send queue + // + for (n = 0; n < MAX_IDD_IN_SYSTEM; n++) + { + IDD *idd = GlobalIddTbl[n]; + + if (idd && (idd->state == IDD_S_RUN)) + EventNum += idd->PollTx(idd); + } + + TotalEventNum += EventNum; + + } while (EventNum && (TotalEventNum < MAX_EVENTS) ); + + // + // lets go ahead and give some of this data up to the wrapper + // hopefully this will keep us from running out of room in our + // assembly descriptor table + // +// TryToIndicateMtlReceives(Adapter); + + NdisMSetTimer(&Adapter->IddPollTimer, IDD_POLL_T); +} +#endif + +/* get idd name */ +CHAR* +idd_get_name(VOID *idd_1) +{ + IDD *idd = (IDD*)idd_1; + return(idd->name); +} + +USHORT +idd_get_bline(VOID *idd_1) +{ + IDD *idd = (IDD*)idd_1; + return(idd->bline); +} + +USHORT +idd_get_btype(VOID *idd_1) +{ + IDD *idd = (IDD*)idd_1; + return(idd->btype); +} + +VOID* +idd_get_trc (VOID *idd_1) +{ + IDD *idd = (IDD*)idd_1; + return(idd->trc); +} + +VOID +idd_set_trc (VOID *idd_1, TRC* Trace) +{ + IDD *idd = (IDD*)idd_1; + idd->trc = Trace; +} + +INT +idd_reset_area (VOID* idd_1) +{ + IDD *idd = (IDD*)idd_1; + + idd->Area.area_state = AREA_ST_IDLE; + + return(IDD_E_SUCC); +} + +INT +idd_get_area_stat (VOID *idd_1, IDD_AREA *IddStat) +{ + IDD *idd = (IDD*)idd_1; + + *IddStat = idd->Area; + + return(IDD_E_SUCC); +} + + +/* get an idd area (really start operation, complete on handler callback) */ +INT +idd_get_area(VOID *idd_1, ULONG area_id, VOID (*handler)(), VOID *handler_arg) +{ + IDD *idd = (IDD*)idd_1; + IDD_MSG msg; + + D_LOG(D_ENTRY, ("idd_get_area: entry, idd: 0x%lx, area_id: %ld\n", idd, area_id)); + D_LOG(D_ENTRY, ("idd_get_area: handler: 0x%lx, handler_arg: 0x%lx\n", handler, handler_arg)); + + /* check if area is not busy */ + if ( idd->Area.area_state == AREA_ST_PEND ) + return(IDD_E_BUSY); + + /* mark area is pending, store arguments */ + idd->Area.area_state = AREA_ST_PEND; + idd->Area.area_id = area_id; + idd->Area.area_idd = idd; + idd->Area.area_len = 0; + idd->Area.area_handler = handler; + idd->Area.area_handler_arg = handler_arg; + + /* issue idd command to get area */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = CMD_DUMP_PARAM; + msg.param = msg.bufid = area_id; + if ( idd_send_msg(idd, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) + { + /* idd op failed! */ + idd->Area.area_state = AREA_ST_IDLE; + return(IDD_E_AREA); + } + + /* succ here */ + return(IDD_E_SUCC); +} + +VOID +IddSetRxFraming( + IDD *idd, + USHORT bchan, + ULONG FrameType + ) +{ + idd->recit[bchan].RxFrameType = FrameType; +} + +VOID +DetectFramingHandler( + IDD *idd, + USHORT port, + ULONG RxFrameType, + IDD_XMSG *msg + ) +{ + UCHAR DetectBytes[2]; + + DigiDump( DIGIQ931, ("DetectFramingHandler: idd = 0x%x, port = 0x%x, RxFrameType = 0x%x, msg = 0x%x\n", + idd, + port, + RxFrameType, + msg) ); + + if (RxFrameType & IDD_FRAME_DETECT) + { + // + // get detection bytes + // + IddGetDataFromAdapter(idd, + (PUCHAR)&DetectBytes, + (PUCHAR)msg->bufptr, + 2); + +// NdisMoveMemory ((PUCHAR)&DetectBytes, (PUCHAR)msg->bufptr, 2); + + D_LOG(D_ENTRY, ("DetectRxFraming: 0x%x, 0x%x\n",DetectBytes[0], DetectBytes[1])); + + if ((DetectBytes[0] == DKF_UUS_SIG) && (!DetectBytes[1])) + idd->recit[port].RxFrameType = IDD_FRAME_DKF; + + else if ((DetectBytes[0] == PPP_SIG_0) && (DetectBytes[1] == PPP_SIG_1)) + { + idd->recit[port].RxFrameType = IDD_FRAME_PPP; + cm__ppp_conn(idd, port); + } + } +} + +VOID +idd__cmd_handler(IDD *idd, USHORT chan, ULONG Reserved, IDD_MSG *msg) +{ + ULONG bytes; + + /* check for show area more/last frames (3/4) */ + if ( msg->bufid >= 2 ) + { + if ( (idd->Area.area_state == AREA_ST_PEND) && + (idd->Area.area_idd == idd) ) + { + /* copy frame data, as much as possible */ + bytes = MIN(msg->buflen, (sizeof(idd->Area.area_buf) - idd->Area.area_len)); + + IddGetDataFromAdapter(idd, + (PUCHAR)idd->Area.area_buf + idd->Area.area_len, + (PUCHAR)msg->bufptr, + (USHORT)bytes); + +// NdisMoveMemory (idd->Area.area_buf + idd->Area.area_len, msg->bufptr, bytes); + + idd->Area.area_len += bytes; + + /* if last, complete */ + if ( msg->bufid == 3 ) + { + idd->Area.area_state = AREA_ST_DONE; + if ( idd->Area.area_handler ) + (*idd->Area.area_handler)(idd->Area.area_handler_arg, + idd->Area.area_id, + idd->Area.area_buf, + idd->Area.area_len); + } + } + } +} + +#pragma NDIS_INIT_FUNCTION(idd_add_def) + +/* add a definition to initialization definition database */ +INT +idd_add_def(IDD *idd, CHAR *name, CHAR *val) +{ + INT name_len = __strlen(name) + 1; + INT val_len = __strlen(val) + 1; + + D_LOG(D_ENTRY, ("idd_add_def: entry\n")); + + __strlwr(name); + + __strlwr(val); + + D_LOG(D_ENTRY, ("idd_add_def: name: [%s], val: [%s]\n", name, val)); + /* check for room */ + + if ( (idd->DefinitionTableLength + name_len + val_len) > IDD_DEF_SIZE ) + { + D_LOG(DIGIINIT, ("idd_add_def: no room in definition table!\n")); + return(IDD_E_NOROOM); + } + + /* enter into table */ + NdisMoveMemory(idd->DefinitionTable + idd->DefinitionTableLength, name, name_len); + idd->DefinitionTableLength += name_len; + + NdisMoveMemory(idd->DefinitionTable + idd->DefinitionTableLength, val, val_len); + idd->DefinitionTableLength += val_len; + + /* return success */ + return(IDD_E_SUCC); +} // end idd_add_def + +#pragma NDIS_INIT_FUNCTION(idd_get_nvram) + +/* get an nvram location */ +INT +idd_get_nvram(VOID *idd_1, USHORT addr, USHORT *val) +{ + IDD *idd = (IDD*)idd_1; + D_LOG(D_ENTRY, ("idd_get_nvram: entry, idd: 0x%lx, addr: 0x%x\n", idd, addr)); + + /* lock card */ + NdisAcquireSpinLock(&idd->lock); + + /* do the read */ + *val = idd->NVRamRead(idd, addr); + + /* release card & return */ + NdisReleaseSpinLock(&idd->lock); + D_LOG(D_EXIT, ("idd_get_nvram: exit, val: 0x%x\n", *val)); + return(IDD_E_SUCC); +} diff --git a/private/ntos/ndis/digi/pcimac/idd_io.c b/private/ntos/ndis/digi/pcimac/idd_io.c new file mode 100644 index 000000000..4f2c64744 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd_io.c @@ -0,0 +1,672 @@ + /* + * IDD_IO.C - do inp/outp ops for idd modules + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef union +{ + UCHAR uc[4]; + ULONG ul; +}ULONG_UNION; + +typedef union +{ + UCHAR uc[2]; + USHORT us; +}USHORT_UNION; + +/* output to a port */ +VOID +IdpOutp( + IDD *idd, + USHORT port, + UCHAR val) +{ + NdisRawWritePortUchar((ULONG)idd->vhw.vbase_io + port, val); +} + +/* input from a port */ +UCHAR +IdpInp( + IDD *idd, + USHORT port) +{ + UCHAR val; + + NdisRawReadPortUchar((ULONG)idd->vhw.vbase_io + port, &val); + + return(val); +} + +/* output to a port */ +VOID +AdpOutp( + IDD *idd, + USHORT port, + UCHAR val + ) +{ + // + // Determine if this is a multi-channel BRI adapter. If so, then + // we need to select the correct ADP to reference. + // + // IMPORTANT NOTE: I can get away with this because we process IDD's + // on a per adapter basis. If this ever changes, + // then it may be necessary to change what is done + // here. + // + switch( idd->btype ) + { + case IDD_BT_DATAFIRE4ST: + // + // select the correct BRI channel to access. + // + NdisRawWritePortUchar( (ULONG)idd->vhw.vbase_io + ADP_REG_ADAPTER_CTRL, + idd->bline ); + break; + } + + NdisRawWritePortUchar((ULONG)idd->vhw.vbase_io + port, val); +} // end AdpOutp + +/* input from a port */ +UCHAR +AdpInp( + IDD *idd, + USHORT port + ) +{ + UCHAR val; + + // + // Determine if this is a multi-channel BRI adapter. If so, then + // we need to select the correct ADP to reference. + // + // IMPORTANT NOTE: I can get away with this because we process IDD's + // on a per adapter basis. If this ever changes, + // then it may be necessary to change what is done + // here. + // + switch( idd->btype ) + { + case IDD_BT_DATAFIRE4ST: + // + // select the correct BRI channel to access. + // + NdisRawWritePortUchar( (ULONG)idd->vhw.vbase_io + ADP_REG_ADAPTER_CTRL, + idd->bline ); + break; + } + + NdisRawReadPortUchar((ULONG)idd->vhw.vbase_io + port, &val); + + return(val); +} // end AdpInp + +VOID AdpWriteControlBit( IDD *idd, + UCHAR Bit, + UCHAR Value ) +/*++ + +Routine Description: + + Sets bits indicated to specified values. + +Arguments: + + Bit - BitMask of which bits are to be set. + + Value - BitMask to be applied to for Bit. + +Return Value: + + None. + +--*/ +{ + UCHAR OldData, NewData; + + // Read old value. + OldData = idd->InFromPort( idd, ADP_REG_CTRL ); + + // Set new value + NewData = (OldData & Bit) | Value; + +// Data &= ~Bit; +// Data |= (Value ? Bit : 0); + + idd->OutToPort(idd, ADP_REG_CTRL, NewData); +} + +UCHAR +AdpReadReceiveStatus( + IDD *idd + ) +{ + return(AdpGetUByte(idd, ADP_STS_WINDOW)); +} + +// +// this function should be updated to use NdisRawWritePortBufferUshort +// when the datarat is capable of handling it!!!! +// +VOID +AdpPutBuffer ( + IDD *idd, + ULONG Destination, + PUCHAR Source, + USHORT Length + ) +{ + USHORT WordLength = Length >> 1; + PUCHAR OddData = (PUCHAR)(Source + (Length - 1)); + + D_LOG(D_ENTRY, ("AdpPutBuffer: idd: 0x%lx, Destination: 0x%lx, Source: 0x%lx, Length: %d\n", \ + idd, Destination, Source, Length)); + + AdpSetAddress(idd, Destination); + + // + // if WordLength has gone to zero with the shift this macro is just a nop + // + NdisRawWritePortBufferUshort((ULONG)(idd->vhw.vbase_io + ADP_REG_DATA_INC), + (PUSHORT)Source, + WordLength); + + // + // if the length is odd write the last odd byte to adapter + // + if (Length & 0x0001) + NdisRawWritePortUchar((ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC, *OddData); + +#if 0 + NdisRawWritePortBufferUchar( (ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC, + Source, + Length ); +#endif +} + +// +// this function should be updated to use NdisRawReadPortBufferUshort +// when the datarat is capable of handling it!!!! +// +VOID +AdpGetBuffer ( + IDD *idd, + PUCHAR Destination, + ULONG Source, + USHORT Length + ) +{ + USHORT WordLength = Length >> 1; + PUCHAR OddData = (PUCHAR)(Destination + (Length - 1)); + + D_LOG(D_ENTRY, ("AdpGetBuffer: idd: 0x%lx, Destination: 0x%lx, Source: 0x%lx, Length: %d\n", \ + idd, Destination, Source, Length)); + + AdpSetAddress(idd, Source); + + // + // if WordLength has gone to zero with the shift this macro is just a nop + // + NdisRawReadPortBufferUshort((ULONG)(idd->vhw.vbase_io + ADP_REG_DATA_INC), + (PUSHORT)Destination, + WordLength); + + // + // if the length is odd read the last odd byte from adapter + // + if (Length & 0x0001) + NdisRawReadPortUchar((ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC, OddData); + +// NdisRawReadPortBufferUchar((ULONG)idd->vhw.vbase_io + ADP_REG_DATA_INC, +// Buffer, +// Length); +} + +VOID +AdpPutUByte( + IDD *idd, + ULONG Address, + UCHAR Value + ) +{ + AdpSetAddress(idd, Address); + idd->OutToPort(idd, ADP_REG_DATA_INC, Value); +} + +VOID +AdpPutUShort( + IDD *idd, + ULONG Address, + USHORT Value + ) +{ + USHORT_UNION us; + + us.us = Value; + AdpSetAddress(idd, Address); + idd->OutToPort(idd, ADP_REG_DATA_INC, us.uc[1]); + idd->OutToPort(idd, ADP_REG_DATA_INC, us.uc[0]); +} + +VOID +AdpPutULong( + IDD *idd, + ULONG Address, + ULONG Value + ) +{ + ULONG_UNION ul; + + ul.ul = Value; + AdpSetAddress(idd, Address); + idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[3]); + idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[2]); + idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[1]); + idd->OutToPort(idd, ADP_REG_DATA_INC, ul.uc[0]); +} + +UCHAR +AdpGetUByte( + IDD *idd, + ULONG Address + ) +{ + UCHAR Value; + + AdpSetAddress(idd, Address); + + Value = idd->InFromPort(idd, ADP_REG_DATA_INC); + + return(Value); +} + +USHORT +AdpGetUShort( + IDD *idd, + ULONG Address + ) +{ + USHORT_UNION us; + + AdpSetAddress(idd, Address); + us.uc[1] = idd->InFromPort(idd, ADP_REG_DATA_INC); + us.uc[0] = idd->InFromPort(idd, ADP_REG_DATA_INC); + + return(us.us); +} + +ULONG +AdpGetULong( + IDD *idd, + ULONG Address + ) +{ + ULONG_UNION ul; + + AdpSetAddress(idd, Address); + ul.uc[3] = idd->InFromPort(idd, ADP_REG_DATA_INC); + ul.uc[2] = idd->InFromPort(idd, ADP_REG_DATA_INC); + ul.uc[1] = idd->InFromPort(idd, ADP_REG_DATA_INC); + ul.uc[0] = idd->InFromPort(idd, ADP_REG_DATA_INC); + + return(ul.ul); +} + +VOID +AdpWriteCommandStatus( + IDD *idd, + UCHAR Value + ) +{ + // + // setup the address + // + AdpSetAddress(idd, ADP_CMD_WINDOW + 1); + + // + // put out the value + // + idd->OutToPort(idd, ADP_REG_DATA_INC, Value); +} + +UCHAR +AdpReadCommandStatus( + IDD *idd + ) +{ + UCHAR Status; + + // + // setup the address + // + AdpSetAddress(idd, ADP_CMD_WINDOW + 1); + + // + // get status + // + Status = idd->InFromPort(idd, ADP_REG_DATA_INC); + + return(Status); +} + +VOID +AdpSetAddress( + IDD *idd, + ULONG Address + ) +{ + ULONG_UNION ul; + + // + // Look at the heartbeat on the adapter and determine if it is + // still beating. + // + ul.ul = 0x504; + idd->OutToPort(idd, ADP_REG_ADDR_LO, ul.uc[0]); + idd->OutToPort(idd, ADP_REG_ADDR_MID, ul.uc[1]); + idd->OutToPort(idd, ADP_REG_ADDR_HI, ul.uc[2]); + + ul.uc[3] = idd->InFromPort(idd, ADP_REG_DATA_INC); + ul.uc[2] = idd->InFromPort(idd, ADP_REG_DATA_INC); + ul.uc[1] = idd->InFromPort(idd, ADP_REG_DATA_INC); + ul.uc[0] = idd->InFromPort(idd, ADP_REG_DATA_INC); + + D_LOG( D_NEVER, ("Heartbeat: 0x%lx\n", ul.ul) ); + + D_LOG(D_NEVER, ("AdpSetAddress: idd: 0x%lx, Address: 0x%lx\n", \ + idd, Address)); + // + // setup address + // + ul.ul = Address; + idd->OutToPort(idd, ADP_REG_ADDR_LO, ul.uc[0]); + idd->OutToPort(idd, ADP_REG_ADDR_MID, ul.uc[1]); + idd->OutToPort(idd, ADP_REG_ADDR_HI, ul.uc[2]); +} + +UCHAR +IdpGetUByteIO( + IDD* idd, + USHORT port + ) +{ + UCHAR Value; + + Value = idd->InFromPort(idd, port); + + return(Value); +} + +VOID +IdpGetBuffer( + IDD* idd, + ULONG Bank, + ULONG Page, + ULONG Address, + USHORT Length, + PUCHAR Buffer + ) +{ + // + // address from offset 0 on the bank and page described + // + PUCHAR VirtualAddress = idd->vhw.vmem + Address; + + DbgPrint("IdpGetBuffer: idd: 0x%x, Bank: 0x%x, Page: 0x%x, Address: 0x%x, VirtAddres: 0x%x, Length: 0x%x\n", + idd, Bank, Page, Address, VirtualAddress, Length); + + + if (Length > IDP_RAM_PAGE_SIZE) + Length = IDP_RAM_PAGE_SIZE; + + // + // set the bank to the desired bank + // + idd->SetBank(idd, (UCHAR)Bank, 1); + + // + // set the page to the desired page + // + idd->ChangePage(idd, (UCHAR)Page); + + // + // get the stuff + // + NdisMoveFromMappedMemory((PVOID)Buffer, (PVOID)VirtualAddress, Length); +} + +VOID +IdpPutUByteIO( + IDD* idd, + USHORT Port, + UCHAR Value + ) +{ + +} + +VOID +IdpPutBuffer( + IDD* idd, + ULONG Bank, + ULONG Page, + ULONG Address, + USHORT Length, + PUCHAR Buffer + ) +{ + +} + +/* + * IDD_MC.C - IDD board specific functions for MCIMAC + */ + +/* set active bank, control reset state */ +VOID +IdpMcSetBank(IDD *idd, UCHAR bank, UCHAR run) +{ + static UCHAR reset_map[] = { 4, 5, 7 }; + static UCHAR run_map[] = { 0, 1, 3 }; + + idd->OutToPort(idd, 1, (UCHAR)(run ? run_map[bank] : reset_map[bank])); +} + +/* set active page, control memory mapping */ +VOID +IdpMcSetPage(IDD *idd, UCHAR page) +{ + if ( page == IDD_PAGE_NONE ) + idd->OutToPort(idd, 2, 0); + else + idd->OutToPort(idd, 2, (UCHAR)(0x80 | page)); +} + +/* set base memory window, redundent! - already stored by POS */ +VOID +IdpMcSetBasemem(IDD *idd, ULONG basemem) +{ + +} + + +/* + * IDD_PC.C - IDD board specific functions for ARIZONA + */ + +/* set active bank, control reset state */ +VOID +AdpSetBank(IDD *idd, UCHAR bank, UCHAR run) +{ + +} + +/* set active page, control memory mapping */ +VOID +AdpSetPage(IDD *idd, UCHAR page) +{ + +} + +/* set base memory window, redundent! - already stored by POS */ +VOID +AdpSetBasemem(IDD *idd, ULONG basemem) +{ + +} + +/* + * IDD_PC.C - IDD board specific functions for PCIMAC + */ + +/* set active bank, control reset state */ +VOID +IdpPcSetBank(IDD *idd, UCHAR bank, UCHAR run) +{ + // + // reset map means that the reset bit is held in the bank select register + // + static UCHAR reset_map[] = { 4, 5, 7 }; + + // + // run map means that the reset bit is not set in the bank select register + // + static UCHAR run_map[] = { 0, 1, 3 }; + + idd->OutToPort(idd, 4, (UCHAR)(run ? run_map[bank] : reset_map[bank])); +} + +/* set active page, control memory mapping */ +VOID +IdpPcSetPage(IDD *idd, UCHAR page) +{ + if ( page == IDD_PAGE_NONE ) + idd->OutToPort(idd, 5, 0); + else + idd->OutToPort(idd, 5, (UCHAR)(0x80 | page)); +} + +/* set base memory window, over-writes IRQ to 0! */ +VOID +IdpPcSetBasemem(IDD *idd, ULONG basemem) +{ + idd->OutToPort(idd, 6, (UCHAR)(basemem >> 8)); + idd->OutToPort(idd, 7, (UCHAR)(basemem >> 16)); +} + + +/* + * IDD_PC4.C - IDD board specific functions for PCIMAC\4 + */ + +/* + * set active bank, control reset state + * + * this routine makes use of the local data attached to the i/o resource. + * as local dta is a long, it is used as an image of registers 3,4,x,x + */ +VOID +IdpPc4SetBank(IDD *idd, UCHAR bank, UCHAR run) +{ + static UCHAR reset_map[] = { 4, 5, 7 }; + static UCHAR run_map[] = { 0, 1, 3 }; + ULONG lreg; + UCHAR *reg = (UCHAR*)&lreg; + UCHAR val = run ? run_map[bank] : reset_map[bank]; + + D_LOG(D_ENTRY, ("idd__pc4_set_bank: entry, idd: 0x%lx, bank: 0x%x, run: 0x%x\n", idd, bank, run)); + + /* lock i/o resource, get local data - which is register image */ + res_own(idd->res_io, idd); + res_get_data(idd->res_io, &lreg); + + /* the easy way is to switch on bline & write bline specific code */ + switch ( idd->bline ) + { + case 0 : + reg[0] = (reg[0] & 0xF0) | val; + idd->OutToPort(idd, 3, reg[0]); + break; + + case 1 : + reg[0] = (val << 4) | (reg[0] & 0x0F); + idd->OutToPort(idd, 3, reg[0]); + break; + + case 2 : + reg[1] = (reg[1] & 0xF0) | val; + idd->OutToPort(idd, 4, reg[1]); + break; + + case 3 : + reg[1] = (val << 4) | (reg[1] & 0x0F); + idd->OutToPort(idd, 4, reg[1]); + break; + } + + /* return local data, release resource */ + res_set_data(idd->res_io, lreg); + res_unown(idd->res_io, idd); + + D_LOG(D_EXIT, ("idd__pc4_set_bank: exit\n")); +} + +/* set active page, control memory mapping */ +VOID +IdpPc4SetPage(IDD *idd, UCHAR page) +{ + if ( page == IDD_PAGE_NONE ) + idd->OutToPort(idd, 5, 0); + else + idd->OutToPort(idd, 5, (UCHAR)(0x80 | page | (UCHAR)(idd->bline << 5))); +} + +/* set base memory window, over-writes IRQ to 0! */ +VOID +IdpPc4SetBasemem(IDD *idd, ULONG basemem) +{ + idd->OutToPort(idd, 6, (UCHAR)(basemem >> 8)); + idd->OutToPort(idd, 7, (UCHAR)(basemem >> 16)); +} + + +/* + * IDD_MEM.C - some memory handling routines + */ + + +/* fill a memory block using word moves */ +VOID +IdpMemset(UCHAR*dst, USHORT val, INT size) +{ + D_LOG(D_ENTRY, ("idd__memwset: entry, dst: 0x%lx, val: 0x%x, size: 0x%x\n", dst, val, size)); + +// for ( size /= sizeof(USHORT) ; size ; size--, dst++ ) +// NdisMoveToMappedMemory((PVOID)dst, (PVOID)&val, sizeof(USHORT)); + NdisZeroMappedMemory((PVOID)dst, size); +} + +/* copy a memory block using word moves */ +VOID +IdpMemcpy(UCHAR *dst, UCHAR *src, INT size) +{ + D_LOG(D_ENTRY, ("idd__memwcpy: entry, dst: 0x%lx, src: 0x%lx, size: 0x%x\n", dst, src, size)); + +// for ( size /= sizeof(USHORT) ; size ; size--, dst++, src++ ) +// NdisMoveToMappedMemory((PVOID)dst, (PVOID)src, sizeof(USHORT)); + + NdisMoveToMappedMemory((PVOID)dst, (PVOID)src, size); +} + + + diff --git a/private/ntos/ndis/digi/pcimac/idd_msg.c b/private/ntos/ndis/digi/pcimac/idd_msg.c new file mode 100644 index 000000000..d888cff45 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd_msg.c @@ -0,0 +1,168 @@ +/* + * IDD_MSG.C - message handling code + */ + +#include +#include +#include +#include +#include +#include +#include + +/* send a message down a port. only really queues message for transmittion */ +INT +idd_send_msg(VOID *idd_1, IDD_MSG *msg, USHORT port, VOID (*handler)(), VOID *handler_arg) +{ + IDD *idd = (IDD*)idd_1; + INT ret = IDD_E_SUCC; + IDD_SENDQ *sq; + + D_LOG((D_ENTRY|DIGIIDD), ("idd_send_msg: entry, idd: 0x%lx, msg: 0x%lx\n", + idd, msg)); + D_LOG((D_ENTRY|DIGIIDD), ("idd_send_msg: port: %u, handler: 0x%lx, handler_arg: 0x%lx\n", \ + port, handler, handler_arg)); + D_LOG((D_ENTRY|DIGIIDD), ("idd_send_msg: opcode: 0x%x, buflen: 0x%x, bufptr: 0x%lx\n", \ + msg->opcode, msg->buflen, msg->bufptr)); + D_LOG((D_ENTRY|DIGIIDD), ("idd_send_msg: bufid: 0x%x, param: 0x%x\n", \ + msg->bufid, msg->param)); + + /* check port */ + if ( port >= IDD_TX_PORTS ) + { + D_LOG(DIGIIDD, ("idd_send_msg: invalid port!\n")); + return(IDD_E_BADPORT); + } + sq = idd->sendq + port; + + /* lock port queue */ + NdisAcquireSpinLock(&sq->lock); + + /* check for space */ + if ( sq->num >= sq->max ) + { + DbgPrint("sq->num: %d, sq->max: %d\n", sq->num, sq->max); + ret = IDD_E_NOROOM; + } + else + { + D_LOG( DIGITXFRAGDATA, ("Sending Frag:\n") ); + DigiDumpData( DIGITXFRAGDATA, msg->bufptr, (msg->buflen & H_TX_LEN_MASK) ); + + /* space avail, fill in entry */ + sq->tbl[sq->put].msg = *msg; + sq->tbl[sq->put].handler = handler; + sq->tbl[sq->put].handler_arg = handler_arg; + /* update queue vars */ + if ( (sq->put += 1) >= sq->max ) + sq->put = 0; + sq->num++; + } + + /* release lock */ + NdisReleaseSpinLock(&sq->lock); + + +// /* (maybe) trigger processing */ +// if ( ret == IDD_E_SUCC ) +// idd_process(idd, 1); + + if (ret == IDD_E_SUCC) + idd->PollTx(idd); + + /* return here */ + D_LOG(D_EXIT, ("idd_send_msg: exit, ret=0x%x\n", ret)); + return(ret); +} // end idd_send_msg + +/* attach a user handler to a port */ +// +INT +idd_attach(VOID *idd_1, USHORT port, VOID (*handler)(), VOID *handler_arg) +{ + INT ret = IDD_E_SUCC; + IDD_RECIT *rt; + IDD *idd = (IDD*)idd_1; + + D_LOG(D_ENTRY, ("idd_attach: entry, idd: 0x%lx\n", idd)); + D_LOG(D_ENTRY, ("idd_attach: port: %u, handler: 0x%lx, handler_arg: 0x%lx", \ + port, handler, handler_arg)); + + /* check port */ + if ( port >= IDD_RX_PORTS ) + { + D_LOG((DIGIIDD|DIGIINIT), ("idd_attach: invalid port!\n")); + return(IDD_E_BADPORT); + } + rt = idd->recit + port; + + /* lock port table */ + NdisAcquireSpinLock(&rt->lock); + + /* check for space */ + if ( rt->num >= rt->max ) + ret = IDD_E_NOROOM; + else + { + /* space avail, fill in entry */ + rt->tbl[rt->num].handler = handler; + rt->tbl[rt->num].handler_arg = handler_arg; + + /* update table vars */ + rt->num++; + } + + /* release lock */ + NdisReleaseSpinLock(&rt->lock); + + /* return here */ + D_LOG(D_EXIT, ("idd_attach: exit, ret=0x%x\n", ret)); + return(ret); +} + +/* detach a user handler to a port */ +INT +idd_detach(VOID *idd_1, USHORT port, VOID (*handler)(), VOID *handler_arg) +{ + + INT ret = IDD_E_SUCC; + IDD_RECIT *rt; + INT n; + IDD *idd = (IDD*)idd_1; + + D_LOG(D_ENTRY, ("idd_detach: entry, idd: 0x%lx\n", idd)); + D_LOG(D_ENTRY, ("idd_detach: port: %u, handler: 0x%lx, handler_arg: 0x%lx", \ + port, handler, handler_arg)); + + /* check port */ + if ( port >= IDD_RX_PORTS ) + { + D_LOG(DIGIIDD, ("idd_detach: invalid port!\n")); + return(IDD_E_BADPORT); + } + rt = idd->recit + port; + + /* lock port table */ + NdisAcquireSpinLock(&rt->lock); + + /* scan table for handler/handler_arg */ + for ( n = 0 ; n < rt->num ; n++ ) + if ( (rt->tbl[n].handler == handler) && (rt->tbl[n].handler_arg == handler_arg) ) + break; + if ( n >= rt->num ) + ret = IDD_E_NOSUCH; + else + { + /* found, shrink table */ + NdisMoveMemory(rt->tbl + n, rt->tbl + n + 1, sizeof(rt->tbl[0]) * (rt->num - n - 1)); + rt->num--; + } + + /* release lock */ + NdisReleaseSpinLock(&rt->lock); + + /* return here */ + D_LOG(D_EXIT, ("idd_detach: exit, ret=0x%x\n", ret)); + return(ret); +} + diff --git a/private/ntos/ndis/digi/pcimac/idd_nv.c b/private/ntos/ndis/digi/pcimac/idd_nv.c new file mode 100644 index 000000000..bda07f281 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd_nv.c @@ -0,0 +1,140 @@ +/* + * IDD_NV.C - nvram handling routines + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static USHORT nv_op (IDD*, SHORT, USHORT, USHORT, USHORT); +static INT nv_clk (IDD*, USHORT); + +/* clock one nvram bit in/out */ +static INT +nv_clk(IDD *idd, USHORT dat) +{ + INT ret; + + dat &= 1; /* make sure dat is one bit only */ + + idd->OutToPort(idd, 0, (UCHAR)(0x04 | dat)); /* setup data */ + idd->OutToPort(idd, 0, (UCHAR)(0x06 | dat)); /* clock high */ + idd->OutToPort(idd, 0, (UCHAR)(0x04 | dat)); /* clock low */ + ret = idd->InFromPort(idd, 0) & 0x01; /* return out bit */ + + return(ret); +} + +/* perform a basic nvram operation */ +static USHORT +nv_op(IDD *idd, SHORT op, USHORT addr, USHORT val, USHORT has_val) +{ + INT n; + USHORT word = 0; + + D_LOG(D_ENTRY, ("nv_op: entry, idd: 0x%lx op: %d, addr: 0x%x, val: 0x%x, has_val: %d", \ + idd, op, addr, val, has_val)); + + /* own i/o resource */ + res_own(idd->res_io, idd); + + /* set CS */ + idd->OutToPort(idd, 0, 0x4); + + /* if waiting for chip to be done, stay here */ + if ( op < 0 ) + { + while ( !(idd->InFromPort(idd, 0) & 0x01) ) + ; + /* remove ownership of i/o */ + res_unown(idd->res_io, idd); + return(0); + } + + /* clock in SB + opcode */ + nv_clk(idd, (USHORT)1); + nv_clk(idd, (USHORT)(op >> 1)); + nv_clk(idd, (USHORT)(op & 1)); + + /* clock in address */ + for ( n = 5 ; n >= 0 ; n-- ) + nv_clk(idd, (USHORT)(addr >> n)); + + if ( has_val ) + { + /* clock data/val in/out */ + for ( n = 15 ; n >= 0 ; n-- ) + word = (word << 1) | nv_clk(idd, (USHORT)(val >> n)); + } + + /* remove CS */ + idd->OutToPort(idd, 0, 0x00); + + /* remove ownership of i/o */ + res_unown(idd->res_io, idd); + + + D_LOG(D_EXIT, ("nv_op: exit, word: 0x%x", word)); + return(word); +} + +/* read a nvram location */ +USHORT +IdpNVRead(IDD *idd, USHORT addr) +{ + /* a basic op */ + return(nv_op(idd, 2, addr, 0, 1)); +} + + +/* read a nvram location */ +USHORT +AdpNVRead(IDD *idd, USHORT addr) +{ + return(AdpGetUShort(idd, ADP_NVRAM_WINDOW + addr)); +} + +/* write a nvram location */ +VOID +IdpNVWrite(IDD *idd, USHORT addr, USHORT val) +{ + /* enable writes */ + nv_op(idd, 0, 0x30, 0, 0); + + /* do the write */ + nv_op(idd, 1, addr, val, 1); + + /* wait for part to be done */ + nv_op(idd, -1, 0, 0, 0); +} + +/* write a nvram location */ +VOID +AdpNVWrite(IDD *idd, USHORT addr, USHORT val) +{ + +} + + +/* erase all nvram */ +VOID +IdpNVErase(IDD *idd) +{ + /* enable writes */ + nv_op(idd, 0, 0x30, 0, 0); + + /* erase */ + nv_op(idd, 0, 0x20, 0, 0); +} + +/* erase all nvram */ +VOID +AdpNVErase(IDD *idd) +{ + +} diff --git a/private/ntos/ndis/digi/pcimac/idd_proc.c b/private/ntos/ndis/digi/pcimac/idd_proc.c new file mode 100644 index 000000000..eac4e52cd --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd_proc.c @@ -0,0 +1,988 @@ +/* + * IDD_PROC.C - do real tx/rx processing + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if DBG +#define AddBufferToList(_idd, _Part, _Buffer) \ +{ \ + BUFFER_MANAGER *IdpBufferStuff = &(_idd)->BufferStuff[_Part]; \ + ULONG *PutBuffer = &IdpBufferStuff->Buffer[IdpBufferStuff->Put % 32]; \ + ASSERT(!*PutBuffer); \ + *PutBuffer = _Buffer; \ + IdpBufferStuff->Put++; \ + IdpBufferStuff->Count++; \ + ASSERT(IdpBufferStuff->Count < 32); \ +} + +#define RemoveBufferFromList(_idd, _Part) \ +{ \ + BUFFER_MANAGER *IdpBufferStuff = &(_idd)->BufferStuff[_Part]; \ + ULONG *GetBuffer = &IdpBufferStuff->Buffer[IdpBufferStuff->Get % 32]; \ + ASSERT(*GetBuffer); \ + *GetBuffer = 0; \ + IdpBufferStuff->Get++; \ + ASSERT(IdpBufferStuff->Count > 0); \ + IdpBufferStuff->Count--; \ +} +#endif + +/* poll (process) trasmitter side */ +ULONG +IdpPollTx(IDD *idd) +{ + INT n, has_msg; + ULONG EventNum = 0; + IDD_SMSG smsg; + USHORT buf_len = 0, TxFlags = 0, TempUshort; + UCHAR status; + ULONG msg_bufptr, TempUlong; + + D_LOG(D_NEVER, ("IdpPollTx: entry, idd: 0x%lx\n", idd)); + + /* must get semaphore */ + if ( !sema_get(&idd->proc_sema) ) + return(IDD_E_SUCC); + + /* lock idd */ + NdisAcquireSpinLock(&idd->lock); + + if (!GetResourceSem (idd->res_mem)) + { + NdisReleaseSpinLock(&idd->lock); + sema_free(&idd->proc_sema); + return(IDD_E_SUCC); + } + + IdpCPage(idd, 0); + + /* loop on all tx ports */ + for ( n = 0 ; n < IDD_TX_PORTS ; n++ ) + { + USHORT part = idd->tx_partq[n]; + + /* skip non existent ports */ + if ( !idd->tx_port[n] ) + continue; + + /* check if port is blocked on a buffer */ + if ( !idd->tx_buf[part] ) + { + /* try to get a buffer for this partition */ + IdpCPage(idd, 0); + + TempUlong = (ULONG)(part + 4); + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_param, (PVOID)&TempUlong, sizeof (ULONG)); + + status = idd->Execute(idd, IDP_L_GET_WBUF); + + if ( status != IDP_S_OK) + { + D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #1: status=0x%x\n", + ((ULONG)status & 0x000000FF)) ); + continue; + } + + /* if here, buffer allocated, register it */ + NdisMoveFromMappedMemory( (PVOID)&idd->tx_buf[part], (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG)); + +#if DBG + AddBufferToList(idd, part, idd->tx_buf[part]); +#endif + + } + + /* check if a message is waiting to be sent on a port */ + NdisAcquireSpinLock(&idd->sendq[n].lock); + if ( has_msg = idd->sendq[n].num ) + { + /* extract message off queue */ + smsg = idd->sendq[n].tbl[idd->sendq[n].get]; + if ( ++idd->sendq[n].get >= idd->sendq[n].max ) + idd->sendq[n].get = 0; + idd->sendq[n].num--; + } + NdisReleaseSpinLock(&idd->sendq[n].lock); + + /* if no message, escape here */ + if ( !has_msg ) + continue; + + /* debug print message */ + D_LOG(DIGIIDD, ("poll_tx: smsg: opcode: 0x%x, buflen: 0x%x, bufptr: 0x%lx\n", \ + smsg.msg.opcode, smsg.msg.buflen, smsg.msg.bufptr)); + D_LOG(DIGIIDD, ("poll_tx: bufid: 0x%x, param: 0x%x, handler: 0x%lx, arg: 0x%lx\n", \ + smsg.msg.bufid, smsg.msg.param, smsg.handler, smsg.handler_arg)); + + // + // save xmitflags clearing out dkf fragment indicator + // they are in most significant nible + // Bits - xxxx + // ||||__ fragment indicator + // |||___ tx flush flag + // ||____ !tx end flag + // |_____ !tx begin flag + // + TxFlags = smsg.msg.buflen & TX_FLAG_MASK; + + +#if DBG + switch (idd->BufferStuff[part].TxState) + { + case TX_BEGIN: + case TX_END: + if (TxFlags & H_TX_N_BEG) + { + DbgPrint("Missed a begining buffer! idd: 0x%x, part: %d\n", idd, part); + DbgPrint("TxFlags: 0x%x, State: 0x%x\n", TxFlags, idd->BufferStuff[part].TxState); + DbgBreakPoint(); + } + else if (TxFlags & H_TX_N_END) + { + idd->BufferStuff[part].TxState = TX_MIDDLE; + idd->BufferStuff[part].FragsSinceBegin = 0; + } + break; + + case TX_MIDDLE: + if (TxFlags & H_TX_N_BEG) + break; + else + { + DbgPrint("Missed an ending buffer! idd: 0x%x, part: %d\n", idd, part); + DbgPrint("TxFlags: 0x%x, State: 0x%x\n", TxFlags, idd->BufferStuff[part].TxState); + DbgBreakPoint(); + } + break; + + default: + DbgPrint("Unknown State! idd: 0x%x, part: %d\n", idd, part); + DbgPrint("TxFlags: 0x%x, State: 0x%x\n", TxFlags, idd->BufferStuff[part].TxState); + DbgBreakPoint(); + idd->BufferStuff[part].TxState = TX_BEGIN; + idd->BufferStuff[part].FragsSinceBegin = 0; + break; + } + + idd->BufferStuff[part].FragsSinceBegin++; + if (!(TxFlags & H_RX_N_END)) + idd->BufferStuff[part].TxState = TX_END; + +#endif + /* check for buffer, if has one, copyin */ + + IdpCPage(idd, 0); + + if( idd->tx_buf[part] == 0 ) + DbgPrint( "Giving a 0 buffer back in IDP_L_WRITE call!\n" ); + + NdisMoveToMappedMemory( (PVOID)&idd->IdpCmd->msg_bufptr, + (PVOID)&idd->tx_buf[part], + sizeof (ULONG) ); + +#if DBG + RemoveBufferFromList(idd, part); +#endif + + if ( smsg.msg.bufptr ) + buf_len = IdpCopyin(idd, (char*)idd->tx_buf[part], + smsg.msg.bufptr, smsg.msg.buflen); + else + buf_len = 0; + + IdpCPage(idd, 0); + + TempUshort = (USHORT)(buf_len | TxFlags); + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_buflen, (PVOID)&TempUshort, sizeof(USHORT)); + + /* copy rest of command area */ + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_opcode, (PVOID)&smsg.msg.opcode, sizeof(USHORT)); + + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_bufid, (PVOID)&smsg.msg.bufid, sizeof (ULONG)); + + TempUlong = (ULONG)(part + 4); + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_param, (PVOID)&TempUlong, sizeof (ULONG)); + + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_id, (PVOID)&idd->tx_port[n], sizeof(USHORT)); + + /* execute the command, mark an event */ + + status = idd->Execute(idd, IDP_L_WRITE); + + EventNum++; + + /* if came back with no buffer, mark it - else store buffer */ + if ( status != IDP_S_OK ) + { + idd->tx_buf[part] = 0; + D_LOG(D_RARE, ("poll_tx: no buffer!, part: %d\n", part)); + D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #2: status=0x%x\n", + ((ULONG)status & 0x000000FF)) ); + } + else + { + NdisMoveFromMappedMemory((PVOID)&msg_bufptr, (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG)); + + if ( msg_bufptr ) + { + idd->tx_buf[part] = msg_bufptr; + +#if DBG + AddBufferToList(idd, part, idd->tx_buf[part]); +#endif + + D_LOG(D_RARE, ("poll_tx: new buffer, part: %d, buf: 0x%lx\n", \ + part, idd->tx_buf[part])); + } + else + { + idd->tx_buf[part] = 0; + DbgPrint( "Adapter did not return buffer in IDP_L_WRITE\n" ); + } + } + + /* call user's handler */ + if ( smsg.handler ) { + (*smsg.handler)(smsg.handler_arg, n, &smsg); + } + + } + + /* unset page, free memory window */ + IdpCPage(idd, IDD_PAGE_NONE); + + FreeResourceSem (idd->res_mem); + + NdisReleaseSpinLock(&idd->lock); + + sema_free(&idd->proc_sema); + + return(EventNum); +} + +/* poll (process) trasmitter side */ +ULONG +AdpPollTx(IDD *idd) +{ + USHORT buf_len = 0, TxFlags = 0; + UCHAR status; + ULONG n, part, has_msg, EventNum = 0; + IDD_SMSG smsg; + + D_LOG(D_NEVER, ("AdpPollTx: entry, idd: 0x%lx\n", idd)); + + /* must get semaphore */ + if ( !sema_get(&idd->proc_sema) ) + return(IDD_E_SUCC); + + /* lock idd */ + NdisAcquireSpinLock(&idd->lock); + + // + // Lock access to the I/O ports in case this is a multi-BRI adapter + // e.g. DataFire4 + // + if (!GetResourceSem (idd->res_io)) + { + NdisReleaseSpinLock(&idd->lock); + sema_free(&idd->proc_sema); + return(IDD_E_SUCC); + } + + // + // for all tx ports + // + for (n = 0; n < IDD_TX_PORTS; n++) + { + // + // skip non existent ports + // + if (!idd->tx_port[n]) + continue; + + // + // clear command structure + // + NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD)); + + // + // see if port is blocked needing a buffer + // + if ( !idd->tx_buf[part = idd->tx_partq[n]] ) + { + + // + // fill port id and status bit + // + idd->AdpCmd.msg_param = (UCHAR)part + 4; + // + // execute command + // + status = idd->Execute(idd, ADP_L_GET_WBUF); + + // + // if no buffer then go to next port + // + if (status != ADP_S_OK) + { + D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #1: status=0x%x\n", + ((ULONG)status & 0x000000FF)) ); + continue; + } + + // + // if here, buffer was allocate, register it + // + idd->tx_buf[part] = (ULONG)idd->AdpCmd.msg_bufptr; + + } + + // + // see if there is a message waiting to be sent + // + NdisAcquireSpinLock(&idd->sendq[n].lock); + if ( has_msg = idd->sendq[n].num ) + { + /* extract message off queue */ + smsg = idd->sendq[n].tbl[idd->sendq[n].get]; + if ( ++idd->sendq[n].get >= idd->sendq[n].max ) + idd->sendq[n].get = 0; + idd->sendq[n].num--; + } + NdisReleaseSpinLock(&idd->sendq[n].lock); + + // + // if no message go to next port + // + if (!has_msg) + continue; + + /* debug print message */ + D_LOG(DIGIIDD, ("AdpPollTx: smsg: opcode: 0x%x, buflen: 0x%x, bufptr: 0x%lx\n", \ + smsg.msg.opcode, smsg.msg.buflen, smsg.msg.bufptr)); + D_LOG(DIGIIDD, ("AdpPollTx: bufid: 0x%x, param: 0x%x, handler: 0x%lx, arg: 0x%lx\n", \ + smsg.msg.bufid, smsg.msg.param, smsg.handler, smsg.handler_arg)); + + + // + // save xmitflags clearing out dkf fragment indicator + // they are in most significant nible + // Bits - xxxx + // ||||__ fragment indicator + // |||___ tx flush flag + // ||____ !tx end flag + // |_____ !tx begin flag + // + TxFlags = smsg.msg.buflen & TX_FLAG_MASK; + + // + // see if there is a buffer to be copied + // + (ULONG)idd->AdpCmd.msg_bufptr = idd->tx_buf[part]; + + if ( smsg.msg.bufptr ) + buf_len = AdpCopyin(idd, smsg.msg.bufptr, smsg.msg.buflen); + else + buf_len = 0; + + idd->AdpCmd.msg_buflen = buf_len | TxFlags; + idd->AdpCmd.msg_opcode = smsg.msg.opcode; + idd->AdpCmd.msg_bufid = smsg.msg.bufid; + idd->AdpCmd.msg_param = (ULONG)(part + 4); + idd->AdpCmd.port_id = idd->tx_port[n]; + + status = idd->Execute(idd, ADP_L_WRITE); + + EventNum++; + + if (status != ADP_S_OK) + { + idd->tx_buf[part] = 0; + D_LOG(D_RARE, ("poll_tx: no buffer!, part: %d\n", part)); + D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #2: status=0x%x\n", + ((ULONG)status & 0x000000FF)) ); + } + else + { + if (idd->AdpCmd.msg_bufptr) + { + idd->tx_buf[part] = (ULONG)idd->AdpCmd.msg_bufptr; + D_LOG(D_RARE, ("poll_tx: new buffer, part: %d, buf: 0x%lx\n", \ + part, idd->tx_buf[part])); + + } + } + /* call user's handler */ + if ( smsg.handler ) + (*smsg.handler)(smsg.handler_arg, n, &smsg); + } + + FreeResourceSem (idd->res_io); + + NdisReleaseSpinLock(&idd->lock); + + sema_free(&idd->proc_sema); + + return(EventNum); +} // end AdpPollTx + +/* poll (process) reciever ports */ +ULONG +IdpPollRx(IDD *idd) +{ + INT n, m; + USHORT stat, ofs; + IDD_XMSG msg; + UCHAR status, Page; + ULONG TempUlong, EventNum = 0; + + /* must get semaphore */ + if ( !sema_get(&idd->proc_sema) ) + return(IDD_E_SUCC); + + /* lock idd */ + NdisAcquireSpinLock(&idd->lock); + + if (!GetResourceSem (idd->res_mem)) + { + NdisReleaseSpinLock(&idd->lock); + sema_free(&idd->proc_sema); + return(IDD_E_SUCC); + } + + /* get status port */ + IdpCPage(idd, 0); + + NdisMoveFromMappedMemory((PVOID)&stat, (PVOID)idd->IdpStat, sizeof(USHORT)); + + D_LOG(D_NEVER, ("poll_rx: stat: 0x%x (@0x%lx)\n", stat, idd->IdpStat)); + + /* make one pass on all rx ports which have a status bit on */ + for ( n = 0 ; n < IDD_RX_PORTS ; n++, stat >>= 1 ) + if ( stat & 1 ) + { + // + // skip non existent ports + // + if (!idd->rx_port[n]) + continue; + + /* install returned read buffer */ + IdpCPage(idd, 0); + + TempUlong = MAKELONG(HIWORD(idd->rx_buf), 0); + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_bufid, (PVOID)&TempUlong, sizeof (ULONG)); + + idd->rx_buf = 0; + + /* install port & execute a read */ + D_LOG(DIGIIDD, ("poll_rx: index: %d, ReadPort 0x%x\n", n, idd->rx_port[n])); + + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_id, (PVOID)&idd->rx_port[n], sizeof(USHORT)); + + status = idd->Execute(idd, IDP_L_READ); + + if ( status != IDP_S_OK ) + { + continue; + } + + EventNum++; + + /* copy message out */ + NdisMoveFromMappedMemory((PVOID)&msg.opcode, (PVOID)&idd->IdpCmd->msg_opcode, sizeof(USHORT)); + + NdisMoveFromMappedMemory((PVOID)&msg.buflen, (PVOID)&idd->IdpCmd->msg_buflen, sizeof(USHORT)); + + // save receive fragment flags + // they are in most significant nible + // Bits - xxxx + // ||||__ reserved + // |||___ reserved + // ||____ !rx end flag + // |_____ !rx begin flag + // + msg.FragmentFlags = msg.buflen & RX_FLAG_MASK; + + // + // get real buffer length + // + msg.buflen &= H_RX_LEN_MASK; + + NdisMoveFromMappedMemory((PVOID)&msg.bufptr, (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG)); + + NdisMoveFromMappedMemory((PVOID)&msg.bufid, (PVOID)&idd->IdpCmd->msg_bufid, sizeof (ULONG)); + + NdisMoveFromMappedMemory((PVOID)&msg.param, (PVOID)&idd->IdpCmd->msg_param, sizeof (ULONG)); + + /* save rx buffer */ + idd->rx_buf = (ULONG)msg.bufptr; + D_LOG(DIGIIDD, ("poll_rx: 0x%x 0x%x %lx %lx %lx\n", \ + msg.opcode, \ + msg.buflen, \ + msg.bufptr, \ + msg.bufid, \ + msg.param)); + + if ( msg.bufptr) + { + ofs = LOWORD(msg.bufptr); + Page = (UCHAR)(ofs >> 14) & 3; +#if DBG + if (Page > 1 ) + { + DbgPrint("Page changed to %d on idd 0x%lx!\n", Page, idd); + DbgBreakPoint(); + } +#endif + msg.bufptr = idd->vhw.vmem + (ofs & 0x3FFF); + IdpCPage(idd, Page); + } + + /* loop on rx handler, call user to copyout buffer */ + for ( m = 0 ; m < idd->recit[n].num ; m++ ) + (*idd->recit[n].tbl[m].handler)(idd->recit[n].tbl[m].handler_arg, + n, + idd->recit[n].RxFrameType, + &msg); + } + + /* unset page, free memory window */ + IdpCPage(idd, IDD_PAGE_NONE); + + FreeResourceSem (idd->res_mem); + + NdisReleaseSpinLock(&idd->lock); + + sema_free(&idd->proc_sema); + + return(EventNum); +} + +/* poll (process) receiver side */ +ULONG +AdpPollRx(IDD *idd) +{ + INT n, m; + UCHAR status; + ULONG EventNum = 0; + USHORT stat = 0; + IDD_XMSG msg; + + /* must get semaphore */ + if ( !sema_get(&idd->proc_sema) ) + return(IDD_E_SUCC); + + /* lock idd */ + NdisAcquireSpinLock(&idd->lock); + + if (!GetResourceSem (idd->res_io)) + { + NdisReleaseSpinLock(&idd->lock); + sema_free(&idd->proc_sema); + return(IDD_E_SUCC); + } + + stat = AdpReadReceiveStatus(idd); + + for( n = 0; stat && (n < IDD_RX_PORTS); n++, stat >>= 1 ) + if (stat & 1) + { + // + // clear command structure + // + NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD)); + + D_LOG(DIGIIDD, ("poll_rx: index: %d, ReadPort 0x%x\n", n, idd->rx_port[n])); + // + // return read buffer + // + idd->AdpCmd.msg_bufid = MAKELONG(HIWORD(idd->rx_buf), 0); + idd->rx_buf = 0; + + idd->AdpCmd.port_id = idd->rx_port[n]; + + status = idd->Execute(idd, ADP_L_READ); + + if (status != ADP_S_OK) + continue; + + EventNum++; + + msg.opcode = idd->AdpCmd.msg_opcode; + msg.buflen = idd->AdpCmd.msg_buflen; + + // save receive fragment flags + // they are in most significant nible + // Bits - xxxx + // ||||__ reserved + // |||___ reserved + // ||____ !rx end flag + // |_____ !rx begin flag + // + msg.FragmentFlags = msg.buflen & RX_FLAG_MASK; + + // + // get real buffer length + // + msg.buflen &= H_RX_LEN_MASK; + + msg.bufptr = (UCHAR*)LOWORD(idd->AdpCmd.msg_bufptr); + idd->rx_buf = (ULONG)idd->AdpCmd.msg_bufptr; + msg.bufid = idd->AdpCmd.msg_bufid; + msg.param = idd->AdpCmd.msg_param; + + + D_LOG(DIGIIDD, ("AdpPollRx: Opcode: 0x%x, BufLen: 0x%x, BufPtr: 0x%x\n", \ + msg.opcode, \ + msg.buflen, \ + msg.bufptr)); + D_LOG(DIGIIDD, ("AdpPollRx: FragmentFlags: 0x%x, BufId: 0x%x, Param: 0x%x\n", \ + msg.FragmentFlags,\ + msg.bufid, \ + msg.param)); + + /* loop on rx handler, call user to copyout buffer */ + for ( m = 0 ; m < idd->recit[n].num ; m++ ) + (*idd->recit[n].tbl[m].handler)(idd->recit[n].tbl[m].handler_arg, + n, + idd->recit[n].RxFrameType, + &msg); + } + + FreeResourceSem( idd->res_io ); + + NdisReleaseSpinLock(&idd->lock); + + sema_free(&idd->proc_sema); + + return(EventNum); +} // end AdpPollRx + +/* execute an idp command. assumes cpage=0 */ +UCHAR +IdpExec(IDD *idd, UCHAR opcode) +{ + UCHAR status = IDP_S_PEND; + ULONG TempWaitCounter; + +#if DBG + USHORT IdpCounter1 = 0; + ULONG IdpCounter2 = 0; +#endif + + D_LOG(D_ENTRY, ("IdpExec: entry, idd: 0x%lx, opcode=%d\n", idd, opcode)); + + /* install opcode, get command started */ + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->opcode, (PVOID)&opcode, sizeof(UCHAR)); + + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->status, (PVOID)&status, sizeof(UCHAR)); + + status = IDP_S_EXEC; + +#if DBG + NdisMoveFromMappedMemory((PVOID)&IdpCounter1, (PVOID)(idd->vhw.vmem + 0x804), sizeof(USHORT)); + NdisMoveFromMappedMemory((PVOID)&IdpCounter2, (PVOID)(idd->vhw.vmem + 0x808), sizeof(ULONG)); +#endif + + idd->WaitCounter = 0; + + while ( idd->state != IDD_S_SHUTDOWN ) + { + NdisMoveFromMappedMemory((PVOID)&TempWaitCounter, (PVOID)(idd->vhw.vmem + 0x80C), sizeof(ULONG)); + NdisMoveFromMappedMemory((PVOID)&status, (PVOID)&idd->IdpCmd->status, sizeof(UCHAR)); + + if ( IDP_S_DONE(status) ) + break; + + // + // wait for 1ms + // the ddk says that this function uses milliseconds but it + // actually takes microseconds + // + NdisStallExecution(1000L); + + idd->WaitCounter++; + NdisMoveToMappedMemory((PVOID)(idd->vhw.vmem + 0x80C), (PVOID)&idd->WaitCounter, sizeof(ULONG)); + + // + // this should wait for about one second + // + if (idd->WaitCounter > 1000) + { + + idd->state = IDD_S_SHUTDOWN; +#if DBG + DbgPrint("Shutdown! idd: 0x%lx, Status: 0x%x\n", idd, status); + DbgPrint("Original: IdpCounter1: 0x%x, IdpCounter2: 0x%x\n", IdpCounter1, IdpCounter2); + NdisMoveFromMappedMemory((PVOID)&IdpCounter1, (PVOID)(idd->vhw.vmem + 0x804), sizeof(USHORT)); + NdisMoveFromMappedMemory((PVOID)&IdpCounter2, (PVOID)(idd->vhw.vmem + 0x808), sizeof(ULONG)); + DbgPrint("Current: IdpCounter1: 0x%x, IdpCounter2: 0x%x\n", IdpCounter1, IdpCounter2); + NdisMoveFromMappedMemory((PVOID)&status, (PVOID)&idd->IdpCmd->status, sizeof(UCHAR)); + DbgPrint("CurrentStatus: 0x%x\n",status); + DbgBreakPoint(); +#endif + break; + } + else + status = IDP_S_EXEC; + } + + D_LOG(D_EXIT, ("IdpExec: exit, IdpCmd->status: 0x%x\n", status)); + +#if DBG + if (status && (status != IDP_S_NOBUF) + && (status != IDP_S_NOMSG)) + { + USHORT MsgOpcode; + USHORT MsgBuflen; + UCHAR *MsgBufPtr; + ULONG MsgBufId; + ULONG MsgParam; + + DbgPrint("Idd 0x%lx error executing opcode: 0x%x, status: 0x%x\n", idd, opcode, status); + NdisMoveFromMappedMemory((PVOID)&MsgOpcode, (PVOID)&idd->IdpCmd->msg_opcode, sizeof(USHORT)); + NdisMoveFromMappedMemory((PVOID)&MsgBuflen, (PVOID)&idd->IdpCmd->msg_buflen, sizeof(USHORT)); + NdisMoveFromMappedMemory( (PVOID)&MsgBufPtr, (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG)); + NdisMoveFromMappedMemory((PVOID)&MsgBufId, (PVOID)&idd->IdpCmd->msg_bufid, sizeof (ULONG)); + NdisMoveFromMappedMemory((PVOID)&MsgParam, (PVOID)&idd->IdpCmd->msg_param, sizeof (ULONG)); + DbgPrint("IdpExec: MsgOpcode: 0x%x, MsgBufLen: 0x%x, MsgBufPtr: 0x%x\n", MsgOpcode, MsgBuflen, MsgBufPtr); + DbgPrint("IdpExec: MsgBufId: 0x%x, MsgParam: 0x%x\n", MsgBufId, MsgParam); + } +#endif + + if (idd->WaitCounter > idd->MaxWaitCounter) + idd->MaxWaitCounter = idd->WaitCounter; + + return(status); +} + +/* execute an Adp command. assumes cpage=0 */ +UCHAR +AdpExec(IDD *idd, UCHAR opcode) +{ + UCHAR status = ADP_S_PEND; + ULONG TempWaitCounter; + + // + // set opcode + // + idd->AdpCmd.opcode = opcode; + + D_LOG(D_ENTRY, ("AdpExec: entry, idd: 0x%lx, opcode: %d\n", idd, opcode)); + D_LOG(D_ENTRY, ("status: 0x%x, port_id: 0x%x", idd->AdpCmd.status, idd->AdpCmd.port_id)); + D_LOG(D_ENTRY, ("msg_opcode: 0x%x, msg_buflen: 0x%x\n", idd->AdpCmd.msg_opcode, idd->AdpCmd.msg_buflen)); + D_LOG(D_ENTRY, ("msg_bufptr: 0x%x, msg_bufid: 0x%x\n", idd->AdpCmd.msg_bufptr, idd->AdpCmd.msg_bufid)); + D_LOG(D_ENTRY, ("msg_param: 0x%x\n", idd->AdpCmd.msg_param)); + + // + // copy in command buffer + // + AdpPutBuffer(idd, ADP_CMD_WINDOW, (PUCHAR)&idd->AdpCmd, sizeof(ADP_CMD)); + + // + // start operation + // + AdpWriteCommandStatus(idd, ADP_S_PEND); + + idd->WaitCounter = 0; + + while ( idd->state != IDD_S_SHUTDOWN ) + { + TempWaitCounter = AdpGetULong(idd, 0x50C); + + status = AdpReadCommandStatus(idd); + + if ( ADP_S_DONE(status) ) + break; + + // + // wait for 1ms + // the ddk says that this function uses milliseconds but it + // actually takes microseconds + // + NdisStallExecution(1000L); + + idd->WaitCounter++; + AdpPutULong(idd, 0x50C, idd->WaitCounter); + + // + // this should wait for about one second + // + if (idd->WaitCounter > 1000) + { + idd->state = IDD_S_SHUTDOWN; + idd->AbortReason = AdpGetUShort(idd, ADP_STS_WINDOW + 12); + } + } + + AdpGetBuffer(idd, (PUCHAR)&idd->AdpCmd, ADP_CMD_WINDOW, sizeof(ADP_CMD)); + + if (idd->WaitCounter > idd->MaxWaitCounter) + idd->MaxWaitCounter = idd->WaitCounter; + + D_LOG(D_EXIT, ("AdpExec: exit, AdpCmd.status: 0x%x\n", status)); + + return(status); +} // end AdpExec + +/* map current idp page in */ +VOID +IdpCPage(IDD *idd, UCHAR page) +{ + D_LOG(D_RARE, ("IdpCPage: entry, idd: 0x%lx, page: 0x%x\n", idd, page)); + + /* if page is IDD_PAGE_NONE, idd is releasing ownership of the page */ + if ( page == IDD_PAGE_NONE ) + { + idd->SetPage(idd, IDD_PAGE_NONE); + res_unown(idd->res_mem, idd); + } + else + { + page &= 3; + + /* real mapping required, lock memory resource */ + res_own(idd->res_mem, idd); + idd->SetPage(idd, page); + } +} + +/* map current Adp page in */ +VOID +AdpCPage(IDD *idd, UCHAR page) +{ + +} + +/* copy data from user buffer to idp */ +USHORT +IdpCopyin(IDD *idd, UCHAR *dst, UCHAR *src, USHORT src_len) +{ + USHORT ofs, copylen; + UCHAR Page; + UINT tot_len, frag_num; + IDD_FRAG *frag; + + D_LOG(D_RARE, ("Idpcopyin: entry, idd: 0x%lx, dst: 0x%lx, src: 0x%lx, src_len: 0x%x\n", \ + idd, dst, src, src_len)); + + /* convert destination pointer to address & map in */ + ofs = LOWORD((long)dst); + Page = (UCHAR)(ofs >> 14) & 3; + +#if DBG + if (Page > 1 ) + DbgPrint("Page changed to %d on idd 0x%lx!\n", Page, idd); +#endif + + dst = idd->vhw.vmem + (ofs & 0x3FFF); + + IdpCPage(idd, Page); + + // + // mask out various flags to get length to copy + // + copylen = src_len & H_TX_LEN_MASK; + + /* check for a simple copy, real easy - doit here */ + if ( !(src_len & TX_FRAG_INDICATOR) ) + { + NdisMoveToMappedMemory (dst, src, copylen); + return(copylen); + } + + /* if here, its a fragment descriptor */ + tot_len = 0; + frag_num = (copylen) / sizeof(IDD_FRAG); + frag = (IDD_FRAG*)src; + + /* copy fragments */ + for ( ; frag_num ; frag_num--, frag++ ) + { + NdisMoveToMappedMemory (dst, frag->ptr, frag->len); + dst += frag->len; + tot_len += frag->len; + } + + /* read total length */ + return(tot_len); +} + +/* copy data from user buffer to idp */ +USHORT +AdpCopyin(IDD *idd, UCHAR *src, USHORT src_len) +{ + USHORT Destination, CopyLength; + UINT tot_len, frag_num; + IDD_FRAG *frag; + + D_LOG(D_RARE, ("Adpcopyin: entry, idd: 0x%lx, src: 0x%lx, src_len: 0x%x\n", \ + idd, src, src_len)); + + /* convert destination pointer to address & map in */ + Destination = LOWORD(idd->AdpCmd.msg_bufptr); + + // + // mask out various flags to get length to copy + // + CopyLength = src_len & H_TX_LEN_MASK; + + /* check for a simple copy, real easy - doit here */ + if ( !(src_len & TX_FRAG_INDICATOR) ) + { + AdpPutBuffer(idd, Destination, src, CopyLength); + return(CopyLength); + } + + /* if here, its a fragment descriptor */ + tot_len = 0; + frag_num = (CopyLength) / sizeof(IDD_FRAG); + frag = (IDD_FRAG*)src; + + /* copy fragments */ + for ( ; frag_num ; frag_num--, frag++ ) + { + AdpPutBuffer(idd, Destination, frag->ptr, frag->len); + Destination += frag->len; + tot_len += frag->len; + } + + /* read total length */ + return(tot_len); +} // end AdpCopyin + +VOID +IddGetDataFromAdapter( + VOID *idd_1, + PUCHAR Destination, + PUCHAR Source, + USHORT Length + ) +{ + IDD *idd = (IDD*)idd_1; + + if( (idd->btype != IDD_BT_DATAFIREU) && + (idd->btype != IDD_BT_DATAFIREST) && + (idd->btype != IDD_BT_DATAFIRE4ST) ) + { + NdisMoveFromMappedMemory(Destination, Source, Length); + } + else + { + AdpGetBuffer(idd, Destination, (ULONG)Source, Length); + } +} diff --git a/private/ntos/ndis/digi/pcimac/idd_pub.h b/private/ntos/ndis/digi/pcimac/idd_pub.h new file mode 100644 index 000000000..da43ee2b4 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd_pub.h @@ -0,0 +1,59 @@ +/* + * IDD_PUB.H - IDP Device Driver public header for PCIMAC/ISA + */ + +#ifndef _IDD_PUB_ +#define _IDD_PUB_ + +#define IDD_MAX_AREA 512 /* max size of area got in get_area */ + +// +// global idd def's +// +/* IDD message descriptor */ +typedef struct +{ + USHORT opcode; /* message opcode (type) */ + USHORT buflen; /* related buffer length */ + UCHAR *bufptr; /* related buffer pointer (0=none) */ + ULONG bufid; /* related buffer id */ + ULONG param; /* parameter area */ +} IDD_MSG; + +/* IDD extended message descriptor */ +typedef struct +{ + USHORT opcode; /* message opcode (type) */ + USHORT buflen; /* related buffer length */ + UCHAR *bufptr; /* related buffer pointer (0=none) */ + ULONG bufid; /* related buffer id */ + ULONG param; /* parameter area */ + USHORT FragmentFlags; /* fragmentation flags */ +} IDD_XMSG; + +/* IDD fragment descriptor */ +typedef struct +{ + USHORT len; /* fragment length */ + CHAR *ptr; /* fragment buffer pointer */ +} IDD_FRAG; + +typedef struct +{ + VOID (*area_handler)(); /* handler for get_area */ + VOID *area_handler_arg; /* argument for handler */ + + ULONG area_state; /* state of last/current get_area command */ +#define AREA_ST_IDLE 0 /* - idle, no area defined */ +#define AREA_ST_PEND 1 /* - pending, get_area in progress */ +#define AREA_ST_DONE 2 /* - done, results ready */ + + ULONG area_id; /* area id (number) pend/done */ + + VOID *area_idd; /* related idd (from which area is retreived) */ + UCHAR area_buf[IDD_MAX_AREA]; /* buffer receiving/containing area data */ + ULONG area_len; /* length of actual data */ +}IDD_AREA; + +#endif /* _IDD_PUB_ */ + diff --git a/private/ntos/ndis/digi/pcimac/idd_run.c b/private/ntos/ndis/digi/pcimac/idd_run.c new file mode 100644 index 000000000..1ba415857 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/idd_run.c @@ -0,0 +1,868 @@ +/* + * IDD_RUN.C - run (startup) and shutdown idd object + */ + +#include +#include +#include +#include +#include +#include +#include + +/* a port descriptor */ +typedef struct +{ + char *name; /* port name */ + INT must; /* mast map this port? */ +} PORT; + +/* port tables */ +static PORT api_rx_port_tbl[] = +{ + { "b1_rx ", 1 }, + { "b2_rx ", 1 }, + { "uart_rx ", 0 }, + { "tdat ", 1 }, + { "Cm.0 ", 1 }, + { "Cm.1 ", 0 }, + { NULL } +}; +static PORT api_tx_port_tbl[] = +{ + { "b1_tx ", 1 }, + { "b2_tx ", 1 }, + { "uart_tx ", 0 }, + { "cmd ", 1 }, + { "Q931.0 ", 1 }, + { "Q931.1 ", 0 }, + { NULL } +}; + +/* partition queue table */ + +static INT api_tx_partq_tbl[] = +{ + 0, // b1_tx --- I don't know if the relationship is correct or not?? + 1, // b2_tx + 2, // uart_tx + 3, // cmd + 3, // Q931.0 + 3 // Q931.1 +}; + +/* local prototypes */ +INT api_setup(IDD* idd); +INT api_map_ports(IDD* idd); +INT api_bind_ports(IDD* idd); +INT api_setup_partq(IDD* idd); +INT api_alloc_partq(IDD* idd); + +#pragma NDIS_INIT_FUNCTION(idd_startup) + +/* startup (run) an idd object */ +INT +idd_startup(VOID *idd_1) +{ + IDD *idd = (IDD*)idd_1; + INT ret; + D_LOG(D_ENTRY, ("idd_startup: entry, idd: 0x%lx\n", idd)); + + /* lock idd */ + NdisAcquireSpinLock(&idd->lock); + + /* mark starting */ + idd->state = IDD_S_STARTUP; + + switch( idd->btype ) + { + case IDD_BT_PCIMAC: + case IDD_BT_PCIMAC4: + case IDD_BT_MCIMAC: + while(!GetResourceSem (idd->res_mem)); + break; + + case IDD_BT_DATAFIREU : + case IDD_BT_DATAFIREST: + case IDD_BT_DATAFIRE4ST: + while( !GetResourceSem( idd->res_io ) ); + break; + } + + /* do the startup */ + if ( (ret = idd->LoadCode(idd)) != IDD_E_SUCC ) + { + /* release idd */ + switch( idd->btype ) + { + case IDD_BT_PCIMAC: + case IDD_BT_PCIMAC4: + case IDD_BT_MCIMAC: + FreeResourceSem( idd->res_mem ); + break; + + case IDD_BT_DATAFIREU : + case IDD_BT_DATAFIREST: + case IDD_BT_DATAFIRE4ST: + FreeResourceSem( idd->res_io ); + break; + } + + NdisReleaseSpinLock(&idd->lock); + D_LOG(D_EXIT, ("idd_startup: error exit, ret=0x%x\n", ret)); + return(ret); + + } + + // + // stall for a 50 millisecond + // + NdisStallExecution(50000L); + + /* initialize api level - talks to memory! */ + ret = api_setup(idd); + + /* change state */ + idd->state = IDD_S_RUN; + + switch( idd->btype ) + { + case IDD_BT_PCIMAC: + case IDD_BT_PCIMAC4: + case IDD_BT_MCIMAC: + FreeResourceSem( idd->res_mem ); + break; + + case IDD_BT_DATAFIREU : + case IDD_BT_DATAFIREST: + case IDD_BT_DATAFIRE4ST: + FreeResourceSem( idd->res_io ); + break; + } + + /* release idd */ + NdisReleaseSpinLock(&idd->lock); + + /* return result */ + D_LOG(D_EXIT, ("idd_startup: exit, ret=0x%x\n", ret)); + return(ret); +} + +/* shutdown an idd object, not implemented yet */ +INT +idd_shutdown(VOID *idd_1) +{ + IDD *idd = (IDD*)idd_1; + D_LOG(D_ENTRY, ("idd_shutdown: idd: 0x%lx\n", idd)); + + idd->state = IDD_S_SHUTDOWN; + + idd->ResetAdapter(idd); + + return(IDD_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(IdpLoadCode) + +/* load idp code in & run it */ +INT +IdpLoadCode(IDD *idd) +{ + ULONG CurrentTime = 0, TimeOut = 0; + USHORT bank, page, n, NumberOfBanks; + UCHAR *fbin_data; + NDIS_STATUS stat; + UCHAR status = IDP_S_PEND; + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(0xffffffff, 0xffffffff); + + D_LOG(D_ENTRY, ("load_code: entry, idd=0x%lx\n", idd)); + + /* setup pointers into shared memory */ + idd->IdpStat = (USHORT*)(idd->vhw.vmem + IDP_STS_WINDOW); + idd->IdpCmd = (IDP_CMD*)(idd->vhw.vmem + IDP_CMD_WINDOW); + idd->IdpEnv = (UCHAR*)(idd->vhw.vmem + IDP_ENV_WINDOW); + + /* setup base memory address registers */ + idd->SetBasemem(idd, idd->phw.base_mem); + + /* while in reset, clear all idp banks/pages */ + for ( bank = 0 ; bank < 3 ; bank++ ) + { + /* setup bank */ + idd->SetBank(idd, (UCHAR)bank, 0); + + /* loop on pages */ + for ( page = 0 ; page < 4 ; page++ ) + { + /* setup page */ + idd->ChangePage (idd, (UCHAR)page); + + /* zero out (has to be a word fill!) */ + IdpMemset((UCHAR*)idd->vhw.vmem, 0, 0x4000); + } + } + //free page + idd->ChangePage (idd, (UCHAR)IDD_PAGE_NONE); + + /* set idp to code bank, keep in reset */ + idd->SetBank(idd, IDD_BANK_CODE, 0); + + /* map file data in */ + NdisMapFile(&stat, (PVOID*)&fbin_data, idd->phw.fbin); + + if ( stat != NDIS_STATUS_SUCCESS ) + { + D_LOG(DIGIIDD, ("load_code: file mapping failed!, stat: 0x%x\n", stat)); + return(IDD_E_FMAPERR); + } + +// code to check for filelength greater than 64K + if (idd->phw.fbin_len > 0x10000) + NumberOfBanks = 2; + else + NumberOfBanks = 1; + + for (n = 0; n < NumberOfBanks; n++) + { + /* copy data in (must be a word operation) */ + for ( page = 0 ; page < 4 ; page++ ) + { + idd->ChangePage(idd, (UCHAR)page); + + IdpMemcpy((UCHAR*)idd->vhw.vmem, + (UCHAR*)(fbin_data + (page * 0x4000) + (n * 0x10000)), 0x4000); + +// DbgPrint ("Load: Src: 0x%lx, Dst: 0x%lx, Page: %d\n", +// (fbin_data + (page*0x4000) + (n * 0x10000)), idd->vhw.vmem, page); + + } + + /* set idp to data bank, keep in reset */ + idd->SetBank(idd, IDD_BANK_DATA, 0); + } + + /* map file data out */ + NdisUnmapFile(idd->phw.fbin); + + /* switch back to buffer bank */ + idd->ChangePage(idd, 0); + idd->SetBank(idd, IDD_BANK_BUF, 0); + + /* add 'no_uart' definition */ + NdisMoveMemory(idd->DefinitionTable + idd->DefinitionTableLength, + "no_uart\0any\0", + 12); + + idd->DefinitionTableLength += 12; + + /* load initial environment */ + NdisMoveToMappedMemory((PVOID)idd->IdpEnv, (PVOID)idd->DefinitionTable, idd->DefinitionTableLength); + + /* install startup byte signal */ + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->status, (PVOID)&status, sizeof(UCHAR)); + + /* start idp running, wait for 1 second to complete */ + idd->SetBank(idd, IDD_BANK_BUF, 1); + + while ( !TimeOut ) + { + NdisMoveFromMappedMemory((PVOID)&status, (PVOID)&idd->IdpCmd->status, sizeof(UCHAR)); + + if ( !status ) + break; + + // + // stall for a 1 millisecond + // + NdisStallExecution(1000L); + + // + // add 1 millisecond to timeout counter + // + CurrentTime += 1; + + // + // if timeout counter is greater the 2 seconds we have a problem + // + if ( CurrentTime > 2000) + TimeOut = 1; + } + + if (TimeOut) + { + D_LOG((DIGIIDD|DIGIINIT), ("load_code: idp didn't start!\n")); + + idd->state = IDD_S_SHUTDOWN; + + /* unset page, free memory window */ + idd->ChangePage(idd, IDD_PAGE_NONE); + + return(IDD_E_RUNERR); + } + + + /* unset page, free memory window */ + idd->ChangePage(idd, IDD_PAGE_NONE); + + /* if here, idp runs now! */ + D_LOG(D_EXIT, ("load_code: exit, idp running\n")); + return(IDD_E_SUCC); +} + + +#pragma NDIS_INIT_FUNCTION(AdpLoadCode) + +/* load idp code in & run it */ +INT +AdpLoadCode(IDD *idd) +{ + UCHAR *Zero; + UCHAR *fbin_data, status; + NDIS_STATUS stat; + ADP_BIN_HEADER *Header; + ADP_BIN_BLOCK *Block, *FirstBlock; + ULONG CurrentTime = 0, TimeOut = 0; + USHORT BlockCount = 0; + ULONG n; + + NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + + D_LOG(D_ENTRY, ("AdpLoadCode: entry, idd: 0x%lx\n", idd)); + + // + // Determine if this is a multi-channel BRI adapter. If so, then + // we need to select the correct ADP to reference. + // + switch( idd->btype ) + { + case IDD_BT_DATAFIRE4ST: + // + // select the correct BRI channel to access. + // + idd->OutToPort( idd, ADP_REG_ADAPTER_CTRL, idd->bline ); + break; + } + + // + // reset the adapter + // + idd->OutToPort( idd, ADP_REG_CTRL, ADP_RESET_BIT ); +// idd->OutToPort( idd, ADP_REG_CTRL, ADP_RESET_BIT|ADP_HLT_BIT|ADP_PIRQ_BIT ); +// AdpWriteControlBit( idd, +// ADP_RESET_BIT|ADP_PIRQEN_BIT|ADP_PIRQ_BIT|ADP_HLT_BIT, +// 0x90); + + // + // clear adapter memory + // + D_LOG(D_ENTRY, ("AdpLoadCode: Clear Memory\n")); + + NdisAllocateMemory( (PVOID*)&Zero, + 0xFFFF, + 0, + HighestAcceptableMax ); + + + NdisZeroMemory(Zero, 0xFFFF); + + for (n = 0; n < ADP_RAM_SIZE; n += 0xFFFF) + AdpPutBuffer(idd, n, Zero, (USHORT)0xFFFF); + +// NdisFreeMemory(Zero, 0xFFFF, 0); + + // + // map file data into memory + // + NdisMapFile(&stat, (PVOID*)&fbin_data, idd->phw.fbin); + + if ( stat != NDIS_STATUS_SUCCESS ) + { + D_LOG((DIGIINIT|DIGIIDD), ("AdpLoadCode: file mapping failed!, stat: 0x%x\n", stat)); + return(IDD_E_FMAPERR); + } + + // + // Get bin file header + // + (UCHAR*)Header = fbin_data; + + if (Header->Format != ADP_BIN_FORMAT) + return(IDD_E_FMAPERR); + + // + // Check file size + // + if (Header->ImageSize > ADP_RAM_SIZE) + return(IDD_E_FMAPERR); + + BlockCount = Header->BlockCount; + (UCHAR*)FirstBlock = fbin_data + sizeof(ADP_BIN_HEADER); + + for (n = 0; n < BlockCount; n++) + { +#if 0 + ULONG t; +#endif + + Block = FirstBlock + n; + + AdpPutBuffer(idd, Block->Address, Block->Data, ADP_BIN_BLOCK_SIZE); + +#if 0 + AdpGetBuffer( idd, Zero, Block->Address, ADP_BIN_BLOCK_SIZE ); + + for( t = 0; t < ADP_BIN_BLOCK_SIZE; t++ ) + { + if( Zero[t] != Block->Data[t] ) + DbgBreakPoint(); + } + + NdisZeroMemory(Zero, 1024); +#endif + } + + NdisFreeMemory(Zero, 0xFFFF, 0); + + // + // unmap file data + // + NdisUnmapFile(idd->phw.fbin); + + // + // add initial enviornment + // + /* add 'no_uart' definition */ + NdisMoveMemory(idd->DefinitionTable + idd->DefinitionTableLength, "no_uart\0any\0", 12); + idd->DefinitionTableLength += 12; + + D_LOG(D_ENTRY, ("AdpLoadCode: Add Enviornment\n")); + + AdpPutBuffer(idd, ADP_ENV_WINDOW, idd->DefinitionTable, idd->DefinitionTableLength); + + // + // write startup byte + // + AdpWriteCommandStatus(idd, ADP_S_PEND); + + // + // release processor from reset + // + idd->OutToPort( idd, ADP_REG_CTRL, 0 ); +// AdpWriteControlBit( idd, ADP_RESET_BIT, 0 ); + + while ( !TimeOut ) + { + status = AdpReadCommandStatus(idd); + + if ( !status ) + break; + + // + // stall for a 1 millisecond + // + NdisStallExecution(1000L); + + // + // add 1 millisecond to timeout counter + // + CurrentTime += 1; + + // + // if timeout counter is greater the 2 seconds we have a problem + // + if ( CurrentTime > 2000) + TimeOut = 1; + } + + if (TimeOut) + { + + idd->AbortReason = AdpGetUShort( idd, + ADP_STS_WINDOW + + FIELD_OFFSET(ADP_STATUS, AbortReason) ); + D_LOG((DIGIINIT|DIGIIDD), ("AdpLodeCode: Adp didn't start! AbortReason = 0x%x(%d)\n", + idd->AbortReason, + idd->AbortReason)); + return(IDD_E_RUNERR); + } + + /* if here, Adp runs now! */ + D_LOG(D_EXIT, ("AdpLoadCode: exit, Adp running\n")); + + return(IDD_E_SUCC); +} + + +#pragma NDIS_INIT_FUNCTION(api_setup) + +/* setup idp api related fields */ +INT +api_setup(IDD *idd) +{ + INT ret; + + D_LOG(D_ENTRY, ("api_setup: entry, idd: 0x%lx\n", idd)); + + /* map port names */ + if ( (ret = api_map_ports(idd)) != IDD_E_SUCC ) + return(ret); + + /* bind ports to status bits */ + if ( (ret = api_bind_ports(idd)) != IDD_E_SUCC ) + return(ret); + + /* setup partition queues */ + if ( (ret = api_setup_partq(idd)) != IDD_E_SUCC ) + return(ret); + + /* allocate initial buffers off partition queues */ + if ( (ret = api_alloc_partq(idd)) != IDD_E_SUCC ) + return(ret); + D_LOG(D_EXIT, ("api_setup: exit, success\n")); + + return(IDD_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(api_map_ports) + +/* map port names to ids */ +INT +api_map_ports(IDD *idd) +{ + INT n; + + D_LOG(D_ENTRY, ("api_map_ports: entry, idd: 0x%lx\n", idd)); + + /* map rx ports */ + for ( n = 0 ; api_rx_port_tbl[n].name ; n++ ) + { + idd->rx_port[n] = idd->ApiGetPort(idd, api_rx_port_tbl[n].name); + + D_LOG((DIGIIDD|DIGIINIT), ("api_map_ports: RxPorts: PortName: %s, PortId: 0x%x\n", api_rx_port_tbl[n].name, idd->rx_port[n])); + + if ( !idd->rx_port[n] && api_rx_port_tbl[n].must ) + { + D_LOG((DIGIINIT|DIGIIDD), ("api_map_ports: failed to map rx port [%s]\n", \ + api_rx_port_tbl[n].name)); + return(IDD_E_PORTMAPERR); + } + } + + /* map tx ports */ + for ( n = 0 ; api_tx_port_tbl[n].name ; n++ ) + { + idd->tx_port[n] = idd->ApiGetPort(idd, api_tx_port_tbl[n].name); + + D_LOG((DIGIINIT|DIGIIDD), ("api_map_ports: TxPorts: PortName: %s, PortId: 0x%x\n", api_tx_port_tbl[n].name, idd->tx_port[n])); + + if ( !idd->tx_port[n] && api_tx_port_tbl[n].must ) + { + D_LOG((DIGIINIT|DIGIIDD), ("api_map_ports: failed to map tx port [%s]\n", \ + api_tx_port_tbl[n].name)); + return(IDD_E_PORTMAPERR); + } + } + return(IDD_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(api_bind_ports) + +/* bind ports to status bits */ +INT +api_bind_ports(IDD *idd) +{ + INT n; + + D_LOG(D_ENTRY, ("api_bind_ports: entry, idd: 0x%lx\n", idd)); + + /* bind rx ports */ + for ( n = 0 ; api_rx_port_tbl[n].name; n++ ) + { + if (idd->rx_port[n]) + if ( idd->ApiBindPort(idd, idd->rx_port[n], (USHORT)(1 << n)) < 0 ) + { + D_LOG((DIGIINIT|DIGIIDD), ("api_bind_ports: failed to bind status bit on port [%s]\n", \ + api_rx_port_tbl[n].name)); + return(IDD_E_PORTBINDERR); + } + } + + return(IDD_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(api_setup_partq) + +/* setup partition queues */ +INT +api_setup_partq(IDD *idd) +{ + INT n; + + D_LOG(D_ENTRY, ("api_setup_partq: entry, idd: 0x%lx\n", idd)); + + /* simply copy table */ + for ( n = 0 ; n < IDD_TX_PORTS ; n++ ) + idd->tx_partq[n] = api_tx_partq_tbl[n]; + + return(IDD_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(api_alloc_partq) + +/* allocate initial buffers off partition queues */ +INT +api_alloc_partq(IDD *idd) +{ + INT n, part; + + D_LOG(D_ENTRY, ("api_alloc_partq: entry, idd: 0x%lx\n", idd)); + + /* scan using partq_tbl as a refrence. allocate only once per partq */ + for ( n = 0 ; n < IDD_TX_PORTS ; n++ ) + if ( !idd->tx_buf[part = api_tx_partq_tbl[n]] ) + { + if ( !(idd->tx_buf[part] = idd->ApiAllocBuffer(idd, part)) ) + { + D_LOG((DIGIINIT|DIGIIDD), ("api_alloc_partq: failed to alloc initial buffer, part: %d\n", part)); + DbgPrint("api_alloc_partq: failed to alloc initial buffer, part: %d\n", part); + return(IDD_E_PARTQINIT); + } +#if DBG + ASSERT(!idd->BufferStuff[part].Buffer[0]); + idd->BufferStuff[part].Buffer[0] = idd->tx_buf[part]; + idd->BufferStuff[part].Count++; + idd->BufferStuff[part].Put++; + idd->BufferStuff[part].Get = 0; + ASSERT(idd->BufferStuff[part].Count < 32); +#endif + } + + return(IDD_E_SUCC); +} + +#pragma NDIS_INIT_FUNCTION(IdpGetPort) + +/* get port id from a name */ +USHORT +IdpGetPort(IDD *idd, CHAR name[8]) +{ + UCHAR status; + USHORT port_id; + + D_LOG(D_ENTRY, ("IdpGetPort: entry, idd: 0x%lx, name: [%s]\n", idd, name)); + + idd->ChangePage(idd, 0); + + /* install target name & execute a map */ + NdisMoveToMappedMemory ((CHAR *)idd->IdpCmd->port_name, (CHAR *)name, 8); + + status = idd->Execute(idd, IDP_L_MAP); + + NdisMoveFromMappedMemory((PVOID)&port_id, (PVOID)&idd->IdpCmd->port_id, sizeof(USHORT)); + + idd->ChangePage(idd, IDD_PAGE_NONE); + + D_LOG(D_EXIT, ("IdpGetPort: exit, port_id: 0x%x\n", port_id)); + + return( (status == IDP_S_OK) ? port_id : 0); +} + +#pragma NDIS_INIT_FUNCTION(AdpGetPort) + +/* get port id from a name */ +USHORT +AdpGetPort(IDD *idd, CHAR name[8]) +{ + UCHAR status; + D_LOG(D_ENTRY, ("AdpGetPort: entry, idd: 0x%lx, name: [%s]\n", idd, name)); + + // + // clear command structure + // + NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD)); + + // + // put port name in command structure + // + NdisMoveMemory((PVOID)&idd->AdpCmd.port_name, name, 8); + + // + // execute command + // + status = idd->Execute(idd, ADP_L_MAP); + + // + // check return status + // + if (status != ADP_S_OK) + return(0); + + D_LOG((DIGIINIT|DIGIIDD), ("AdpGetPort: PortId: 0x%x\n", idd->AdpCmd.port_id)); + // + // return port + // + return(idd->AdpCmd.port_id); +} + + +#pragma NDIS_INIT_FUNCTION(IdpBindPort) + +/* bind a port to a status bit */ +INT +IdpBindPort(IDD *idd, USHORT port, USHORT bitpatt) +{ + UCHAR status; + + D_LOG(D_ENTRY, ("IdpBindPort: entry, idd: 0x%lx, port: 0x%x, bitpatt: 0x%x\n", + idd, port, bitpatt)); + + idd->ChangePage(idd, 0); + + /* fillup cmd & execute a bind */ + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_id, (PVOID)&port, sizeof(USHORT)); + NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_bitpatt, (PVOID)&bitpatt, sizeof(USHORT)); + + status = idd->Execute(idd, IDP_L_BIND); + + idd->ChangePage(idd, IDD_PAGE_NONE); + + return( (status == IDP_S_OK) ? 0 : -1 ); +} + +#pragma NDIS_INIT_FUNCTION(AdpBindPort) + +/* bind a port to a status bit */ +INT +AdpBindPort(IDD *idd, USHORT port, USHORT bitpatt) +{ + UCHAR status; + + D_LOG(D_ENTRY, ("AdpBindPort: entry, idd: 0x%lx, port: 0x%x, bitpatt: 0x%x\n", + idd, port, bitpatt)); + // + // clear command structure + // + NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD)); + + // + // fill port id and status bit + // + idd->AdpCmd.port_id = port; + idd->AdpCmd.port_bitpatt = bitpatt; + + // + // execute command + // + status = idd->Execute(idd, ADP_L_BIND); + + D_LOG((DIGIINIT|DIGIIDD), ("AdpBindPort: ExecuteStatus: 0x%x\n", status)); + + if (status != ADP_S_OK) + return(1); + + return(0); +} + + +#pragma NDIS_INIT_FUNCTION(IdpAllocBuf) + +/* allocate a buffer off a partition */ +ULONG +IdpAllocBuf(IDD *idd, INT part) +{ + UCHAR status; + ULONG msg_bufptr; + ULONG temp; + + D_LOG(D_ENTRY, ("IdpAllocBuf: entry, idd: 0x%lx, part: %d\n", idd, part)); + + idd->ChangePage(idd, 0); + + /* fillup & execute */ + temp = (ULONG)(part + 4); + + NdisMoveToMappedMemory ((PVOID)&idd->IdpCmd->msg_param, (PVOID)&temp, sizeof (ULONG)); + + status = idd->Execute(idd, IDP_L_GET_WBUF); + + NdisMoveFromMappedMemory((PVOID)&msg_bufptr, (PVOID)&idd->IdpCmd->msg_bufptr, (ULONG)sizeof (ULONG)); + + idd->ChangePage(idd, IDD_PAGE_NONE); + + return( (status == IDP_S_OK) ? msg_bufptr : 0 ); +} + +#pragma NDIS_INIT_FUNCTION(AdpAllocBuf) + +/* allocate a buffer off a partition */ +ULONG +AdpAllocBuf(IDD *idd, INT part) +{ + UCHAR status; + + D_LOG(D_ENTRY, ("AdpAllocBuf: entry, idd: 0x%lx, part: %d\n", idd, part)); + + // + // clear command structure + // + NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD)); + + // + // fill port id and status bit + // + idd->AdpCmd.msg_param = (UCHAR)part + 4; + // + // execute command + // + status = idd->Execute(idd, ADP_L_GET_WBUF); + + D_LOG((DIGIINIT|DIGIIDD), ("AdpAllocBuf: status: 0x%x, BufPtr: 0x%x\n", status, idd->AdpCmd.msg_bufptr)); + + return ((status == ADP_S_OK) ? (ULONG)idd->AdpCmd.msg_bufptr : 0); +} + +/* reset idp board */ +INT +IdpResetBoard(IDD *idd) +{ + USHORT bank, page; + D_LOG(D_ENTRY, ("reset_board: entry, idd: 0x%lx\n", idd)); + + /* while in reset, clear all idp banks/pages */ + for ( bank = 0 ; bank < 3 ; bank++ ) + { + /* setup bank */ + idd->SetBank(idd, (UCHAR)bank, 0); + + /* loop on pages */ + for ( page = 0 ; page < 4 ; page++ ) + { + /* setup page */ + idd->ChangePage (idd, (UCHAR)page); + + /* zero out (has to be a word fill!) */ + IdpMemset((UCHAR*)idd->vhw.vmem, 0, 0x4000); + } + } + + idd->SetBank(idd, IDD_BANK_CODE, 0); + + //free page + idd->ChangePage (idd, (UCHAR)IDD_PAGE_NONE); + + return(IDD_E_SUCC); +} + +/* reset idp board */ +INT +AdpResetBoard(IDD *idd) +{ + // + // reset the adapter + // + idd->OutToPort( idd, ADP_REG_CTRL, ADP_RESET_BIT ); +// AdpWriteControlBit(idd, ADP_RESET_BIT, 0x80); + + return(IDD_E_SUCC); +} + diff --git a/private/ntos/ndis/digi/pcimac/io.h b/private/ntos/ndis/digi/pcimac/io.h new file mode 100644 index 000000000..52530f68d --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/io.h @@ -0,0 +1,27 @@ +/* + * IO.H - include file for all IO modules + */ + +#ifndef _IO_ +#define _IO_ + +#include + +// This is only for NT +#if !BINARY_COMPATIBLE + +/* forward for ioctl filter function */ +NTSTATUS PcimacIoctl(DEVICE_OBJECT* DeviceObject, IRP* Irp); + +NTSTATUS ExecIrp(IRP *irp, IO_STACK_LOCATION *irpsp); + + +/* ioctl opcode to executing commands */ +#define IO_IOCTL_PCIMAC_EXEC 0x160040/* temp!!! */ + +INT io_execute(IO_CMD* cmd, VOID *Irp_1); + +#endif + + +#endif /* _IO_ */ diff --git a/private/ntos/ndis/digi/pcimac/io_core.c b/private/ntos/ndis/digi/pcimac/io_core.c new file mode 100644 index 000000000..daa0f0f52 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/io_core.c @@ -0,0 +1,435 @@ +/* + * IO_CORE.C - core routines for IO module + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern DRIVER_BLOCK Pcimac; + +/* store location for prev. ioctl handler */ +extern NTSTATUS (*PrevIoctl)(DEVICE_OBJECT* DeviceObject, IRP* Irp); + +/* ioctl filter */ +NTSTATUS +PcimacIoctl(DEVICE_OBJECT *DeviceObject, IRP *Irp) +{ + NTSTATUS status = STATUS_SUCCESS; + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS ini_exec_irp(IRP* irp, IO_STACK_LOCATION* irpsp); + + /* must be an ioctl, else pass this one */ + if ( irpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL ) + { + NdisReleaseSpinLock(&Pcimac.lock); + + return(PrevIoctl(DeviceObject, Irp)); + } + + /* must be our own private ioctl code */ + + switch( irpSp->Parameters.DeviceIoControl.IoControlCode ) + { + case IO_IOCTL_PCIMAC_EXEC: + case DIGI_ATLAS_IOCTL: + break; + } + + /* one of our own, execute */ + Irp->IoStatus.Information = 0L; + ExecIrp(Irp, irpSp); + + /* complete irp */ + Irp->IoStatus.Status = status; + IoSetCancelRoutine (Irp, NULL); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(status); +} + +/* execute ioctl irp */ +NTSTATUS +ExecIrp(IRP *irp, IO_STACK_LOCATION *irpsp) +{ + UCHAR *in_buf, *out_buf; + ULONG in_len, out_len; + NTSTATUS stat; + + /* establish in/out buffers */ + out_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength; + in_len = irpsp->Parameters.DeviceIoControl.InputBufferLength; + + + /* in/out length must be the same */ + if ( in_len != out_len ) + return(STATUS_UNSUCCESSFUL); + + switch( irpsp->Parameters.DeviceIoControl.IoControlCode ) + { + case IO_IOCTL_PCIMAC_EXEC: + out_buf = irp->UserBuffer; + in_buf = irp->AssociatedIrp.SystemBuffer; + /* copy in buffer into output buffer */ + NdisMoveMemory(out_buf, in_buf, out_len); + + /* execute command in place */ + if ( (stat = io_execute((IO_CMD*)out_buf,irp)) == IO_E_PENDING) + /* event added pend irp */ + return (STATUS_PENDING); + else + /* return success */ + return(STATUS_SUCCESS); + + break; + + case DIGI_ATLAS_IOCTL: + { + PATLAS_PDU_HEADER Atlas; + + // + // We need to decapsulate the DIGI_Opcode wrapper to get to + // the IO_CMD + // + + out_buf = irp->AssociatedIrp.SystemBuffer; + in_buf = irp->AssociatedIrp.SystemBuffer; + Atlas = (PATLAS_PDU_HEADER)out_buf; + + switch( Atlas->dwCommand ) + { + case EnumAdapters: + { + ULONG n, m, NumberOfAdapters; + PDIGI_SYSTEM SystemInfo; + + // + // We need to let Atlas know about all the adapters + // we are controlling. + // + SystemInfo = (PDIGI_SYSTEM)GET_PAYLOAD(Atlas); + NumberOfAdapters = EnumAdaptersInSystem(); + + for( n = 0, m = 0; n < NumberOfAdapters; n++ ) + { + ADAPTER *Adapter = GetAdapterByIndex(n); + + if( Adapter ) + { + PDIGI_ADAPTER AtlasAdapterInfo; + + AtlasAdapterInfo = &SystemInfo->Adapters[m]; + + AtlasAdapterInfo->dwMemoryAddress = Adapter->BaseMem; + + if( Adapter->BaseMem ) + AtlasAdapterInfo->dwMemoryRange = 0x4000; + else + AtlasAdapterInfo->dwMemoryRange = 0; + + AtlasAdapterInfo->dwIOAddress = Adapter->BaseIO; + AtlasAdapterInfo->dwIORange = 8; + + AtlasAdapterInfo->dwInterruptNumber = 0; + AtlasAdapterInfo->dwDMA = 0; + + AtlasAdapterInfo->dwPersonalities = 1; + AtlasAdapterInfo->Personalities[0].dwPersonalityTag = DIGI_PERSONALITY_BRI; + AtlasAdapterInfo->Personalities[0].dwId = (DWORD)Adapter; + + NdisMoveMemory( AtlasAdapterInfo->Personalities[0].szDesc, + Adapter->Name, + BRI_MAX_NAMELEN ); + + m++; + } + } + + SystemInfo->dwAdapters = m; + + irp->IoStatus.Information = out_len; + break; + } // end case EnumAdapters: + + case BRIOldMethod: + { + PDIGI_OLD_METHOD OldMethodInfo; + + OldMethodInfo = (PDIGI_OLD_METHOD)GET_PAYLOAD(Atlas); + + // + // We decapsulate the Atlas stuff and feed through the + // old method of getting this information. + // + if( (stat = io_execute( &(OldMethodInfo->ioCmd), + irp )) == IO_E_PENDING ) + /* event added pend irp */ + return (STATUS_PENDING); + else + { + irp->IoStatus.Information = out_len; + return(STATUS_SUCCESS); + } + + break; + } + } + + break; + + } + } + +} + + +/* execute an io command */ +INT +io_execute(IO_CMD *cmd, VOID *Irp_1) +{ + IRP *Irp = (IRP*)Irp_1; + + D_LOG(D_ENTRY, ("io_execute: entry, cmd: 0x%lx\n", cmd)); + + /* check signature & version */ + if ( cmd->sig != IO_CMD_SIG ) + return(IO_E_BADSIG); + if ( (cmd->ver_major != IO_VER_MAJOR) || + (cmd->ver_minor != IO_VER_MINOR) ) + return(IO_E_BADVER); + + D_LOG(D_ALWAYS, ("io_execute: opcode: 0x%x, cm: 0x%lx, idd: 0x%lx\n", \ + cmd->opcode, cmd->cm, cmd->idd)); + D_LOG(D_ALWAYS, ("io_execute: args: 0x%x 0x%x 0x%x 0x%x\n", \ + cmd->arg[0], cmd->arg[1], cmd->arg[2], cmd->arg[3])); + + + /* clear status, assume success */ + cmd->status = IO_E_SUCC; + + /* branch on opcode */ + switch ( cmd->opcode ) + { + + case IO_CMD_ENUM_ADAPTERS : + cmd->status = IoEnumAdapter(cmd); + break; + + case IO_CMD_ENUM_CM: + cmd->status = IoEnumCm(cmd); + break; + + case IO_CMD_ENUM_IDD : + cmd->status = IoEnumIdd(cmd); + break; + + case IO_CMD_TRC_RESET : + cmd->status = trc_control(cmd->idd, + TRC_OP_RESET, (ULONG)cmd->idd); + break; + + case IO_CMD_TRC_STOP : + cmd->status = trc_control(cmd->idd, + TRC_OP_STOP, (ULONG)cmd->idd); + break; + + case IO_CMD_TRC_START : + cmd->status = trc_control(cmd->idd, + TRC_OP_START, (ULONG)cmd->idd); + break; + + case IO_CMD_TRC_SET_FILT : + cmd->status = trc_control(cmd->idd, + TRC_OP_SET_FILTER, cmd->arg[0]); + break; + + case IO_CMD_IDD_RESET_AREA : + cmd->status = idd_reset_area(cmd->idd); + break; + + case IO_CMD_IDD_GET_AREA : + cmd->status = idd_get_area(cmd->idd, cmd->arg[0], NULL, NULL); + break; + + case IO_CMD_IDD_GET_STAT : + cmd->status = idd_get_area_stat(cmd->idd, &cmd->val.IddStat); + break; + + case IO_CMD_TRC_CREATE: + cmd->status = trc_control(cmd->idd, + TRC_OP_CREATE, cmd->arg[0]); + break; + + case IO_CMD_TRC_DESTROY: + cmd->status = trc_control(cmd->idd, + TRC_OP_DESTROY, cmd->arg[0]); + break; + + case IO_CMD_TRC_GET_STAT : + cmd->status = trc_get_status(idd_get_trc(cmd->idd), + &cmd->val.trc_stat); + break; + + case IO_CMD_TRC_GET_ENT : + cmd->status = trc_get_entry(idd_get_trc(cmd->idd), + cmd->arg[0], &cmd->val.trc_ent); + break; + + case IO_CMD_DBG_LEVEL : + DigiDebugLevel = (INT)(cmd->arg[0]); + break; + + case IO_CMD_DO_IDP_CMD: + DbgPrint("DoIdpCmd: Cmd: 0x%x\n", cmd->arg[0]); + if( cmd->idd && (( ((IDD*)cmd->idd)->btype != IDD_BT_DATAFIREU) && + ( ((IDD*)cmd->idd)->btype != IDD_BT_DATAFIREST) && + ( ((IDD*)cmd->idd)->btype != IDD_BT_DATAFIRE4ST)) ) + { + switch (cmd->arg[0]) + { + case GET_IDP_IO_VALUE: + cmd->val.IdpRaw.uc = IdpGetUByteIO(cmd->idd, + cmd->val.IdpRaw.us); + cmd->status = IO_E_SUCC; + break; + + + case GET_IDP_BUFFER: + IdpGetBuffer(cmd->idd, + cmd->val.IdpRaw.Bank, + cmd->val.IdpRaw.Page, + cmd->val.IdpRaw.Address, + cmd->val.IdpRaw.Length, + cmd->val.IdpRaw.Buffer); + + cmd->status = IO_E_SUCC; + break; + + case SET_IDP_IO_VALUE: + IdpPutUByteIO(cmd->idd, + (USHORT)cmd->val.IdpRaw.Address, + cmd->val.IdpRaw.uc); + cmd->status = IO_E_SUCC; + break; + + case SET_IDP_BUFFER: + IdpPutBuffer(cmd->idd, + cmd->val.IdpRaw.Bank, + cmd->val.IdpRaw.Page, + cmd->val.IdpRaw.Address, + cmd->val.IdpRaw.Length, + cmd->val.IdpRaw.Buffer); + + cmd->status = IO_E_SUCC; + break; + + default: + cmd->status = IO_E_BADCMD; + break; + } + } + else + cmd->status = IO_E_BADIDD; + break; + + case IO_CMD_DO_ADP_CMD: + if( cmd->idd && (( ((IDD*)cmd->idd)->btype == IDD_BT_DATAFIREU) || + ( ((IDD*)cmd->idd)->btype == IDD_BT_DATAFIREST) || + ( ((IDD*)cmd->idd)->btype == IDD_BT_DATAFIRE4ST)) ) + { + switch (cmd->arg[0]) + { + case GET_ADP_UCHAR: + cmd->val.AdpRaw.uc = AdpGetUByte(cmd->idd, + cmd->val.AdpRaw.Address); + + cmd->status = IO_E_SUCC; + break; + + case GET_ADP_USHORT: + cmd->val.AdpRaw.us = AdpGetUShort(cmd->idd, + cmd->val.AdpRaw.Address); + + cmd->status = IO_E_SUCC; + break; + + case GET_ADP_ULONG: + cmd->val.AdpRaw.ul = AdpGetULong(cmd->idd, + cmd->val.AdpRaw.Address); + + cmd->status = IO_E_SUCC; + break; + + case GET_ADP_BUFFER: + AdpGetBuffer(cmd->idd, + cmd->val.AdpRaw.Buffer, + cmd->val.AdpRaw.Address, + cmd->val.AdpRaw.Length + ); + + cmd->status = IO_E_SUCC; + break; + + case SET_ADP_UCHAR: + AdpPutUByte(cmd->idd, + cmd->val.AdpRaw.Address, + cmd->val.AdpRaw.uc); + + cmd->status = IO_E_SUCC; + break; + + case SET_ADP_USHORT: + AdpPutUShort(cmd->idd, + cmd->val.AdpRaw.Address, + cmd->val.AdpRaw.us); + + cmd->status = IO_E_SUCC; + break; + + case SET_ADP_ULONG: + AdpPutULong(cmd->idd, + cmd->val.AdpRaw.Address, + cmd->val.AdpRaw.ul); + + cmd->status = IO_E_SUCC; + break; + + case SET_ADP_BUFFER: + AdpPutBuffer(cmd->idd, + cmd->val.AdpRaw.Address, + cmd->val.AdpRaw.Buffer, + cmd->val.AdpRaw.Length); + + cmd->status = IO_E_SUCC; + break; + + default: + cmd->status = IO_E_BADCMD; + break; + } + } + else + cmd->status = IO_E_BADIDD; + + break; + + default : + cmd->status = IO_E_BADCMD; + break; + } + + /* return status code */ + return((INT)cmd->status); +} diff --git a/private/ntos/ndis/digi/pcimac/io_pub.h b/private/ntos/ndis/digi/pcimac/io_pub.h new file mode 100644 index 000000000..080fef7fb --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/io_pub.h @@ -0,0 +1,153 @@ +/* + * IO_PUB.H - include file for all IO modules + */ + +#ifndef _IO_PUB_ +#define _IO_PUB_ + +#define BRI_MAX_NAMELEN 64 /* anything that can be named < 64 chars */ + +/* error codes */ +#define IO_E_SUCC 0 /* success */ +#define IO_E_NOROOM 1 /* no room in local tables */ +#define IO_E_NOSUCH 2 /* no such object */ +#define IO_E_BADSIG 3 /* bad signature */ +#define IO_E_BADVER 4 /* bad version */ +#define IO_E_BADCMD 5 /* bad command opcode */ +#define IO_E_BADIDD 6 +#define IO_E_BADCM 7 +#define IO_E_PENDING 0xFF /* command is pending */ + +/* IO commands available listed here */ +#define IO_CMD_ENUM_ADAPTERS 0x100 /* enumerate network interfaces */ +#define IO_CMD_ENUM_IDD 0x101 /* enumerate isdn device drivers */ +#define IO_CMD_ENUM_CM 0x102 /* enumerate connection managers */ + +#define IO_CMD_TRC_RESET 0x300 /* reset trace */ +#define IO_CMD_TRC_STOP 0x301 /* stop trace */ +#define IO_CMD_TRC_START 0x302 /* start trace */ +#define IO_CMD_TRC_SET_FILT 0x305 /* set filter for trace context */ +#define IO_CMD_TRC_GET_STAT 0x306 /* get status of trace context */ +#define IO_CMD_TRC_GET_ENT 0x307 /* get a trace entry */ +#define IO_CMD_TRC_CREATE 0x30A /* create trc object */ +#define IO_CMD_TRC_DESTROY 0x30B /* destroy trc object */ + +#define IO_CMD_DO_ADP_CMD 0x400 +#define MAX_ADP_OPERATIONS 8 +#define GET_ADP_UCHAR 1 +#define GET_ADP_USHORT 2 +#define GET_ADP_ULONG 3 +#define GET_ADP_BUFFER 4 +#define SET_ADP_UCHAR 5 +#define SET_ADP_USHORT 6 +#define SET_ADP_ULONG 7 +#define SET_ADP_BUFFER 8 + +#define IO_CMD_DO_IDP_CMD 0x401 +#define MAX_IDP_OPERATIONS 4 +#define GET_IDP_IO_VALUE 1 +#define GET_IDP_BUFFER 2 +#define SET_IDP_IO_VALUE 3 +#define SET_IDP_BUFFER 4 + +#define IO_CMD_IDD_GET_AREA 0x900 /* get idd area */ +#define IO_CMD_IDD_RESET_AREA 0x901 /* reset idd area state */ +#define IO_CMD_IDD_GET_STAT 0x902 /* get area state */ + +#define IO_CMD_DBG_LEVEL 0xF00 /* set debug level */ + +typedef struct _ENUM_ADAPTERS_ +{ + USHORT num; + ULONG BaseIO[MAX_ADAPTERS_IN_SYSTEM]; + ULONG BaseMem[MAX_ADAPTERS_IN_SYSTEM]; + ULONG BoardType[MAX_ADAPTERS_IN_SYSTEM]; + CHAR Name[MAX_ADAPTERS_IN_SYSTEM][BRI_MAX_NAMELEN]; + VOID *tbl[MAX_ADAPTERS_IN_SYSTEM]; +} ENUM_ADAPTERS, *PENUM_ADAPTERS; + +typedef struct ENUM_CM +{ + USHORT num; + CHAR name[MAX_CM_IN_SYSTEM][BRI_MAX_NAMELEN]; + VOID *tbl[MAX_CM_IN_SYSTEM]; +} ENUM_CM, *PENUM_CM; + +typedef struct _ENUM_IDD_ +{ + USHORT num; + VOID *tbl[MAX_IDD_IN_SYSTEM]; + CHAR name[MAX_IDD_IN_SYSTEM][BRI_MAX_NAMELEN]; +} ENUM_IDD, *PENUM_IDD; + +typedef struct _DBG_LEVEL_ +{ + INT cmplen; + CHAR filestr[9]; +} DBG_LEVEL, *PDBG_LEVEL; + +typedef struct _ADPRAW_ +{ + UCHAR uc; + USHORT us; + ULONG ul; + ULONG Address; + USHORT Length; + UCHAR Buffer[ADP_RAM_SIZE]; +} ADPRAW, *PADPRAW; + +typedef struct _IDPRAW_ +{ + UCHAR uc; + USHORT us; + ULONG ul; + USHORT Bank; + USHORT Page; + ULONG Address; + USHORT Length; + UCHAR Buffer[IDP_RAM_PAGE_SIZE]; +} IDPRAW, *PIDPRAW; + +/* master descriptor structure for ioctl commands to IO module */ +typedef struct +{ + ULONG sig; /* identifing signature */ +#define IO_CMD_SIG 0x321B71B7 + + USHORT ver_major, ver_minor; /* interface version (curr: 0.1) */ +#define IO_VER_MAJOR 0 +#define IO_VER_MINOR 1 + + ULONG opcode; /* command opcode, IO_CMD_* */ + + ULONG status; /* completion status, ok: 0 */ + + VOID *cm; /* related connection object */ + VOID *idd; /* related idd */ + ULONG arg[4]; /* 4 general purpose args */ + + union /* opcode specific data */ + { + ENUM_ADAPTERS enum_adapters; /* IO_CMD_ENUM_ADAPTERS */ + + ENUM_CM enum_cm; /* IO_CMD_ENUM_MTL */ + + ENUM_IDD enum_idd; /* IO_CMD_ENUM_IDD */ + + DBG_LEVEL dbg_level; + + CM_STATUS cm_stat; /* IO_CMD_CM_GET_STAT */ + + TRC_STATUS trc_stat; /* IO_CMD_TRC_GET_STAT */ + TRC_ENTRY trc_ent; /* IO_CMD_TRC_GET_ENT */ + IDD_AREA IddStat; // IO_CMD_GET_IDD_STAT + + ADPRAW AdpRaw; + + IDPRAW IdpRaw; + } val; + +} IO_CMD; + +#endif /* _IO_PUB_ */ + diff --git a/private/ntos/ndis/digi/pcimac/lanoid.c b/private/ntos/ndis/digi/pcimac/lanoid.c new file mode 100644 index 000000000..33b3eb476 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/lanoid.c @@ -0,0 +1,240 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PCIMAC_MAJOR_VERSION 2 +#define PCIMAC_MINOR_VERSION 0 + +// +// Lan OID's +// +static UINT SupportedLanOids[] = + { + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_LOOKAHEAD, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_MAC_OPTIONS, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BUFFER_SPACE, + OID_GEN_RECEIVE_BUFFER_SPACE, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_VENDOR_ID, + OID_GEN_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_GEN_RCV_NO_BUFFER, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS + }; + +#define MAX_SUPPORTED_LAN_OIDS 31 + + + + +NDIS_STATUS +LanOidProc( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesReadWritten, + PULONG BytesNeeded + ) +{ + ADAPTER *Adapter = (ADAPTER*)AdapterContext; + CM *cm = (CM*)Adapter->CmTbl[0]; + ULONG GenericULong; + USHORT GenericUShort; + UCHAR GenericArray[6]; + UINT MoveBytes = sizeof(ULONG); + PVOID MoveSource = (PVOID)(&GenericULong); + UINT BytesLeft = InfoBufferLen; + NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS; + NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady; + NDIS_MEDIUM Medium = NdisMedium802_3; + ULONG OidType = 0; + ULONG Filter; + + switch (Oid) + { + case OID_802_3_MULTICAST_LIST: + case OID_GEN_CURRENT_LOOKAHEAD: + MoveBytes = BytesLeft; + OidType = 1; + break; + + case OID_GEN_CURRENT_PACKET_FILTER: + MoveBytes = BytesLeft; + OidType = 1; + NdisMoveMemory(&Filter, InfoBuffer, 4); + + if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING | + NDIS_PACKET_TYPE_SMT | + NDIS_PACKET_TYPE_MAC_FRAME | + NDIS_PACKET_TYPE_FUNCTIONAL | + NDIS_PACKET_TYPE_ALL_FUNCTIONAL | + NDIS_PACKET_TYPE_GROUP + )) + StatusToReturn = NDIS_STATUS_NOT_SUPPORTED; + break; + + case OID_GEN_MAC_OPTIONS: + GenericULong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | + NDIS_MAC_OPTION_RECEIVE_SERIALIZED | + NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | + NDIS_MAC_OPTION_NO_LOOPBACK); + + break; + + case OID_GEN_SUPPORTED_LIST: + MoveSource = (PVOID)(SupportedLanOids); + MoveBytes = sizeof(SupportedLanOids); + break; + + case OID_GEN_HARDWARE_STATUS: + MoveSource = (PVOID)(&HardwareStatus); + MoveBytes = sizeof(NDIS_HARDWARE_STATUS); + break; + + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + MoveSource = (PVOID)(&Medium); + MoveBytes = sizeof(NDIS_MEDIUM); + break; + + case OID_GEN_MAXIMUM_LOOKAHEAD: + GenericULong = (ULONG)1514; + break; + + case OID_GEN_MAXIMUM_FRAME_SIZE: + GenericULong = (ULONG)1500; + break; + + case OID_GEN_MAXIMUM_TOTAL_SIZE: + GenericULong = (ULONG)1514; + break; + + case OID_GEN_LINK_SPEED: + GenericULong = (ULONG)12800; + break; + + case OID_GEN_TRANSMIT_BUFFER_SPACE: + GenericULong = (ULONG)(1514 * 16); + break; + + case OID_GEN_RECEIVE_BUFFER_SPACE: + GenericULong = (ULONG)(1514 * 16); + break; + + case OID_GEN_TRANSMIT_BLOCK_SIZE: + GenericULong = (ULONG)256; + break; + + case OID_GEN_RECEIVE_BLOCK_SIZE: + GenericULong = (ULONG)256; + break; + + case OID_GEN_VENDOR_ID: + NdisMoveMemory((PVOID)&GenericULong, + cm->SrcAddr, + 3); + + GenericULong &= 0xFFFFFF00; + GenericULong |= 0x01; + break; + + case OID_GEN_VENDOR_DESCRIPTION: + MoveSource = (PVOID)"DigiBoard Pcimac ISDN Adapter."; + MoveBytes = strlen("DigiBoard Pcimac ISDN Adapter."); + break; + + case OID_GEN_DRIVER_VERSION: + GenericUShort = ((USHORT)PCIMAC_MAJOR_VERSION << 8) | + PCIMAC_MINOR_VERSION; + MoveSource = (PVOID)(&GenericUShort); + MoveBytes = sizeof(USHORT); + break; + + case OID_802_3_PERMANENT_ADDRESS: + NdisMoveMemory((PVOID)GenericArray, + cm->SrcAddr, + 6); + MoveSource = (PVOID)GenericArray; + MoveBytes = 6; + break; + + case OID_802_3_CURRENT_ADDRESS: + NdisMoveMemory((PVOID)GenericArray, + cm->SrcAddr, + 6); + MoveSource = (PVOID)GenericArray; + MoveBytes = 6; + break; + + case OID_GEN_XMIT_OK: + case OID_GEN_RCV_OK: + case OID_GEN_XMIT_ERROR: + case OID_GEN_RCV_ERROR: + case OID_GEN_RCV_NO_BUFFER: + case OID_802_3_RCV_ERROR_ALIGNMENT: + case OID_802_3_XMIT_ONE_COLLISION: + case OID_802_3_XMIT_MORE_COLLISIONS: + GenericULong = (ULONG)0; + break; + + case OID_802_3_MAXIMUM_LIST_SIZE: + GenericULong = (ULONG)16; + break; + + default: + StatusToReturn = NDIS_STATUS_INVALID_OID; + break; + } + + if (StatusToReturn == NDIS_STATUS_SUCCESS) + { + *BytesNeeded = 0; + if (MoveBytes > BytesLeft) + { + *BytesNeeded = MoveBytes; + StatusToReturn = NDIS_STATUS_INVALID_LENGTH; + } + else if (OidType == 0) + { + NdisMoveMemory(InfoBuffer, MoveSource, MoveBytes); + (*BytesReadWritten) = MoveBytes; + } + } + return(StatusToReturn); +} + + diff --git a/private/ntos/ndis/digi/pcimac/makefile b/private/ntos/ndis/digi/pcimac/makefile new file mode 100644 index 000000000..677d610db --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/digi/pcimac/mtl.h b/private/ntos/ndis/digi/pcimac/mtl.h new file mode 100644 index 000000000..06d71919c --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mtl.h @@ -0,0 +1,306 @@ +/* + * MTL.H - include file for all MTL modules + */ + +#ifndef _MTL_ +#define _MTL_ + +/* some constants values */ +// The value for mtl_max_chan has to be <= the value for +// cm_max_chan in cm_pub.h + +// +// I set the MTU to a large enough value to allow multi-link, +// bridging and any other future expansion to occur. +// +#define MTL_MAC_MTU 1600 /* mac size mtu, fixed */ + +#define MTL_IDD_MTU 260 /* idd size mtu, default value */ + +// +// a guess at how much receive space we will need this is 1514 * 16 wich seems +// like alot to me +// +#define MTL_RX_BUFS 16 /* # of recieve buffers, must be 2^n */ + +// +// max local tx descriptor buffers based on the maximum number of +// wanpackets we told the wrapper it could send (mydefs.h MAX_WANPACKET_XMITS) +// +#define MTL_TX_BUFS 8 /* # of transmit buffers */ + +// +// max fragments per packet +// +#define MTL_MAX_FRAG 16 + +// +// index into buffer where destination ethernet address starts +// +#define DST_ADDR_INDEX 0 + +// +// index into buffer where source ethernet address starts +// +#define SRC_ADDR_INDEX 6 + +// +// index into buffer where length of buffer starts +// +#define PKT_LEN_INDEX 12 + +/* mtl error codes */ +#define MTL_E_SUCC 0 +#define MTL_E_NOMEM 1 +#define MTL_E_NOTIMPL 2 +#define MTL_E_NOROOM 3 +#define MTL_E_NOSUCH 4 + +// +// local mtl defs +// +/* packet receive/transmit assembly/disassembly descriptor */ +typedef struct +{ + LIST_ENTRY link; + ULONG Queued; + ULONG QueueOverRun; + UCHAR seq; /* recorded sequence number */ + UCHAR tot; /* total # of fragments (0 free) */ + UCHAR num; /* # of fragments received/transmitted */ + ULONG ttl; /* time to live, in seconds */ + USHORT len; /* accumulated packet length */ + struct _MTL *mtl; /* back pointer to mtl */ + USHORT State; /* State of current large frame */ + UCHAR* DataPtr; /* current data index into buffer */ + USHORT MaxRxLength; /* max frame receive length */ + ULONG MissCount; /* rx miss count */ + PUCHAR buf; +} MTL_AS; + +typedef struct +{ + UCHAR NextFree; + NDIS_SPIN_LOCK lock; /* access spinlock */ + ULONG DKFReceiveError1; + ULONG DKFReceiveError2; + ULONG DKFReceiveError3; + ULONG DKFReceiveError4; + ULONG DKFReceiveError5; + ULONG PPPReceiveError1; + ULONG PPPReceiveError2; + ULONG PPPReceiveError3; + ULONG PPPReceiveError4; + ULONG PPPReceiveError5; + ULONG IndicateReceiveError1; + ULONG IndicateReceiveError2; + ULONG IndicateReceiveError3; + ULONG TimeOutReceiveError1; + MTL_AS as_tbl[MTL_RX_BUFS]; + PUCHAR Data; +}MTL_RX_TBL; + +typedef struct +{ + LIST_ENTRY head; + NDIS_SPIN_LOCK lock; +} MTL_AS_FIFO; + +// +// Fifo for storing wan packets before fragment processing +// +typedef struct +{ + LIST_ENTRY head; /* head pointer, head==NULL -> empty */ + NDIS_SPIN_LOCK lock; /* access lock */ + ULONG Count; + ULONG Max; +} MTL_WANPACKET_FIFO; + +/* idd packet header */ +typedef struct +{ + UCHAR sig_tot; /* signature + total fragments */ + UCHAR seq; /* packet sequence number */ + USHORT ofs; /* offset of fragment data into packet */ +} MTL_HDR; + +// +// this structure is used for data this is fragmented in the DKF format +// +typedef struct +{ + IDD_FRAG IddFrag[2]; /* two fragments (hdr+data) required */ + MTL_HDR MtlHeader; /* header storage */ +} DKF_FRAG; + +/* trasmit fragement descriptor */ +// +// The DKF_FRAG member must be kept at the begining of this structure +// !!!!!!!!!!!!!! mtl_tx.c relies on this !!!!!!!!!!!!!!! +// +typedef struct +{ + DKF_FRAG DkfFrag; /* frament descriptor for idd poll_tx */ + IDD_MSG frag_msg; /* fragments waiting to be sent vector */ + VOID *frag_idd; /* idd accepting fragments */ + USHORT frag_bchan; /* destination bchannels */ + VOID *frag_arg; /* argument to completion function */ + ULONG FragSent; /* flag to indicate if this frag has been xmitted */ +} MTL_TX_FRAG; + +/* trasmit packet descriptor */ +typedef struct +{ + LIST_ENTRY TxPacketQueue; + NDIS_SPIN_LOCK lock; + ULONG InUse; /* this entry is in use */ + USHORT NumberOfFrags; /* # of fragments in frag_tbl */ + USHORT NumberOfFragsSent; /* # of fragments already sent */ + USHORT FragReferenceCount; /* refrence count */ + UCHAR *frag_buf; /* pointer to real data buffer */ + NDIS_WAN_PACKET *WanPacket; /* related user packet */ + struct _MTL *mtl; /* back pointer to mtl */ + MTL_TX_FRAG frag_tbl[MTL_MAX_FRAG]; /* fragment table (assembled) */ +} MTL_TX_PKT; + +/* trasmit packet control table */ +typedef struct +{ + LIST_ENTRY head; + NDIS_SPIN_LOCK lock; /* access lock */ + ULONG seq; /* packet sequence number (for next) */ + ULONG NextFree; /* next available packet */ + MTL_TX_PKT TxPacketTbl[MTL_TX_BUFS]; /* packet table */ +} MTL_TX_TBL; + +/* a channel descriptor */ +typedef struct +{ + VOID *idd; /* related idd object */ + USHORT bchan; /* related channel within idd, b1=0, b2=1 */ + ULONG speed; /* channel speed in bps */ + struct _MTL *mtl; /* mtl back pointer */ +} MTL_CHAN; + +/* channel table */ +typedef struct +{ + MTL_CHAN tbl[MAX_CHAN_PER_CONN]; /* table of channels */ + USHORT num; /* # of entries used */ + NDIS_SPIN_LOCK lock; /* access spinlock */ +} MTL_CHAN_TBL; + +/* an MTL object */ +typedef struct _MTL +{ + ADAPTER *Adapter; /* adapter that owns this mtl */ + + NDIS_HANDLE LinkHandle; /* handle from wrapper for this link */ + + //statistics + ULONG FramesXmitted; + ULONG FramesReceived; + ULONG BytesXmitted; + ULONG BytesReceived; + + NDIS_SPIN_LOCK lock; /* access lock */ + + VOID (*rx_handler)(); /* mgr receiver handler routine */ + VOID *rx_handler_arg; /* ... handler argument */ + + VOID (*tx_handler)(); /* mgr transmitter handler routine */ + VOID *tx_handler_arg; /* ... handler argument */ + + USHORT idd_mtu; /* idd max frame size */ + BOOL is_conn; /* is connected now? */ + + ULONG IddTxFrameType; /* 0/1 - PPP/DKF */ + ULONG IddRxFrameType; /* 0/1 - PPP/DKF */ + + MTL_CHAN_TBL chan_tbl; /* the channel table */ + + // + // Receive table + // + MTL_RX_TBL rx_tbl; + + // + // Receive Completion Fifo + // + MTL_AS_FIFO RxIndicationFifo; + + // + // fifo of wan packets to be transmitted + // + MTL_WANPACKET_FIFO WanPacketFifo; + + // + // transmit table + // + MTL_TX_TBL tx_tbl; + + // + // flag to show + // + BOOL RecvCompleteScheduled; + + // + // backpointer to connection object + // + VOID *cm; + + SEMA tx_sema; /* transmit processing sema */ + + // + // wan wrapper information + // + ULONG MaxSendFrameSize; + ULONG MaxRecvFrameSize; + ULONG PreamblePadding; + ULONG PostamblePadding; + ULONG SendFramingBits; + ULONG RecvFramingBits; + ULONG SendCompressionBits; + ULONG RecvCompressionBits; + +} MTL; + +// +// public mtl defs +// +/* MTL object operations */ +INT mtl_create(VOID** mtl_1, NDIS_HANDLE AdapterHandle); +INT mtl_destroy(VOID* mtl_1); +INT mtl_set_rx_handler(VOID* mtl_1, VOID (*handler)(), VOID* handler_arg); +INT mtl_set_tx_handler(VOID* mtl_1, VOID (*handler)(), VOID* handler_arg); +INT mtl_set_idd_mtu(VOID* mtl_1, USHORT idd_mtu); +INT mtl_set_conn_state(VOID* mtl_1, USHORT NumberOfChannels, BOOL is_conn); +INT mtl_get_conn_speed(VOID* mtl_1, ULONG *speed); +INT mtl_get_mac_mtu(VOID* mtl_1, ULONG* mtu); +VOID mtl_tx_packet(VOID* mtl_1, PNDIS_WAN_PACKET pkt); +INT mtl_add_chan(VOID* mtl_1, VOID* idd, USHORT chan, ULONG speed, ULONG ConnectionType); +INT mtl_del_chan(VOID* mtl_1, VOID* idd, USHORT chan); +INT GetStatistics (VOID*, VOID*); +INT ClearStatistics (VOID*); +INT MtlSetFramingType (VOID*, ULONG); + + +/* prototypes for internal functions */ +VOID mtl__rx_bchan_handler(MTL_CHAN* chan, USHORT bchan, ULONG RxFrameType, IDD_XMSG* xmsg); +VOID IndicateRxToWrapper(MTL*); +VOID mtl__tx_cmpl_handler(MTL_TX_PKT *pkt, USHORT bchan, IDD_MSG* msg); +VOID mtl__rx_tick(MTL* mtl); +VOID mtl__tx_tick(MTL* mtl); +VOID MtlPollFunction(VOID* a1, ADAPTER *Adapter, VOID* a3, VOID* a4); +VOID MtlRecvCompleteFunction(ADAPTER *Adapter); +BOOLEAN IsRxIndicationFifoEmpty(MTL*); +MTL_AS* GetAssemblyFromRxIndicationFifo(MTL*); +VOID QueueDescriptorForRxIndication(MTL*, MTL_AS*); +VOID MtlSendCompleteFunction(ADAPTER *Adapter); +VOID IndicateTxCompletionToWrapper(MTL*); +VOID MtlFlushWanPacketTxQueue(MTL*); +VOID mtl__tx_packet(MTL*, NDIS_WAN_PACKET*); +VOID TryToIndicateMtlReceives(ADAPTER *Adapter); + +#endif /* _MTL_ */ diff --git a/private/ntos/ndis/digi/pcimac/mtl_init.c b/private/ntos/ndis/digi/pcimac/mtl_init.c new file mode 100644 index 000000000..1aa8158fd --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mtl_init.c @@ -0,0 +1,195 @@ +/* + * MTL_INIT.C - Media Translation Layer, initialization + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma NDIS_INIT_FUNCTION(mtl_create) + +/* create an mtl object */ +mtl_create(VOID **mtl_1, NDIS_HANDLE AdapterHandle) +{ + MTL **ret_mtl = (MTL**)mtl_1; + MTL *mtl; + INT n; + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(0xffffffff, 0xffffffff); + + D_LOG(D_ENTRY, ("mtl_create: entry, ret_mtl: 0x%lx\n", ret_mtl)); + + // + // allocate memory for mtl object + // + NdisAllocateMemory((PVOID*)&mtl, sizeof(*mtl), 0, pa); + if ( !mtl ) + { + D_LOG((DIGIMTL|DIGIINIT), ("mtl_create: memory allocate failed!\n")); + NdisWriteErrorLogEntry (AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 0); + return(MTL_E_NOMEM); + } + D_LOG((DIGIMTL|DIGIINIT), ("mtl_create: mtl: 0x%lx\n", mtl)); + NdisZeroMemory(mtl, sizeof(MTL)); + + // + // allocate rx table + // + NdisAllocateMemory((PVOID*)&mtl->rx_tbl.Data, (MTL_RX_BUFS * MTL_MAC_MTU), 0, pa); + if ( !mtl->rx_tbl.Data ) + { + D_LOG((DIGIMTL|DIGIINIT), ("mtl_create: RxData memory allocate failed!\n")); + + NdisWriteErrorLogEntry (AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 0); + + /* free memory */ + NdisFreeMemory(mtl, sizeof(*mtl), 0); + + return(MTL_E_NOMEM); + } + D_LOG((DIGIMTL|DIGIINIT), ("mtl_create: RxData: 0x%lx\n", mtl->rx_tbl.Data)); + NdisZeroMemory(mtl->rx_tbl.Data, (MTL_RX_BUFS * MTL_MAC_MTU)); + + /* setup some simple fields */ + mtl->idd_mtu = MTL_IDD_MTU; + + /* allocate spinlock for mtl */ + NdisAllocateSpinLock(&mtl->lock); + + /* allocate spinlock for channel table */ + NdisAllocateSpinLock(&mtl->chan_tbl.lock); + + // + // create assembly descriptor pointers into rx table + // + for (n = 0; n < MTL_RX_BUFS; n++) + mtl->rx_tbl.as_tbl[n].buf = mtl->rx_tbl.Data + (n * MTL_MAC_MTU); + + NdisAllocateSpinLock(&mtl->rx_tbl.lock); + + // + // spinlock for RxIndicationFifo + // + NdisAllocateSpinLock(&mtl->RxIndicationFifo.lock); + + // + // initialize assembly completion fifo + // + NdisAcquireSpinLock(&mtl->RxIndicationFifo.lock); + + InitializeListHead(&mtl->RxIndicationFifo.head); + + NdisReleaseSpinLock(&mtl->RxIndicationFifo.lock); + + // + // tx packet table lock + // + NdisAllocateSpinLock(&mtl->tx_tbl.lock); + + for (n = 0; n < MTL_TX_BUFS; n++) + { + MTL_TX_PKT *MtlTxPacket = &mtl->tx_tbl.TxPacketTbl[n]; + + NdisAllocateSpinLock(&MtlTxPacket->lock); + } + + // + // initialize MtlTxPacket Queue + // + NdisAcquireSpinLock(&mtl->tx_tbl.lock); + + InitializeListHead(&mtl->tx_tbl.head); + + NdisReleaseSpinLock(&mtl->tx_tbl.lock); + + // + // Tx WanPacket storage + // + NdisAllocateSpinLock(&mtl->WanPacketFifo.lock); + + NdisAcquireSpinLock(&mtl->WanPacketFifo.lock); + + InitializeListHead(&mtl->WanPacketFifo.head); + + NdisReleaseSpinLock(&mtl->WanPacketFifo.lock); + + // + // setup default wan link fields + // + mtl->MaxSendFrameSize = MTL_MAC_MTU; + mtl->MaxRecvFrameSize = MTL_MAC_MTU; + mtl->PreamblePadding = 14; + mtl->PostamblePadding = 0; + mtl->SendFramingBits = RAS_FRAMING | + PPP_FRAMING | + MEDIA_NRZ_ENCODING; + mtl->RecvFramingBits = RAS_FRAMING | + PPP_FRAMING | + MEDIA_NRZ_ENCODING; + mtl->SendCompressionBits = 0; + mtl->RecvCompressionBits = 0; + + /* init sema */ + sema_init(&mtl->tx_sema); + + /* return success */ + *ret_mtl = mtl; + D_LOG(D_EXIT, ("mtl_create: exit\n")); + return(MTL_E_SUCC); +} + +/* destroy an mtl object */ +mtl_destroy(VOID* mtl_1) +{ + MTL *mtl = (MTL*)mtl_1; + INT n; + + D_LOG(D_ENTRY, ("mtl_destroy: entry, mtl: 0x%lx\n", mtl)); + + /* allocate spinlock for mtl */ + NdisFreeSpinLock(&mtl->lock); + + /* allocate spinlock for channel table */ + NdisFreeSpinLock(&mtl->chan_tbl.lock); + + /* allocate spin locks for receive table */ +// for ( n = 0 ; n < MTL_RX_BUFS ; n++ ) +// NdisFreeSpinLock(&mtl->rx_tbl.as_tbl[n].lock); + + NdisFreeSpinLock(&mtl->rx_tbl.lock); + + /* allocate spin lock for trasmit table & fifo */ + NdisFreeSpinLock(&mtl->tx_tbl.lock); + + for (n = 0; n < MTL_TX_BUFS; n++) + { + MTL_TX_PKT *MtlTxPacket = &mtl->tx_tbl.TxPacketTbl[n]; + + NdisFreeSpinLock(&MtlTxPacket->lock); + } + + NdisFreeSpinLock(&mtl->WanPacketFifo.lock); + NdisFreeSpinLock(&mtl->RxIndicationFifo.lock); + + /* term sema */ + sema_term(&mtl->tx_sema); + + NdisFreeMemory(mtl->rx_tbl.Data, (MTL_RX_BUFS * MTL_MAC_MTU), 0); + + /* free memory */ + NdisFreeMemory(mtl, sizeof(*mtl), 0); + + D_LOG(D_EXIT, ("mtl_destroy: exit\n")); + return(MTL_E_SUCC); +} diff --git a/private/ntos/ndis/digi/pcimac/mtl_rx.c b/private/ntos/ndis/digi/pcimac/mtl_rx.c new file mode 100644 index 000000000..fdc591c55 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mtl_rx.c @@ -0,0 +1,840 @@ +/* + * MTL_RX.C - Receive side processing for MTL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* main handler, called when data arrives at bchannels */ +VOID +mtl__rx_bchan_handler + ( + MTL_CHAN *chan, + USHORT bchan, + ULONG IddRxFrameType, + IDD_XMSG *msg + ) +{ + MTL *mtl; + MTL_HDR hdr; + MTL_AS *as; + USHORT FragmentFlags, CopyLen; + MTL_RX_TBL *RxTable; + D_LOG(D_ENTRY, ("mtl__rx_bchan_handler: chan: 0x%lx, bchan: %d, msg: 0x%lx\n", chan, bchan, msg)); + + /* assigned mtl using back pointer */ + mtl = chan->mtl; + + // + // acquire the lock fot this mtl + // + NdisAcquireSpinLock(&mtl->lock); + + /* if not connected, ignore */ + if ( !mtl->is_conn ) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: packet on non connected mtl, ignored\n")); + goto exit_code; + } + + RxTable = &mtl->rx_tbl; + D_LOG(D_ENTRY, ("mtl__rx_bchan_handler: mtl: 0x%lx, buflen: %d, bufptr: 0x%lx\n", \ + mtl, msg->buflen, msg->bufptr)); + // + // if we are in detect mode + // + if (!mtl->RecvFramingBits) + { + UCHAR DetectData[3]; + + /* extract header, check for fields */ + IddGetDataFromAdapter(chan->idd, + (PUCHAR)&hdr, + (PUCHAR)msg->bufptr, + sizeof(MTL_HDR)); + + DigiDump( DIGIRXFRAGDATA, ("Recv Frag (detect):\n") ); + DigiDumpData( DIGIRXFRAGDATA, (PUCHAR)&hdr, sizeof(MTL_HDR) ); + +// NdisMoveMemory ((PUCHAR)&hdr, (PUCHAR)msg->bufptr, sizeof(MTL_HDR)); + + // + // this is used for inband signalling - ignore it + // + if (hdr.sig_tot == 0x50) + goto exit_code; + + // + // if this is dkf we need offset of zero for detection to work + // + if ( ((hdr.sig_tot & 0xF0) == 0x50) && (hdr.ofs != 0) ) + goto exit_code; + + // + // extract some data from the frame + // + IddGetDataFromAdapter(chan->idd, + (PUCHAR)&DetectData, + (PUCHAR)&msg->bufptr[4], + 2); + + DigiDump( DIGIRXFRAGDATA, ("Recv Frag (detect con't):\n") ); + DigiDumpData( DIGIRXFRAGDATA, (PUCHAR)&DetectData, 2 ); + +// NdisMoveMemory((PUCHAR)&DetectData, (PUCHAR)&msg->bufptr[4], 2); + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: hdr: 0x%x 0x%x 0x%x\n", hdr.sig_tot, \ + hdr.seq, hdr.ofs)); + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: DetectData: 0x%x 0x%x\n", DetectData[0], DetectData[1])); + + if ( (IddRxFrameType & IDD_FRAME_PPP) || + ((IddRxFrameType & IDD_FRAME_DKF) && + ((DetectData[0] == 0xFF) && (DetectData[1] == 0x03)))) + { + mtl->RecvFramingBits = PPP_FRAMING; + mtl->SendFramingBits = PPP_FRAMING; + RxTable->NextFree = 0; + } + else + { + mtl->RecvFramingBits = RAS_FRAMING; + mtl->SendFramingBits = RAS_FRAMING; + } + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: Deteced WrapperFrameType: 0x%x\n", mtl->RecvFramingBits)); + + // + // don't pass up detected frame for now + // + goto exit_code; + } + + if (IddRxFrameType & IDD_FRAME_DKF) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: Received IddFrameType: DKF\n")); + + /* size of packet has to be atleast as size of header */ + if ( msg->buflen < sizeof(hdr) ) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: packet size too small, ignored\n")); + RxTable->DKFReceiveError1++; + goto exit_code; + } + + /* extract header, check for fields */ + IddGetDataFromAdapter(chan->idd, + (PUCHAR)&hdr, + (PUCHAR)msg->bufptr, + sizeof(MTL_HDR)); + + DigiDump( DIGIRXFRAGDATA, ("Recv Frag (DKF hdr):\n") ); + DigiDumpData( DIGIRXFRAGDATA, (PUCHAR)&hdr, sizeof(MTL_HDR) ); + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: hdr: 0x%x 0x%x 0x%x\n", hdr.sig_tot, \ + hdr.seq, hdr.ofs)); + + // + // if this is not our header of if this is an inband uus + // ignore it + // + if ( (hdr.sig_tot & 0xF0) != 0x50 || hdr.sig_tot == 0x50) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: bad header signature, ignored\n")); + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: mtl: 0x%lx, [0]: 0x%x", mtl, hdr.sig_tot)); + RxTable->DKFReceiveError2++; + goto exit_code; + } + + if ( (hdr.ofs >= MTL_MAC_MTU) || ((hdr.ofs + msg->buflen - sizeof(hdr)) > MTL_MAC_MTU) ) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: bad offset/buflen, ignored\n")); + D_LOG(DIGIMTL, ("mtl: 0x%lx, Offset: %d, BufferLength: %d\n", mtl, hdr.ofs, msg->buflen)); + RxTable->DKFReceiveError3++; + goto exit_code; + } + + NdisAcquireSpinLock(&RxTable->lock); + + /* build pointer to assembly descriptor & lock it */ + as = RxTable->as_tbl + (hdr.seq % MTL_RX_BUFS); + + // + // if this assembly pointer is not free (queued) then + // just drop this fragment + // + if (as->Queued) + { + D_LOG(DIGIMTL, ("DKFRx: AssemblyQueue Overrun! mtl: 0x%lx, as: 0x%lx, seq: %d\n", \ + mtl, as, hdr.seq)); + + RxTable->DKFReceiveError4++; + as->QueueOverRun++; + NdisReleaseSpinLock(&RxTable->lock); + goto exit_code; + } + + /* check for new slot */ + if ( !as->tot ) + { + new_slot: + + /* new entry, fill-up */ + as->seq = hdr.seq; /* record sequence number */ + as->num = 1; /* just received 1'st fragment */ + as->ttl = 1000; /* time to live init val */ + as->len = msg->buflen - sizeof(hdr); /* record received length */ + as->tot = hdr.sig_tot & 0x0F; /* record number of expected fragments */ + + /* copy received data into buffer */ + copy_data: + IddGetDataFromAdapter(chan->idd, + (PUCHAR)as->buf + hdr.ofs, + (PUCHAR)msg->bufptr + sizeof(hdr), + (USHORT)(msg->buflen - sizeof(hdr))); + DigiDump( DIGIRXFRAGDATA, ("Recv Frag (DKF data):\n") ); + DigiDumpData( DIGIRXFRAGDATA, + (PUCHAR)as->buf + hdr.ofs, + (msg->buflen - sizeof(hdr)) ); + +// NdisMoveMemory (as->buf + hdr.ofs, msg->bufptr + sizeof(hdr), msg->buflen - sizeof(hdr)); + } + else if ( as->seq == hdr.seq ) + { + /* same_seq: */ + + /* same sequence number, accumulate */ + as->num++; + as->len += (msg->buflen - sizeof(hdr)); + + goto copy_data; + } + else + { + /* bad_frag: */ + + /* + * if this case, an already taken slot is hit, but with a different + * sequence number. this indicates a wrap-around in as_tbl. prev + * entry is freed and then this fragment is recorded as first + */ + D_LOG(DIGIMTL, ("DKFRx: Bad Fragment! mtl: 0x%lx, as: 0x%lx, as->seq: %d, seq: %d\n", \ + mtl, as, as->seq, hdr.seq)); + + D_LOG(DIGIMTL, ("as->tot: %d, as->num: %d\n", as->tot, as->num)); + + RxTable->DKFReceiveError5++; + goto new_slot; + } + + /* if all fragments recieved for packet, time to mail it up */ + if ( as->tot == as->num ) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: pkt mailed up, buf: 0x%lx, len: 0x%x\n", \ + as->buf, as->len)); + + QueueDescriptorForRxIndication(mtl, as); + + // + // mark this guy as being queued + // + as->Queued = 1; + } + + /* release assembly descriptor */ + NdisReleaseSpinLock(&RxTable->lock); + } + else if (IddRxFrameType & IDD_FRAME_PPP) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: Received IddFrameType: PPP\n")); + + NdisAcquireSpinLock(&RxTable->lock); + + /* build pointer to assembly descriptor & lock it */ + as = RxTable->as_tbl + (RxTable->NextFree % MTL_RX_BUFS); + + // + // if this assembly pointer is not free (queued) then + // just drop this fragment + // + if (as->Queued) + { + D_LOG(DIGIMTL, ("PPPRx: AssemblyQueue Overrun! mtl: 0x%lx, as: 0x%lx, NextFree: %d\n", \ + mtl, as, RxTable->NextFree)); + + as->QueueOverRun++; + + RxTable->PPPReceiveError1++; + + NdisReleaseSpinLock(&RxTable->lock); + + goto exit_code; + } + + FragmentFlags = msg->FragmentFlags; + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: FragmentFlags: 0x%x, CurrentRxState: 0x%x\n", FragmentFlags, as->State)); + + switch (as->State) + { + case RX_MIDDLE: + if (FragmentFlags & H_RX_N_BEG) + break; + + as->MissCount++; + + // + // missed an end buffer + // + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: mtl: 0x%lx, Miss in State: %d, FragmentFlags: 0x%x, MissCount: %d\n", \ + mtl, as->State, FragmentFlags, as->MissCount)); + + RxTable->PPPReceiveError2++; + + goto clearbuffer; + + break; + + case RX_BEGIN: + case RX_END: + if (FragmentFlags & H_RX_N_BEG) + { + // + // missed a begining buffer + // + as->MissCount++; + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: mtl: 0x%lx, Miss in State: %d, FragmentFlags: 0x%x, MissCount: %d\n", \ + mtl, as->State, FragmentFlags, as->MissCount)); + + RxTable->PPPReceiveError3++; + + goto done; + } +clearbuffer: + // + // clear rx buffer + // + NdisZeroMemory(as->buf, sizeof(as->buf)); + + // + // start data at begin of buffer + // + as->DataPtr = as->buf; + + // + // new buffer + // + as->len = 0; + + // + // set rx state + // + as->State = RX_MIDDLE; + + // + // set time to live + // + as->ttl = 1000; + + // + // there is always only one fragment with PPP + // maybe a big one but still only one + // + as->tot = 1; + + break; + + default: + D_LOG(DIGIMTL, ("Invalid PPP Rx State! mtl: 0x%lx, as: 0x%lx State: 0x%x\n", \ + mtl, as, as->State)); + + as->State = RX_BEGIN; + + as->tot = 0; + + as->MissCount++; + + goto done; + + break; + } + + // + // get the length to be copy + // + CopyLen = msg->buflen; + + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: CopyLen: %d\n", CopyLen)); + + if (FragmentFlags & H_RX_N_END) + { + // + // if this is not the last buffer and length is 0 + // we are done + // + if (CopyLen == 0) + goto done_copy; + + } + else + { + // + // if CopyLen = 0 buffer only contains 2 CRC bytes + // + if (CopyLen == 0) + { + goto done_copy; + } + + // + // buffer contains only 1 CRC byte + // + else if (CopyLen == (-1 & H_RX_LEN_MASK)) + { + // + // previous buffer had a crc byte in it so remove it + // + as->len -= 1; + goto done_copy; + } + + // + // buffer contains no crc or data bytes + // + else if (CopyLen == (-2 & H_RX_LEN_MASK)) + { + // + // previous buffer had 2 crc bytes in it so remove them + // + as->len -= 2; + goto done_copy; + } + + } + + // + // if larger than max rx size throw away + // + if (CopyLen > IDP_MAX_RX_LEN) + { + // + // buffer to big so dump it + // + as->State = RX_BEGIN; + + as->MissCount++; + + RxTable->PPPReceiveError4++; + + /* mark as free now */ + as->tot = 0; + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: mtl: 0x%lx, RxToLarge: RxSize: %d, MissCount: %d\n", mtl, CopyLen, as->MissCount)); + goto done; + } + + as->len += CopyLen; + + if (as->len > MTL_MAC_MTU) + { + // + // Frame is to big so dump it + // + as->State = RX_BEGIN; + + RxTable->PPPReceiveError5++; + + as->MissCount++; + + /* mark as free now */ + as->tot = 0; + + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: AssembledRxToLarge: mtl: 0x%lx, AsRxSize: %d, MissCount: %d\n", mtl, as->len, as->MissCount)); + goto done; + } + + // + // copy the data to rx descriptor + // + IddGetDataFromAdapter(chan->idd, + (PUCHAR)as->DataPtr, + (PUCHAR)msg->bufptr, + CopyLen); + DigiDump( DIGIRXFRAGDATA, ("Recv Frag (PPP):\n") ); + DigiDumpData( DIGIRXFRAGDATA, + (PUCHAR)as->DataPtr, + CopyLen ); + +// NdisMoveMemory(as->DataPtr, msg->bufptr, CopyLen); + + // + // update data ptr + // + as->DataPtr += CopyLen; + + +done_copy: + if (!(FragmentFlags & H_RX_N_END)) + { + // + // if this is the end of the frame indicate to wrapper + // + as->State = RX_END; + + RxTable->NextFree++; + + QueueDescriptorForRxIndication(mtl, as); + + // + // mark this guy as being queued + // + as->Queued = 1; + } + +done: + /* release assembly descriptor */ + NdisReleaseSpinLock(&RxTable->lock); + } + else + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: Received IddFrameType: ??????!!!!!!\n")); + + // + // exit code + // release spinlock and return + // + exit_code: + + NdisReleaseSpinLock(&mtl->lock); +} + +VOID +IndicateRxToWrapper( + MTL *mtl + ) +{ + UCHAR *BufferPtr; + USHORT BufferLength = 0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ADAPTER *Adapter; + MTL_AS *as; + MTL_RX_TBL *RxTable; + + NdisAcquireSpinLock(&mtl->lock); + + Adapter = mtl->Adapter; + RxTable = &mtl->rx_tbl; + + while (!IsRxIndicationFifoEmpty(mtl)) + { + NdisAcquireSpinLock(&RxTable->lock); + + // + // get the next completed rx assembly + // + as = GetAssemblyFromRxIndicationFifo(mtl); + + if (!as) + { + D_LOG(DIGIMTL, ("IndicateRx: Got a NULL as from queue! mtl: 0x%lx\n", mtl)); + RxTable->IndicateReceiveError1++; + NdisReleaseSpinLock(&RxTable->lock); + goto exit_code; + } + + + // + // if this is an old ras frame then we must strip off + // the mac header Dst[6] + Src[6] + Length[2] + // + if (mtl->RecvFramingBits & RAS_FRAMING) + { + // + // pass over the mac header - tommyd does not want to see this + // + BufferPtr = as->buf + 14; + + // + // indicate with the size of the ethernet packet not the received size + // this takes care of the old driver that does padding on small frames + // + BufferLength = as->buf[12]; + BufferLength = BufferLength << 8; + BufferLength += as->buf[13]; + D_LOG(DIGIMTL, ("IndicateRxToWrapper: WrapperFrameType: RAS\n")); + D_LOG(DIGIMTL, ("IndicateRxToWrapper: BufPtr: 0x%lx, BufLen: %d\n", BufferPtr, BufferLength)); + } + else if (mtl->RecvFramingBits & PPP_FRAMING) + { + // + // the received buffer is the data that needs to be inidcated + // + BufferPtr = as->buf; + + // + // the received length is the length that needs to be indicated + // + BufferLength = as->len; + D_LOG(DIGIMTL, ("IndicateRxToWrapper: WrapperFrameType: PPP\n")); + D_LOG(DIGIMTL, ("IndicateRxToWrapper: BufPtr: 0x%lx, BufLen: %d\n", BufferPtr, BufferLength)); + } + else + { + // + // unknown framing - what to do what to do + // throw it away + // + D_LOG(DIGIMTL, ("IndicateRxToWrapper: mtl: 0x%lx, Unknown WrapperFramming: 0x%x\n", mtl, mtl->RecvFramingBits)); + RxTable->IndicateReceiveError2++; + as->tot = 0; + as->Queued = 0; + NdisReleaseSpinLock(&RxTable->lock); + goto exit_code; + } + + if (BufferLength > MTL_MAC_MTU) + { + D_LOG(DIGIMTL, ("IndicateRxToWrapper: mtl: 0x%lx, ReceiveLength > MAX ALLOWED (1514): RxLength: %d\n", mtl, as->len)); + RxTable->IndicateReceiveError3++; + as->tot = 0; + as->Queued = 0; + NdisReleaseSpinLock(&RxTable->lock); + goto exit_code; + } + + // + // send frame up + // + if (mtl->LinkHandle) + { + /* release assembly descriptor */ + NdisReleaseSpinLock(&RxTable->lock); + + NdisReleaseSpinLock(&mtl->lock); + + DigiDump( DIGIRXDATA, ("Indicating Recv Data:\n") ); + DigiDumpData( DIGIRXDATA, BufferPtr, BufferLength ); + + NdisMWanIndicateReceive(&Status, + Adapter->Handle, + mtl->LinkHandle, + BufferPtr, + BufferLength); + + NdisAcquireSpinLock(&mtl->lock); + + NdisAcquireSpinLock(&RxTable->lock); + + mtl->RecvCompleteScheduled = 1; + } + + + /* mark as free now */ + as->tot = 0; + + // + // mark this guy as being free + // + as->Queued = 0; + + /* release assembly descriptor */ + NdisReleaseSpinLock(&RxTable->lock); + } + + // + // exit code + // release spinlock and return + // + exit_code: + + NdisReleaseSpinLock(&mtl->lock); +} + +// +// this function checks all of the mtl's on this adapter to see if +// the protocols need to be given a chance to do some work +// +VOID +MtlRecvCompleteFunction( + ADAPTER *Adapter + ) +{ + ULONG n; + + for ( n = 0; n < MAX_MTL_PER_ADAPTER; n++) + { + MTL *mtl = Adapter->MtlTbl[n] ; + + // + // if this is a valid mtl + // + if (mtl) + { + // + // get lock for this mtl + // + NdisAcquireSpinLock(&mtl->lock); + + // + // is a receive complete scheduled on a valid link? + // + if (mtl->RecvCompleteScheduled && mtl->LinkHandle) + { + // + // release the lock + // + NdisReleaseSpinLock(&mtl->lock); + + NdisMWanIndicateReceiveComplete(Adapter->Handle, + mtl->LinkHandle); + + // + // reaquire the lock + // + NdisAcquireSpinLock(&mtl->lock); + + // + // clear the schedule flag + // + mtl->RecvCompleteScheduled = 0; + } + + // + // release the lock + // + NdisReleaseSpinLock(&mtl->lock); + } + } +} + +BOOLEAN +IsRxIndicationFifoEmpty( + MTL *mtl) +{ + BOOLEAN Ret = 0; + + NdisAcquireSpinLock(&mtl->RxIndicationFifo.lock); + + Ret = IsListEmpty(&mtl->RxIndicationFifo.head); + + NdisReleaseSpinLock(&mtl->RxIndicationFifo.lock); + + return(Ret); + +} + +MTL_AS* +GetAssemblyFromRxIndicationFifo( + MTL *mtl + ) +{ + MTL_AS *as = NULL; + + NdisAcquireSpinLock(&mtl->RxIndicationFifo.lock); + + if (!IsListEmpty(&mtl->RxIndicationFifo.head)) + as = (MTL_AS*)RemoveHeadList(&mtl->RxIndicationFifo.head); + + NdisReleaseSpinLock(&mtl->RxIndicationFifo.lock); + + return(as); +} + +VOID +QueueDescriptorForRxIndication( + MTL *mtl, + MTL_AS *as + ) +{ + NdisAcquireSpinLock(&mtl->RxIndicationFifo.lock); + + InsertTailList(&mtl->RxIndicationFifo.head, &as->link); + + NdisReleaseSpinLock(&mtl->RxIndicationFifo.lock); +} + +/* do timer tick processing for rx side */ +VOID +mtl__rx_tick(MTL *mtl) +{ + INT n; + MTL_AS *as; + MTL_RX_TBL *RxTable = &mtl->rx_tbl; + + // + // see if there are any receives to give to wrapper + // + IndicateRxToWrapper(mtl); + + NdisAcquireSpinLock(&mtl->lock); + + NdisAcquireSpinLock(&RxTable->lock); + + /* scan assembly table */ + for ( n = 0, as = RxTable->as_tbl ; n < MTL_RX_BUFS ; n++, as++ ) + { + /* update ttl & check */ + if ( as->tot && !(as->ttl -= 25) ) + { + D_LOG(DIGIMTL, ("mtl__rx_bchan_handler: Pkt Kill ttl = 0: Slot: %d, mtl: 0x%lx\n", n, mtl)); + + D_LOG(DIGIMTL, ("AS Timeout! mtl: 0x%lx, as: 0x%lx, as->seq: 0x%x\n", mtl, as, as->seq)); + D_LOG(DIGIMTL, ("as->tot: %d, as->num: %d", as->tot, as->num)); + + RxTable->TimeOutReceiveError1++; + + // + // if this guy was queued for indication to wrapper + // and was not indicated within a second something is wrong + // + if (as->Queued) + { + D_LOG(DIGIMTL, ("AS Timeout while queued for indication! mtl: 0x%lx, as: 0x%lx\n", mtl, as)); +#if DBG + DbgBreakPoint(); +#endif + } + + as->tot = 0; + + // + // mark this guy as being free + // + as->Queued = 0; + } + } + + NdisReleaseSpinLock(&RxTable->lock); + + NdisReleaseSpinLock(&mtl->lock); +} + +// +// see if there are any receives to give to wrapper +// +VOID +TryToIndicateMtlReceives( + ADAPTER *Adapter + ) +{ + ULONG n; + + for (n = 0; n < MAX_MTL_PER_ADAPTER; n++) + { + MTL *mtl = Adapter->MtlTbl[n]; + + if (mtl) + IndicateRxToWrapper(mtl); + } +} + diff --git a/private/ntos/ndis/digi/pcimac/mtl_set.c b/private/ntos/ndis/digi/pcimac/mtl_set.c new file mode 100644 index 000000000..66f0169d9 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mtl_set.c @@ -0,0 +1,228 @@ +/* + * MTL_SET.C - set routines for MTL object + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* set rx handler */ +mtl_set_rx_handler (VOID *mtl_1, VOID (*handler)(), VOID *handler_arg) +{ + MTL *mtl = (MTL*)mtl_1; + + D_LOG(D_ENTRY, ("mtl_set_rx_handler: entry, handler: 0x%lx, handler_arg: 0x%lx\n", \ + handler, handler_arg)); + + /* get lock, set, release & return */ + NdisAcquireSpinLock(&mtl->lock); + mtl->rx_handler = handler; + mtl->rx_handler_arg = handler_arg; + NdisReleaseSpinLock(&mtl->lock); + return(MTL_E_SUCC); +} + +/* set tx handler */ +mtl_set_tx_handler(VOID *mtl_1, VOID (*handler)(), VOID *handler_arg) +{ + MTL *mtl = (MTL*)mtl_1; + + D_LOG(D_ENTRY, ("mtl_set_tx_handler: entry, handler: 0x%lx, handler_arg: 0x%lx\n", \ + handler, handler_arg)); + + /* get lock, set, release & return */ + NdisAcquireSpinLock(&mtl->lock); + mtl->tx_handler = handler; + mtl->tx_handler_arg = handler_arg; + NdisReleaseSpinLock(&mtl->lock); + return(MTL_E_SUCC); +} + +/* set idd mtu */ +mtl_set_idd_mtu(VOID *mtl_1, USHORT mtu) +{ + MTL *mtl = (MTL*)mtl_1; + + D_LOG(D_ENTRY, ("mtl_set_idd_mtu: entry, mtu: 0x%x\n", mtu)); + + /* get lock, set, release & return */ + NdisAcquireSpinLock(&mtl->lock); + mtl->idd_mtu = mtu; + NdisReleaseSpinLock(&mtl->lock); + return(MTL_E_SUCC); +} + +/* set connection state */ +mtl_set_conn_state( + VOID *mtl_1, + USHORT NumberOfChannels, + BOOL is_conn) +{ + MTL *mtl = (MTL*)mtl_1; + ADAPTER *Adapter = mtl->Adapter; + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(0xffffffff, 0xffffffff); + + D_LOG(D_ENTRY, ("mtl_set_conn_state: entry, is_conn: %d\n", is_conn)); + + /* get lock, set, release & return */ + NdisAcquireSpinLock(&mtl->lock); + + mtl->is_conn = is_conn; + + // + // if we are being notified of a new connection we need to do some stuff + // + if (is_conn) + { + mtl->FramesXmitted = 0; + mtl->FramesReceived = 0; + mtl->BytesXmitted = 0; + mtl->BytesReceived = 0; + mtl->RecvFramingBits = 0; + mtl->tx_tbl.NextFree = 0; + mtl->rx_tbl.NextFree = 0; + } + NdisReleaseSpinLock(&mtl->lock); + + return(MTL_E_SUCC); +} + +/* get connection speed, add channels from chan_tbl */ +mtl_get_conn_speed(VOID *mtl_1, ULONG *speed) +{ + MTL *mtl = (MTL*)mtl_1; + USHORT n; + + D_LOG(D_ENTRY, ("mtl_get_conn_speed: entry, mtk: 0x%lx, @speed: 0x%lx\n", mtl, speed)); + + /* get lock, count, release */ + NdisAcquireSpinLock(&mtl->chan_tbl.lock); + for ( n = 0, *speed = 0 ; n < mtl->chan_tbl.num ; n++ ) + *speed += mtl->chan_tbl.tbl[n].speed; + NdisReleaseSpinLock(&mtl->chan_tbl.lock); + + D_LOG(D_EXIT, ("mtl_get_conn_speed: exit, speed: %ld bps\n", *speed)); + return(MTL_E_SUCC); +} + +/* get mac mtu on connection */ +mtl_get_mac_mtu(VOID *mtl_1, ULONG *mtu) +{ + MTL *mtl = (MTL*)mtl_1; + + D_LOG(D_ENTRY, ("mtl_get_mac_mtu: entry, mtl: 0x%lx, @mtu: 0x%lx\n", mtl, mtu)); + + *mtu = MTL_MAC_MTU; + + D_LOG(D_EXIT, ("mtl_get_mac_mtu: exit, mtu: %ld\n", *mtu)); + return(MTL_E_SUCC); +} + +/* add a channel to channel table */ +mtl_add_chan(VOID *mtl_1, VOID *idd, USHORT bchan, ULONG speed, ULONG ConnectionType) +{ + MTL *mtl = (MTL*)mtl_1; + INT ret = MTL_E_SUCC; + MTL_CHAN *chan; + INT n; + + D_LOG(D_ENTRY, ("mtl_add_chan: entry, mtl: 0x%lx, idd: 0x%lx, bchan: %d, speed: 0x%x\n", \ + mtl, idd, bchan, speed)); + + /* lock */ + NdisAcquireSpinLock(&mtl->chan_tbl.lock); + + /* check for space */ + if ( mtl->chan_tbl.num >= MAX_CHAN_PER_CONN ) + ret = MTL_E_NOROOM; + else + { + /* find free slot, MUST find! */ + for ( chan = mtl->chan_tbl.tbl, n = 0 ; n < MAX_CHAN_PER_CONN ; n++, chan++ ) + if ( !chan->idd ) + break; + if ( n >= MAX_CHAN_PER_CONN ) + { + D_LOG(DIGIMTL, ("mtl_add_chan: not free slot when num < MAX!\n")); + ret = MTL_E_NOROOM; + } + else + { + /* slot found, fill it */ + mtl->chan_tbl.num++; + + if (ConnectionType == CM_DKF) + { + mtl->IddTxFrameType = IDD_FRAME_DKF; + mtl->SendFramingBits = RAS_FRAMING; + } + else + { + mtl->IddTxFrameType = IDD_FRAME_PPP; + mtl->SendFramingBits = PPP_FRAMING; + } + + chan->idd = idd; + chan->bchan = bchan; + chan->speed = speed; + chan->mtl = mtl; + + /* add handler for slot */ + idd_attach(idd, bchan, (VOID*)mtl__rx_bchan_handler, chan); + } + } + + /* release & return */ + NdisReleaseSpinLock(&mtl->chan_tbl.lock); + D_LOG(D_EXIT, ("mtl_add_chan: exit, ret: %d\n", ret)); + return(ret); +} + +/* delete a channel from channel table */ +mtl_del_chan(VOID* mtl_1, VOID* idd, USHORT bchan) +{ + MTL *mtl = (MTL*)mtl_1; + INT ret = MTL_E_SUCC; + MTL_CHAN *chan; + INT n; + + D_LOG(D_ENTRY, ("mtl_del_chan: entry, mtl: 0x%lx, idd: 0x%lx, bchan: %d\n", \ + mtl, idd, bchan)); + + /* lock */ + NdisAcquireSpinLock(&mtl->chan_tbl.lock); + + /* scan table for a match */ + for ( chan = mtl->chan_tbl.tbl, n = 0 ; n < MAX_CHAN_PER_CONN ; n++, chan++ ) + if ( (chan->idd == idd) && (chan->bchan == bchan) ) + break; + + /* check for error */ + if ( n >= MAX_CHAN_PER_CONN ) + { + D_LOG(DIGIMTL, ("mtl_del_chan: channel not found!\n")); + ret = MTL_E_NOSUCH; + } + else + { + /* found, delete handler & mark free it */ + idd_detach(idd, bchan, (VOID*)mtl__rx_bchan_handler, chan); + chan->idd = NULL; + mtl->chan_tbl.num--; + } + + /* release & return */ + NdisReleaseSpinLock(&mtl->chan_tbl.lock); + D_LOG(D_EXIT, ("mtl_del_chan: exit, ret: %d\n", ret)); + return(ret); +} diff --git a/private/ntos/ndis/digi/pcimac/mtl_tick.c b/private/ntos/ndis/digi/pcimac/mtl_tick.c new file mode 100644 index 000000000..63b178fcf --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mtl_tick.c @@ -0,0 +1,47 @@ +/* + * MTL_TICK.C - tick (timer) processing for mtl + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* driver global vars */ +extern DRIVER_BLOCK Pcimac; + +// +// mtl polling function +// +// +/* tick process */ +VOID +MtlPollFunction(VOID *a1, ADAPTER *Adapter, VOID *a3, VOID *a4) +{ + ULONG n; + + for (n = 0; n < MAX_MTL_PER_ADAPTER; n++) + { + MTL *mtl = Adapter->MtlTbl[n]; + + if (mtl) + { + mtl__rx_tick(mtl); + + mtl__tx_tick(mtl); + + MtlRecvCompleteFunction(Adapter); + + MtlSendCompleteFunction(Adapter); + } + } + + NdisMSetTimer(&Adapter->MtlPollTimer, MTL_POLL_T); +} diff --git a/private/ntos/ndis/digi/pcimac/mtl_tx.c b/private/ntos/ndis/digi/pcimac/mtl_tx.c new file mode 100644 index 000000000..2d3089f9d --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mtl_tx.c @@ -0,0 +1,1092 @@ + /* + * MTL_TX.C - trasmit side processing for MTL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern DRIVER_BLOCK Pcimac; + +/* local prototypes */ +BOOLEAN IsWanPacketTxFifoEmpty(MTL*); +VOID AddToWanPacketTxFifo(MTL*, NDIS_WAN_PACKET*); +MTL_TX_PKT* GetLocalTxDescriptor(MTL*); +VOID FreeLocalTxDescriptor(MTL*, MTL_TX_PKT*); +VOID TryToXmitFrags(MTL*); +VOID SetTxDescriptorInWanPacket(MTL*,NDIS_WAN_PACKET*,MTL_TX_PKT*); +VOID CheckWanPacketTimeToLive(MTL *mtl); +VOID ReleaseTxDescriptor(MTL *mtl, MTL_TX_PKT *MtlTxPacket); + +#define IsWanPacketMarkedForCompletion(_WanPacket) \ + ((_WanPacket)->MacReserved2 == (PVOID)TRUE) + +#define ClearTxDescriptorInWanPacket(_WanPacket) \ + (_WanPacket)->MacReserved1 = (PVOID)NULL + +#define ClearReadyToCompleteInWanPacket(_WanPacket) \ + (_WanPacket)->MacReserved2 = (PVOID)NULL + +#define SetTimeToLiveInWanPacket(_WanPacket, _TimeOut) \ + (_WanPacket)->MacReserved3 = (PVOID)_TimeOut + +#define DecrementTimeToLiveForWanPacket(_WanPacket, _Decrement) \ + (ULONG)((_WanPacket)->MacReserved3) -= (ULONG)_Decrement + +#define GetWanPacketTimeToLive(_WanPacket) \ + (ULONG)((_WanPacket)->MacReserved3) + +#define GetTxDescriptorFromWanPacket(_WanPacket) \ + ((MTL_TX_PKT*)((_WanPacket)->MacReserved1)) + +#define MarkWanPacketForCompletion(_WanPacket) \ + (_WanPacket)->MacReserved2 = (PVOID)TRUE + +#define SetTxDescriptorInWanPacket(_WanPacket, _TxDescriptor) \ + (_WanPacket)->MacReserved1 = (PVOID)_TxDescriptor + +#define IncrementGlobalCount(_Counter) \ +{ \ + NdisAcquireSpinLock(&Pcimac.lock); \ + _Counter++; \ + NdisReleaseSpinLock(&Pcimac.lock); \ +} + +ULONG GlobalSends = 0; +ULONG GlobalSendsCompleted = 0; +ULONG MtlSends1 = 0; +ULONG MtlSends2 = 0; +ULONG MtlSends3 = 0; +ULONG MtlSends4 = 0; +ULONG MtlSends5 = 0; + +/* trasmit side timer tick */ +VOID +mtl__tx_tick(MTL *mtl) +{ + D_LOG(D_NEVER, ("mtl__tx_tick: entry, mtl: 0x%lx\n", mtl)); + + NdisAcquireSpinLock(&mtl->lock); + + // + // try to transmit frags to the adapter + // + TryToXmitFrags(mtl); + + // + // Check time to live on wan packet tx fifo + // + CheckWanPacketTimeToLive(mtl); + + NdisReleaseSpinLock(&mtl->lock); + +} + +VOID +MtlSendCompleteFunction( + ADAPTER *Adapter + ) +{ + ULONG n; + + for ( n = 0; n < MAX_MTL_PER_ADAPTER; n++) + { + MTL *mtl = Adapter->MtlTbl[n] ; + + if (mtl && !IsWanPacketTxFifoEmpty(mtl)) + { + // + // try to complete any wan packets ready for completion + // + IndicateTxCompletionToWrapper(mtl); + } + } +} + +// +// process a wan packet for transmition to idd level +// +// all packets will stay on one queue and the MacReserved fields will be used +// to indicate what state the packet is in +// +// we will use the MacReserved fields provided in the NdisWanPacket as follows: +// +// MacReserved1 - Store a pointer to our local tx descriptor +// MacReserved2 - This will be a boolean flag that will be set when this packet +// can be completed (NdisMWanSendComplete) +// MacReserved3 - This will be the time to live counter for the wanpacket. +// If it is not completed we will go ahead and complete it. +// +// MacReserved4 +// +VOID +mtl__tx_packet( + MTL *mtl, + NDIS_WAN_PACKET *WanPacket + ) +{ + UINT BytesLeftToTx, FragDataLength, FragNumber, FragSize; + UINT TotalPacketLength; + UCHAR *FragDataPtr; + MTL_TX_PKT *MtlTxPacket; + MTL_HDR MtlHeader; + USHORT TxFlags; + ADAPTER *Adapter = mtl->Adapter; + PUCHAR MyStartBuffer; + CM *cm = (CM*)mtl->cm; + + D_LOG(D_ENTRY, ("mtl_tx_packet: entry, mtl: 0x%lx, WanPacket: 0x%lx\n", mtl, WanPacket)); + + NdisAcquireSpinLock(&mtl->lock); + + IncrementGlobalCount(GlobalSends); + + // + // queue up the wanpacket + // + AddToWanPacketTxFifo(mtl, WanPacket); + + // + // get a local packet descriptor + // + MtlTxPacket = GetLocalTxDescriptor(mtl); + + // + // make sure this is a valid descriptor + // + if (!MtlTxPacket) + { + D_LOG(DIGIMTL, ("mtl__tx_proc: Got a NULL Packet off of Local Descriptor Free List\n")); + + // + // grab wan packet fifo lock + // + NdisAcquireSpinLock(&mtl->WanPacketFifo.lock); + + MarkWanPacketForCompletion(WanPacket); + + // + // release the wan packet fifo lock + // + NdisReleaseSpinLock(&mtl->WanPacketFifo.lock); + + goto exit_code; + } + + // + // grab wan packet fifo lock + // + NdisAcquireSpinLock(&mtl->WanPacketFifo.lock); + + SetTxDescriptorInWanPacket(WanPacket, MtlTxPacket); + + // + // release the wan packet fifo lock + // + NdisReleaseSpinLock(&mtl->WanPacketFifo.lock); + + // + // grab the descriptor lock + // + NdisAcquireSpinLock(&MtlTxPacket->lock); + + IncrementGlobalCount(MtlSends1); + + /* if not connected, give up */ + if ( !mtl->is_conn || cm->PPPToDKF) + { + D_LOG(DIGIMTL, ("mtl__tx_proc: packet on non-connected mtl, ignored\n")); + + IncrementGlobalCount(MtlSends2); + + goto xmit_error; + } + + D_LOG(DIGIMTL, ("mtl__tx_proc: LocalPkt: 0x%lx, WanPkt: 0x%lx, WanPktLen: %d\n", MtlTxPacket, WanPacket, WanPacket->CurrentLength)); + + // + // get length of wan packet + // + TotalPacketLength = WanPacket->CurrentLength; + + // + // my start buffer is WanPacket->CurrentBuffer - 14 + // + MyStartBuffer = WanPacket->CurrentBuffer - 14; + + if (mtl->SendFramingBits & RAS_FRAMING) + { + D_LOG(DIGIMTL, ("mtl__tx_proc: Transmit WrapperFrameType: RAS\n")); + + // add dest eaddr + // StartBuffer + 0 + // + NdisMoveMemory (MyStartBuffer + DST_ADDR_INDEX, + cm->DstAddr, + 6); + + // + // add source eaddr + // StartBuffer + 6 + // + NdisMoveMemory (MyStartBuffer + SRC_ADDR_INDEX, + cm->SrcAddr, + 6); + + // + // add new length to buffer + // StartBuffer + 12 + // + MyStartBuffer[12] = TotalPacketLength >> 8; + MyStartBuffer[13] = TotalPacketLength & 0xFF; + + // + // data now begins at MyStartBuffer + // + MtlTxPacket->frag_buf = MyStartBuffer; + + // + // new transmit length is a mac header larger + // + TotalPacketLength += 14; + } + else if (mtl->SendFramingBits & PPP_FRAMING) + { + D_LOG(DIGIMTL, ("mtl__tx_proc: Transmit WrapperFrameType: PPP\n")); + + // + // data now begins at CurrentBuffer + // + MtlTxPacket->frag_buf = WanPacket->CurrentBuffer; + } + else + { + // + // unknown framing - what to do what to do + // + D_LOG(DIGIMTL, ("mtl__tx_proc: Packet sent with uknown framing, ignored\n")); + + IncrementGlobalCount(MtlSends3); + + goto xmit_error; + } + + + if (TotalPacketLength > MTL_MAC_MTU) + { + D_LOG(DIGIMTL, ("mtl__tx_proc: packet too long, TotalPacketLength: %d\n", TotalPacketLength)); + + IncrementGlobalCount(MtlSends4); + + goto xmit_error; + } + + /* step 4: calc number of fragments */ + D_LOG(DIGIMTL, ("mtl__tx_proc: calc frag num, TotalPacketLength: %d\n", TotalPacketLength)); + + // + // Calculate the number of fragments per link given + // the size of data we can give the adapter. + // + MtlTxPacket->NumberOfFrags = (USHORT)(TotalPacketLength / mtl->chan_tbl.num / mtl->idd_mtu); + + if ( TotalPacketLength != (USHORT)(MtlTxPacket->NumberOfFrags * mtl->chan_tbl.num * mtl->idd_mtu) ) + MtlTxPacket->NumberOfFrags++; + + MtlTxPacket->NumberOfFrags *= mtl->chan_tbl.num; + + if ( MtlTxPacket->NumberOfFrags > MTL_MAX_FRAG ) + { + D_LOG(DIGIMTL, ("mtl__tx_proc: pkt has too many frags, NumberOfFrags: %d\n", \ + MtlTxPacket->NumberOfFrags)); + + IncrementGlobalCount(MtlSends5); + + goto xmit_error; + } + + D_LOG(DIGIMTL, ("mtl__tx_proc: NumberOfFrags: %d\n", MtlTxPacket->NumberOfFrags)); + + /* step 5: build generic header */ + if (mtl->IddTxFrameType & IDD_FRAME_DKF) + { + MtlHeader.sig_tot = MtlTxPacket->NumberOfFrags | 0x50; + MtlHeader.seq = (UCHAR)(mtl->tx_tbl.seq++); + MtlHeader.ofs = 0; + } + + /* step 6: build fragments */ + + // + // bytes left to send is initially the packet size + // + BytesLeftToTx = TotalPacketLength; + + // + // FragDataPtr initially points to begining of frag buffer + // + FragDataPtr = MtlTxPacket->frag_buf; + + // + // initial txflags are for a complete frame + // + TxFlags = 0; + + for ( FragNumber = 0 ; FragNumber < MtlTxPacket->NumberOfFrags ; FragNumber++ ) + { + MTL_TX_FRAG *FragPtr = &MtlTxPacket->frag_tbl[FragNumber]; + IDD_MSG *FragMsg = &FragPtr->frag_msg; + MTL_CHAN *chan; + + /* if it's first channel, establish next fragment size */ + if ( !(FragNumber % mtl->chan_tbl.num) ) + FragSize = MIN((BytesLeftToTx / mtl->chan_tbl.num), mtl->idd_mtu); + + /* establish related channel */ + chan = mtl->chan_tbl.tbl + (FragNumber % mtl->chan_tbl.num); + + /* calc size of this fragment */ + if ( FragNumber == (USHORT)(MtlTxPacket->NumberOfFrags - 1) ) + FragDataLength = BytesLeftToTx; + else + FragDataLength = FragSize; + + D_LOG(DIGIMTL, ("mtl__proc_tx: FragNumber: %d, FragDataPtr: 0x%lx, FragLength: %d\n", \ + FragNumber, FragDataPtr, FragDataLength)); + + if (mtl->IddTxFrameType & IDD_FRAME_DKF) + { + DKF_FRAG *DkfFrag = &FragPtr->DkfFrag; + IDD_FRAG *IddFrag0 = &DkfFrag->IddFrag[0]; + IDD_FRAG *IddFrag1 = &DkfFrag->IddFrag[1]; + + D_LOG(DIGIMTL, ("mtl__tx_proc: Transmit IddFrameType: DKF\n")); + + // + // setup fragment descriptor for DKF data + // + /* setup fragment header */ + DkfFrag->MtlHeader = MtlHeader; + + /* set pointer to header */ + IddFrag0->len = sizeof(MTL_HDR); + IddFrag0->ptr = (CHAR*)(&DkfFrag->MtlHeader); + + /* set pointer to data */ + IddFrag1->len = FragDataLength; + IddFrag1->ptr = FragDataPtr; + + // + // fill idd message + // + FragMsg->buflen = sizeof(DKF_FRAG) | TX_FRAG_INDICATOR; + + // + // this assumes that the DKF_FRAG structure is the first + // member of the MTL_TX_FRAG structure !!!!! + // + FragMsg->bufptr = (UCHAR*)FragPtr; + } + else + { + D_LOG(DIGIMTL, ("mtl__tx_proc: Transmit IddFrameType: PPP\n")); + // + // setup fragment descriptor for ppp frame + // + + if (BytesLeftToTx <= mtl->idd_mtu ) + { + // + // if all that is left can be sent this is the end + // + FragMsg->buflen = FragDataLength | TxFlags; + } + else + { + // + // if there is still more this is not end + // + FragMsg->buflen = FragDataLength | TxFlags | H_TX_N_END; + } + + // + // setup data pointer + // + FragMsg->bufptr = (UCHAR*)FragDataPtr; + } + + FragPtr->FragSent = 0; + FragPtr->frag_idd = chan->idd; + FragPtr->frag_bchan = chan->bchan; + FragPtr->frag_arg = MtlTxPacket; + + /* update variables */ + TxFlags = H_TX_N_BEG; + BytesLeftToTx -= FragDataLength; + FragDataPtr += FragDataLength; + MtlHeader.ofs += FragDataLength; + } + /* step 7: setup more fields */ + MtlTxPacket->WanPacket = WanPacket; + MtlTxPacket->FragReferenceCount = MtlTxPacket->NumberOfFrags; + MtlTxPacket->mtl = mtl; + MtlTxPacket->NumberOfFragsSent = 0; + + mtl->FramesXmitted++; + mtl->BytesXmitted += TotalPacketLength; + + // + // release the lock befor xmitting + // + NdisReleaseSpinLock(&MtlTxPacket->lock); + + // + // put this tx descriptor on list for transmition + // + NdisAcquireSpinLock(&mtl->tx_tbl.lock); + + InsertTailList(&mtl->tx_tbl.head, &MtlTxPacket->TxPacketQueue); + + NdisReleaseSpinLock(&mtl->tx_tbl.lock); + + // + // Try to xmit some frags + // + TryToXmitFrags(mtl); + + goto exit_code; + + // + // error while setting up for transmition + // + xmit_error: + + ClearTxDescriptorInWanPacket(WanPacket); + + // + // free tx descriptor + // + FreeLocalTxDescriptor(mtl, MtlTxPacket); + + // + // free descriptors lock + // + NdisReleaseSpinLock(&MtlTxPacket->lock); + + // + // grab wan packet fifo lock + // + NdisAcquireSpinLock(&mtl->WanPacketFifo.lock); + + // + // mark wan packet for completion + // + MarkWanPacketForCompletion(WanPacket); + + // + // release the wan packet fifo lock + // + NdisReleaseSpinLock(&mtl->WanPacketFifo.lock); + + // + // exit code + // release spinlock and return + // + exit_code: + + NdisReleaseSpinLock(&mtl->lock); +} + +// +// Try to transmit fragments to idd +// +VOID +TryToXmitFrags( + MTL *mtl + ) +{ + LIST_ENTRY *MtlTxPacketQueueHead; + MTL_TX_TBL *MtlTxTbl = &mtl->tx_tbl; + MTL_TX_PKT *MtlTxPacket; + ULONG Ret = IDD_E_SUCC; + BOOLEAN WeCanXmit = 1; + + // + // get tx table spin lock + // + NdisAcquireSpinLock(&MtlTxTbl->lock); + + MtlTxPacketQueueHead = &MtlTxTbl->head; + + // + // while we can still transmit and we are not at the end of the list + // + while (WeCanXmit && !IsListEmpty(MtlTxPacketQueueHead)) + { + USHORT n, NumberOfFragsToSend; + + MtlTxPacket = (MTL_TX_PKT*)MtlTxPacketQueueHead->Flink; + + // + // get the number of frags we will try to send + // + NdisAcquireSpinLock(&MtlTxPacket->lock); + + NumberOfFragsToSend = MtlTxPacket->NumberOfFrags; + + NdisReleaseSpinLock(&MtlTxPacket->lock); + + for (n = 0; n < NumberOfFragsToSend; n++) + { + MTL_TX_FRAG *FragToSend; + + NdisAcquireSpinLock(&MtlTxPacket->lock); + + FragToSend = &MtlTxPacket->frag_tbl[n]; + + NdisReleaseSpinLock(&MtlTxPacket->lock); + + // + // if this frag has already been sent get the next one + // + if (FragToSend->FragSent) + continue; + + D_LOG(DIGIMTL, ("TryToXmitFrag: mtl: 0x%x\n", mtl)); + D_LOG(DIGIMTL, ("Next Packet To Xmit: MtlTxPacket: 0x%x\n", MtlTxPacket)); + D_LOG(DIGIMTL, ("Xmitting Packet: MtlTxPacket: 0x%x\n", MtlTxPacket)); + D_LOG(DIGIMTL, ("TryToXmitFrag: FragToSend: 0x%x\n", FragToSend)); + D_LOG(DIGIMTL, ("TryToXmitFrag: Idd: 0x%x, Msg: 0x%x, Bchan: 0x%x, Arg: 0x%x\n", \ + FragToSend->frag_idd, &FragToSend->frag_msg, \ + FragToSend->frag_bchan, FragToSend->frag_arg)); + + // + // Something was ready to send + // release all locks before sending + // + NdisReleaseSpinLock(&MtlTxTbl->lock); + + Ret = idd_send_msg(FragToSend->frag_idd, + &FragToSend->frag_msg, + FragToSend->frag_bchan, + (VOID*)mtl__tx_cmpl_handler, + FragToSend->frag_arg); + + // + // acquire Tx Tbl fifo lock + // exit code expects the lock to be held + // + NdisAcquireSpinLock(&MtlTxTbl->lock); + + if (Ret == IDD_E_SUCC) + { + // + // this means frag was sent to idd + // all locks will be released before next frag is sent + // + + // + // acquire descriptor lock + // exit code expects the lock to be held + // + NdisAcquireSpinLock(&MtlTxPacket->lock); + + // + // message was queued or sent! + // + MtlTxPacket->NumberOfFragsSent++; + + FragToSend->FragSent++; + + if (MtlTxPacket->NumberOfFragsSent == MtlTxPacket->NumberOfFrags) + { + // + // if things are working ok this guy will be on top + // + ASSERT((PVOID)MtlTxPacketQueueHead->Flink == (PVOID)MtlTxPacket); + + // + // take a guy off of the to be transmitted list + // + RemoveEntryList(&MtlTxPacket->TxPacketQueue); + } + + // + // release the lock for this descriptor + // + NdisReleaseSpinLock(&MtlTxPacket->lock); + } + else + { + // + // if this frag is not sent to idd + // then stop xmitting + // + WeCanXmit = 0; + } + } + + } + + // + // release the tx tbl fifo lock + // + NdisReleaseSpinLock(&MtlTxTbl->lock); +} + +/* trasmit completion routine */ +VOID +mtl__tx_cmpl_handler( + MTL_TX_PKT *MtlTxPacket, + USHORT port, + IDD_MSG *msg + ) +{ + MTL *mtl; + PNDIS_WAN_PACKET WanPacket; + + D_LOG(D_ENTRY, ("mtl__tx_cmpl_handler: entry, MtlTxPacket: 0x%lx, port: %d, msg: 0x%lx\n", \ + MtlTxPacket, port, msg)); + + NdisAcquireSpinLock(&MtlTxPacket->lock); + + mtl = MtlTxPacket->mtl; + + // + // if this guy was set free from a disconnect while he was + // on the idd tx queue. Just throw him away! + // if this is not the last reference to the packet get the hell out!!! + // + if (!MtlTxPacket->InUse || --MtlTxPacket->FragReferenceCount ) + { + NdisReleaseSpinLock(&MtlTxPacket->lock); + return; + } + + D_LOG(DIGIMTL, ("mtl__tx_cmpl_handler: FragReferenceCount==0, mtl: 0x%lx\n", mtl)); + + // + // Get hold of PNDIS_WAN_PACKET associated with this descriptor + // + WanPacket = MtlTxPacket->WanPacket; + + if (!WanPacket) + { + ASSERT(WanPacket); + NdisReleaseSpinLock(&MtlTxPacket->lock); + return; + } + + ClearTxDescriptorInWanPacket(WanPacket); + + // + // return local packet descriptor to free list + // + FreeLocalTxDescriptor(mtl, MtlTxPacket); + + NdisReleaseSpinLock(&MtlTxPacket->lock); + + // + // grab wan packet fifo lock + // + NdisAcquireSpinLock(&mtl->WanPacketFifo.lock); + + // + // mark wan packet as being ready for completion + // + MarkWanPacketForCompletion(WanPacket); + + // + // release the wan packet fifo lock + // + NdisReleaseSpinLock(&mtl->WanPacketFifo.lock); +} + +// +// get a local packet descriptor off of the free list +// +MTL_TX_PKT* +GetLocalTxDescriptor( + MTL *mtl + ) +{ + MTL_TX_PKT* FreePkt = NULL; + MTL_TX_TBL* TxTbl = &mtl->tx_tbl; + + NdisAcquireSpinLock (&mtl->tx_tbl.lock); + + // + // get next available freepkt + // + FreePkt = TxTbl->TxPacketTbl + (TxTbl->NextFree % MTL_TX_BUFS); + + // + // if still in use we have a wrap + // + if (FreePkt->InUse) + { + ASSERT(!FreePkt->InUse); + NdisReleaseSpinLock (&mtl->tx_tbl.lock); + return(NULL); + } + + // + // mark as being used + // + FreePkt->InUse = 1; + + // + // bump pointer to next free + // + TxTbl->NextFree++; + + NdisReleaseSpinLock (&mtl->tx_tbl.lock); + + return(FreePkt); +} + +// +// return a local packet descriptor to free pool +// assumes that the MtlTxPacket lock is held +// +VOID +FreeLocalTxDescriptor( + MTL *mtl, + MTL_TX_PKT *MtlTxPacket + ) +{ + + ASSERT(MtlTxPacket->InUse); + + MtlTxPacket->InUse = 0; + + MtlTxPacket->WanPacket = NULL; +} + +// +// see if wan packet fifo is empty +// +BOOLEAN +IsWanPacketTxFifoEmpty( + MTL *mtl + ) +{ + BOOLEAN Result; + + NdisAcquireSpinLock (&mtl->WanPacketFifo.lock); + + Result = IsListEmpty(&mtl->WanPacketFifo.head); + + NdisReleaseSpinLock (&mtl->WanPacketFifo.lock); + + return(Result); +} + +// +// add a wan packet to the wan packet fifo +// +VOID +AddToWanPacketTxFifo( + MTL *mtl, + NDIS_WAN_PACKET *WanPacket + ) +{ + MTL_WANPACKET_FIFO *WanPacketFifo = &mtl->WanPacketFifo; + PLIST_ENTRY TempQueue; + + D_LOG(D_ENTRY, ("AddToWanPacketTxFifo: mtl: 0x%x, head: 0x%x\n", mtl, WanPacketFifo->head)); + + NdisAcquireSpinLock (&WanPacketFifo->lock); + + // + // We do a little consistency check and make sure we don't have + // have this wan packet allready on the queue. + // + TempQueue = &WanPacketFifo->head; + +#if DBG + while( TempQueue->Flink != &WanPacketFifo->head ) + { + NDIS_WAN_PACKET *TempWanPacket; + TempWanPacket = CONTAINING_RECORD( TempQueue->Flink, + NDIS_WAN_PACKET, + WanPacketQueue ); + + ASSERT( TempWanPacket != NULL ); + + ASSERT( TempWanPacket != WanPacket ); + + TempQueue = TempQueue->Flink; + } +#endif + + ClearReadyToCompleteInWanPacket(WanPacket); + + SetTimeToLiveInWanPacket(WanPacket, 5000); + + ClearTxDescriptorInWanPacket(WanPacket); + + InsertTailList(&WanPacketFifo->head, &WanPacket->WanPacketQueue); + + WanPacketFifo->Count++; + + if (WanPacketFifo->Count > WanPacketFifo->Max) + WanPacketFifo->Max = WanPacketFifo->Count; + + NdisReleaseSpinLock (&WanPacketFifo->lock); +} + +// +// indicate xmit completion of wan packet to wrapper +// +VOID +IndicateTxCompletionToWrapper( + MTL *mtl + ) +{ + ADAPTER *Adapter = (ADAPTER*)mtl->Adapter; + NDIS_WAN_PACKET *WanPacket; + LIST_ENTRY *WanPacketFifoHead; + MTL_WANPACKET_FIFO *WanPacketFifo = &mtl->WanPacketFifo; + + // + // acquire wan packet fifo lock + // + NdisAcquireSpinLock(&WanPacketFifo->lock); + + // + // get head of wan packet fifo + // + WanPacketFifoHead = &WanPacketFifo->head; + + // + // visit the first packet on the tx list + // + WanPacket = (NDIS_WAN_PACKET*)WanPacketFifoHead->Flink; + + // + // if the list is not empty and this packet is ready to be completed + // + while (((PVOID)WanPacket != (PVOID)WanPacketFifoHead) && + IsWanPacketMarkedForCompletion(WanPacket)) + { + + WanPacket = (PNDIS_WAN_PACKET)RemoveHeadList(&WanPacketFifo->head); + + WanPacketFifo->Count--; + + if (!WanPacket) + break; + + IncrementGlobalCount(GlobalSendsCompleted); + + ClearReadyToCompleteInWanPacket(WanPacket); + + // + // release wan packet fifo lock + // + NdisReleaseSpinLock(&WanPacketFifo->lock); + + NdisMWanSendComplete(Adapter->Handle, WanPacket, NDIS_STATUS_SUCCESS); + + // + // acquire wan packet fifo lock + // + NdisAcquireSpinLock(&WanPacketFifo->lock); + + // + // visit the new head of the list + // + WanPacket = (NDIS_WAN_PACKET*)WanPacketFifoHead->Flink; + } + + // + // release wan packet fifo lock + // + NdisReleaseSpinLock(&WanPacketFifo->lock); +} + +VOID +MtlFlushWanPacketTxQueue( + MTL *mtl + ) +{ + LIST_ENTRY *WanPacketFifoHead; + MTL_WANPACKET_FIFO *WanPacketFifo = &mtl->WanPacketFifo; + NDIS_WAN_PACKET *WanPacket; + MTL_TX_PKT *MtlTxPacket; + + // + // acquire wan packet fifo lock + // + NdisAcquireSpinLock(&WanPacketFifo->lock); + + // + // get head of wan packet fifo + // + WanPacketFifoHead = &WanPacketFifo->head; + + // + // visit the first packet on the tx list + // + WanPacket = (NDIS_WAN_PACKET*)WanPacketFifoHead->Flink; + + // + // if the wan packet queue is not empty + // we need to drain it! + // + while ((PVOID)WanPacket != (PVOID)WanPacketFifoHead) + { + // + // get the associated MtlTxPacket + // + if (MtlTxPacket = GetTxDescriptorFromWanPacket(WanPacket)) + ReleaseTxDescriptor(mtl, MtlTxPacket); + + // + // mark wan packet for completion + // + MarkWanPacketForCompletion(WanPacket); + + // + // get the next packet on the list + // + WanPacket = (NDIS_WAN_PACKET*)(WanPacket->WanPacketQueue).Flink; + } + + // + // release wan packet fifo lock + // + NdisReleaseSpinLock(&WanPacketFifo->lock); +} + +// +// walk through the WanPacketFifo and see if anyone has been sitting there +// too long! This could happen if there was some kind of xmit failure to +// the adapter. +// +VOID +CheckWanPacketTimeToLive( + MTL *mtl + ) +{ + LIST_ENTRY *WanPacketFifoHead; + MTL_WANPACKET_FIFO *WanPacketFifo = &mtl->WanPacketFifo; + NDIS_WAN_PACKET *WanPacket; +// MTL_TX_PKT *MtlTxPacket; + + // + // acquire wan packet fifo lock + // + NdisAcquireSpinLock(&WanPacketFifo->lock); + + // + // get head of wan packet fifo + // + WanPacketFifoHead = &WanPacketFifo->head; + + // + // visit the first packet on the tx list + // + WanPacket = (NDIS_WAN_PACKET*)WanPacketFifoHead->Flink; + + // + // if the wan packet is not empty + // + while ((PVOID)WanPacket != (PVOID)WanPacketFifoHead) + { + + // + // decrement the count by 25ms + // + DecrementTimeToLiveForWanPacket(WanPacket, 25); + + // + // if the count has gone to zero this guy has + // been waiting for more then 1sec so complete him + // + if (!GetWanPacketTimeToLive(WanPacket)) + { + +// if (IsWanPacketMarkedForCompletion(WanPacket)) +// DbgPrint("PCIMAC.SYS: WanPacket was already marked for completion!\n"); +// +// // +// // get the associated MtlTxPacket and free +// // +// if (MtlTxPacket = GetTxDescriptorFromWanPacket(WanPacket)) +// ReleaseTxDescriptor(mtl, MtlTxPacket); +// +// // +// // mark the packet for completion +// // +// MarkWanPacketForCompletion(WanPacket); + } + + // + // get the next packet on the list + // + WanPacket = (NDIS_WAN_PACKET*)(WanPacket->WanPacketQueue).Flink; + } + + // + // release wan packet fifo lock + // + NdisReleaseSpinLock(&WanPacketFifo->lock); +} + +VOID +ReleaseTxDescriptor( + MTL *mtl, + MTL_TX_PKT *MtlTxPacket + ) +{ + LIST_ENTRY *MtlTxPacketQueueHead; + MTL_TX_TBL *MtlTxTbl = &mtl->tx_tbl; + MTL_TX_PKT *NextMtlTxPacket; + + // + // act like this local descriptor was sent + // keeps desriptor table pointers in line + // + NdisAcquireSpinLock(&MtlTxTbl->lock); + + MtlTxPacketQueueHead = &MtlTxTbl->head; + + // + // get the descriptor lock + // + NdisAcquireSpinLock(&MtlTxPacket->lock); + + // + // visit the first packet on the list + // + NextMtlTxPacket = (MTL_TX_PKT*)MtlTxPacketQueueHead->Flink; + + // + // break if the list has been traversed or if we find the packet + // + while (((PVOID)NextMtlTxPacket != MtlTxPacketQueueHead) && (NextMtlTxPacket != MtlTxPacket)) + NextMtlTxPacket = (MTL_TX_PKT*)(NextMtlTxPacket->TxPacketQueue).Flink; + + // + // if this descriptor is marked for transmition + // we should remove it from the tx descriptor list + // + if (NextMtlTxPacket == MtlTxPacket) + RemoveEntryList(&MtlTxPacket->TxPacketQueue); + + FreeLocalTxDescriptor(mtl, MtlTxPacket); + + NdisReleaseSpinLock(&MtlTxPacket->lock); + + NdisReleaseSpinLock(&MtlTxTbl->lock); +} diff --git a/private/ntos/ndis/digi/pcimac/mydefs.h b/private/ntos/ndis/digi/pcimac/mydefs.h new file mode 100644 index 000000000..aa36f8241 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mydefs.h @@ -0,0 +1,376 @@ +#ifndef _MYDEFS_ +#define _MYDEFS_ + +// +// maximum number of idd's per adapter +// this is one pcimac/4 adapter +// +#define MAX_IDD_PER_ADAPTER 4 + +// +// maximum number of conection objects per adapter +// this is one for each bchannel of a pcimac/4 +// +#define MAX_CM_PER_ADAPTER 8 + +// maximum number of mtl objects per adapter +// this is one for each bchannel of a pcimac/4 +// +#define MAX_MTL_PER_ADAPTER 8 + +// +// number of adapters in system +// +#define MAX_ADAPTERS_IN_SYSTEM 8 + +// +// maximum number of idd's in system +// this is 5 pcimac/4 adapters +// +#define MAX_IDD_IN_SYSTEM 20 + +// +// maximum number of connection objects +// in system +// this is 5 pcimac/4 adpaters with a +// connection object for each bchannel +// +#define MAX_CM_IN_SYSTEM 40 + +// +// maximum number of mtl objects +// in system +// this is 5 pcimac/4 adpaters with a +// connection object for each bchannel +// +#define MAX_MTL_IN_SYSTEM 40 + +// +// maximum number of cm channel objects +// in system +// this is 5 pcimac/4 adpaters with a +// connection object for each bchannel +// +#define MAX_CHAN_IN_SYSTEM 40 + +// +// maximum number of calls that can be made on +// single line +// +//#define MAX_CALL_PER_LINE 2 +#define MAX_CALL_PER_LINE 1 + +// +// maximum number of channels supported by an idd +// +#define MAX_CHANNELS_PER_IDD 2 + +// +// maximum number of channels supported by an idd +// +#define MAX_LTERMS_PER_IDD 2 + +#define MAX_WANPACKET_XMITS 3 +#define MAX_WANPACKET_BUFFERSIZE 1500 +#define MAX_WANPACKET_HEADERPADDING 14 +#define MAX_WANPACKET_TAILPADDING 0 + +// +// connection data type's +// +#define CM_PPP 0 +#define CM_DKF 1 + +// +// maximum number of channels allowed in a single connection +// +#define MAX_CHAN_PER_CONN 8 + +// +// defines for adapter boardtypes +// +#define IDD_BT_PCIMAC 0 /* - ISA, single channel */ +#define IDD_BT_PCIMAC4 1 /* - ISA, four channel */ +#define IDD_BT_MCIMAC 2 /* - MCA, single channel */ +#define IDD_BT_DATAFIREU 3 /* - ISA/U, single channel */ +#define IDD_BT_DATAFIREST 4 /* - ISA/ST, single channel */ +#define IDD_BT_DATAFIRE4ST 5 /* - ISA/ST, four channel */ + +// +// Send window size +// +#define ISDN_WINDOW_SIZE 10 + +// +// Ndis Version Info +// +#define NDIS_MAJOR_VER 0x03 +#define NDIS_MINOR_VER 0x00 + +// +// OID Switch +// +#define OID_GEN_INFO 0x00000000 +#define OID_8023_INFO 0x01000000 +#define OID_WAN_INFO 0x04000000 +#define OID_TAPI_INFO 0x07000000 + +// +// idd polling timer value +// +#define IDD_POLL_T 25 // 25ms polling frequency (msec) + +// +// cm polling timer +// +#define CM_POLL_T 1000 /* 1 second timer */ + +// +// mtl polling timer +// +#define MTL_POLL_T 25 // 25 ms timer + +// +// flag to indicate this is not a beginning buffer +// +#define H_TX_N_BEG 0x8000 +#define H_RX_N_BEG 0x8000 + +// +// flag to indicate this is not an ending buffer +// +#define H_TX_N_END 0x4000 +#define H_RX_N_END 0x4000 + +// +// flag to cause an immediate send of queued tx buffers +// +#define H_TX_FLUSH 0x2000 + +// +// masks off tx flags to leave the tx length +// +#define H_TX_LEN_MASK 0x01FF +#define H_RX_LEN_MASK 0x01FF + +// +// mask off length leaving rx flags +// +#define RX_FLAG_MASK 0xF000 + +// +// mask off length and fragment indicator leaving tx flags +// +#define TX_FLAG_MASK 0xE000 + +// +// indicator that this tx is actually a fragment +// +#define TX_FRAG_INDICATOR 0x1000 + +// +// states for receive ppp state machine +// +#define RX_BEGIN 0 +#define RX_MIDDLE 1 +#define RX_END 2 + +#ifdef DBG +// +// states for tx ppp state machine +// +#define TX_BEGIN 0 +#define TX_MIDDLE 1 +#define TX_END 2 +#endif + +// +// idp tx and rx lengths +// +#define IDP_MAX_TX_LEN 280 +#define IDP_MAX_RX_LEN 280 + +// +// Idd frame type defines +// +#define IDD_FRAME_PPP 1 /* raw hdlc frames */ +#define IDD_FRAME_DKF 2 /* dror encapsulated frames */ +#define IDD_FRAME_DONTCARE 4 /* No data can pass yet */ +#define IDD_FRAME_DETECT 8 /* detect bchannel framing */ + +// +// ADP Stuff +// + +// +// ADP Register Defines +// +#define ADP_REG_ID 0 +#define ADP_REG_CTRL 1 +#define ADP_REG_ADDR_LO 2 +#define ADP_REG_ADDR_MID 3 +#define ADP_REG_ADDR_HI 4 +#define ADP_REG_DATA 5 +#define ADP_REG_DATA_INC 6 +#define ADP_REG_RESERVE1 7 // Currently unused. +#define ADP_REG_ADAPTER_CTRL 8 + +// +// ADP_REG_ID Bits +// +#define ADP_BT_ADP1 0xA1 +#define ADP_BT_ADP4 0xA4 + +// +// ADP_REG_CTRL Bits +// +#define ADP_RESET_BIT 0x80 // R/W 1 - Holds Adapter in reset +#define ADP_PIRQ_BIT 0x40 // R 1 - Adapter to PC Interrupt Active + // W 1 - Clear Adapter to PC Interrupt +#define ADP_AIRQ_BIT 0x20 // W 1 - PC to Adapter Interrupt Active + // R 0 - PC to Adapter Interrupt seen +#define ADP_HLT_BIT 0x10 // R/W 1 - Holds Adapter in halt +#define ADP_PIRQEN_BIT 0x08 // R/W 1 - Enables Adapter to PC Interrupt +#define ADP_INT_SEL_BITS 0x07 // R/W Adapter to PC Interrupt select + // Code IRQ + // 000 0 (Disabled) + // 001 3 + // 010 5 + // 011 7 + // 100 10 + // 101 11 + // 110 12 + // 111 15 + +// +// ADP_REG_ADDR_LO Bits +// +// R/W Adapter Memory Address Bits A0..A7 + +// +// ADP_REG_ADDR_MID Bits +// +// R/W Adapter Memory Address Bits A8..A15 + +// +// ADP_REG_ADDR_HI Bits +// +// R/W Adapter Memory Address Bits A16..A23 + +// +// ADP_REG_DATA Bits +// +// R/W Adapter Memory Data Bits D0..D7 +// The 24 bit adapter memory address pointer remains constant +// after each access to the data register. + +// +// ADP_REG_DATA_INC Bits +// +// R/W Adapter Memory Data Bits D0..D7 +// The 24 bit adapter memory address pointer increments by one +// after each access to the data register. + +// +// ADP_REG_ADAPTER_CTRL Bits +// +// The Adapter Control Register is used by the host to determine IRQL +// status and select a specific channel. +// +#define ADP_CSEL_BITS 0x03 // R/W Channel select bits + // 00 - select channel 0 + // 01 - select channel 1 + // 10 - select channel 2 + // 11 - select channel 3 +#define ADP_ADAPTER_PIRQL 0xF0 // R replica of the IRQ lines from all + // four channel. They are provided + // for quick reference and can only + // be cleared by accessing the Channel + // Control Register. + +// +// Maxium Adapter RAM Size +// +#define ADP_RAM_SIZE 0x40000L + +// +// Offset to message to PC pending status windows +// +#define ADP_STS_WINDOW 0x500L + +// +// Offset to PC to adapter command window +// +#define ADP_CMD_WINDOW 0x510L + +// +// Offset to adapter enviornment window +// +#define ADP_ENV_WINDOW 0x540L + +// +// Offset to adapter NVRAM window (copy in adapter memory) +// +#define ADP_NVRAM_WINDOW 0x940L + +// +// some Adp bin file stuff +// +#define ADP_BIN_BLOCK_SIZE 256 +#define ADP_BIN_FORMAT 1 + +// +// Adp Status +// +typedef struct +{ + UCHAR ReceiveStatus; // 0 + UCHAR Reserved1; // 1 + UCHAR MajorVersion; // 2 + UCHAR MinorVersion; // 3 + ULONG HeartBeat; // 4 + ULONG IdleCount; // 8 + USHORT AbortReason; // 12 + USHORT SpuriousInterrupt; // 14 +} ADP_STATUS; + +// +// Adp bin file header +// +typedef struct +{ + USHORT Format; + USHORT BlockCount; + ULONG ImageSize; +}ADP_BIN_HEADER; + +// +// Adp bin file data block +// +typedef struct +{ + ULONG Address; + UCHAR Data[ADP_BIN_BLOCK_SIZE]; +}ADP_BIN_BLOCK; + +// +// NVRAM stuff +// +#define ADP_NVRAM_MAX 64 + +typedef struct +{ + USHORT NVRamImage[ADP_NVRAM_MAX]; +}ADP_NVRAM; + +// +// IDP Stuff +// + +#define IDP_STS_WINDOW 0x800 +#define IDP_CMD_WINDOW 0x810 +#define IDP_ENV_WINDOW 0x910 +#define IDP_RAM_PAGE_SIZE 0x4000 + +#endif /* _MYTYPES_ */ + diff --git a/private/ntos/ndis/digi/pcimac/mytypes.h b/private/ntos/ndis/digi/pcimac/mytypes.h new file mode 100644 index 000000000..c54295e4f --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/mytypes.h @@ -0,0 +1,39 @@ +#ifndef _MYTYPES_ +#define _MYTPYES_ + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef DWORD +typedef ULONG DWORD; +#endif + +#ifndef WORD +typedef USHORT WORD; +#endif + +#ifndef BYTE +typedef UCHAR BYTE; +#endif + +#ifndef NOMINMAX + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#endif /* NOMINMAX */ + +#define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8)) +#define MAKELONG(a, b) ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16)) +#define LOWORD(l) ((WORD)(l)) +#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) +#define LOBYTE(w) ((BYTE)(w)) +#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) + +#endif /* _MYTYPES_ */ diff --git a/private/ntos/ndis/digi/pcimac/opcodes.h b/private/ntos/ndis/digi/pcimac/opcodes.h new file mode 100644 index 000000000..3393f7a79 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/opcodes.h @@ -0,0 +1,152 @@ +/* + * OPCODES.H - This file defines opcodes for messages of K_MSG type + * + * opcodes are assigned to a specific module ans are a 16 bit quantity. + * upper 8 bits are designated as the module name. lower 8 bits are a + * running index of the messages within a module. + */ + +#ifndef _OPCODES_ +#define _OPCODES_ + +/* a general purpose macro to extract module name off an opcode */ +#define MOD_NAME(_op) (_op & 0xFF00) + +/* module names are defined here */ +#define DCH_MOD 0x100 +#define LAP_MOD 0x200 +#define LAPD_MOD 0x300 +#define Q931_MOD 0x400 +#define MDL_MOD 0x500 +#define UART_MOD 0x600 +#define SER_MOD 0x700 +#define HDLC_MOD 0x800 +#define CMD_MOD 0x900 + +/* the different modules are defined here */ +#define DCH(_op) (_op | DCH_MOD) /* d channel control */ +#define LAP(_op) (_op | LAP_MOD) /* lap sub-protocol */ +#define LAPD(_op) (_op | LAPD_MOD) /* lap for d channel */ +#define Q931(_op) (_op | Q931_MOD) /* q931 network prot */ +#define MDL(_op) (_op | MDL_MOD) /* mdl protocol */ +#define UART(_op) (_op | UART_MOD) /* uart device driver */ +#define SER(_op) (_op | SER_MOD) /* serial channel device*/ +#define HDLC(_op) (_op | HDLC_MOD) /* hdlc formatter */ +#define CMD(_op) (_op | CMD_MOD) /* command module */ + + +/* d channel messages */ +#define DCH_ACT_RQ DCH(1) /* ph activation rq */ +#define DCH_DEACT_RQ DCH(2) /* ph deactivation rq */ +#define DCH_BCH_EN DCH(3) /* enable bch tx/rx */ +#define DCH_BCH_DIS DCH(4) /* disable bch tx/rx */ +#define DCH_FST_IND DCH(5) /* Fx state chg ind */ +#define DCH_DATA_RQ DCH(6) /* request for data send */ +#define DCH_DATA_IND DCH(7) /* new data indication */ +#define DCH_ASSOC_RQ DCH(8) /* assoc tei/sapi with mbx */ +#define DCH_DEASSOC_RQ DCH(9) /* deassoc tei/sapi from mbx */ +#define DCH_ASSOC_CNF DCH(10) /* assoc has succ */ +#define DCH_ASSOC_ERR DCH(11) /* assoc has failed */ + +/* lap sub-protocol messages */ +#define LAP_MAKE_RQ LAP(1) /* make a new DLC */ +#define LAP_KILL_RQ LAP(2) /* kill a DLC */ +#define LAP_EST_RQ LAP(3) /* establish multi frame rq */ +#define LAP_REL_RQ LAP(4) /* release multi frame request */ +#define LAP_DATA_RQ LAP(5) /* send data request (ack info) */ +#define LAP_UI_RQ LAP(6) /* send unack info request */ +#define LAP_XID_RQ LAP(7) /* send XID info */ +#define LAP_T200_EXP LAP(8) /* internal: t200 expired */ +#define LAP_T203_EXP LAP(9) /* internal: t203 expired */ +#define LAP_QUEUED_UP LAP(10) /* internal: I frame queued up */ +#define LAP_SET_BUSY LAP(11) /* internal: set own busy */ +#define LAP_RESET_BUSY LAP(12) /* internal: reset own busy */ +#define LAP_ACK_PEND LAP(13) /* internal: ack pending */ +#define LAP_EST_IND LAP(14) /* MF establish, other side init*/ +#define LAP_EST_CNF LAP(15) /* MF establish, this side init */ +#define LAP_REL_IND LAP(16) /* MF released, other side init */ +#define LAP_REL_CNF LAP(17) /* MF released, this side init */ +#define LAP_DATA_IND LAP(18) /* data received indication */ +#define LAP_UI_IND LAP(19) /* unack info received ind */ +#define LAP_XID_IND LAP(20) /* XID received indication */ +#define LAP_ERR_IND LAP(21) /* error indication */ +#define LAP_PH_DATA_RQ LAP(22) /* send data down ph */ +#define LAP_PH_DATA_IND LAP(23) /* received data from ph */ + +/* lap for d channel messages */ +#define LAPD_EST_RQ LAPD(1) /* establish dlc request */ +#define LAPD_EST_CNF LAPD(2) /* establish confirmed */ +#define LAPD_REL_RQ LAPD(3) /* release dlc request */ +#define LAPD_REL_IND LAPD(4) /* dlc release by other side */ +#define LAPD_REL_CNF LAPD(5) /* release confirmed */ +#define LAPD_PROC_IND LAPD(6) /* proceeding indication */ +#define LAPD_DATA_RQ LAPD(7) /* request to send data */ +#define LAPD_DATA_IND LAPD(8) /* new data indication */ +#define LAPD_ERROR_IND LAPD(9) /* error indication */ + +/* q931 messages */ +#define Q931_EST_RQ Q931(1) /* outgoing conn request */ +#define Q931_EST_IND Q931(2) /* incoming oconn indication */ +#define Q931_EST_CNF Q931(3) /* outgoing conn confirmed */ +#define Q931_EST_RSP Q931(4) /* response to incoming conn */ +#define Q931_REL_RQ Q931(5) /* teardown conn reqeust */ +#define Q931_REL_IND Q931(6) /* teardown indicated by remote */ +#define Q931_REL_CNF Q931(7) /* teardown confired */ +#define Q931_REL_RSP Q931(8) /* respose to teardown */ +#define Q931_DATA_RQ Q931(9) /* send data on a conneciton */ +#define Q931_DATA_IND Q931(10) /* new data received on conn */ +#define Q931_TIMER_EXP Q931(11) /* internal: timer expired */ +#define Q931_RESTART_RQ Q931(12) /* request for line restart */ +#define Q931_RESTART_IND Q931(13) /* indication that line restarts*/ +#define Q931_RESTART_CNF Q931(14) /* confirmation of line restart */ +#define Q931_ERROR_IND Q931(15) /* error indcation */ +#define Q931_CID_IND Q931(16) /* cid indication */ +#define Q931_STATE_IND Q931(17) /* state transition indication */ +#define Q931_ELEM_RQ Q931(18) /* requesting elem notification */ +#define Q931_ELEM_IND Q931(19) /* element indication */ +#define Q931_TSPID_EXP Q931(20) /* internal: spid timer expired */ +#define Q931_P_STATE_IND Q931(21) /* protocol state indications */ +#define Q931_CAN_TU10_RQ Q931(22) /* cancel U10 deadman timer */ +#define Q931_EST_IGNORE Q931(23) /* cm code will ignore this new call */ + +/* managment data link (mdl) messages */ +#define MDL_ASSIGN_RQ MDL(1) /* assign tei request */ +#define MDL_ASSIGN_CNF MDL(2) /* assign confirmed */ +#define MDL_REMOVE_RQ MDL(3) /* remove tei request */ +#define MDL_REMOVE_IND MDL(4) /* remove tei indicated */ +#define MDL_REMOVE_CNF MDL(5) /* remove tei confirmed */ +#define MDL_ERROR_IND MDL(6) /* error in mdl procedure */ +#define MDL_T202_EXP MDL(7) /* internal: T202 expired */ + +/* uart device driver */ +#define UART_DATA_RQ UART(1) /* send bytes request */ +#define UART_DATA_IND UART(2) /* recieved bytes indication */ + +/* serial channel device driver */ +#define SER_CONN_RX SER(1) /* connect receiver */ +#define SER_CONN_TX SER(2) /* connect transmitter */ +#define SER_DISC_RX SER(3) /* disconnect receiver */ +#define SER_DISC_TX SER(4) /* disconnect transmitter */ + +/* hdlc formatter module */ +#define HDLC_CONN_RX HDLC(1) /* connect receiver */ +#define HDLC_CONN_TX HDLC(2) /* connect transmitter */ +#define HDLC_DISC_RX HDLC(3) /* disconnect receiver */ +#define HDLC_DISC_TX HDLC(4) /* disconnect transmitter */ + +/* command module */ +#define CMD_TRC_ON CMD(1) /* turn dchan trace on */ +#define CMD_TRC_OFF CMD(2) /* turn dchan trace off */ +#define CMD_BCHAN_OFF CMD(3) /* turn transmission off */ +#define CMD_BCHAN_HDLC CMD(4) /* turn hdlc on a channel */ +#define CMD_BCHAN_56 CMD(5) /* force channel to run 7 bits */ +#define CMD_BCHAN_VOICE CMD(6) /* voice mode b channel */ +#define CMD_ENV_DEF CMD(7) /* env variable defined */ +#define CMD_ENV_UNDEF CMD(8) /* env variable undefined */ +#define CMD_GO CMD(9) /* start execution */ +#define CMD_LOOPBACK CMD(10) /* channel loopback control */ +#define CMD_TRACE_MASK CMD(11) /* set trace/debug mask */ +#define CMD_DUMP_PARAM CMD(12) /* dump parameter block */ +#define CMD_COMPRESS CMD(13) // control B channel compression + +#endif /* _OPCODES_ */ diff --git a/private/ntos/ndis/digi/pcimac/pcimac.c b/private/ntos/ndis/digi/pcimac/pcimac.c new file mode 100644 index 000000000..74b56788c --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/pcimac.c @@ -0,0 +1,2385 @@ +// +// Pcimac.c - Main file for pcimac miniport wan driver +// +// +// +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +/* driver global vars */ +DRIVER_BLOCK Pcimac; + +ULONG DigiDebugLevel = ( DIGIERRORS | DIGIBUGCHECK | DIGIINIT ); + +ULONG DigiDontLoadDriver = FALSE; + +USHORT MCAIOAddressTable[] = { 0x108, 0x118, + 0x128, 0x208, + 0x228, 0x308, + 0x328, 0 }; + +#if !BINARY_COMPATIBLE +/* store location for prev. ioctl handler */ +NTSTATUS (*PrevIoctl)(DEVICE_OBJECT* DeviceObject, IRP* Irp) = NULL; +#endif + +/* forward for external name manager */ +VOID BindName(ADAPTER *Adapter, BOOL create); + +//VOID RegistryInit (VOID); +//VOID NdisTapiRequest(PNDIS_STATUS, NDIS_HANDLE, PNDIS_REQUEST); + +ULONG +GetBaseConfigParams( + CONFIGPARAM *ConfigParam, + CHAR *Key + ); + + +ULONG +GetLineConfigParams( + CONFIGPARAM *ConfigParam, + ULONG LineNumber, + CHAR *Key + ); + +ULONG +GetLTermConfigParams( + CONFIGPARAM *ConfigParam, + ULONG LineNumber, + ULONG LTermNumber, + CHAR *Key + ); + +VOID +IdpGetEaddrFromNvram( + IDD *idd, + CM *cm, + USHORT Line, + USHORT LineIndex + ); + +VOID +AdpGetEaddrFromNvram( + IDD *idd, + CM *cm, + USHORT Line, + USHORT LineIndex + ); + + +NTSTATUS PcimacInitMCA( NDIS_HANDLE AdapterHandle, + PULONG BaseIO, + PULONG BaseMemory, + ULONG SlotNumber ); + + +NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath ); + +/* driver entry point */ +#pragma NDIS_INIT_FUNCTION( DriverEntry ) +NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath ) +/*++ + +Routine Description: + + Entry point for loading driver. + +Arguments: + + DriverObject - Pointer to this drivers object. + + RegistryPath - Pointer to a unicode string which points to this + drivers registry entry. + +Return Value: + + STATUS_SUCCESS - If the driver was successfully loaded, otherwise, + a value which indicates why it wasn't able to load. + + +--*/ +{ + ULONG RetVal, n, m; + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + NDIS_HANDLE NdisWrapperHandle; + + NDIS_MINIPORT_CHARACTERISTICS MiniportChars; + + PWCHAR path; + ULONG DebugLevel; + ULONG zero = 0; + ULONG shouldBreak = 0; +#if !BINARY_COMPATIBLE + ULONG defaultMemPrintFlags=MEM_PRINT_FLAG_FILE; + + RTL_QUERY_REGISTRY_TABLE paramTable[5]; + + // + // First, read the registry to determine some initial information. + // + DigiInitMem( 'irbD' ); + + if( path = DigiAllocMem( PagedPool, + RegistryPath->Length+sizeof(WCHAR) )) + { + RtlZeroMemory( ¶mTable[0], sizeof(paramTable) ); + RtlZeroMemory( path, RegistryPath->Length+sizeof(WCHAR) ); + RtlMoveMemory( path, RegistryPath->Buffer, RegistryPath->Length ); + + paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + paramTable[0].Name = L"DigiBreakOnEntry"; + paramTable[0].EntryContext = &shouldBreak; + paramTable[0].DefaultType = REG_DWORD; + paramTable[0].DefaultData = &zero; + paramTable[0].DefaultLength = sizeof(ULONG); + + paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; + paramTable[1].Name = L"DigiDebugLevel"; + paramTable[1].EntryContext = &DebugLevel; + paramTable[1].DefaultType = REG_DWORD; + paramTable[1].DefaultData = &DigiDebugLevel; + paramTable[1].DefaultLength = sizeof(ULONG); + + paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; + paramTable[2].Name = L"DigiPrintFlags"; + paramTable[2].EntryContext = &DigiPrintFlags; + paramTable[2].DefaultType = REG_DWORD; + paramTable[2].DefaultData = &defaultMemPrintFlags; + paramTable[2].DefaultLength = sizeof(ULONG); + + if( !NT_SUCCESS(RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, + path, + ¶mTable[0], + NULL, NULL ))) + { + // No, don't break on entry if there isn't anything to over- + // ride. + shouldBreak = 0; + + // Set debug level to what ever was compiled into the driver. + DebugLevel = DigiDebugLevel; + } + + } + + DigiDebugLevel = DebugLevel; + + if( shouldBreak ) + { + DbgBreakPoint(); + } + + if( DigiDontLoadDriver ) + return( STATUS_CANCELLED ); + + MemPrintPreInitSettings( "\\SystemRoot\\digibri.log", + (65536 * 8) ); + + MemPrintInitialize(); + +#endif + + NdisZeroMemory(&Pcimac, sizeof(DRIVER_BLOCK)); + + /* initialize ndis wrapper */ + NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL); + + /* initialize debug support */ + D_LOG(DIGIINIT, ("PCIMAC WanMiniport NT Driver, Copyright Digi Intl. Inc, 1992-1994\n")); + D_LOG(DIGIINIT, ("DriverObject: 0x%x\n", DriverObject)); + D_LOG(DIGIINIT, ("RegisteryPath: 0x%x\n", RegistryPath)); + D_LOG(DIGIINIT, ("WrapperHandle: 0x%x\n", NdisWrapperHandle)); + + Pcimac.NdisWrapperHandle = NdisWrapperHandle; + + NdisAllocateSpinLock (&Pcimac.lock); + + /* initialize classes */ + if ((RetVal = idd_init()) != IDD_E_SUCC) + goto exit_idd_error; + + if ((RetVal = cm_init()) != CM_E_SUCC) + goto exit_cm_error; + + if ((RetVal = res_init()) != RES_E_SUCC) + goto exit_res_error; + + NdisZeroMemory(&MiniportChars, + sizeof(NDIS_MINIPORT_CHARACTERISTICS)); + + MiniportChars.MajorNdisVersion = NDIS_MAJOR_VER; + MiniportChars.MinorNdisVersion = NDIS_MINOR_VER; + MiniportChars.Reserved = NDIS_USE_WAN_WRAPPER; + MiniportChars.CheckForHangHandler = PcimacCheckForHang; + MiniportChars.DisableInterruptHandler = NULL; + MiniportChars.EnableInterruptHandler = NULL; + MiniportChars.HaltHandler = PcimacHalt; + MiniportChars.HandleInterruptHandler = NULL; + MiniportChars.InitializeHandler = PcimacInitialize; + MiniportChars.ISRHandler = NULL; + MiniportChars.QueryInformationHandler = PcimacSetQueryInfo; + MiniportChars.ReconfigureHandler = PcimacReconfigure; + MiniportChars.ResetHandler = PcimacReset; + MiniportChars.WanSendHandler = PcimacSend; + MiniportChars.SetInformationHandler = PcimacSetQueryInfo; + MiniportChars.WanTransferDataHandler = NULL; + + NdisMRegisterMiniport (NdisWrapperHandle, + (PNDIS_MINIPORT_CHARACTERISTICS)&MiniportChars, + sizeof(MiniportChars)); + + if (!EnumAdaptersInSystem()) + goto exit_event_error; + + /* initialize ioctl filter */ +#if !BINARY_COMPATIBLE + PrevIoctl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PcimacIoctl; +#endif + + // + // get an adapter to create a binding I/O name binding to + // + for( n = 0; n < MAX_ADAPTERS_IN_SYSTEM; n++ ) + { + ADAPTER *Adapter = Pcimac.AdapterTbl[n]; + + if (Adapter) + { + /* create external name binding */ + BindName(Adapter, TRUE); + break; + } + } + + // + // turn off the trace on all idd's in the system + // + for (n = 0; n < MAX_ADAPTERS_IN_SYSTEM; n++) + { + ADAPTER *Adapter = Pcimac.AdapterTbl[n]; + IDD_MSG msg; + + if (Adapter) + { + for (m = 0; m < MAX_IDD_PER_ADAPTER; m++) + { + IDD *idd = Adapter->IddTbl[m]; + + if (idd) + { + /* issue idd command to stop trace */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = CMD_TRC_OFF; + idd_send_msg(idd, &msg, IDD_PORT_CMD_TX, NULL, NULL); + } + } + } + } + + D_LOG(D_EXIT, ("DriverEntry: exit success!\n")); + + /* if successful here, done */ + return(STATUS_SUCCESS); + +exit_event_error: + D_LOG(D_ALWAYS, ("EventError!\n")); + res_term(); + +exit_res_error: + D_LOG(D_ALWAYS, ("ResError!\n")); + cm_term(); + +exit_cm_error: +exit_idd_error: + D_LOG(D_ALWAYS, ("CmIddError!\n")); + + NdisFreeSpinLock(&Pcimac.lock); + + NdisTerminateWrapper(Pcimac.NdisWrapperHandle, NULL); + +#if !BINARY_COMPATIBLE + if( path ) + { + DigiFreeMem(path); + } + + MemPrintQuit(); +#endif + + return(NDIS_STATUS_FAILURE); +} + +BOOLEAN +PcimacCheckForHang( + NDIS_HANDLE AdapterContext + ) +{ + ULONG n, IdpCounter = 0; + ADAPTER *Adapter = (ADAPTER *)AdapterContext; + BOOLEAN ReturnStatus = FALSE; + + D_LOG(D_ENTRY, ("PcimacCheckForHang: Adapter: 0x%lx\n", AdapterContext)); + + // + // for all idd's that belong to this adpater + // + for (n = 0; Adapter->IddTbl[n] && n < MAX_IDD_PER_ADAPTER; n++) + { + IDD *idd = Adapter->IddTbl[n]; + + // + // see if this idd is dead + // + if (!idd || idd->state == IDD_S_SHUTDOWN) + continue; + + IdpCounter++; + } + + // + // if there are no idps alive on this adapter tell the wrapper + // + if (!IdpCounter) + ReturnStatus = TRUE; + + D_LOG(D_ALWAYS, ("PcimacCheckForHang: ReturnStatus: %d\n", ReturnStatus)); + + return(ReturnStatus); +} + +VOID +PcimacHalt( + NDIS_HANDLE AdapterContext + ) +{ + ULONG n; + ADAPTER *Adapter = (ADAPTER*)AdapterContext; + + D_LOG(D_ENTRY, ("PcimacHalt: Adapter: 0x%lx\n", AdapterContext)); + DbgPrint("PcimacHalt: Adapter: 0x%lx\n", AdapterContext); + + // + // destroy cm objects + // + for (n = 0; n < MAX_CM_PER_ADAPTER; n++) + { + CM *cm = Adapter->CmTbl[n]; + + Adapter->CmTbl[n] = NULL; + + if (cm) + cm_destroy(cm); + } + + // + // destroy mtl objects + // + for (n = 0; n < MAX_MTL_PER_ADAPTER; n++) + { + MTL *mtl = Adapter->MtlTbl[n]; + + Adapter->MtlTbl[n] = NULL; + + if (mtl) + mtl_destroy(mtl); + } + + // + // destroy idd objects + // + for (n = 0; n < MAX_IDD_PER_ADAPTER; n++) + { + IDD *idd = (IDD*)Adapter->IddTbl[n]; + + Adapter->IddTbl[n] = NULL; + + if (idd) + idd_destroy(idd); + } + + /* delete external name binding */ + BindName(Adapter, FALSE); + + // + // deregister adapter + // + AdapterDestroy(Adapter); +} + +#pragma NDIS_INIT_FUNCTION(PcimacInitialize) + +NDIS_STATUS PcimacInitialize( PNDIS_STATUS OpenErrorStatus, + PUINT SelectMediumIndex, + PNDIS_MEDIUM MediumArray, + UINT MediumArraySize, + NDIS_HANDLE AdapterHandle, + NDIS_HANDLE WrapperConfigurationContext ) +{ + ADAPTER *Adapter; + USHORT BoardType, NumberOfLines, NumberOfLTerms, BoardNumber; + ULONG BaseMem, BaseIO, n, m, l, IddStarted = 0; + PVOID VBaseMem, VBaseIO; + ANSI_STRING AnsiStr; + NDIS_STRING NdisStr; + CHAR DefName[128]; + NDIS_STATUS RetVal = NDIS_STATUS_SUCCESS; + CONFIGPARAM ConfigParam; + NDIS_INTERFACE_TYPE NdisInterfaceType = NdisInterfaceIsa; + NDIS_PHYSICAL_ADDRESS MemPhyAddr; + NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + + D_LOG(D_ENTRY, ("PcimacInitialize: AdapterHandle: 0x%x\n", AdapterHandle)); + + for (n = 0; n < MediumArraySize; n++) + if (MediumArray[n] == NdisMediumWan) + break; + + if (n == MediumArraySize) + return(NDIS_STATUS_UNSUPPORTED_MEDIA); + + *SelectMediumIndex = n; + + // + // allocate control block for this adapter + // + NdisAllocateMemory((PVOID*)&Adapter, + sizeof(ADAPTER), + 0, + HighestAcceptableMax); + if ( !Adapter) + { + D_LOG(D_ALWAYS, ("PcimacInitiailize: Adapter memory allocate failed!\n")); + return (NDIS_STATUS_ADAPTER_NOT_FOUND); + } + D_LOG(D_ALWAYS, ("PcimacInitialize: Allocated an Adapter: 0x%lx\n", Adapter)); + NdisZeroMemory(Adapter, sizeof(ADAPTER)); + + // + // store adapter in global structure + // + for (n = 0; n < MAX_ADAPTERS_IN_SYSTEM; n++) + { + if (!Pcimac.AdapterTbl[n]) + { + Pcimac.AdapterTbl[n] = Adapter; + Pcimac.NumberOfAdaptersInSystem++; + BoardNumber = (USHORT)n; + break; + } + } + + // + // if no room destroy and leave + // + if (n >= MAX_ADAPTERS_IN_SYSTEM) + { + D_LOG(D_ALWAYS, ("PcimacInitialize: No room in Adapter Table\n")); + NdisFreeMemory(Adapter, sizeof(ADAPTER), 0); + return (NDIS_STATUS_ADAPTER_NOT_FOUND); + } + + // + // set in driver access lock + // +// NdisAllocateSpinLock (&Adapter->InDriverLock); + + + // + // store adapter handle + // + Adapter->Handle = AdapterHandle; + + // + // initialize adapter specific timers + // + NdisMInitializeTimer(&Adapter->IddPollTimer, Adapter->Handle, IddPollFunction, Adapter); + NdisMSetTimer(&Adapter->IddPollTimer, IDD_POLL_T); + + NdisMInitializeTimer(&Adapter->MtlPollTimer, Adapter->Handle, MtlPollFunction, Adapter); + NdisMSetTimer(&Adapter->MtlPollTimer, MTL_POLL_T); + + NdisMInitializeTimer(&Adapter->CmPollTimer, Adapter->Handle, CmPollFunction, Adapter); + NdisMSetTimer(&Adapter->CmPollTimer, CM_POLL_T); + + ConfigParam.AdapterHandle = AdapterHandle; + + // + // Open registry + // + NdisOpenConfiguration(&RetVal, &ConfigParam.ConfigHandle, WrapperConfigurationContext); + + if (RetVal != NDIS_STATUS_SUCCESS) + { + D_LOG(D_ALWAYS, ("PcimacInitialize: Error Opening Config: RetVal: 0x%x\n", RetVal)); + NdisWriteErrorLogEntry (AdapterHandle, + NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER, + 1, + 0); + goto InitErrorExit; + } + + // + // read registry board type + // + ConfigParam.StringLen = sizeof(ConfigParam.String); + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = TRUE; + if (!GetBaseConfigParams(&ConfigParam, PCIMAC_KEY_BOARDTYPE)) + goto InitErrorExit; + + if (!__strncmp(ConfigParam.String, "PCIMAC4", 7)) + BoardType = IDD_BT_PCIMAC4; + else if (!__strncmp(ConfigParam.String, "PCIMAC - ISA", 12)) + BoardType = IDD_BT_PCIMAC; + else if (!__strncmp(ConfigParam.String, "PCIMAC - MC", 11)) + { + NdisInterfaceType = NdisInterfaceMca; + BoardType = IDD_BT_MCIMAC; + } + else if (!__strncmp(ConfigParam.String, "DATAFIRE - ISA1U", 16)) + BoardType = IDD_BT_DATAFIREU; + else if (!__strncmp(ConfigParam.String, "DATAFIRE - ISA1ST", 17)) + BoardType = IDD_BT_DATAFIREST; + else if (!__strncmp(ConfigParam.String, "DATAFIRE - ISA4ST", 17)) + BoardType = IDD_BT_DATAFIRE4ST; + else + { + D_LOG(D_ALWAYS, ("PcimacInitialize: Invalid BoardType: %s\n", ConfigParam.String)); + goto InitErrorExit; + } + + // + // save board type + // + Adapter->BoardType = BoardType; + + // + // set miniport attributes (only isa for now) + // + NdisMSetAttributes( AdapterHandle, Adapter, FALSE, NdisInterfaceType ); + + // + // read registry base io + // + ConfigParam.StringLen = 0; + ConfigParam.ParamType = NdisParameterInteger; + ConfigParam.MustBePresent = TRUE; + if (!GetBaseConfigParams(&ConfigParam,PCIMAC_KEY_BASEIO)) + goto InitErrorExit; + + BaseIO = ConfigParam.Value; + + if( NdisInterfaceType != NdisInterfaceMca ) + { + // + // save base I/O for this adapter + // + Adapter->BaseIO = BaseIO; + + } + else + { + // + // Must be a MCA adapter. + // + // Note, BaseIO should be the slot number for this adapter instance. + // + RetVal = PcimacInitMCA( AdapterHandle, + &Adapter->BaseIO, + &Adapter->BaseMem, + BaseIO ); + + BaseMem = Adapter->BaseMem; + BaseIO = Adapter->BaseIO; + + if( RetVal != NDIS_STATUS_SUCCESS ) + goto InitErrorExit; + + } + + // + // register I/O range + // + RetVal = NdisMRegisterIoPortRange(&VBaseIO, + AdapterHandle, + BaseIO, + 8); + + if (RetVal != NDIS_STATUS_SUCCESS) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS, + 0); + goto InitErrorExit; + } + + Adapter->VBaseIO = VBaseIO; + + if( (BoardType != IDD_BT_DATAFIREU) && + (BoardType != IDD_BT_DATAFIREST) && + (BoardType != IDD_BT_DATAFIRE4ST) ) + { + // + // This is a PCIMAC family of adapters + // + // + // read registry base mem + // + + if( NdisInterfaceType != NdisInterfaceMca ) + { + ConfigParam.StringLen = 0; + ConfigParam.ParamType = NdisParameterInteger; + ConfigParam.MustBePresent = TRUE; + if( !GetBaseConfigParams(&ConfigParam, PCIMAC_KEY_BASEMEM) ) + goto InitErrorExit; + + BaseMem = ConfigParam.Value; + + // + // save base memory for this adapter + // + Adapter->BaseMem = BaseMem; + + } + + // + // since our adapters can share the same base memory we need to + // see if we have already mapped this memory range. if we have already + // mapped the memory once then save that previous value + // + for (n = 0; n < MAX_ADAPTERS_IN_SYSTEM; n++) + { + ADAPTER *PreviousAdapter = Pcimac.AdapterTbl[n]; + + // + // if this is a valid adapter, this is not the current adapter, and + // this adapter has the same shared memory address as the current + // adapter, then use this adapters mapped memory for the current + // adpaters mapped memory + // + if (PreviousAdapter && + (PreviousAdapter != Adapter) && + (PreviousAdapter->BaseMem == Adapter->BaseMem)) + { + VBaseMem = PreviousAdapter->VBaseMem; + break; + } + } + + // + // if we did not find a previous adapter with this memory range + // we need to map this memory range + // + if (n >= MAX_ADAPTERS_IN_SYSTEM) + { + // + // map our physical memory into virtual memory + // + NdisSetPhysicalAddressHigh(MemPhyAddr, 0); + NdisSetPhysicalAddressLow(MemPhyAddr, BaseMem); + + RetVal = NdisMMapIoSpace(&VBaseMem, + AdapterHandle, + MemPhyAddr, + 0x4000); + + if (RetVal != NDIS_STATUS_SUCCESS) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_RESOURCE_CONFLICT, + 0); + goto InitErrorExit; + } + + Adapter->VBaseMem = VBaseMem; + } + } + + // + // read registry name + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = sizeof(Adapter->Name); + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = TRUE; + if (!GetBaseConfigParams(&ConfigParam, PCIMAC_KEY_BOARDNAME)) + goto InitErrorExit; + + NdisMoveMemory( Adapter->Name, + ConfigParam.String, + ConfigParam.StringLen ); + // + // read the number of lines for this board + // + ConfigParam.StringLen = 0; + ConfigParam.ParamType = NdisParameterInteger; + ConfigParam.MustBePresent = TRUE; + if (!GetBaseConfigParams(&ConfigParam, PCIMAC_KEY_NUMLINES)) + NumberOfLines = (BoardType == IDD_BT_PCIMAC4) ? 4 : 1; + else + NumberOfLines = (USHORT)ConfigParam.Value; + + // + // for number of lines + // + for (n = 0; n < NumberOfLines; n++) + { + IDD *idd; + + // + // Create idd object + // + if (idd_create(&idd, BoardType) != IDD_E_SUCC) + { + NdisWriteErrorLogEntry (AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 0); + + goto InitErrorExit; + } + + // + // store idd in idd table + // + for (l = 0; l < MAX_IDD_PER_ADAPTER; l++) + { + if (!Adapter->IddTbl[l]) + { + Adapter->IddTbl[l] = idd; + break; + } + } + + Adapter->NumberOfIddOnAdapter++; + + // + // set idd physical base i/o and memory + // + idd->phw.base_io = BaseIO; + idd->phw.base_mem = BaseMem; + + // + // set idd virtual base i/o and memory + // + idd->vhw.vbase_io = (ULONG)VBaseIO; + idd->vhw.vmem = VBaseMem; + + // + // create an i/o resource manager for this idd + // + idd->res_io = res_create(RES_CLASS_IO, (ULONG)BaseIO); + + // + // create a memory resource manager for this idd + // + idd->res_mem = res_create(RES_CLASS_MEM, (ULONG)BaseMem); + res_set_data(idd->res_mem, (ULONG)VBaseMem); + + // + // save adapter handle + // + idd->adapter_handle = AdapterHandle; + + // + // save the board number of this idd + // + idd->bnumber = BoardNumber; + + // + // save the line number of this idd + // +// idd->bline = (USHORT)NumberOfLines - 1 - n; + idd->bline = (USHORT)n; + + // + // save the board type that this idd belongs to + // + idd->btype = BoardType; + + if(idd->CheckIO(idd)) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS, + 0); + goto InitErrorExit; + } + + // + // read registry line name + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = sizeof(idd->name); + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = TRUE; + if (!GetLineConfigParams(&ConfigParam, n, PCIMAC_KEY_LINENAME)) + goto InitErrorExit; + + sprintf(idd->name, "%s-%s", Adapter->Name, ConfigParam.String); + +// NdisMoveMemory(idd->name, +// ConfigParam.String, +// ConfigParam.StringLen); + + // + // read registry idp file name + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = sizeof(idd->phw.idp_bin); + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = TRUE; + if (!GetLineConfigParams(&ConfigParam, n, PCIMAC_KEY_IDPFILENAME)) + goto InitErrorExit; + + NdisMoveMemory(idd->phw.idp_bin, + ConfigParam.String, + ConfigParam.StringLen); + + + // + // Try to open idp bin file + // + RtlInitAnsiString(&AnsiStr, idd->phw.idp_bin); + + // + // allocate buffer and turn ansi to unicode + // + RtlAnsiStringToUnicodeString(&NdisStr, &AnsiStr, TRUE); + + NdisOpenFile(&RetVal, + &idd->phw.fbin, + &idd->phw.fbin_len, + &NdisStr, + HighestAcceptableMax); + + // + // free up unicode string buffer + // + RtlFreeUnicodeString(&NdisStr); + + if (RetVal != NDIS_STATUS_SUCCESS) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION, + 0); + goto InitErrorExit; + } + + // + // read registry switch style + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = 128; + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = TRUE; + if (!GetLineConfigParams(&ConfigParam, n, PCIMAC_KEY_SWITCHSTYLE)) + goto InitErrorExit; + + // + // added to support the new switch styles + // + CmSetSwitchStyle(ConfigParam.String); + + idd_add_def(idd, "q931.style", ConfigParam.String); + + // + // read registry terminal management + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = 128; + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = TRUE; + if (!GetLineConfigParams(&ConfigParam, n, + PCIMAC_KEY_TERMINALMANAGEMENT)) + goto InitErrorExit; + + idd_add_def(idd, "q931.tm", ConfigParam.String); + + // + // read WaitForL3 value + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = 128; + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = FALSE; + if (!GetLineConfigParams(&ConfigParam, n, + PCIMAC_KEY_WAITFORL3)) + strcpy(ConfigParam.String, "5"); + + idd_add_def(idd, "q931.wait_l3", ConfigParam.String); + + // + // read registry logical terminals + // + ConfigParam.StringLen = 0; + ConfigParam.ParamType = NdisParameterInteger; + ConfigParam.MustBePresent = TRUE; + if (!GetLineConfigParams(&ConfigParam, n, PCIMAC_KEY_NUMLTERMS)) + goto InitErrorExit; + + NumberOfLTerms = (USHORT)ConfigParam.Value; + + if (NumberOfLTerms > 1) + idd_add_def(idd, "dual_q931", "any"); + + // + // store number of lterms that this idd has + // + idd->CallInfo.NumLTerms = NumberOfLTerms; + + // + // for each logical terminal + // + for (l = 0; l < NumberOfLTerms; l++) + { + // + // read registry tei + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = 128; + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = FALSE; + if (!GetLTermConfigParams(&ConfigParam, n, l, PCIMAC_KEY_TEI)) + __strcpy(ConfigParam.String, "127"); + + NdisZeroMemory(DefName, sizeof(DefName)); + sprintf(DefName, "q931.%d.tei", l); + idd_add_def(idd, DefName, ConfigParam.String); + + // + // read registry spid + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = 128; + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = FALSE; + if (GetLTermConfigParams(&ConfigParam, n, l, PCIMAC_KEY_SPID)) + { + CHAR TempVal[64]; + ULONG i, j; + + // + // remove any non digits except # & * + // + NdisZeroMemory(TempVal, sizeof(TempVal)); + + for (i = 0, j = 0; i < ConfigParam.StringLen; i++) + { + if ((ConfigParam.String[i] >= '0' && ConfigParam.String[i] <= '9') || + ConfigParam.String[i] == '*' || + ConfigParam.String[i] == '#') + { + TempVal[j++] = ConfigParam.String[i]; + } + } + + NdisZeroMemory(DefName, sizeof(DefName)); + sprintf(DefName, "q931.%d.spid", l); + idd_add_def(idd, DefName, TempVal); + idd_add_def(idd, "q931.multipoint", "any"); + } + + // + // read registry address + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = 128; + ConfigParam.ParamType = NdisParameterString; + ConfigParam.MustBePresent = FALSE; + if (GetLTermConfigParams(&ConfigParam, n, l, PCIMAC_KEY_ADDRESS)) + { + CHAR TempVal[64]; + ULONG i, j; + + // + // remove any non digits except # & * + // + NdisZeroMemory(TempVal, sizeof(TempVal)); + + for (i = 0, j = 0; i < ConfigParam.StringLen; i++) + { + if ((ConfigParam.String[i] >= '0' && ConfigParam.String[i] <= '9') || + ConfigParam.String[i] == '*' || + ConfigParam.String[i] == '#') + { + TempVal[j++] = ConfigParam.String[i]; + } + } + + NdisZeroMemory(DefName, sizeof(DefName)); + sprintf(DefName, "q931.%d.addr", l); + idd_add_def(idd, DefName, TempVal); + } + + // + // add code to read generic multistring at the lterm level + // Key is "LTermDefinitions" these will be added to + // the enviornment database + // each string will look like "name=value\0" should + // remove "=" and replace with '\0' + // + } + + // + // add code to read generic multistring at the board level + // Key is "GenericDefines" + // each string will look like "name=value\0" should + // remove "=" and replace with '\0' + // + NdisZeroMemory(ConfigParam.String, sizeof(ConfigParam.String)); + ConfigParam.StringLen = sizeof(ConfigParam.String); + ConfigParam.ParamType = NdisParameterMultiString; + ConfigParam.MustBePresent = FALSE; + if (GetBaseConfigParams(&ConfigParam, PCIMAC_KEY_GENERICDEFINES)) + { + CHAR Name[50] = {0}; + CHAR Value[50] = {0}; + CHAR *StringPointer = ConfigParam.String; + + while (__strlen(StringPointer)) + { + // + // copy the name part of the generic define + // + __strcpy(Name, StringPointer); + + D_LOG(D_ALWAYS, ("PcimacInitialize: GenericDefines: Name: %s\n", Name)); + // + // push pointer over the name + // + StringPointer += __strlen(StringPointer); + + // + // get over the null character + // + StringPointer += 1; + + // + // copy the value part of the generic define + // + __strcpy(Value, StringPointer); + D_LOG(D_ALWAYS, ("PcimacInitialize: GenericDefines: Value: %s\n", Value)); + + idd_add_def(idd, Name, Value); + + // + // push pointer over the value + // + StringPointer += __strlen(StringPointer); + + // + // get over the null character + // + StringPointer += 1; + } + } + + // + // startup idd + // + if (idd_startup(idd) != IDD_E_SUCC) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_HARDWARE_FAILURE, + 2, + (ULONG)idd->bnumber, + (ULONG)idd->bline); + idd_destroy(idd); + for (m = 0; m < MAX_IDD_PER_ADAPTER; m++) + if (Adapter->IddTbl[m] == idd) + Adapter->IddTbl[m] = NULL; + + Adapter->NumberOfIddOnAdapter--; + continue; + } + + // + // register handlers for idd + // + cm_register_idd(idd); + + IddStarted++; + } + + if (!IddStarted) + goto InitErrorExit; + + + for (n = 0; n < IddStarted; n++) + { + CM *cm; + MTL *mtl; + IDD *idd; + + idd = Adapter->IddTbl[n]; + + // + // build two cm's and two mtl's per line + // + for (l = 0; l < 2; l++) + { + ULONG m; + + // + // Allocate memory for cm object + // + if (cm_create(&cm, AdapterHandle) != CM_E_SUCC) + goto InitErrorExit; + + for (m = 0; m < MAX_CM_PER_ADAPTER; m++) + { + if (!Adapter->CmTbl[m]) + { + Adapter->CmTbl[m] = cm; + break; + } + } + + // + // back pointer to adapter structure + // + cm->Adapter = Adapter; + + // + // pointer to idd that belongs to this cm + // + cm->idd = idd; + + // + // name cm object format: AdapterName-LineName-chan# + // + sprintf(cm->name,"%s-%d", idd->name, l); + + // + // set local address, format: NetCard#-idd#-chan# + // +#if !BINARY_COMPATIBLE + sprintf( cm->LocalAddress, "%d-%d-%d", + atoi( &Adapter->Name[6] ), + (idd->bline * 2) + l, + 0 ); +#else + sprintf(cm->LocalAddress, "1-%d-%d", (idd->bline * 2) + l, 0); +#endif + + // + // get ethernet addresses for this cm + // + if( (idd->btype == IDD_BT_DATAFIREU) || + (idd->btype == IDD_BT_DATAFIREST) || + (idd->btype == IDD_BT_DATAFIRE4ST) ) + AdpGetEaddrFromNvram(idd, cm, (USHORT)n, (USHORT)l); + else + IdpGetEaddrFromNvram(idd, cm, (USHORT)n, (USHORT)l); + + // + // Allocate memory for mtl object + // + if (mtl_create(&mtl, AdapterHandle) != MTL_E_SUCC) + goto InitErrorExit; + + for (m = 0; m < MAX_MTL_PER_ADAPTER; m++) + { + if (!Adapter->MtlTbl[m]) + { + Adapter->MtlTbl[m] = mtl; + break; + } + } + + // + // back pointer to adapter structure + // + mtl->Adapter = Adapter; + + // + // link between cm and mtl + // + cm->mtl = mtl; + mtl->cm = cm; + } + } + + NdisCloseConfiguration(ConfigParam.ConfigHandle); + + NdisMRegisterAdapterShutdownHandler( + AdapterHandle, + Adapter, + (PVOID)PcimacHalt + ); + + return (NDIS_STATUS_SUCCESS); + +InitErrorExit: + NdisCloseConfiguration(ConfigParam.ConfigHandle); + + // + // clean up all idd's allocated + // + for (l = 0; l < MAX_IDD_PER_ADAPTER; l++) + { + IDD *idd = Adapter->IddTbl[l]; + + // + // if memory has been mapped release + // + if (idd) + { + idd_destroy(idd); + Adapter->IddTbl[l] = NULL; + } + } + + // + // clean up all cm's allocated + // + for (l = 0; l < MAX_CM_PER_ADAPTER; l++) + { + CM *cm = Adapter->CmTbl[l]; + + if (cm) + { + cm_destroy(cm); + Adapter->CmTbl[l] = NULL; + } + } + + // + // clean up all mtl's allocated + // + for (l = 0; l < MAX_MTL_PER_ADAPTER; l++) + { + MTL *mtl = Adapter->MtlTbl[l]; + + if (mtl) + { + mtl_destroy(mtl); + Adapter->MtlTbl[l] = NULL; + } + } + + // + // clean up adapter block allocated + // + AdapterDestroy(Adapter); + + return (NDIS_STATUS_ADAPTER_NOT_FOUND); +} // end PcimacInitialize + +NDIS_STATUS +PcimacSetQueryInfo( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesReadWritten, + PULONG BytesNeeded + ) +{ + ULONG OidType; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + D_LOG(D_ENTRY, ("PcimacSetQueryInfo: Adapter: 0x%lx, Oid: 0x%x\n", AdapterContext, Oid)); + + // + // get oid type + // + OidType = Oid & 0xFF000000; + + switch (OidType) + { + case OID_WAN_INFO: + Status = WanOidProc(AdapterContext, + Oid, + InfoBuffer, + InfoBufferLen, + BytesReadWritten, + BytesNeeded); + break; + + case OID_TAPI_INFO: + Status = TapiOidProc(AdapterContext, + Oid, + InfoBuffer, + InfoBufferLen, + BytesReadWritten, + BytesNeeded); + break; + + + case OID_GEN_INFO: + case OID_8023_INFO: + Status = LanOidProc(AdapterContext, + Oid, + InfoBuffer, + InfoBufferLen, + BytesReadWritten, + BytesNeeded); + break; + + default: + Status = NDIS_STATUS_INVALID_OID; + break; + } + + D_LOG(D_EXIT, ("PcimacSetQueryInfo: Status: 0x%x, BytesReadWritten: %d, BytesNeeded: %d\n", Status, *BytesReadWritten, *BytesNeeded)); + return(Status); +} + +NDIS_STATUS +PcimacReconfigure( + PNDIS_STATUS OpenErrorStatus, + NDIS_HANDLE AdapterContext, + NDIS_HANDLE WrapperConfigurationContext + ) +{ + D_LOG(D_ENTRY, ("PcimacReconfigure: Adapter: 0x%lx\n", AdapterContext)); + // + // not supported for now + // + return(NDIS_STATUS_FAILURE); +} + +NDIS_STATUS +PcimacReset( + PBOOLEAN AddressingReset, + NDIS_HANDLE AdapterContext + ) +{ + D_LOG(D_ENTRY, ("PcimacReset: Adapter: 0x%lx\n", AdapterContext)); + + return(NDIS_STATUS_HARD_ERRORS); +} + +NDIS_STATUS +PcimacSend( + NDIS_HANDLE MacBindingHandle, + NDIS_HANDLE LinkContext, + PNDIS_WAN_PACKET WanPacket + ) +{ + MTL *mtl = (MTL*)LinkContext; + + D_LOG(D_ENTRY, ("PcimacSend: Link: 0x%lx\n", mtl)); + + /* send packet */ + mtl__tx_packet(mtl, WanPacket); + + return(NDIS_STATUS_PENDING); +} + +/* create/delete external name binding */ +VOID +BindName(ADAPTER *Adapter, BOOL create) +{ +#if !BINARY_COMPATIBLE + +#define LINKNAME "\\DosDevices\\PCIMAC0" + UNICODE_STRING linkname, devname; + NTSTATUS stat; + CHAR name[128]; + ANSI_STRING aname; + ANSI_STRING lname; + + if (Adapter) + sprintf(name,"\\Device\\%s",Adapter->Name); + + if ( !name ) + sprintf(name,"\\Device\\Pcimac69"); + + D_LOG(D_ENTRY, ("BindName: LinkName: %s, NdisName: %s\n", LINKNAME, name)); + + /* convert to unicode string */ + RtlInitAnsiString(&lname, LINKNAME); + stat = RtlAnsiStringToUnicodeString(&linkname, &lname, TRUE); + + /* convert to unicode string */ + RtlInitAnsiString(&aname, name); + stat = RtlAnsiStringToUnicodeString(&devname, &aname, TRUE); + + /* create? */ + if ( create ) + { + UNICODE_STRING AtlasVName, AtlasVEntry; + + RtlInitAnsiString( &aname, "DigiBRI" ); + RtlAnsiStringToUnicodeString( &AtlasVName, &aname, TRUE ); + + RtlInitAnsiString( &aname, "DgBRIAtlas" ); + RtlAnsiStringToUnicodeString( &AtlasVEntry, &aname, TRUE ); + + stat = DigiRegisterAtlasName( &devname, + &AtlasVName, + &AtlasVEntry ); + + if( NT_ERROR(stat) ) + stat = IoCreateSymbolicLink (&linkname, &devname); + + RtlFreeUnicodeString( &AtlasVName ); + RtlFreeUnicodeString( &AtlasVEntry ); + } + else /* delete */ + stat = IoDeleteSymbolicLink (&linkname); + + D_LOG(D_ENTRY, ("BindName: Operation: 0x%x, stat: 0x%x\n", create, stat)); + + RtlFreeUnicodeString(&devname); + RtlFreeUnicodeString(&linkname); + +#endif + +} + +// +// Function commented out for change in how RAS picks up tapi name and address info +// This will help make the driver more portable. +// +//#pragma NDIS_INIT_FUNCTION(RegistryInit) +// +//VOID +//RegistryInit(VOID) +//{ +// UNICODE_STRING AddressUnicodeString; +// UNICODE_STRING UnicodeString; +// ANSI_STRING AnsiString; +// PWCHAR AddressBuffer; +// NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); +// ULONG l, m; +// +// NdisAllocateMemory((PVOID)&AddressBuffer, +// 1024, +// 0, +// HighestAcceptableMax); +// +// if (!AddressBuffer) +// { +// D_LOG(D_ALWAYS, ("RegistryInit: Memory Allocation Failed!\n")); +// return; +// } +// +// AddressUnicodeString.MaximumLength = 1024; +// AddressUnicodeString.Length = 0; +// NdisZeroMemory(AddressBuffer, 1024); +// AddressUnicodeString.Buffer = AddressBuffer; +// +// // +// // create tapi devices key +// // +// RtlCreateRegistryKey (RTL_REGISTRY_DEVICEMAP, L"Tapi Devices"); +// +// // +// // create pcimac service provider key +// // +// RtlCreateRegistryKey (RTL_REGISTRY_DEVICEMAP, L"Tapi Devices\\PCIMAC"); +// +// // +// // write media type - isdn for us +// // +// RtlInitAnsiString(&AnsiString, "ISDN"); +// +// RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); +// +// RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, +// L"Tapi Devices\\PCIMAC", +// L"Media Type", +// REG_SZ, +// UnicodeString.Buffer, +// UnicodeString.Length); +// +// RtlFreeUnicodeString(&UnicodeString); +// +// for (l = 0; l < MAX_ADAPTERS_IN_SYSTEM; l++) +// { +// ADAPTER *Adapter = (ADAPTER*)Pcimac.AdapterTbl[l]; +// +// if (Adapter) +// { +// for (m = 0; m < MAX_CM_PER_ADAPTER; m++) +// { +// CM *cm = Adapter->CmTbl[m]; +// +// if (cm) +// { +// RtlInitAnsiString(&AnsiString, cm->LocalAddress); +// +// RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); +// +// RtlAppendUnicodeStringToString(&AddressUnicodeString, &UnicodeString); +// +// AddressUnicodeString.Buffer[AddressUnicodeString.Length + 1] = '\0'; +// AddressUnicodeString.Length += 2; +// +// RtlFreeUnicodeString(&UnicodeString); +// } +// } +// } +// } +// +// // +// // write value +// // +// RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, +// L"Tapi Devices\\PCIMAC", +// L"Address", +// REG_MULTI_SZ, +// AddressUnicodeString.Buffer, +// AddressUnicodeString.Length); +// +// NdisFreeMemory(AddressBuffer, 1024, 0); +//} + +#pragma NDIS_INIT_FUNCTION(GetBaseConfigParams) + +ULONG +GetBaseConfigParams( + CONFIGPARAM *RetParam, + CHAR *Key + ) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + NDIS_STRING KeyWord; + ANSI_STRING AnsiKey; + ULONG n; + PNDIS_CONFIGURATION_PARAMETER ConfigParam; + + D_LOG(D_ALWAYS, ("GetBaseConfigParams: Key: %s\n", Key)); + // + // turn passed in key to an ansi string + // + RtlInitAnsiString(&AnsiKey, Key); + + // + // allocate buffer and turn ansi to unicode + // + RtlAnsiStringToUnicodeString(&KeyWord, &AnsiKey, TRUE); + + NdisReadConfiguration(&Status, + &ConfigParam, + RetParam->ConfigHandle, + &KeyWord, + RetParam->ParamType); + + D_LOG(D_ALWAYS, ("GetBaseConfigParams: Status: 0x%x\n", Status)); + // + // free up unicode string buffer + // + RtlFreeUnicodeString(&KeyWord); + + if (Status != NDIS_STATUS_SUCCESS) + { + D_LOG(D_ALWAYS, ("GetBaseConfigParams: Error Reading Config: RetVal: 0x%x\n", Status)); + if (RetParam->MustBePresent) + NdisWriteErrorLogEntry (RetParam->AdapterHandle, + NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER, + 0); + return(0); + } + + D_LOG(D_ALWAYS, ("GetBaseConfigParams: StringLength: %d\n", ConfigParam->ParameterData.StringData.Length)); + switch (ConfigParam->ParameterType) + { + case NdisParameterString: + { +#if !BINARY_COMPATIBLE + ANSI_STRING AnsiRet; + + RtlUnicodeStringToAnsiString(&AnsiRet, &ConfigParam->ParameterData.StringData, TRUE); + __strncpy(RetParam->String, AnsiRet.Buffer, AnsiRet.Length); + RetParam->StringLen = AnsiRet.Length; + RtlFreeAnsiString(&AnsiRet); +#else + RetParam->StringLen = __strlen((PUCHAR)ConfigParam->ParameterData.StringData.Buffer); + __strncpy(RetParam->String, (PUCHAR) ConfigParam->ParameterData.StringData.Buffer, RetParam->StringLen); +#endif + D_LOG(D_ALWAYS, ("GetBaseConfigParams: String: %s, Length: %d\n", RetParam->String, RetParam->StringLen)); + + break; + } + case NdisParameterMultiString: + D_LOG(D_ALWAYS, ("GetBaseConfigParams: String: %s, Length: %d\n", RetParam->String, RetParam->StringLen)); + +#if !BINARY_COMPATIBLE + for (n = 0; n < RetParam->StringLen && n < ConfigParam->ParameterData.StringData.Length; n++) + RetParam->String[n] = (CHAR)ConfigParam->ParameterData.StringData.Buffer[n]; + + RetParam->StringLen = n/2; + +#else + // Ansi + for (n = 0; n < RetParam->StringLen && n < ConfigParam->ParameterData.StringData.Length; n++) + RetParam->String[n] = ((PUCHAR)ConfigParam->ParameterData.StringData.Buffer)[n]; + + RetParam->StringLen = n; + +#endif + for (n = 0; n < RetParam->StringLen; n++) + if (!__strnicmp((CHAR*)&RetParam->String[n], (CHAR*)"=", 1)) + RetParam->String[n] = '\0'; + break; + + case NdisParameterInteger: + case NdisParameterHexInteger: + RetParam->Value = ConfigParam->ParameterData.IntegerData; + D_LOG(D_ALWAYS, ("GetBaseConfigParams: Integer: 0x%x\n", RetParam->Value)); + break; + + default: + return(0); + } + return(1); +} + +#pragma NDIS_INIT_FUNCTION(GetLineConfigParams) + +ULONG +GetLineConfigParams( + CONFIGPARAM *RetParam, + ULONG LineNumber, + CHAR *Key + ) +{ + ULONG n; + CHAR LinePath[64]; + NDIS_STRING KeyWord; + ANSI_STRING AnsiKey; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PNDIS_CONFIGURATION_PARAMETER ConfigParam; + + sprintf(LinePath, + "%s%d.%s", + PCIMAC_KEY_LINE, + LineNumber, + Key); + + D_LOG(D_ALWAYS, ("GetLineConfigParams: LineNumber: %d, Key: %s\n", LineNumber, Key)); + // + // turn passed in key to an ansi string + // + RtlInitAnsiString(&AnsiKey, LinePath); + + // + // allocate buffer and turn ansi to unicode + // + RtlAnsiStringToUnicodeString(&KeyWord, &AnsiKey, TRUE); + + NdisReadConfiguration(&Status, + &ConfigParam, + RetParam->ConfigHandle, + &KeyWord, + RetParam->ParamType); + + // + // free up unicode string buffer + // + RtlFreeUnicodeString(&KeyWord); + + if (Status != NDIS_STATUS_SUCCESS) + { + D_LOG(D_ALWAYS, ("GetLineConfigParams: Error Reading Config: RetVal: 0x%x\n", Status)); + if (RetParam->MustBePresent) + NdisWriteErrorLogEntry (RetParam->AdapterHandle, + NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER, + 0); + return(0); + } + + switch (ConfigParam->ParameterType) + { + case NdisParameterString: + { +#if !BINARY_COMPATIBLE + ANSI_STRING AnsiRet; + + RtlUnicodeStringToAnsiString(&AnsiRet, &ConfigParam->ParameterData.StringData, TRUE); + __strncpy(RetParam->String, AnsiRet.Buffer, AnsiRet.Length); + RetParam->StringLen = AnsiRet.Length; + RtlFreeAnsiString(&AnsiRet); +#else + RetParam->StringLen = __strlen((PUCHAR)ConfigParam->ParameterData.StringData.Buffer); + __strncpy(RetParam->String, (PUCHAR) ConfigParam->ParameterData.StringData.Buffer, RetParam->StringLen); +#endif + + D_LOG(D_ALWAYS, ("GetLineConfigParams: String: %s, Length: %d\n", RetParam->String, RetParam->StringLen)); + break; + } + + case NdisParameterMultiString: + for (n = 0; n < RetParam->StringLen && n < ConfigParam->ParameterData.StringData.Length; n++) + RetParam->String[n] = (CHAR)ConfigParam->ParameterData.StringData.Buffer[n]; + + RetParam->StringLen = n/2; + + for (n = 0; n < RetParam->StringLen; n++) + if (!__strnicmp((CHAR*)&RetParam->String[n], (CHAR*)"=", 1)) + RetParam->String[n] = '\0'; + D_LOG(D_ALWAYS, ("GetBaseConfigParams: String: %s, Length: %d\n", RetParam->String, RetParam->StringLen)); + break; + + case NdisParameterInteger: + case NdisParameterHexInteger: + RetParam->Value = ConfigParam->ParameterData.IntegerData; + D_LOG(D_ALWAYS, ("GetLineConfigParams: Integer: 0x%x\n", RetParam->Value)); + break; + + default: + return(0); + } + return(1); +} + +#pragma NDIS_INIT_FUNCTION(GetLTermConfigParams) + +ULONG +GetLTermConfigParams( + CONFIGPARAM *RetParam, + ULONG LineNumber, + ULONG LTermNumber, + CHAR *Key + ) +{ + ULONG n; + CHAR LTermPath[64]; + NDIS_STRING KeyWord; + ANSI_STRING AnsiKey; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PNDIS_CONFIGURATION_PARAMETER ConfigParam; + + D_LOG(D_ALWAYS, ("GetLTermConfigParams: LineNumber: %d, LTerm: %d, Key: %s\n", LineNumber, LTermNumber, Key)); + + sprintf(LTermPath, + "%s%d.%s%d.%s", + PCIMAC_KEY_LINE, + LineNumber, + PCIMAC_KEY_LTERM, + LTermNumber, + Key); + + // + // turn passed in key to an ansi string + // + RtlInitAnsiString(&AnsiKey, LTermPath); + + // + // allocate buffer and turn ansi to unicode + // + RtlAnsiStringToUnicodeString(&KeyWord, &AnsiKey, TRUE); + + NdisReadConfiguration(&Status, + &ConfigParam, + RetParam->ConfigHandle, + &KeyWord, + RetParam->ParamType); + + // + // free up unicode string buffer + // + RtlFreeUnicodeString(&KeyWord); + + if (Status != NDIS_STATUS_SUCCESS) + { + D_LOG(D_ALWAYS, ("GetLTermConfigParams: Error Reading Config: RetVal: 0x%x\n", Status)); + if (RetParam->MustBePresent) + NdisWriteErrorLogEntry (RetParam->AdapterHandle, + NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER, + 0); + return(0); + } + + switch (ConfigParam->ParameterType) + { + case NdisParameterString: + { +#if !BINARY_COMPATIBLE + ANSI_STRING AnsiRet; + + RtlUnicodeStringToAnsiString(&AnsiRet, &ConfigParam->ParameterData.StringData, TRUE); + __strncpy(RetParam->String, AnsiRet.Buffer, AnsiRet.Length); + RetParam->StringLen = AnsiRet.Length; + RtlFreeAnsiString(&AnsiRet); +#else + RetParam->StringLen = __strlen((PUCHAR)ConfigParam->ParameterData.StringData.Buffer); + __strncpy(RetParam->String, (PUCHAR) ConfigParam->ParameterData.StringData.Buffer, RetParam->StringLen); +#endif + D_LOG(D_ALWAYS, ("GetLTermConfigParams: String: %s, Length: %d\n", RetParam->String, RetParam->StringLen)); + break; + } + + case NdisParameterMultiString: + for (n = 0; n < RetParam->StringLen && n < ConfigParam->ParameterData.StringData.Length; n++) + RetParam->String[n] = (CHAR)ConfigParam->ParameterData.StringData.Buffer[n]; + + RetParam->StringLen = n/2; + + for (n = 0; n < RetParam->StringLen; n++) + if (!__strnicmp((CHAR*)&RetParam->String[n], (CHAR*)"=", 1)) + RetParam->String[n] = '\0'; + D_LOG(D_ALWAYS, ("GetLTermConfigParams: String: %s, Length: %d\n", RetParam->String, RetParam->StringLen)); + break; + + case NdisParameterInteger: + case NdisParameterHexInteger: + RetParam->Value = ConfigParam->ParameterData.IntegerData; + D_LOG(D_ALWAYS, ("GetLTermConfigParams: Integer: 0x%x\n", RetParam->Value)); + break; + + default: + return(0); + } + return(1); +} + +VOID +SetInDriverFlag ( + ADAPTER *Adapter + ) +{ + NdisAcquireSpinLock(&Pcimac.lock); + + Pcimac.InDriverFlag = 1; + + Pcimac.CurrentAdapter = Adapter; + + Pcimac.NextAdapterToPoll++; + + if (Pcimac.NextAdapterToPoll == Pcimac.NumberOfAdaptersInSystem) + Pcimac.NextAdapterToPoll = 0; + + NdisReleaseSpinLock(&Pcimac.lock); +} + +VOID +ClearInDriverFlag ( + ADAPTER *Adapter +) +{ + NdisAcquireSpinLock(&Pcimac.lock); + + Pcimac.InDriverFlag = 0; + + NdisReleaseSpinLock(&Pcimac.lock); +} + +ULONG +CheckInDriverFlag ( + ADAPTER *Adapter +) +{ + ADAPTER *CurrentAdapter; + INT RetVal = 0; + + NdisAcquireSpinLock(&Pcimac.lock); + + // + // get the current in driver adapter + // + CurrentAdapter = (ADAPTER*)Pcimac.CurrentAdapter; + + // + // if someone is in the driver and they are using the same + // shared memory window as the new prospective user send them + // away unhappy + // + if (Pcimac.InDriverFlag && CurrentAdapter && (Adapter->VBaseMem == CurrentAdapter->VBaseMem)) + RetVal = 1; + + NdisReleaseSpinLock(&Pcimac.lock); + + return(RetVal); +} + +#pragma NDIS_INIT_FUNCTION(IdpGetEaddrFromNvram) + +/* + * get ethernet address(s) out on nvram & register + * + * note that line number inside board (bline) argument was added here. + * for each idd installed, this function is called to add two ethernet + * addresses associated with it (it's two B channels - or it's capability to + * handle two connections). All ethernet address are derived from the + * single address stored starting at nvram address 8. since the manufecturer + * code is the first 3 bytes, we must not modify these bytes. therefor, + * addresses are generated by indexing the 4'th byte by bline*2 (need two + * address - remember?). + */ +VOID +IdpGetEaddrFromNvram( + IDD *idd, + CM *cm, + USHORT Line, + USHORT LineIndex + ) +{ + UCHAR eaddr[6]; + USHORT nvval; + + /* extract original stored ethernet address */ + idd_get_nvram(idd, (USHORT)(8), &nvval); + eaddr[0] = LOBYTE(nvval); + eaddr[1] = HIBYTE(nvval); + idd_get_nvram(idd, (USHORT)(9), &nvval); + eaddr[2] = LOBYTE(nvval); + eaddr[3] = HIBYTE(nvval); + idd_get_nvram(idd, (USHORT)(10), &nvval); + eaddr[4] = LOBYTE(nvval); + eaddr[5] = HIBYTE(nvval); + + /* create derived address and store it */ + eaddr[3] += (Line * 2) + LineIndex; + + NdisMoveMemory(cm->SrcAddr, eaddr, sizeof(cm->SrcAddr)); +} // end IdpGetEaddrFromNvram + +#pragma NDIS_INIT_FUNCTION(AdpGetEaddrFromNvram) + +/* + * get ethernet address(s) out on nvram & register + * + * note that line number inside board (bline) argument was added here. + * for each idd installed, this function is called to add two ethernet + * addresses associated with it (it's two B channels - or it's capability to + * handle two connections). All ethernet address are derived from the + * single address stored starting at nvram address 8. since the manufecturer + * code is the first 3 bytes, we must not modify these bytes. therefor, + * addresses are generated by indexing the 4'th byte by bline*2 (need two + * address - remember?). + */ +VOID +AdpGetEaddrFromNvram( + IDD *idd, + CM *cm, + USHORT Line, + USHORT LineIndex + ) +{ + UCHAR eaddr[6]; + USHORT nvval; + + // + // the MAC address lines at offset 0x950 in the onboard memory + // this is NVRAM_WINDOW 0x940 + 0x10 + // + idd_get_nvram(idd, (USHORT)(0x10), &nvval); + eaddr[0] = LOBYTE(nvval); + eaddr[1] = HIBYTE(nvval); + idd_get_nvram(idd, (USHORT)(0x12), &nvval); + eaddr[2] = LOBYTE(nvval); + eaddr[3] = HIBYTE(nvval); + idd_get_nvram(idd, (USHORT)(0x14), &nvval); + eaddr[4] = LOBYTE(nvval); + eaddr[5] = HIBYTE(nvval); + + /* create derived address and store it */ + eaddr[3] += (Line * 2) + LineIndex; + + NdisMoveMemory(cm->SrcAddr, eaddr, sizeof(cm->SrcAddr)); +} // end AdpGetEaddrFromNvram + +#ifdef OLD +ULONG +EnumAdaptersInSystem() +{ + ULONG n, NumAdapters = 0; + + for (n = 0; n < MAX_ADAPTERS_IN_SYSTEM; n++) + { + if (Pcimac.AdapterTbl[n]) + NumAdapters++; + } + return(NumAdapters); +} +#endif + +ULONG +EnumAdaptersInSystem() +{ + ULONG NumAdapters; + + NdisAcquireSpinLock(&Pcimac.lock); + + NumAdapters = Pcimac.NumberOfAdaptersInSystem; + + NdisReleaseSpinLock(&Pcimac.lock); + + return(NumAdapters); +} + +ADAPTER* +GetAdapterByIndex( + ULONG Index + ) +{ + ADAPTER *Adapter; + + NdisAcquireSpinLock(&Pcimac.lock); + + Adapter = Pcimac.AdapterTbl[Index]; + + NdisReleaseSpinLock(&Pcimac.lock); + + return(Adapter); +} + +INT +IoEnumAdapter(VOID *cmd_1) +{ + IO_CMD *cmd = (IO_CMD*)cmd_1; + ULONG n, m, NumberOfAdapters; + + NumberOfAdapters = cmd->val.enum_adapters.num = (USHORT)EnumAdaptersInSystem(); + + for (n = 0, m = 0; n < NumberOfAdapters; n++) + { + ADAPTER *Adapter = GetAdapterByIndex(n); + + if (Adapter) + { + cmd->val.enum_adapters.BaseIO[m] = Adapter->BaseIO; + cmd->val.enum_adapters.BaseMem[m] = Adapter->BaseMem; + cmd->val.enum_adapters.BoardType[m] = Adapter->BoardType; + NdisMoveMemory (&cmd->val.enum_adapters.Name[m], Adapter->Name, sizeof(cmd->val.enum_adapters.Name[n])); + cmd->val.enum_adapters.tbl[m] = Adapter; + m++; + } + } + + return(0); +} + +VOID +AdapterDestroy( + ADAPTER *Adapter + ) +{ + ULONG n; + + for (n = 0; n < MAX_ADAPTERS_IN_SYSTEM; n++) + { + if (Adapter == Pcimac.AdapterTbl[n]) + break; + } + + if (n == MAX_ADAPTERS_IN_SYSTEM) + return; + + // + // stop idd timers + // + StopTimers(Adapter); + + Pcimac.AdapterTbl[n] = NULL; + + Pcimac.NumberOfAdaptersInSystem--; + + // + // if we have successfully mapped our base i/o then we need to release + // + if (Adapter->VBaseIO) + { + // + // deregister adapters I/O and memory + // + NdisMDeregisterIoPortRange((NDIS_HANDLE)Adapter->Handle, + Adapter->BaseIO, + 8, + Adapter->VBaseIO); + } + + // + // if we have successfully mapped our base memory then we need to release + // + if (Adapter->VBaseMem) + { + NdisMUnmapIoSpace((NDIS_HANDLE)Adapter->Handle, + Adapter->VBaseMem, + 0x4000); + } + +// NdisFreeSpinLock(&Adapter->lock); + + NdisFreeMemory(Adapter, sizeof(ADAPTER), 0); +} + +#pragma NDIS_INIT_FUNCTION(StartTimers) + +VOID +StartTimers( + ADAPTER *Adapter + ) +{ + NdisMSetTimer(&Adapter->IddPollTimer, IDD_POLL_T); + NdisMSetTimer(&Adapter->MtlPollTimer, MTL_POLL_T); + NdisMSetTimer(&Adapter->CmPollTimer, CM_POLL_T); +} + +VOID +StopTimers( + ADAPTER *Adapter + ) +{ + BOOLEAN TimerCanceled; + + NdisMCancelTimer(&Adapter->IddPollTimer, &TimerCanceled); + NdisMCancelTimer(&Adapter->MtlPollTimer, &TimerCanceled); + NdisMCancelTimer(&Adapter->CmPollTimer, &TimerCanceled); +} + +#pragma NDIS_INIT_FUNCTION(IdpCheckIO) + +ULONG +IdpCheckIO(IDD *idd) +{ + ULONG ReturnValue = 1; + + // + // check for board at this I/O address + // + if (idd->btype == IDD_BT_PCIMAC || idd->btype == IDD_BT_PCIMAC4) + { + UCHAR BoardID; + + BoardID = (idd->InFromPort(idd, 5) & 0x0F); + + if ( ((idd->btype == IDD_BT_PCIMAC) && (BoardID == 0x02)) || + ((idd->btype == IDD_BT_PCIMAC4) && (BoardID == 0x04))) + ReturnValue = 0; + } + else if( idd->btype == IDD_BT_MCIMAC ) + ReturnValue = 0; + + return(ReturnValue); +} + +#pragma NDIS_INIT_FUNCTION(AdpCheckIO) + +ULONG +AdpCheckIO(IDD *idd) +{ + UCHAR BoardId = idd->InFromPort(idd, ADP_REG_ID); + + D_LOG(D_ENTRY, ("AdpCheckIO: entry, idd: 0x%lx BoardType: %d\n", idd, idd->btype)); + + D_LOG(D_ALWAYS, ("AdpCheckIO: ADP_REG_ID: %d\n", BoardId)); + + switch( idd->btype ) + { + case IDD_BT_DATAFIREU: + case IDD_BT_DATAFIREST: + if (BoardId != ADP_BT_ADP1) + return(1); + break; + + case IDD_BT_DATAFIRE4ST: + if (BoardId != ADP_BT_ADP4) + return(1); + break; + } + + return( 0 ); +} + +#pragma NDIS_INIT_FUNCTION(IdpCheckMem) + +ULONG +IdpCheckMem(IDD *idd) +{ + return(0); +} + +#pragma NDIS_INIT_FUNCTION(AdpCheckMem) + +ULONG +AdpCheckMem(IDD *idd) +{ + return(0); + +} + + +NTSTATUS PcimacInitMCA( NDIS_HANDLE AdapterHandle, + PULONG BaseIO, + PULONG BaseMemory, + ULONG SlotNumber ) +/*++ + +Routine Description: + + This routine will be called if it is determined the type of bus + is MCA. We verify that the controller is actually a DigiBoard + PCIMAC controller, read the POS to determine the I/O address and + Memory Mapped address, so the initialization process can continue. + +Arguments: + + AdapterHandle - Handle passed in the initialization routine. Required + so mapping of POS I/O ports can take place. + + BaseIO - Pointer where the adapters base I/O address is passed back. + + BaseMemory - Pointer where the adapters base memory address is passed back. + + SlotNumber - Number indicating what slot this MCA adapter should be in. + +Return Value: + + STATUS_SUCCESS - If we were able to complete successfully + + ?? - We were not able to get the information required to continue. + +--*/ +{ +#define PcimacPOSID 0x7F9E +#define MCA_BASE_POS_IO_PORT 0x96 +#define MCA_INFO_POS_IO_PORT 0x100 + +#define MCA_IO_PORT_MASK 0x0070 + + USHORT ActualPosId, POSConfig; + USHORT IOPortOffset; + ULONG MemoryAddress; + + PVOID VirtualPOSBaseAddress; // Virtual address + PVOID VirtualPOSInfoAddress; // Virtual address + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UCHAR OneByte; + + // + // We need to read the POS Adapter ID and make sure the controller + // is one of ours. Use the Slot number and the POS ID we + // installed during configuration from the registry. + // + + DigiDump( DIGIINIT, ("Pcimac: PcimacPOSID: 0x%x\n", + PcimacPOSID) ); + + DigiDump( DIGIINIT, ("--------- SlotNumber: 0x%x\n", + SlotNumber) ); + + *BaseIO = 0; + *BaseMemory = 0; + + Status = NdisMRegisterIoPortRange( &VirtualPOSBaseAddress, + AdapterHandle, + MCA_BASE_POS_IO_PORT, + 1 ); + + if( Status != NDIS_STATUS_SUCCESS ) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS, + 0); + goto PcimacInitMCAExit; + } + + Status = NdisMRegisterIoPortRange( &VirtualPOSInfoAddress, + AdapterHandle, + MCA_INFO_POS_IO_PORT, + 1 ); + + if( Status != NDIS_STATUS_SUCCESS ) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS, + 0); + goto PcimacInitMCAExit; + } + + + // Enable the POS information for the slot we are interested in. + NdisRawWritePortUchar( VirtualPOSBaseAddress, (UCHAR)(SlotNumber + 7) ); + + NdisRawReadPortUchar( (PVOID)((ULONG)VirtualPOSInfoAddress + 1), + (PUCHAR)&OneByte ); + ActualPosId = ((USHORT)OneByte << 8); + NdisRawReadPortUchar( VirtualPOSInfoAddress, (PUCHAR)&OneByte ); + ActualPosId |= OneByte; + + DigiDump( DIGIINIT, ("POS Adapter ID = 0x%hx\n", ActualPosId) ); + + if( ActualPosId != PcimacPOSID ) + { + NdisWriteErrorLogEntry(AdapterHandle, + NDIS_ERROR_CODE_ADAPTER_NOT_FOUND, + 0); + Status = NDIS_STATUS_ADAPTER_NOT_FOUND; + goto PcimacInitMCAError2; + } + + // + // Clear the VPD. + // + NdisRawWritePortUchar( (ULONG)VirtualPOSInfoAddress + 6, 0 ); + + NdisRawReadPortUchar( (ULONG)VirtualPOSInfoAddress + 4, + (PUCHAR)&OneByte ); + MemoryAddress = ((ULONG)OneByte << 22); + NdisRawReadPortUchar( (ULONG)VirtualPOSInfoAddress + 3, + (PUCHAR)&OneByte ); + MemoryAddress |= ((ULONG)OneByte << 14); + + NdisRawReadPortUchar( (ULONG)VirtualPOSInfoAddress + 2, + (PUCHAR)&OneByte ); + POSConfig = OneByte; + + IOPortOffset = (POSConfig & MCA_IO_PORT_MASK) >> 4; + + DigiDump( DIGIINIT, ("POS config read = 0x%hx\n" + " IOPortOffset = 0x%hx, MemoryAddress = 0x%x," + " IOPort = 0x%hx\n", + POSConfig, IOPortOffset, MemoryAddress, + MCAIOAddressTable[IOPortOffset]) ); + + *BaseIO = MCAIOAddressTable[IOPortOffset]; + + *BaseMemory = MemoryAddress; + + // Disable the POS information. + NdisRawWritePortUchar( VirtualPOSBaseAddress, 0 ); + + // + // Unmap the POS register + // + +PcimacInitMCAError2:; + + NdisMDeregisterIoPortRange( AdapterHandle, + MCA_INFO_POS_IO_PORT, + 1, + VirtualPOSInfoAddress ); + + NdisMDeregisterIoPortRange( AdapterHandle, + MCA_BASE_POS_IO_PORT, + 1, + VirtualPOSBaseAddress ); + +PcimacInitMCAExit:; + + return( Status ); +} // end PcimacInitMCA + + + diff --git a/private/ntos/ndis/digi/pcimac/pcimac.rc b/private/ntos/ndis/digi/pcimac/pcimac.rc new file mode 100644 index 000000000..9d4532558 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/pcimac.rc @@ -0,0 +1,28 @@ +#if !BINARY_COMPATIBLE +#include +#else +#include +#endif + +#include + +#ifdef VER_COMPANYNAME_STR +#undef VER_COMPANYNAME_STR +#endif +#define VER_COMPANYNAME_STR "Digi International Inc." + +#define VER_LEGALCOPYRIGHT_YEARS "1992-1996" + +#define VER_LEGALCOPYRIGHT_STR "Copyright " VER_LEGALCOPYRIGHT_YEARS ", Digi International Inc. All rights reserved." + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_NETWORK +#define VER_FILEDESCRIPTION_STR "Digi BRI-ISDN Adapter Device Driver" +#define VER_INTERNALNAME_STR "pcimac.sys" +#define VER_ORIGINALFILENAME_STR "pcimac.sys" + +#define VER_FILEVERSION 2.5.0.3 +#define VER_FILEVERSION_STR "v2.5.0.3 (E)" + +#include "common.ver" + diff --git a/private/ntos/ndis/digi/pcimac/res.h b/private/ntos/ndis/digi/pcimac/res.h new file mode 100644 index 000000000..15bd9f5d0 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/res.h @@ -0,0 +1,52 @@ +/* + * RES.H - Resource ownership classe, master include file + */ + + +#ifndef _RES_ +#define _RES_ + +/* resource classes */ +#define RES_CLASS_MEM 0 +#define RES_CLASS_IO 1 + +/* return values */ +#define RES_E_SUCC 0 +#define RES_E_NOMEM 1 + +// Return Values for GetResourceSem +#define RES_BUSY 0 +#define RES_FREE 1 + +/* resource structure */ +typedef struct _RES +{ + ULONG class; /* resource class */ + ULONG id; /* resource id (value) */ + ULONG data; /* resource attached data */ + + ULONG cre_ref; /* creation refrence */ + ULONG own_ref; /* ownership refrence */ + + VOID *owner; /* current owner, NULL == none */ + + NDIS_SPIN_LOCK lock; /* scheduling lock */ + + SEMA proc_sema; /* processing sema */ + +} RES; + + +/* operations */ +INT res_init(VOID); +VOID res_term(VOID); +RES* res_create(ULONG class, ULONG id); +INT res_destroy(VOID* res_1); +VOID res_own(VOID* res_1, VOID *owner); +VOID res_unown(VOID* res_1, VOID *owner); +VOID res_get_data(VOID* res_1, ULONG* data); +VOID res_set_data(VOID* res_1, ULONG data); +INT GetResourceSem (VOID*); +VOID FreeResourceSem (VOID*); + +#endif /* _RES_ */ diff --git a/private/ntos/ndis/digi/pcimac/res_core.c b/private/ntos/ndis/digi/pcimac/res_core.c new file mode 100644 index 000000000..892b4f325 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/res_core.c @@ -0,0 +1,261 @@ +/* + * RES_CORE.C - Resource ownership class, implementation + * + * as defined here, a resource has a class and an id (value). one ULONG + * of data may be attached to a resource. + * + * objects create a reference (handle) to the resource using res_create + * and free it using res_destroy. multiple objects may create references + * to the same object. + * + * ownership is aquired using res_own and released using res_unown. if + * an object already owns a resource, it may own it again (class keeps + * a refrence count). if an object (thread) asks for ownership of an + * already owned resource, if is suspended (using NdisAquireSpinLock) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* system limits */ +#define MAX_RES 128 + +/* assists */ +//#define LOCK NdisAcquireSpinLock(&res__lock) +//#define UNLOCK NdisReleaseSpinLock(&res__lock) + +/* global variables */ +NDIS_SPIN_LOCK res__lock; /* management lock */ +RES *res__tbl; + +/* initialize support */ +INT +res_init(VOID) +{ + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + + /* allocate memory object */ + NdisAllocateMemory((PVOID*)&res__tbl, (sizeof(RES) * MAX_RES), 0, pa); + if ( !res__tbl ) + { + D_LOG(D_ALWAYS, ("res_init: memory allocate failed!")); + return(RES_E_NOMEM); + } + D_LOG(D_ALWAYS, ("res_init: res__tbl: 0x%lx", res__tbl)); + + NdisZeroMemory (res__tbl, sizeof(RES) * MAX_RES); +// NdisAllocateSpinLock(&res__lock); + return(RES_E_SUCC); +} + +/* terminate support */ +VOID +res_term(VOID) +{ +// DbgPrint ("Resource Term: Entry\n"); +// NdisFreeSpinLock(&res__lock); + /* free memory */ + NdisFreeMemory(res__tbl, (sizeof(RES) * MAX_RES), 0); +} + +/* create a (refrence to a ) resource */ +RES* +res_create(ULONG class, ULONG id) +{ + RES *res; + INT n; + +// LOCK; + +// DbgPrint ("Resource Create: class: 0x%x, id: 0x%x\n",class, id); +// DbgPrint ("IRQL: 0x%x\n",KeGetCurrentIrql()); + /* scan for a matching slot */ + for ( n = 0 ; n < MAX_RES ; n++ ) + { + res = res__tbl + n; + + if ( res->cre_ref && (res->class == class) && (res->id == id) ) + { + /* found an already existing resource */ +// DbgPrint ("Resource Create: resource already exists!\n"); + res->cre_ref++; + break; + } + } + + /* if no such, try to create a new one */ + if (n >= MAX_RES) + for ( n = 0 ; n < MAX_RES ; n++ ) + { + res = res__tbl + n; + + if ( !res->cre_ref ) + { +// DbgPrint ("Resource Create: resource created!\n"); + /* found a free slot, fill */ + res->cre_ref++; + res->class = class; + res->id = id; + res->data = 0; + res->own_ref = 0; + NdisAllocateSpinLock(&res->lock); + /* init sema */ + sema_init(&res->proc_sema); + break; + } + } + +// UNLOCK; +// DbgPrint ("Resource Create exit: res: 0x%lx refcount: %d\n",res, res->cre_ref); +// DbgPrint (": IRQL: 0x%x\n",KeGetCurrentIrql()); + return(res); +} + +/* free (a refrence to) a resource, return 1 if really destroyed */ +INT +res_destroy(VOID *res_1) +{ + RES *res = (RES*)res_1; + INT really = 0; + +// LOCK; + +// DbgPrint ("Resource Destroy: Entry res: 0x%lx, refcount: %d\n",res, res->cre_ref); +// DbgPrint (": IRQL: 0x%x\n",KeGetCurrentIrql()); + /* decrement refrence count, if down to zero, free */ + res->cre_ref--; + if ( !res->cre_ref ) + { + NdisFreeSpinLock(&res->lock); + sema_term (&res->proc_sema); + really = 1; + } + +// UNLOCK; +// DbgPrint ("Resource Destroy: Exit\n"); +// DbgPrint (": IRQL: 0x%x\n",KeGetCurrentIrql()); + return(really); +} + +/* establish owership for a resource */ +VOID +res_own(VOID *res_1, VOID *owner) +{ + RES *res = (RES*)res_1; +// LOCK; + +// DbgPrint("res_own: enter, res: 0x%lx, owner: 0x%lx, owner ref: %d\n", res, res->owner, res->own_ref); +// DbgPrint (": IRQL: 0x%x\n",KeGetCurrentIrql()); + + /* if not owned, get it */ + if ( !res->own_ref ) + { + NdisAcquireSpinLock(&res->lock); + res->own_ref++; + res->owner = owner; + goto bye; + } + + /* check if already owned by self */ + if ( res->owner == owner ) + goto bye; + + /* else we have to wait for it */ +// UNLOCK; + NdisAcquireSpinLock(&res->lock); +// LOCK; + + /* no I have it, fill */ + res->own_ref++; + res->owner = owner; + + bye: +// UNLOCK; +// DbgPrint("res_own: exit, res: 0x%lx, owner: 0x%lx, owner ref: %d\n", res, res->owner, res->own_ref); +// DbgPrint (": IRQL: 0x%x\n",KeGetCurrentIrql()); + return; +} + +/* release ownership of a resource, it is assumed that owner is releasing */ +VOID +res_unown(VOID *res_1, VOID *owner) +{ + RES *res = (RES*)res_1; +// LOCK; + +// DbgPrint("res_unown: entry, res: 0x%lx, owner: 0x%lx owner ref: %d\n", res, owner, res->own_ref); +// DbgPrint (": IRQL: 0x%x\n",KeGetCurrentIrql()); + + if (!res->own_ref) + { + /* if free, onwership released */ +// UNLOCK; + return; + } + + /* decrement ownership count, if not down to zero - still owned */ + res->own_ref--; + + if ( res->own_ref ) + { +// UNLOCK; + return; + } + + res->owner = NULL; + + NdisReleaseSpinLock(&res->lock); + + /* if free, onwership released */ +// UNLOCK; + +// DbgPrint("res_unown: exit, res: 0x%lx, owner ref: %d\n", res, res->own_ref); +// DbgPrint (": IRQL: 0x%x\n",KeGetCurrentIrql()); +} + + + +/* get private data for a resource */ +VOID +res_get_data(VOID *res_1, ULONG *data) +{ + RES *res = (RES*)res_1; + *data = res->data; +} + + +/* set private data for a resource */ +VOID +res_set_data(VOID *res_1, ULONG data) +{ + RES *res = (RES*)res_1; + res->data = data; +} + +INT +GetResourceSem (VOID *Resource) +{ + RES *res = (RES*)Resource; + + if ( !sema_get(&res->proc_sema) ) + return(RES_BUSY); + else + return(RES_FREE); +} + +VOID +FreeResourceSem (VOID *Resource) +{ + RES *res = (RES*)Resource; + sema_free(&res->proc_sema); +} + diff --git a/private/ntos/ndis/digi/pcimac/sema.h b/private/ntos/ndis/digi/pcimac/sema.h new file mode 100644 index 000000000..97e70f200 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/sema.h @@ -0,0 +1,8 @@ +/* + * SEMA.H - simple semaphores + */ + +#ifndef _SEMA_ +#define _SEMA_ + +#endif /* _SEMA */ diff --git a/private/ntos/ndis/digi/pcimac/sources b/private/ntos/ndis/digi/pcimac/sources new file mode 100644 index 000000000..edece9873 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/sources @@ -0,0 +1,74 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=ndis + +TARGETNAME=pcimac +TARGETPATH=$(BASEDIR)\public\sdk\lib +TARGETTYPE=DRIVER + +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib \ + ..\lib\*\digifile.lib + +!IF 0 + The order of the following include file paths is important +!ENDIF +INCLUDES=..\inc;$(BASEDIR)\private\ntos\inc + +C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DBINARY_COMPATIBLE=0 + +MSC_WARNING_LEVEL=/W3 /WX + +SOURCES= \ + pcimac.c \ + ansihelp.c \ + idd_init.c \ + idd_nv.c \ + idd_io.c \ + idd_run.c \ + idd_proc.c \ + idd_msg.c \ + mtl_tx.c \ + mtl_init.c \ + mtl_set.c \ + mtl_rx.c \ + mtl_tick.c \ + cm_init.c \ + cm_prof.c \ + cm_stat.c \ + cm_timer.c \ + cm_state.c \ + cm_q931.c \ + cm_conn.c \ + cm_chan.c \ + res_core.c \ + io_core.c \ + wan_conn.c \ + trc_core.c \ + util.c \ + wanoid.c \ + tapioid.c \ + lanoid.c \ + pcimac.rc +# disp.c \ + + +RELATIVE_DEPTH=..\.. diff --git a/private/ntos/ndis/digi/pcimac/tapioid.c b/private/ntos/ndis/digi/pcimac/tapioid.c new file mode 100644 index 000000000..f9dd9fa99 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/tapioid.c @@ -0,0 +1,2535 @@ +// +// Tapioid.c - File contains all functions that handle NDIS_OID's that +// come from the connection wrapper. +// +// +// +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +typedef struct tagOID_DISPATCH +{ + ULONG Oid; + NDIS_STATUS (*FuncPtr)(); +}OID_DISPATCH; + +// +// Tapi OID's +// +static OID_DISPATCH TapiOids[] = + { + {OID_TAPI_ACCEPT, TSPI_LineAccept}, + {OID_TAPI_ANSWER, TSPI_LineAnswer}, + {OID_TAPI_CLOSE, TSPI_LineClose}, + {OID_TAPI_CLOSE_CALL, TSPI_LineCloseCall}, + {OID_TAPI_CONDITIONAL_MEDIA_DETECTION, TSPI_LineConditionalMediaDetect}, + {OID_TAPI_CONFIG_DIALOG, TSPI_LineConfigDialog}, + {OID_TAPI_DEV_SPECIFIC, TSPI_LineDevSpecific}, + {OID_TAPI_DIAL, TSPI_LineDial}, + {OID_TAPI_DROP, TSPI_LineDrop}, + {OID_TAPI_GET_ADDRESS_CAPS, TSPI_LineGetAddressCaps}, + {OID_TAPI_GET_ADDRESS_ID, TSPI_LineGetAddressID}, + {OID_TAPI_GET_ADDRESS_STATUS, TSPI_LineGetAddressStatus}, + {OID_TAPI_GET_CALL_ADDRESS_ID, TSPI_LineGetCallAddressID}, + {OID_TAPI_GET_CALL_INFO, TSPI_LineGetCallInfo}, + {OID_TAPI_GET_CALL_STATUS, TSPI_LineGetCallStatus}, + {OID_TAPI_GET_DEV_CAPS, TSPI_LineGetDevCaps}, + {OID_TAPI_GET_DEV_CONFIG, TSPI_LineGetDevConfig}, + {OID_TAPI_GET_EXTENSION_ID, TSPI_LineGetExtensionID}, + {OID_TAPI_GET_ID, TSPI_LineGetID}, + {OID_TAPI_GET_LINE_DEV_STATUS, TSPI_LineGetLineDevStatus}, + {OID_TAPI_MAKE_CALL, TSPI_LineMakeCall}, + {OID_TAPI_NEGOTIATE_EXT_VERSION, TSPI_LineNegotiateExtVersion}, + {OID_TAPI_OPEN, TSPI_LineOpen}, + {OID_TAPI_PROVIDER_INITIALIZE, TSPI_ProviderInit}, + {OID_TAPI_PROVIDER_SHUTDOWN, TSPI_ProviderShutdown}, + {OID_TAPI_SECURE_CALL, TSPI_LineSecureCall}, + {OID_TAPI_SELECT_EXT_VERSION, TSPI_LineSelectExtVersion}, + {OID_TAPI_SEND_USER_USER_INFO, TSPI_LineSendUserToUserInfo}, + {OID_TAPI_SET_APP_SPECIFIC, TSPI_LineSetAppSpecific}, + {OID_TAPI_SET_CALL_PARAMS, TSPI_LineSetCallParams}, + {OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, TSPI_LineSetDefaultMediaDetection}, + {OID_TAPI_SET_DEV_CONFIG, TSPI_LineSetDevConfig}, + {OID_TAPI_SET_MEDIA_MODE, TSPI_LineSetMediaMode}, + {OID_TAPI_SET_STATUS_MESSAGES, TSPI_LineSetStatusMessage} + }; + +#define MAX_TAPI_SUPPORTED_OIDS 34 + + +VOID +(*CallStateProc[MAX_STATE][MAX_STATE])(CM*) = +{ + // + // LINE_ST_IDLE + // + { + NoSignal, // LINE_ST_IDLE + NoSignal, // LINE_ST_LISTEN + SignalCallProceeding, // LINE_ST_WAITCONN + SignalConnectSuccess, // LINE_ST_CONN + }, + + // + // LINE_ST_LISTEN + // + { + SignalListenFailure, // LINE_ST_IDLE + NoSignal, // LINE_ST_LISTEN + NoSignal, // LINE_ST_WAITCONN + SignalListenSuccess // LINE_ST_CONN + }, + + // + // LINE_ST_WAITCONN + // + { + SignalConnectFailure, // LINE_ST_IDLE + NoSignal, // LINE_ST_LISTEN + SignalCallProceeding, // LINE_ST_WAITCONN + SignalConnectSuccess // LINE_ST_CONN + }, + + // + // LINE_ST_CONN + // + { + SignalDisconnect, // LINE_ST_IDLE (only for incoming disconnect) + NoSignal, // LINE_ST_LISTEN + NoSignal, // LINE_ST_WAITCONN + NoSignal // LINE_ST_CONN + } +}; + +NDIS_STATUS +TapiOidProc( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesReadWritten, + PULONG BytesNeeded + ) +{ + ADAPTER *Adapter = (ADAPTER*)AdapterContext; + ULONG n; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + for (n = 0; n < MAX_TAPI_SUPPORTED_OIDS; n++) + { + if (Oid == TapiOids[n].Oid) + { + Status = (*TapiOids[n].FuncPtr)(Adapter, InfoBuffer); + return(Status); + } + } + return(NDIS_STATUS_INVALID_OID); +} + + +NDIS_STATUS +TSPI_LineAccept( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_ACCEPT TapiBuffer = (PNDIS_TAPI_ACCEPT)InfoBuffer; + + D_LOG(D_ENTRY, ("LineAccept: hdCall: 0x%lx", TapiBuffer->hdCall)); + +// return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); + return(NDIS_STATUS_SUCCESS); + +} + +NDIS_STATUS +TSPI_LineAnswer( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_ANSWER TapiBuffer = (PNDIS_TAPI_ANSWER)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + CM *cm; + CM_PROF *Prof; + ULONG Param1 = 0, Param2 = 0, Param3 = 0, m, n; + + D_LOG(D_ENTRY, ("LineAnwser: hdCall: 0x%lx", TapiBuffer->hdCall)); + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + // + // get the profile pointer for this call + // + Prof = (CM_PROF*)&cm->dprof; + + TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + + cm->TapiCallState = LINECALLSTATE_CONNECTED; + + // + // indicate line event with callstate connected + // + Param1 = cm->TapiCallState; + Param3 = LINEMEDIAMODE_DIGITALDATA; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + cm->htCall, + LINE_CALLSTATE, + &Param1, + &Param2, + &Param3); + + mtl_set_conn_state(cm->mtl, Prof->chan_num, 1); + + // + // indicate line up to wan wrapper + // + WanLineup(cm, NULL); + + // + // mark idd resources as being in use + // + for (n = 0; n < Prof->chan_num; n++) + { + IDD *idd = Prof->chan_tbl[n].idd; + + // + // this idd should not be busy yet + // + if (idd->CallInfo.ChannelsUsed < MAX_CHANNELS_PER_IDD) + { + // + // each idd can support two calls + // + for (m = 0; m < MAX_CHANNELS_PER_IDD; m++) + { + if (idd->CallInfo.cm[m] == NULL) + { + idd->CallInfo.cm[m] = cm; + idd->CallInfo.ChannelsUsed++; + break; + } + } + } + } + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineClose( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_CLOSE TapiBuffer = (PNDIS_TAPI_CLOSE)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + ULONG n; + CM *cm; + + D_LOG(D_ENTRY, ("LineClose: hdLine: 0x%lx", TapiBuffer->hdLine)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_FAILURE); + + // + // store lineinfo pointer in line table + // +// for (n = 0; n < MAX_IDD_PER_ADAPTER; n++) + for (n = 0; n < MAX_CM_PER_ADAPTER; n++) + { + if (Adapter->TapiLineInfo[n] == TapiLineInfo) + break; + } + +// if (n == MAX_IDD_PER_ADAPTER) + if (n == MAX_CM_PER_ADAPTER) + return(NDIS_STATUS_FAILURE); + + Adapter->TapiLineInfo[n] = NULL; + + // + // get backpointer to connection object + // + cm = TapiLineInfo->cm; + + cm->TapiLineInfo = NULL; + + // + // if call is active disconnect it + // + if (cm->TapiCallState != LINECALLSTATE_IDLE) + cm_disconnect(cm); + + // + // destroy line object + // + NdisFreeMemory((PVOID)TapiLineInfo, + sizeof(TAPI_LINE_INFO), + 0); + + + return(NDIS_STATUS_SUCCESS); +} + + +NDIS_STATUS +TSPI_LineCloseCall( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_CLOSE_CALL TapiBuffer = (PNDIS_TAPI_CLOSE_CALL)InfoBuffer; + CM* cm; + + D_LOG(D_ENTRY, ("LineCloseCall: hdCall: 0x%lx", TapiBuffer->hdCall)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + // + // if call is active disconnect it + // + if (cm->TapiCallState != LINECALLSTATE_IDLE) + cm_disconnect(cm); + + cm->TapiCallState = LINECALLSTATE_IDLE; + cm->htCall = (HTAPI_CALL)NULL; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineConditionalMediaDetect( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION TapiBuffer = (PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + + D_LOG(D_ENTRY, ("LineConditionalMediaDetect: hdLine: 0x%lx, MediaModes: 0x%x", TapiBuffer->hdLine, TapiBuffer->ulMediaModes)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + if (TapiBuffer->ulMediaModes & + (TapiLineInfo->MediaModes ^ 0xFFFFFFFF)) + return(NDIS_STATUS_TAPI_INVALMEDIAMODE); + + if (TapiBuffer->LineCallParams.ulBearerMode & + (TapiLineInfo->BearerModes ^ 0xFFFFFFFF)) + return(NDIS_STATUS_TAPI_RESOURCEUNAVAIL); + + if ((TapiBuffer->LineCallParams.ulMinRate < 56000) || + (TapiBuffer->LineCallParams.ulMaxRate > 64000)) + return(NDIS_STATUS_TAPI_RESOURCEUNAVAIL); + + if (TapiBuffer->LineCallParams.ulAddressMode != LINEADDRESSMODE_ADDRESSID) + return(NDIS_STATUS_TAPI_RESOURCEUNAVAIL); + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineConfigDialog( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_CONFIG_DIALOG TapiBuffer = (PNDIS_TAPI_CONFIG_DIALOG)InfoBuffer; + + D_LOG(D_ENTRY, ("LineConfigDialog: DeviceID: 0x%x", TapiBuffer->ulDeviceID)); + + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineDevSpecific( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_DEV_SPECIFIC TapiBuffer = (PNDIS_TAPI_DEV_SPECIFIC)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + + D_LOG(D_ENTRY, ("LineDevSpecific: hdLine: 0x%lx, hdCall: 0x%lx, AddressID: 0x%x", \ + TapiBuffer->hdLine, TapiBuffer->hdCall, TapiBuffer->ulAddressID)); + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineDial( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_DIAL TapiBuffer = (PNDIS_TAPI_DIAL)InfoBuffer; + CM_PROF* Prof; + CM* cm; + + D_LOG(D_ENTRY, ("LineDial: hdCall: 0x%lx", TapiBuffer->hdCall)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + if (cm->TapiCallState != LINECALLSTATE_IDLE) + return(NDIS_STATUS_TAPI_INVALCALLSTATE); + + // + // check address size if zero return error + // + if (TapiBuffer->ulDestAddressSize == 0) + return(NDIS_STATUS_TAPI_INVALADDRESS); + + // + // get profile for this call + // + Prof = (CM_PROF*)&cm->oprof; + + // + // parse address and put in cm + // + StashAddress(Prof, TapiBuffer->ulDestAddressSize, TapiBuffer->szDestAddress); + + // + // get a line to call on + // + if (FindAndStashIdd(cm, Prof)) + return(NDIS_STATUS_TAPI_RESOURCEUNAVAIL); + + // + // set initial line state + // + cm->CallState = CALL_ST_WAITCONN; + + // + // figure out call type + // + cm->ConnectionType = CM_PPP; + + // + // attempt call + // + cm_connect(cm); + + cm->TapiCallState = LINECALLSTATE_PROCEEDING; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineDrop( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_DROP TapiBuffer = (PNDIS_TAPI_DROP)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + CM* cm; + CM_PROF *Prof; + + D_LOG(D_ENTRY, ("LineDrop: hdCall: 0x%lx", TapiBuffer->hdCall)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + // + // get line info pointer + // + TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + cm->CallState = CALL_ST_IDLE; + + // + // disconnect the call + // + if (cm->TapiCallState != LINECALLSTATE_DISCONNECTED && + cm->TapiCallState != LINECALLSTATE_BUSY) + cm_disconnect(cm); + + // + // indicate linedown to wan wrapper + // + if (cm->LinkHandle) + WanLinedown(cm); + + // + // send call state to idle + // + cm->TapiCallState = LINECALLSTATE_IDLE; + + // + // if this was a listening Line reissue a listen + // + if (TapiLineInfo->TapiLineWasListening) + { + Prof = (CM_PROF*)&cm->oprof; + SetDefaultListenProf(Prof, GetIDFromLine(Adapter, TapiLineInfo)); + cm_listen(cm); + cm->CallState = CALL_ST_LISTEN; + } + + FreeIddCallResources(cm); + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetAddressCaps( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_ADDRESS_CAPS TapiBuffer = (PNDIS_TAPI_GET_ADDRESS_CAPS)InfoBuffer; + LINE_ADDRESS_CAPS* AddressCaps = &TapiBuffer->LineAddressCaps; + ULONG AddressLength, AvailMem; + CM *cm; + + D_LOG(D_ENTRY, ("LineGetAddressCaps: DeviceID: 0x%x", TapiBuffer->ulDeviceID)); + // + // Validate extension + // + VALIDATE_EXTENSION(TapiBuffer->ulExtVersion); + + // + // only support two addresss per line + // + if (TapiBuffer->ulAddressID > MAX_CALL_PER_LINE) + return(NDIS_STATUS_TAPI_INVALADDRESSID); + + // + // get conn object that is or would be attached to this line + // +// cm = GetCmFromDeviceID (Adapter, +// TapiBuffer->ulDeviceID, +// TapiBuffer->ulAddressID); + cm = GetCmFromDeviceID (Adapter, + TapiBuffer->ulDeviceID); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALADDRESSID); + + // + // validate structure size + // + AddressLength = __strlen(cm->LocalAddress) + 1; + AddressCaps->ulNeededSize = sizeof(LINE_ADDRESS_CAPS) + AddressLength; + AddressCaps->ulUsedSize = sizeof(LINE_ADDRESS_CAPS); + + AvailMem = AddressCaps->ulTotalSize - AddressCaps->ulUsedSize; + + if (AvailMem > 0) + { + ULONG SizeToCopy = (((ULONG)AvailMem > AddressLength) ? + AddressLength : AvailMem); + + NdisMoveMemory(((LPSTR)AddressCaps) + AddressCaps->ulUsedSize, + cm->LocalAddress, SizeToCopy); + + AddressCaps->ulAddressSize = SizeToCopy; + AddressCaps->ulAddressOffset = AddressCaps->ulUsedSize; + AddressCaps->ulUsedSize += SizeToCopy; + AvailMem -= SizeToCopy; + } + + // + // fill structure + // + AddressCaps->ulLineDeviceID = TapiBuffer->ulDeviceID; + + AddressCaps->ulDevSpecificSize = 0; + AddressCaps->ulDevSpecificOffset = 0; + + AddressCaps->ulAddressSharing = LINEADDRESSSHARING_PRIVATE; + AddressCaps->ulAddressStates = LINEADDRESSSTATE_OTHER | + LINEADDRESSSTATE_INUSEZERO | + LINEADDRESSSTATE_INUSEONE | + LINEADDRESSSTATE_NUMCALLS; + + AddressCaps->ulCallInfoStates = LINECALLINFOSTATE_CALLERID | + LINECALLINFOSTATE_CALLEDID; + + AddressCaps->ulCallerIDFlags = LINECALLPARTYID_ADDRESS | + LINECALLPARTYID_UNAVAIL; + + AddressCaps->ulCalledIDFlags = LINECALLPARTYID_ADDRESS | + LINECALLPARTYID_UNAVAIL; + + AddressCaps->ulConnectedIDFlags = LINECALLPARTYID_UNAVAIL; + + AddressCaps->ulRedirectionIDFlags = LINECALLPARTYID_UNAVAIL; + + AddressCaps->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL; + + AddressCaps->ulCallStates = LINECALLSTATE_IDLE | + LINECALLSTATE_OFFERING | +// LINECALLSTATE_BUSY | + LINECALLSTATE_CONNECTED | + LINECALLSTATE_PROCEEDING | + LINECALLSTATE_DISCONNECTED | + LINECALLSTATE_SPECIALINFO | + LINECALLSTATE_UNKNOWN; + + AddressCaps->ulDialToneModes = LINEDIALTONEMODE_UNAVAIL; + + AddressCaps->ulBusyModes = LINEBUSYMODE_UNAVAIL; + + AddressCaps->ulSpecialInfo = LINESPECIALINFO_UNAVAIL; + + AddressCaps->ulDisconnectModes = LINEDISCONNECTMODE_UNKNOWN; + + AddressCaps->ulMaxNumActiveCalls = 1; + AddressCaps->ulMaxNumOnHoldCalls = 0; + AddressCaps->ulMaxNumOnHoldPendingCalls = 0; + AddressCaps->ulMaxNumConference = 0; + AddressCaps->ulMaxNumTransConf = 0; + + AddressCaps->ulAddrCapFlags = LINEADDRCAPFLAGS_DIALED; + + AddressCaps->ulCallFeatures = LINECALLFEATURE_ANSWER | + LINECALLFEATURE_DIAL | + LINECALLFEATURE_DROP; + + AddressCaps->ulRemoveFromConfCaps = 0; + AddressCaps->ulRemoveFromConfState = 0; + AddressCaps->ulTransferModes = 0; + AddressCaps->ulParkModes = 0; + + AddressCaps->ulForwardModes = 0; + AddressCaps->ulMaxForwardEntries = 0; + AddressCaps->ulMaxSpecificEntries = 0; + AddressCaps->ulMinFwdNumRings = 0; + AddressCaps->ulMaxFwdNumRings = 0; + + AddressCaps->ulMaxCallCompletions = 0; + AddressCaps->ulCallCompletionConds = 0; + AddressCaps->ulCallCompletionModes = 0; + AddressCaps->ulNumCompletionMessages = 0; + AddressCaps->ulCompletionMsgTextEntrySize = 0; + AddressCaps->ulCompletionMsgTextSize = 0; + AddressCaps->ulCompletionMsgTextOffset = 0; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetAddressID( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_ADDRESS_ID TapiBuffer = (PNDIS_TAPI_GET_ADDRESS_ID)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + CM *cm; + UCHAR *LocalAddress; + + D_LOG(D_ENTRY, ("LineGetAddressID: hdLine: 0x%lx, AddressMode: 0x%x", TapiBuffer->hdLine, TapiBuffer->ulAddressMode)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + cm = TapiLineInfo->cm; + + LocalAddress = cm->LocalAddress; + + // + // return address id + // + if (__strncmp(LocalAddress, TapiBuffer->szAddress, TapiBuffer->ulAddressSize)) + return(NDIS_STATUS_TAPI_INVALADDRESS); + + TapiBuffer->ulAddressID = 0; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetAddressStatus( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_ADDRESS_STATUS TapiBuffer = (PNDIS_TAPI_GET_ADDRESS_STATUS)InfoBuffer; + LINE_ADDRESS_STATUS* AddrStatus = &TapiBuffer->LineAddressStatus; + TAPI_LINE_INFO* TapiLineInfo; + CM *cm; + + D_LOG(D_ENTRY, ("LineGetAddressStatus: hdLine: 0x%lx, ulAddressID: 0x%x", TapiBuffer->hdLine, TapiBuffer->ulAddressID)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + +// if (TapiBuffer->ulAddressID > 1) +// return(NDIS_STATUS_TAPI_INVALADDRESSID); + + if (TapiBuffer->ulAddressID != 0) + return(NDIS_STATUS_TAPI_INVALADDRESSID); + + AddrStatus->ulNeededSize = sizeof(LINE_ADDRESS_STATUS); + + if (AddrStatus->ulNeededSize > AddrStatus->ulTotalSize) + return(NDIS_STATUS_TAPI_STRUCTURETOOSMALL); + +// cm = (CM*)TapiLineInfo->cm[TapiBuffer->ulAddressID]; + cm = (CM*)TapiLineInfo->cm; + + AddrStatus->ulUsedSize = AddrStatus->ulNeededSize; + + AddrStatus->ulNumInUse = 1; + + if (cm->TapiCallState == LINECALLSTATE_CONNECTED) + { + AddrStatus->ulNumActiveCalls = 1; + AddrStatus->ulAddressFeatures = 0; + } + else + { + AddrStatus->ulNumActiveCalls = 0; + AddrStatus->ulAddressFeatures = LINEADDRFEATURE_MAKECALL; + } + + AddrStatus->ulNumOnHoldCalls = 0; + AddrStatus->ulNumOnHoldPendCalls = 0; + AddrStatus->ulNumRingsNoAnswer = 0; + AddrStatus->ulForwardNumEntries = 0; + AddrStatus->ulForwardSize = 0; + AddrStatus->ulForwardOffset = 0; + AddrStatus->ulTerminalModesSize = 0; + AddrStatus->ulTerminalModesOffset = 0; + AddrStatus->ulDevSpecificSize = 0; + AddrStatus->ulDevSpecificOffset = 0; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetCallAddressID( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_CALL_ADDRESS_ID TapiBuffer = (PNDIS_TAPI_GET_CALL_ADDRESS_ID)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + CM *cm; + + D_LOG(D_ENTRY, ("LineGetCallAddressID: hdCall: 0x%lx", TapiBuffer->hdCall)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + TapiLineInfo = cm->TapiLineInfo; + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + if( TapiLineInfo->cm != cm ) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + TapiBuffer->ulAddressID = 0; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetCallInfo( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_CALL_INFO TapiBuffer = (PNDIS_TAPI_GET_CALL_INFO)InfoBuffer; + LINE_CALL_INFO* CallInfo = &TapiBuffer->LineCallInfo; + TAPI_LINE_INFO* TapiLineInfo; + CM* cm; + + D_LOG(D_ENTRY, ("LineGetCallInfo: hdCall: 0x%lx", TapiBuffer->hdCall)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + // + // get line handle + // + TapiLineInfo = cm->TapiLineInfo; + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + // + // validate structure size + // + CallInfo->ulNeededSize = sizeof(LINE_CALL_INFO); + CallInfo->ulUsedSize = 0; + + if (CallInfo->ulNeededSize > CallInfo->ulTotalSize) + return(NDIS_STATUS_TAPI_STRUCTURETOOSMALL); + + CallInfo->ulUsedSize = sizeof(LINE_CALL_INFO); + + CallInfo->hLine = (ULONG)TapiLineInfo; + CallInfo->ulLineDeviceID = GetIDFromLine(Adapter, TapiLineInfo); + + if (TapiLineInfo->cm != cm) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + CallInfo->ulAddressID = 0; + + D_LOG(D_ENTRY, ("LineGetCallInfo: AddressId: %d", CallInfo->ulAddressID)); + + CallInfo->ulBearerMode = TapiLineInfo->CurBearerMode; + CallInfo->ulRate = cm->speed; + CallInfo->ulMediaMode = TapiLineInfo->CurMediaMode; + + CallInfo->ulAppSpecific = cm->AppSpecific; + CallInfo->ulCallID = 0; + CallInfo->ulRelatedCallID = 0; + CallInfo->ulCallParamFlags = 0; + CallInfo->ulCallStates = LINECALLSTATE_IDLE | + LINECALLSTATE_OFFERING | +// LINECALLSTATE_BUSY | + LINECALLSTATE_CONNECTED | + LINECALLSTATE_DISCONNECTED | + LINECALLSTATE_SPECIALINFO | + LINECALLSTATE_UNKNOWN; + + + CallInfo->DialParams.ulDialPause = 0; + CallInfo->DialParams.ulDialSpeed = 0; + CallInfo->DialParams.ulDigitDuration = 0; + CallInfo->DialParams.ulWaitForDialtone = 0; + + CallInfo->ulOrigin = (cm->was_listen) ? LINECALLORIGIN_EXTERNAL : LINECALLORIGIN_OUTBOUND; + CallInfo->ulReason = LINECALLREASON_UNAVAIL; + CallInfo->ulCompletionID = 0; + + CallInfo->ulCountryCode = 0; + CallInfo->ulTrunk = (ULONG)-1; + + // + // this should actually fill in called and + // calling address fields. we don't do this + // very well right now so I will defer this. + // + CallInfo->ulCallerIDFlags = LINECALLPARTYID_UNAVAIL; + CallInfo->ulCallerIDSize = 0; + CallInfo->ulCallerIDOffset = 0; + CallInfo->ulCallerIDNameSize = 0; + CallInfo->ulCallerIDNameOffset = 0; + + CallInfo->ulCalledIDFlags = LINECALLPARTYID_UNAVAIL; + CallInfo->ulCalledIDSize = 0; + CallInfo->ulCalledIDOffset = 0; + CallInfo->ulCalledIDNameSize = 0; + CallInfo->ulCalledIDNameOffset = 0; + + CallInfo->ulConnectedIDFlags = LINECALLPARTYID_UNAVAIL; + CallInfo->ulConnectedIDSize = 0; + CallInfo->ulConnectedIDOffset = 0; + CallInfo->ulConnectedIDNameSize = 0; + CallInfo->ulConnectedIDNameOffset = 0; + + CallInfo->ulRedirectionIDFlags = LINECALLPARTYID_UNAVAIL; + CallInfo->ulRedirectionIDSize = 0; + CallInfo->ulRedirectionIDOffset = 0; + CallInfo->ulRedirectionIDNameSize = 0; + CallInfo->ulRedirectionIDNameOffset = 0; + + CallInfo->ulRedirectingIDFlags = LINECALLPARTYID_UNAVAIL; + CallInfo->ulRedirectingIDSize = 0; + CallInfo->ulRedirectingIDOffset = 0; + CallInfo->ulRedirectingIDNameSize = 0; + CallInfo->ulRedirectingIDNameOffset = 0; + + CallInfo->ulDisplaySize = 0; + CallInfo->ulDisplayOffset = 0; + + CallInfo->ulUserUserInfoSize = 0; + CallInfo->ulUserUserInfoOffset = 0; + + CallInfo->ulHighLevelCompSize = 0; + CallInfo->ulHighLevelCompOffset = 0; + + CallInfo->ulLowLevelCompSize = 0; + CallInfo->ulLowLevelCompOffset = 0; + + CallInfo->ulChargingInfoSize = 0; + CallInfo->ulChargingInfoOffset = 0; + + CallInfo->ulTerminalModesSize = 0; + CallInfo->ulTerminalModesOffset = 0; + + CallInfo->ulDevSpecificSize = 0; + CallInfo->ulDevSpecificOffset = 0; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetCallStatus( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_CALL_STATUS TapiBuffer = (PNDIS_TAPI_GET_CALL_STATUS)InfoBuffer; + LINE_CALL_STATUS *CallStatus = &TapiBuffer->LineCallStatus; + CM *cm; + + D_LOG(D_ENTRY, ("LineGetCallStatus: hdCall: 0x%lx", TapiBuffer->hdCall)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + CallStatus->ulNeededSize = CallStatus->ulUsedSize = sizeof(LINE_CALL_STATUS); + + CallStatus->ulCallState = cm->TapiCallState; + + // + // fill the mode depending on the call state + // this should be done more intelligently + // i could find out more about why the call failed + // maybe later + // + switch (cm->TapiCallState) + { + case LINECALLSTATE_IDLE: + CallStatus->ulCallStateMode = 0; + CallStatus->ulCallFeatures = LINECALLFEATURE_DIAL; + break; + + case LINECALLSTATE_CONNECTED: + CallStatus->ulCallStateMode = 0; + CallStatus->ulCallFeatures = LINECALLFEATURE_DROP; + break; + + case LINECALLSTATE_OFFERING: + CallStatus->ulCallStateMode = 0; + CallStatus->ulCallFeatures = LINECALLFEATURE_ANSWER; + break; + + case LINECALLSTATE_DISCONNECTED: + if (cm->CauseValue == 0x11 || cm->SignalValue == 0x04) + CallStatus->ulCallStateMode = LINEDISCONNECTMODE_BUSY; + else + CallStatus->ulCallStateMode = LINEDISCONNECTMODE_NOANSWER; + break; + + case LINECALLSTATE_BUSY: + CallStatus->ulCallStateMode = LINEBUSYMODE_UNAVAIL; + break; + + case LINECALLSTATE_SPECIALINFO: + if (cm->NoActiveLine) + CallStatus->ulCallStateMode = LINESPECIALINFO_NOCIRCUIT; + break; + } + + CallStatus->ulDevSpecificSize = 0; + CallStatus->ulDevSpecificOffset = 0; + + D_LOG(D_ENTRY, ("LineGetCallStatus: CallState: 0x%x, CallStateMode: 0x%x", CallStatus->ulCallState, CallStatus->ulCallStateMode)); + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetDevCaps( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_DEV_CAPS TapiBuffer = (PNDIS_TAPI_GET_DEV_CAPS)InfoBuffer; + ULONG ulProviderInfoSize, ulLineNameSize, ulTotalSize; + LINE_DEV_CAPS* DevCaps = &TapiBuffer->LineDevCaps; + ULONG AvailMem, LocalID; + CHAR LineName[32], ProviderName[32]; + + + D_LOG(D_ENTRY, ("LineGetDevCaps: DeviceID: 0x%x", TapiBuffer->ulDeviceID)); + + // + // validate device ID + // + + LocalID = TapiBuffer->ulDeviceID - Adapter->TapiBaseID; + + // + // save size of buffer + // + ulTotalSize = DevCaps->ulTotalSize; + + // + // clear buffer so all default params will be zero + // + NdisZeroMemory(DevCaps, ulTotalSize); + + // + // restore total size + // + DevCaps->ulTotalSize = ulTotalSize; + + DevCaps->ulUsedSize = sizeof(LINE_DEV_CAPS); + +// +// Changed to support the new way that RAS is building TAPI names and +// address's. +// +// sprintf(ProviderName,"DigiBoard Pcimac"); +// ulProviderInfoSize = __strlen(ProviderName) + 1; + + // Provider info is of the following format + // \0\0 + // where - media name is - ISDN, + // device name is - Digiboard PCIMAC + // +#define MEDIA_STR "ISDN" +#define PROVIDER_STR "Pcimac" + sprintf(ProviderName,"%s%c%s%c", MEDIA_STR, '\0', PROVIDER_STR, '\0'); + ulProviderInfoSize = __strlen(MEDIA_STR) + __strlen(PROVIDER_STR) + 2 ; + + // + // should fill local id with something meaningfull + // + sprintf(LineName, "%s-%s%d", Adapter->Name,"Line", LocalID); + ulLineNameSize = __strlen(LineName) + 1; + + DevCaps->ulNeededSize = DevCaps->ulUsedSize + + ulProviderInfoSize + + ulLineNameSize; + + AvailMem = DevCaps->ulTotalSize - DevCaps->ulUsedSize; + + // + // fill provider info + // + if (AvailMem > 0) + { + ULONG SizeToCopy = (((ULONG)AvailMem > ulProviderInfoSize) ? + ulProviderInfoSize : AvailMem); + + NdisMoveMemory(((LPSTR)DevCaps) + DevCaps->ulUsedSize, + ProviderName, SizeToCopy); + + DevCaps->ulProviderInfoSize = SizeToCopy; + DevCaps->ulProviderInfoOffset = DevCaps->ulUsedSize; + DevCaps->ulUsedSize += SizeToCopy; + AvailMem -= SizeToCopy; + } + + // + // fill line name info + // + if (AvailMem != 0) + { + + ULONG SizeToCopy = (((ULONG)AvailMem > ulLineNameSize) ? + ulLineNameSize : AvailMem); + + NdisMoveMemory(((LPSTR)DevCaps) + DevCaps->ulUsedSize, + Adapter->Name, SizeToCopy); + + DevCaps->ulLineNameSize = SizeToCopy; + DevCaps->ulLineNameOffset = DevCaps->ulUsedSize; + DevCaps->ulUsedSize += SizeToCopy; + AvailMem -= SizeToCopy; + } + + DevCaps->ulPermanentLineID = (ULONG)Adapter; + DevCaps->ulStringFormat = STRINGFORMAT_ASCII; + DevCaps->ulAddressModes = LINEADDRESSMODE_ADDRESSID; + DevCaps->ulNumAddresses = MAX_CALL_PER_LINE; + DevCaps->ulBearerModes = LINEBEARERMODE_VOICE | + LINEBEARERMODE_DATA; + DevCaps->ulMaxRate = 64000; + DevCaps->ulMediaModes = LINEMEDIAMODE_DIGITALDATA | + LINEMEDIAMODE_UNKNOWN; + + DevCaps->ulMaxNumActiveCalls = MAX_CALL_PER_LINE; + DevCaps->ulLineStates = LINEDEVSTATE_CONNECTED | + LINEDEVSTATE_DISCONNECTED | + LINEDEVSTATE_OPEN | + LINEDEVSTATE_CLOSE | + LINEDEVSTATE_NUMCALLS | + LINEDEVSTATE_REINIT | + LINEDEVSTATE_INSERVICE | + LINEDEVSTATE_OUTOFSERVICE; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineGetDevConfig( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_DEV_CONFIG TapiBuffer = (PNDIS_TAPI_GET_DEV_CONFIG)InfoBuffer; + + D_LOG(D_ENTRY, ("LineGetDevConfig: DeviceID: 0x%x", TapiBuffer->ulDeviceID)); + + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineGetExtensionID( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_EXTENSION_ID TapiBuffer = (PNDIS_TAPI_GET_EXTENSION_ID)InfoBuffer; + + D_LOG(D_ENTRY, ("LineGetExtensionID: DeviceID: 0x%x", TapiBuffer->ulDeviceID)); + + // + // validate device ID + // + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineGetID( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_ID TapiBuffer = (PNDIS_TAPI_GET_ID)InfoBuffer; + CHAR *DeviceClass = ((CHAR*)TapiBuffer) + TapiBuffer->ulDeviceClassOffset; + VAR_STRING *DeviceID = &TapiBuffer->DeviceID; + ULONG AvailMem, StringLength; + PVOID VarStringOffset; + TAPI_LINE_INFO* TapiLineInfo; + CM *cm; + + D_LOG(D_ENTRY, ("LineGetID: Select: 0x%x, hdLine: 0x%lx, AddressID: 0x%x, hdCall: 0x%lx", \ + TapiBuffer->ulSelect, TapiBuffer->hdLine, TapiBuffer->ulAddressID, TapiBuffer->hdCall)); + + switch (TapiBuffer->ulSelect) + { + case LINECALLSELECT_LINE: + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + if (!__strnicmp(DeviceClass, "tapi/line", TapiBuffer->ulDeviceClassSize)) + { + AvailMem = DeviceID->ulTotalSize - sizeof(VAR_STRING); + StringLength = (AvailMem > 4) ? 4 : AvailMem; + DeviceID->ulNeededSize = sizeof(VAR_STRING) + 4; + DeviceID->ulUsedSize = sizeof(VAR_STRING) + StringLength; + DeviceID->ulStringFormat = STRINGFORMAT_BINARY; + DeviceID->ulStringSize = StringLength; + + VarStringOffset = ((CHAR*)&TapiBuffer->DeviceID) + sizeof(VAR_STRING); + NdisMoveMemory(VarStringOffset, &TapiLineInfo->LineID, StringLength); + DeviceID->ulStringOffset = sizeof(VAR_STRING); + return(NDIS_STATUS_SUCCESS); + } + break; + + case LINECALLSELECT_ADDRESS: + if (TapiBuffer->ulAddressID > 1) + return(NDIS_STATUS_TAPI_INVALADDRESSID); + break; + + case LINECALLSELECT_CALL: + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + if (cm->TapiCallState != LINECALLSTATE_CONNECTED) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + if (!__strnicmp(DeviceClass, "ndis", TapiBuffer->ulDeviceClassSize)) + { + AvailMem = DeviceID->ulTotalSize - sizeof(VAR_STRING); + StringLength = (AvailMem > 4) ? 4 : AvailMem; + DeviceID->ulNeededSize = sizeof(VAR_STRING) + 4; + DeviceID->ulUsedSize = sizeof(VAR_STRING) + StringLength; + DeviceID->ulStringFormat = STRINGFORMAT_BINARY; + DeviceID->ulStringSize = StringLength; + + VarStringOffset = ((CHAR*)TapiBuffer) + sizeof(NDIS_TAPI_GET_ID); + NdisMoveMemory(VarStringOffset, &cm->htCall, StringLength); + DeviceID->ulStringOffset = sizeof(VAR_STRING); + D_LOG(D_ALWAYS, ("LineGetID: Cookie: 0x%x", (ULONG)*(((CHAR*)TapiBuffer) + sizeof(NDIS_TAPI_GET_ID)))); + return(NDIS_STATUS_SUCCESS); + } + } + return(NDIS_STATUS_TAPI_INVALDEVICECLASS); +} + +NDIS_STATUS +TSPI_LineGetLineDevStatus( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_GET_LINE_DEV_STATUS TapiBuffer = (PNDIS_TAPI_GET_LINE_DEV_STATUS)InfoBuffer; + TAPI_LINE_INFO *TapiLineInfo; + LINE_DEV_STATUS *DevStatus = (LINE_DEV_STATUS*)&TapiBuffer->LineDevStatus; + CM *cm; + + D_LOG(D_ENTRY, ("LineGetLineDevStatus: hdLine: 0x%lx", TapiBuffer->hdLine)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + DevStatus->ulNeededSize = 0; + DevStatus->ulUsedSize = sizeof (LINE_DEV_STATUS); + + cm = (CM*)TapiLineInfo->cm; + + if (cm->TapiCallState == LINECALLSTATE_CONNECTED) + DevStatus->ulNumActiveCalls++; + + DevStatus->ulNumOnHoldCalls = 0; + DevStatus->ulNumOnHoldPendCalls = 0; + DevStatus->ulLineFeatures = LINEFEATURE_MAKECALL; + DevStatus->ulNumCallCompletions = 0; + DevStatus->ulRingMode = 0; + + DevStatus->ulRoamMode = 0; + + if (TapiLineInfo->TapiLineState == LINEDEVSTATE_INSERVICE) + { + DevStatus->ulDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED | + LINEDEVSTATUSFLAGS_INSERVICE; + DevStatus->ulSignalLevel = 0xFFFF; + DevStatus->ulBatteryLevel = 0xFFFF; + } + else + { + DevStatus->ulDevStatusFlags = 0; + DevStatus->ulSignalLevel = 0; + DevStatus->ulBatteryLevel = 0; + } + + DevStatus->ulTerminalModesSize = 0; + DevStatus->ulTerminalModesOffset = 0; + + DevStatus->ulDevSpecificSize = 0; + DevStatus->ulDevSpecificOffset = 0; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineMakeCall( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_MAKE_CALL TapiBuffer = (PNDIS_TAPI_MAKE_CALL)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + LINE_CALL_PARAMS* CallParams = (LINE_CALL_PARAMS*)&TapiBuffer->LineCallParams; + CM_PROF* Prof; + PUCHAR DialAddress; + CM* cm = NULL; + INT Ret, n; + ULONG ChannelsFilled; + + D_LOG(D_ENTRY, ("LineMakeCall: hdLine: 0x%lx, htCall: 0x%lx", \ + TapiBuffer->hdLine, TapiBuffer->htCall)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + // + // get a device to call on + // + if (TapiBuffer->bUseDefaultLineCallParams) + cm = (CM*)TapiLineInfo->cm; + else + { + if (CallParams->ulAddressMode == LINEADDRESSMODE_ADDRESSID) + { + if (CallParams->ulAddressID < MAX_CALL_PER_LINE) + cm = (CM*)TapiLineInfo->cm; + else + return(NDIS_STATUS_TAPI_INVALADDRESSID); + + } +// else if (CallParams->ulAddressMode == LINEADDRESSMODE_DIALABLEADDR) + else + { + cm = (CM*)TapiLineInfo->cm; + + if (__strncmp(cm->LocalAddress, + ((PUCHAR)CallParams) + CallParams->ulOrigAddressOffset, + CallParams->ulOrigAddressSize)) + return(NDIS_STATUS_TAPI_INVALADDRESS); + } +// else +// return(NDIS_STATUS_TAPI_INVALADDRESS); + } + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALADDRESS); + + Prof = &cm->oprof; + + // + // set default calling profile + // + SetDefaultCallingProf(Prof, GetIDFromLine(Adapter, TapiLineInfo)); + + if (!TapiBuffer->bUseDefaultLineCallParams) + { + // + // check address size if zero return error + // + if (TapiBuffer->ulDestAddressSize == 0) + return(NDIS_STATUS_TAPI_INVALADDRESS); + + // + // check media mode and make sure we support it + // + if (CallParams->ulMediaMode & + (TapiLineInfo->MediaModes ^ 0xFFFFFFFF)) + return(NDIS_STATUS_TAPI_INVALMEDIAMODE); + + TapiLineInfo->CurMediaMode = CallParams->ulMediaMode; + + // + // check bearer mode and make sure we support it + // + if (CallParams->ulBearerMode & + (TapiLineInfo->BearerModes ^ 0xFFFFFFFF)) + return(NDIS_STATUS_TAPI_RESOURCEUNAVAIL); + + TapiLineInfo->CurBearerMode = CallParams->ulBearerMode; + + // + // check min-max rate + // + if ((CallParams->ulMinRate < 56000) || + (CallParams->ulMaxRate > (8 * 64000))) + return(NDIS_STATUS_TAPI_RESOURCEUNAVAIL); + + // + // how many channels is this for + // + Prof->chan_num = (USHORT)(CallParams->ulMaxRate / 64000); + + if (CallParams->ulMaxRate > (ULONG)(Prof->chan_num * 64000)) + Prof->chan_num++; + + // + // figure out what the connection is for + // right now assume all single channel connections are PPP + // + if (Prof->chan_num == 1) + cm->ConnectionType = CM_PPP; + else + cm->ConnectionType = CM_DKF; + + // + // if max and min are equal set fallback to off + // + if (CallParams->ulMinRate == CallParams->ulMaxRate) + Prof->fallback = 0; + + // + // we need to set these params for all channels involved + // + for (n = 0; n < Prof->chan_num; n++) + { + // + // from bearer mode and min-max rate set channel type + // + if (CallParams->ulBearerMode & LINEBEARERMODE_VOICE) + Prof->chan_tbl[n].type = 2; + else + { + if ( 1 == (CallParams->ulMaxRate / (64000 * Prof->chan_num))) + Prof->chan_tbl[n].type = 0; + else + Prof->chan_tbl[n].type = 1; + } + + // + // accept any bchannel that the switch will give us + // + Prof->chan_tbl[n].bchan = 2; + } + } + + // + // get a line to call on + // + ChannelsFilled = FindAndStashIdd(cm, Prof); + + D_LOG(D_ALWAYS, ("LineMakeCall: ChannelsFilled %d", ChannelsFilled)); + // + // if there are no channels available we should report an error + // + if (!ChannelsFilled) + return(NDIS_STATUS_TAPI_INUSE); + + if (ChannelsFilled < Prof->chan_num) + { + if(Prof->fallback) + Prof->chan_num = (USHORT)ChannelsFilled; + else + { + FreeIddCallResources(cm); + return(NDIS_STATUS_TAPI_INUSE); + } + } + + // + // get pointer to dial address + // + DialAddress = ((PUCHAR)TapiBuffer) + TapiBuffer->ulDestAddressOffset; + + // + // parse address and put in cm + // + StashAddress(Prof, TapiBuffer->ulDestAddressSize, DialAddress); + + // + // set initial line state + // + cm->CallState = CALL_ST_WAITCONN; + + // + // save tapi's call handle + // + cm->htCall = TapiBuffer->htCall; + + // + // clear out link handle + // + cm->LinkHandle = NULL; + + // + // clear the PPPToRas Flag + // + cm->PPPToDKF = 0; + + // + // return our call handle + // + TapiBuffer->hdCall = (HDRV_CALL)cm; + + D_LOG(D_ENTRY, ("LineMakeCall: hdLine: 0x%lx", TapiLineInfo)); + + cm->TapiCallState = LINECALLSTATE_PROCEEDING; + + // + // attempt call + // + D_LOG(D_ALWAYS, ("LineMakeCall")); + + Ret = cm_connect(cm); + + D_LOG(D_EXIT, ("LineMakeCall: Ret: 0x%x", Ret)); + + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineNegotiateExtVersion( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_NEGOTIATE_EXT_VERSION TapiBuffer = (PNDIS_TAPI_NEGOTIATE_EXT_VERSION)InfoBuffer; + + D_LOG(D_ENTRY, ("LineNegotiateExtVersion: DeviceID: 0x%x", TapiBuffer->ulDeviceID)); + + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineOpen( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_OPEN TapiBuffer = (PNDIS_TAPI_OPEN)InfoBuffer; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + TAPI_LINE_INFO* TapiLineInfo; + NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + CM *cm; + ULONG n; + + D_LOG(D_ENTRY, ("LineOpen: DeviceID: 0x%x, htLine: 0x%lx", \ + TapiBuffer->ulDeviceID, TapiBuffer->htLine)); + + // + // verify device id + // + cm = GetCmFromDeviceID(Adapter, TapiBuffer->ulDeviceID); + + if (cm == NULL) + return(NDIS_STATUS_FAILURE); + + Status = NdisAllocateMemory((PVOID)&TapiLineInfo, + sizeof(TAPI_LINE_INFO), + 0, + HighestAcceptableMax); + + if (Status != NDIS_STATUS_SUCCESS) + return(NDIS_STATUS_TAPI_RESOURCEUNAVAIL); + + NdisZeroMemory(TapiLineInfo, sizeof(TAPI_LINE_INFO)); + + // + // store lineinfo pointer in line table + // + for (n = 0; n < MAX_CM_PER_ADAPTER; n++) + { + if (Adapter->TapiLineInfo[n] == NULL) + break; + } + if (n == MAX_CM_PER_ADAPTER) + return(NDIS_STATUS_FAILURE); + + D_LOG(D_ENTRY, ("LineOpen: hdLine: 0x%lx", TapiLineInfo)); + + TapiBuffer->hdLine = (ULONG)TapiLineInfo; + + TapiLineInfo->cm = cm; + cm->TapiLineInfo = TapiLineInfo; + cm->CallState = CALL_ST_IDLE; + + Adapter->TapiLineInfo[n] = TapiLineInfo; + + TapiLineInfo->LineID = TapiBuffer->ulDeviceID; + + TapiLineInfo->Adapter = Adapter; + + TapiLineInfo->idd = cm->idd; + + TapiLineInfo->htLine = TapiBuffer->htLine; + + TapiLineInfo->MediaModes = LINEMEDIAMODE_DIGITALDATA | + LINEMEDIAMODE_UNKNOWN; + + TapiLineInfo->BearerModes = LINEBEARERMODE_VOICE | + LINEBEARERMODE_DATA; + + TapiLineInfo->TapiLineState = LINEDEVSTATE_INSERVICE | + LINEDEVSTATE_OPEN; + + D_LOG(D_ENTRY, ("LineOpen: hdLine: 0x%lx", TapiBuffer->hdLine)); + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_ProviderInit( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_PROVIDER_INITIALIZE TapiBuffer = (PNDIS_TAPI_PROVIDER_INITIALIZE)InfoBuffer; + + D_LOG(D_ENTRY, ("ProviderInit: Adapter: 0x%x, IDBase: 0x%x", Adapter, TapiBuffer->ulDeviceIDBase)); + + // + // save our Base ID + // + Adapter->TapiBaseID = TapiBuffer->ulDeviceIDBase; + + // + // enumerate the number of lines for this adapter + // and return + // +// TapiBuffer->ulNumLineDevs = EnumIddPerAdapter(Adapter); + TapiBuffer->ulNumLineDevs = EnumCmPerAdapter(Adapter); + + // + // return our provider ID + // + TapiBuffer->ulProviderID = (ULONG)Adapter; + + D_LOG(D_ALWAYS, ("NumLines: 0x%x, ProviderID: 0x%x", \ + TapiBuffer->ulNumLineDevs, TapiBuffer->ulProviderID)); + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_ProviderShutdown( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_PROVIDER_SHUTDOWN TapiBuffer = (PNDIS_TAPI_PROVIDER_SHUTDOWN)InfoBuffer; + ULONG n; + + D_LOG(D_ENTRY, ("ProviderShutdown")); + + for (n = 0; Adapter->CmTbl[n] && n < MAX_CM_PER_ADAPTER; n++) + { + CM* cm = Adapter->CmTbl[n]; + + // + // complete all outstanding async events + // terminate all calls + // close any open lines + // + } + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineSecureCall( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SECURE_CALL TapiBuffer = (PNDIS_TAPI_SECURE_CALL)InfoBuffer; + + D_LOG(D_ENTRY, ("LineSecureCall: hdCall: 0x%lx", TapiBuffer->hdCall)); + + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineSelectExtVersion( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SELECT_EXT_VERSION TapiBuffer = (PNDIS_TAPI_SELECT_EXT_VERSION)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + + D_LOG(D_ENTRY, ("LineSelectExtVersion: hdLine: 0x%lx", TapiBuffer->hdLine)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineSendUserToUserInfo( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SEND_USER_USER_INFO TapiBuffer = (PNDIS_TAPI_SEND_USER_USER_INFO)InfoBuffer; + + D_LOG(D_ENTRY, ("LineSendUserToUserInfo: hdCall: 0x%lx", TapiBuffer->hdCall)); + + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineSetAppSpecific( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SET_APP_SPECIFIC TapiBuffer = (PNDIS_TAPI_SET_APP_SPECIFIC)InfoBuffer; + CM *cm; + + D_LOG(D_ENTRY, ("LineSetAppSpecific: hdCall: 0x%lx", TapiBuffer->hdCall)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + cm->AppSpecific = TapiBuffer->ulAppSpecific; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineSetCallParams( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SET_CALL_PARAMS TapiBuffer = (PNDIS_TAPI_SET_CALL_PARAMS)InfoBuffer; + CM *cm; + + D_LOG(D_ENTRY, ("LineSetCallParams: hdCall: 0x%lx", TapiBuffer->hdCall)); + D_LOG(D_ENTRY, ("BearerMode: 0x%x, MinRate: 0x%x, MaxRate: 0x%x", \ + TapiBuffer->ulBearerMode, TapiBuffer->ulMinRate, TapiBuffer->ulMaxRate)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + // + // should set some profile things here + // + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineSetDefaultMediaDetection( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION TapiBuffer = (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + CM *cm; + CM_PROF *Prof; + + D_LOG(D_ENTRY, ("LineSetDefaultMediaDetection: hdLine: 0x%lx, MediaModes: 0x%x", TapiBuffer->hdLine, TapiBuffer->ulMediaModes)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + // + // check for supported media mode + // +// if (TapiBuffer->ulMediaModes != LINEMEDIAMODE_DIGITALDATA) +// return(NDIS_STATUS_TAPI_INVALMEDIAMODE); + + cm = TapiLineInfo->cm; + Prof = &cm->oprof; + + cm->CallState = CALL_ST_LISTEN; + + SetDefaultListenProf(Prof, GetIDFromLine(Adapter, TapiLineInfo)); + + // + // issue a listen + // + cm_listen(cm); + + TapiLineInfo->TapiLineWasListening = 1; + + return(NDIS_STATUS_SUCCESS); +} + +NDIS_STATUS +TSPI_LineSetDevConfig( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SET_DEV_CONFIG TapiBuffer = (PNDIS_TAPI_SET_DEV_CONFIG)InfoBuffer; + + D_LOG(D_ENTRY, ("LineSetDevConfig: DeviceID: 0x%x", TapiBuffer->ulDeviceID)); + + return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineSetMediaMode( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SET_MEDIA_MODE TapiBuffer = (PNDIS_TAPI_SET_MEDIA_MODE)InfoBuffer; + CM *cm; + + D_LOG(D_ENTRY, ("LineSetMediaMode: hdCall: 0x%lx, MediaMode: 0x%x", TapiBuffer->hdCall, TapiBuffer->ulMediaMode)); + + // + // validate call handle and get call pointer + // + cm = GetCallFromCallHandle(Adapter, TapiBuffer->hdCall); + + if (cm == NULL) + return(NDIS_STATUS_TAPI_INVALCALLHANDLE); + + if (TapiBuffer->ulMediaMode != LINEMEDIAMODE_DIGITALDATA) // if mode is not digital + return (NDIS_STATUS_TAPI_INVALMEDIAMODE); + else + return (NDIS_STATUS_SUCCESS); + + //return(NDIS_STATUS_TAPI_OPERATIONUNAVAIL); +} + +NDIS_STATUS +TSPI_LineSetStatusMessage( + ADAPTER *Adapter, + PVOID InfoBuffer + ) +{ + PNDIS_TAPI_SET_STATUS_MESSAGES TapiBuffer = (PNDIS_TAPI_SET_STATUS_MESSAGES)InfoBuffer; + TAPI_LINE_INFO* TapiLineInfo; + + D_LOG(D_ENTRY, ("LineSetStatusMessage: hdLine: 0x%lx", TapiBuffer->hdLine)); + D_LOG(D_ENTRY, ("LineStates: 0x%x, AddressStates: 0x%x", TapiBuffer->ulLineStates, TapiBuffer->ulAddressStates)); + + // + // validate line handle and get line pointer + // + TapiLineInfo = GetLineFromLineHandle(Adapter, TapiBuffer->hdLine); + + if (TapiLineInfo == NULL) + return(NDIS_STATUS_TAPI_INVALLINEHANDLE); + + TapiLineInfo->LineStates = TapiBuffer->ulLineStates; + TapiLineInfo->AddressStates = TapiBuffer->ulAddressStates; + + return(NDIS_STATUS_SUCCESS); +} + + +TAPI_LINE_INFO* +GetLineFromLineHandle( + ADAPTER* Adapter, + HDRV_LINE hdLine + ) +{ + ULONG n; + CM* cm; + + for (n = 0; Adapter->CmTbl[n] && n < MAX_CM_PER_ADAPTER; n++) + { + cm = Adapter->CmTbl[n]; + + if (cm->TapiLineInfo == (TAPI_LINE_INFO*)hdLine) + break; + } + if (n >= MAX_CM_PER_ADAPTER) + return(NULL); + + return((TAPI_LINE_INFO*)hdLine); +} + +CM* +GetCallFromCallHandle( + ADAPTER* Adapter, + HDRV_CALL hdCall + ) +{ + ULONG n; + CM* cm; + + for (n = 0; n < MAX_CM_PER_ADAPTER; n++) + { + cm = (CM*)Adapter->CmTbl[n]; + + if (cm == (CM*)hdCall) + break; + } + if (n == MAX_CM_PER_ADAPTER) + return(NULL); + + return((CM*)hdCall); +} + +IDD* +GetIddFromDeviceID( + ADAPTER* Adapter, + ULONG DeviceID + ) +{ + ULONG LocalID; + + LocalID = DeviceID - Adapter->TapiBaseID; + + return (Adapter->IddTbl[LocalID]); +} + + +ULONG GetIDFromLine( ADAPTER *Adapter, + TAPI_LINE_INFO *TapiLineInfo ) +{ + ULONG n; + + for (n = 0; n < MAX_CM_PER_ADAPTER; n++) + { + CM *cm = Adapter->CmTbl[n]; + + if (TapiLineInfo->cm == cm) + break; + } + return(Adapter->TapiBaseID + n); +} + +CM* GetCmFromDeviceID( ADAPTER *Adapter, + ULONG DeviceID ) +{ + ULONG LocalID; + + LocalID = DeviceID - Adapter->TapiBaseID; + + return (Adapter->CmTbl[LocalID]); +} + +VOID +DoTapiStateCheck(CM* cm) +{ + TAPI_LINE_INFO* TapiLineInfo = cm->TapiLineInfo; + + D_LOG(D_ENTRY, ("DoTapiStateCheck: Line: 0x%lx, call: 0x%lx", TapiLineInfo, cm)); + + if (TapiLineInfo != NULL) + { + ULONG NewState = CALL_ST_DONTCARE; + + if ((NewState = GetCallState(cm)) != CALL_ST_DONTCARE) + { + D_LOG(D_ENTRY, ("CallState: 0x%x, NewState: 0x%x", cm->CallState, NewState)); + (*CallStateProc[cm->CallState][NewState])(cm); + cm->CallState = NewState; + } + } +} + +ULONG +GetCallState( + CM *cm + ) +{ + switch (cm->state) + { + case CM_ST_IDLE: + return(CALL_ST_IDLE); + + case CM_ST_LISTEN: + return(CALL_ST_LISTEN); + + case CM_ST_ACTIVE: + return(CALL_ST_CONN); + + case CM_ST_WAIT_ACT: + case CM_ST_IN_ACT: + case CM_ST_IN_SYNC: + return(CALL_ST_WAITCONN); + } + return(CALL_ST_DONTCARE); +} + +VOID +SignalCallProceeding( + CM *cm + ) +{ + ADAPTER *Adapter = (ADAPTER*)cm->Adapter; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + ULONG Param1 = 0, Param2 = 0, Param3 = 0; + + D_LOG(D_ENTRY, ("SignalCallProceeding: Line: 0x%lx, call: 0x%lx", TapiLineInfo, cm)); + cm->TapiCallState = LINECALLSTATE_PROCEEDING; + + // + // indicate callstate event call connected + // + Param1 = cm->TapiCallState; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + cm->htCall, + LINE_CALLSTATE, + &Param1, + &Param2, + &Param3); +} + +VOID +SignalListenFailure( + CM *cm + ) +{ + ADAPTER *Adapter = (ADAPTER*)cm->Adapter; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + CM_PROF *Prof = &cm->oprof; + ULONG Param1 = 0, Param2 = 0, Param3 = 0; + + D_LOG(D_ENTRY, ("SignalListenFailure: hdLine: 0x%lx, hdCall: 0x%lx", TapiLineInfo, cm)); + + FreeIddCallResources(cm); + + cm->TapiCallState = LINECALLSTATE_IDLE; + + // + // signal callstate event call idle + // + Param1 = cm->TapiCallState; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + cm->htCall, + LINE_CALLSTATE, + &Param1, + &Param2, + &Param3); + + SetDefaultListenProf(Prof, GetIDFromLine(Adapter, TapiLineInfo)); + cm_listen(cm); + cm->CallState = CALL_ST_LISTEN; +} + +VOID +SignalListenSuccess( + CM *cm + ) +{ + ADAPTER *Adapter = (ADAPTER*)cm->Adapter; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + ULONG Param1 = 0, Param2 = 0, Param3 = 0; + + D_LOG(D_ENTRY, ("SignalListenSuccess: hdLine: 0x%lx, hdcall: 0x%lx", TapiLineInfo, cm)); + + cm->TapiCallState = LINECALLSTATE_OFFERING; + + // + // indicate line_newcall + // + Param1 = (ULONG)cm; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + (ULONG)NULL, + LINE_NEWCALL, + &Param1, + &Param2, + &Param3); + + cm->htCall = Param2; + + D_LOG(D_ENTRY, ("SignalListenSuccess: Got 0x%lx as htCall from TAPI", cm->htCall)); + + // + // indicate callstate event call offering + // + Param1 = cm->TapiCallState; + Param2 = 0; + Param3 = LINEMEDIAMODE_DIGITALDATA; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + cm->htCall, + LINE_CALLSTATE, + &Param1, + &Param2, + &Param3); +} + +VOID +SignalConnectFailure( + CM *cm + ) +{ + ADAPTER *Adapter = (ADAPTER*)cm->Adapter; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + ULONG CauseValue = (ULONG)cm->CauseValue; + ULONG SignalValue = (ULONG)cm->SignalValue; + CM_PROF *Prof = &cm->oprof; + ULONG Param1 = 0, Param2 = 0, Param3 = 0; + + D_LOG(D_ENTRY, ("SignalConnectFailure: hdLine: 0x%lx, hdCall: 0x%lx", TapiLineInfo, cm)); + + + FreeIddCallResources(cm); + + // + // if this is set then the isdn line is not active + // + if (cm->NoActiveLine) + cm->TapiCallState = LINECALLSTATE_SPECIALINFO; + else + cm->TapiCallState = LINECALLSTATE_DISCONNECTED; + + D_LOG(D_ALWAYS, ("SignalConnectFailure: CallState: 0x%x", cm->TapiCallState)); +// +// currently gurdeep is only supporting the disconnect state +// we will give busy notification in getcallstatus with the +// disconnect mode +// +// else +// { +// // +// // if this was a busy line +// // +// if (CauseValue == 0x11 || SignalValue == 0x04) +// cm->TapiCallState = LINECALLSTATE_BUSY; +// else +// cm->TapiCallState = LINECALLSTATE_DISCONNECTED; +// } + + // + // indicate callstate event + // + Param1 = cm->TapiCallState; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + cm->htCall, + LINE_CALLSTATE, + &Param1, + &Param2, + &Param3); +} + +VOID +SignalConnectSuccess( + CM *cm + ) +{ + ADAPTER *Adapter = (ADAPTER*)cm->Adapter; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + ULONG Param1 = 0, Param2 = 0, Param3 = 0; + CM_PROF *Prof = (CM_PROF*)&cm->dprof; + + D_LOG(D_ENTRY, ("SignalConnectSuccess: hdLine: 0x%lx, hdCall: 0x%lx", TapiLineInfo, cm)); + cm->TapiCallState = LINECALLSTATE_CONNECTED; + + mtl_set_conn_state(cm->mtl, Prof->chan_num, 1); + + // + // indicate line up to wan wrapper + // + WanLineup(cm, NULL); + + // + // indicate callstate event call connected + // + Param1 = cm->TapiCallState; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + cm->htCall, + LINE_CALLSTATE, + &Param1, + &Param2, + &Param3); +} + +VOID +SignalDisconnect( + CM *cm + ) +{ + ADAPTER *Adapter = (ADAPTER*)cm->Adapter; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + CM_PROF *Prof = &cm->oprof; + ULONG Param1 = 0, Param2 = 0, Param3 = 0; + + D_LOG(D_ENTRY, ("SignalDisconnect: hdLine: 0x%lx, hdCall: 0x%lx", TapiLineInfo, cm)); + + cm->TapiCallState = LINECALLSTATE_DISCONNECTED; + + FreeIddCallResources(cm); + + // + // indicate callstate event call disconnected + // + Param1 = cm->TapiCallState; + Param3 = LINEMEDIAMODE_DIGITALDATA; + SendLineEvent(Adapter, + TapiLineInfo->htLine, + cm->htCall, + LINE_CALLSTATE, + &Param1, + &Param2, + &Param3); + +} + +VOID +NoSignal( + CM *cm + ) +{ + ADAPTER *Adapter = (ADAPTER*)cm->Adapter; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)cm->TapiLineInfo; + ULONG Param1 = 0, Param2 = 0, Param3 = 0; + + D_LOG(D_ENTRY, ("NoSignal: hdLine: 0x%lx, hdCall: 0x%lx", TapiLineInfo, cm)); + +} + + +// +// Send async line event to connection wrapper +// +VOID +SendLineEvent( + ADAPTER *Adapter, + HTAPI_LINE htLine, + HTAPI_CALL htCall, + ULONG ulMsg, + PULONG Param1, + PULONG Param2, + PULONG Param3 + ) +{ + NDIS_TAPI_EVENT LineEvent; + + LineEvent.htLine = htLine; + LineEvent.htCall = htCall; + LineEvent.ulMsg = ulMsg; + LineEvent.ulParam1 = *Param1; + LineEvent.ulParam2 = *Param2; + LineEvent.ulParam3 = *Param3; + + D_LOG(D_ENTRY, ("SendLineEvent: TapiLine: 0x%lx, TapiCall: 0x%lx", htLine, htCall)); + + + NdisMIndicateStatus(Adapter->Handle, + NDIS_STATUS_TAPI_INDICATION, + &LineEvent, + sizeof(NDIS_TAPI_EVENT)); + + NdisMIndicateStatusComplete(Adapter->Handle); + + // + // stuff to work with conn wrapper without wan wrapper + // +// NdisTapiIndicateStatus(Adapter, +// &LineEvent, +// sizeof(NDIS_TAPI_EVENT)); + + *Param1 = LineEvent.ulParam1; + *Param2 = LineEvent.ulParam2; + *Param3 = LineEvent.ulParam3; +} + + +// +// set default params for outgoing call +// +VOID +SetDefaultCallingProf( + CM_PROF *Profile, + ULONG DeviceID) +{ + CHAR ProfileName[24]; + + D_LOG(D_ENTRY, ("SetDefaultCallingProfile: Profile: 0x%lx, DeviceID: %d", Profile, DeviceID)); + + Profile->nailed = 0; + Profile->persist = 0; + Profile->permanent = 0; + Profile->frame_activated = 0; + Profile->fallback = 1; + Profile->HWCompression = 0; + Profile->rx_idle_timer = 0; + Profile->tx_idle_timer = 0; + Profile->chan_num = 1; + Profile->chan_tbl[0].lterm = 0; + Profile->chan_tbl[0].bchan = 2; + Profile->chan_tbl[0].type = 0; + Profile->chan_tbl[0].idd = NULL; + sprintf(ProfileName,"Connect%d",DeviceID); + NdisMoveMemory(Profile->name, ProfileName, strlen(Profile->name) + 1); + sprintf(ProfileName, "*"); + NdisMoveMemory(Profile->remote_name, ProfileName, strlen(Profile->remote_name) + 1); +} + +// +// set default params for outgoing call +// +VOID +SetDefaultListenProf( + CM_PROF *Profile, + ULONG DeviceID) +{ + CHAR ProfileName[24]; + + D_LOG(D_ENTRY, ("SetDefaultListenProfile: Profile: 0x%lx, DeviceID: %d", Profile, DeviceID)); + + Profile->nailed = 0; + Profile->persist = 0; + Profile->permanent = 0; + Profile->frame_activated = 0; + Profile->fallback = 1; + Profile->HWCompression = 0; + Profile->rx_idle_timer = 0; + Profile->tx_idle_timer = 0; + Profile->chan_num = 1; + Profile->chan_tbl[0].lterm = 0; + Profile->chan_tbl[0].bchan = 2; + Profile->chan_tbl[0].type = 0; + Profile->chan_tbl[0].idd = NULL; + sprintf(ProfileName,"Listen%d",DeviceID); + NdisMoveMemory(Profile->name, ProfileName, __strlen(Profile->name) + 1); + sprintf(ProfileName, "*"); + NdisMoveMemory(Profile->remote_name, ProfileName, __strlen(Profile->remote_name) + 1); +} + +// +// parse address and store in profile +// +VOID +StashAddress( + CM_PROF *Profile, + ULONG AddressLength, + PUCHAR Address + ) +{ + ULONG TempAddressLen, AddressToParseLen, i, j; + UCHAR Temp[128], AddressToParse[128]; + UCHAR *ChanDelim, *TempAddress; + USHORT n; + + TempAddressLen = AddressLength; + + NdisMoveMemory(Temp, Address, AddressLength); + + TempAddress = Temp; + + for (n = 0; n < Profile->chan_num; n++) + { + // + // : is the delimiter between channel address + // + if ( (ChanDelim = __strchr(TempAddress, ':')) == NULL) + { + AddressToParseLen = TempAddressLen; + NdisMoveMemory(AddressToParse, TempAddress, AddressToParseLen); + } + else + { + AddressToParseLen = ChanDelim - TempAddress; + NdisMoveMemory (AddressToParse, TempAddress, AddressToParseLen); + (PUCHAR)TempAddress = ChanDelim + 1; + } + + NdisZeroMemory(Profile->chan_tbl[n].addr, sizeof(Profile->chan_tbl[n].addr)); + + // + // only digits, *, or # are allowed in dialing number + // + for (i = 0, j = 0; i < AddressToParseLen; i++) + if (isdigit(AddressToParse[i]) || + (AddressToParse[i] == '*') || + (AddressToParse[i] == '#')) + Profile->chan_tbl[n].addr[j++] = AddressToParse[i]; + } +} + +VOID +FreeIddCallResources( + CM *cm + ) +{ + IDD *idd; + ULONG n, m; + + + for (n = 0; n < MAX_IDD_IN_SYSTEM; n++) + { + idd = GetIddByIndex(n); + + for (m = 0; m < MAX_CHANNELS_PER_IDD; m++) + { + if (idd && (idd->CallInfo.cm[m] == cm)) + { + idd->CallInfo.cm[m] = NULL; + idd->CallInfo.ChannelsUsed--; + } + } + } +} + +// +// check this cm's idd to see if in use +// if available mark usage and exit +// if not return error +// +ULONG +FindAndStashIdd( + CM *cm, + CM_PROF *Profile + ) +{ + ULONG m, ChannelsNeeded, ChannelsFound, ChannelsFilled; + IDD *idd; + + + ChannelsNeeded = Profile->chan_num; + ChannelsFound = ChannelsFilled = 0; + + // + // first check the idd that we own + // + idd = (IDD*)cm->idd; + + ChannelsFound = GetChannelsFromIdd(idd, cm, ChannelsFilled, ChannelsNeeded); + + ChannelsFilled = ChannelsFound; + + ChannelsNeeded -= ChannelsFound; + + // + // we need to check other idd's to see if we can steal some channels + // this will go away when Microsoft does multilink + // + if (ChannelsNeeded) + { + for (m = 0; m < MAX_IDD_IN_SYSTEM; m++) + { + IDD *idd = GetIddByIndex(m); + + if (idd && ChannelsNeeded) + { + ChannelsFound = GetChannelsFromIdd(idd, + cm, + ChannelsFilled, + ChannelsNeeded); + + ChannelsFilled += ChannelsFound; + + ChannelsNeeded -= ChannelsFound; + } + else + break; + } + } + + return(ChannelsFilled); +} + +ULONG +GetChannelsFromIdd ( + IDD* idd, + CM* cm, + ULONG BeginChannel, + ULONG ChannelsNeeded + ) +{ + ULONG n, m, ChannelsFilled; + CM_PROF *Profile = (CM_PROF*)&cm->oprof; + + + ChannelsFilled = 0; + + NdisAcquireSpinLock(&idd->lock); + + for (n = BeginChannel; n < BeginChannel + ChannelsNeeded; n++) + { + // + // if not all channels have been used + // + if (idd->CallInfo.ChannelsUsed < MAX_CHANNELS_PER_IDD) + { + for (m = 0; m < MAX_CHANNELS_PER_IDD; m++) + { + if (idd->CallInfo.cm[m] == NULL) + { + idd->CallInfo.cm[m] = cm; + idd->CallInfo.ChannelsUsed++; + if (idd->CallInfo.NumLTerms < MAX_LTERMS_PER_IDD) + Profile->chan_tbl[n].lterm = 0; + else + Profile->chan_tbl[n].lterm = (USHORT)m; + Profile->chan_tbl[n].idd = idd; + ChannelsFilled++; + break; + } + } + } + } + + NdisReleaseSpinLock(&idd->lock); + return(ChannelsFilled); +} diff --git a/private/ntos/ndis/digi/pcimac/tapioid.h b/private/ntos/ndis/digi/pcimac/tapioid.h new file mode 100644 index 000000000..f42f601ef --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/tapioid.h @@ -0,0 +1,440 @@ +// +// Tapioid.h - file contains defs and protos for tapioid.c +// +// +// +// + +// +// internal line states +// +#define CALL_ST_IDLE 0 +#define CALL_ST_LISTEN 1 +#define CALL_ST_WAITCONN 2 +#define CALL_ST_CONN 3 +#define CALL_ST_DONTCARE 0xFFFFFFFF +#define MAX_STATE 4 +#define PCIMAC_SPI_VER 0x00000000 + +// +// structure for tapi used line information +// +typedef struct tagTAPI_LINE +{ + // + // id of this line + // + ULONG LineID; + + // + // tapi's handle for this line + // + HTAPI_LINE htLine; + + // + // pointers to connection objects + // these are our tapi call handles + // +// VOID *cm[MAX_CALL_PER_LINE]; + VOID *cm; + + // + // async completion id + // + ULONG ulRequestPendingID; + + // + // media modes supportd + // + ULONG MediaModes; + + // + // bearer modes supported + // + ULONG BearerModes; + + // + // line states + // + ULONG LineStates; + + // + // address states + // + ULONG AddressStates; + + // + // media mode currently being monitored + // + ULONG CurMediaMode; + + // + // bearer mode of current call + // + ULONG CurBearerMode; + + // + // line state + // + ULONG TapiLineState; + + // + // line status + // + ULONG TapiLineStatus; + + // + // the idd for this line + // + VOID *idd; + + // + // the adapter for this line + // + VOID *Adapter; + + // + // listening flag + // + ULONG TapiLineWasListening; + +}TAPI_LINE_INFO; + + +#define VALIDATE_EXTENSION(version) + +NDIS_STATUS +TSPI_LineAccept( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineAnswer( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineClose( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineCloseCall( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineConditionalMediaDetect( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineConfigDialog( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineDevSpecific( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineDial( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineDrop( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetAddressCaps( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetAddressID( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetAddressStatus( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetCallAddressID( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetCallInfo( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetCallStatus( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetDevCaps( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetDevConfig( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetExtensionID( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetID( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineGetLineDevStatus( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineMakeCall( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineNegotiateExtVersion( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineOpen( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_ProviderInit( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_ProviderShutdown( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSecureCall( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSelectExtVersion( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSendUserToUserInfo( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSetAppSpecific( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSetCallParams( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSetDefaultMediaDetection( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSetDevConfig( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSetMediaMode( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +NDIS_STATUS +TSPI_LineSetStatusMessage( + ADAPTER *Adapter, + PVOID InfoBuffer + ); + +VOID +SignalCallProceeding( + CM *cm + ); + +VOID +SignalListenFailure( + CM *cm + ); + +VOID +SignalListenSuccess( + CM *cm + ); + +VOID +SignalConnectFailure( + CM *cm + ); + +VOID +SignalConnectSuccess( + CM *cm + ); + +VOID +SignalDisconnect( + CM *cm + ); + +VOID +NoSignal( + CM *cm + ); + +IDD* +GetIddFromDeviceID( + ADAPTER* Adapter, + ULONG DeviceID + ); + +CM* +GetCallFromCallHandle( + ADAPTER* Adapter, + HDRV_CALL hdCall + ); + +TAPI_LINE_INFO* +GetLineFromLineHandle( + ADAPTER* Adapter, + HDRV_LINE hdLine + ); + +ULONG +GetIDFromLine( + ADAPTER *Adapter, + TAPI_LINE_INFO *TapiLineInfo + ); + +VOID +DoTapiStateCheck( + CM* cm + ); + +ULONG +GetCallState( + CM *cm + ); + +VOID +SendLineEvent( + ADAPTER *Adapter, + HTAPI_LINE htLine, + HTAPI_CALL htCall, + ULONG ulMsg, + PULONG Param1, + PULONG Param2, + PULONG Param3 + ); + +VOID +SetDefaultCallingProf( + CM_PROF *Profile, + ULONG DeviceID + ); + +VOID +SetDefaultListenProf( + CM_PROF *Profile, + ULONG DeviceID + ); + +VOID +StashAddress( + CM_PROF *Profile, + ULONG AddressLength, + PUCHAR Address + ); + +VOID +FreeIddCallResources( + CM *cm + ); + +ULONG +FindAndStashIdd( + CM *cm, + CM_PROF *Profile + ); + +//CM* +//GetCmFromDeviceID( +// ADAPTER *Adapter, +// ULONG DeviceID, +// ULONG AddressID +// ); + +CM* +GetCmFromDeviceID( + ADAPTER *Adapter, + ULONG DeviceID + ); + +ULONG +GetChannelsFromIdd ( + IDD* idd, + CM* cm, + ULONG BeginChannel, + ULONG ChannelsNeeded + ); + diff --git a/private/ntos/ndis/digi/pcimac/trc.h b/private/ntos/ndis/digi/pcimac/trc.h new file mode 100644 index 000000000..05224c24f --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/trc.h @@ -0,0 +1,71 @@ +/* + * TRC.H - include file for all TRC modules + */ + +#ifndef _TRC_ +#define _TRC_ + +#include + +/* a trace context */ +typedef struct _TRC +{ + TRC_STATUS stat; /* status record */ + + TRC_ENTRY *ent_tbl; /* entry table (circ. buffer) */ + ULONG ent_put; /* put pointer */ + ULONG ent_get; /* get pointer */ + ULONG ent_num; /* # of entries */ + ULONG ent_seq; /* sequence # next to use */ + ULONG create_ref; /* object creation reference */ + ULONG start_ref; /* object start reference count */ + IDD *idd; /* idd back pointer */ +} TRC; + +/* TRC class operations */ +INT trc_init(ULONG); +INT trc_term(VOID); +INT trc_register_idd(VOID* idd); +INT trc_deregister_idd(VOID* idd); + +/* TRC context (object) operations */ +INT trc_create(VOID** ret_trc, ULONG depth); +INT trc_destroy(VOID* trc); +INT trc_control(VOID* idd, ULONG op, ULONG arg); +INT trc_get_status(VOID* trc, TRC_STATUS* stat); +INT trc_get_entry(VOID* trc, ULONG seq, TRC_ENTRY* ent); + +/* trace control opcodes */ +#define TRC_OP_RESET 0 /* reset trace */ +#define TRC_OP_STOP 1 /* stop tracing */ +#define TRC_OP_START 2 /* start tracing */ + +#define TRC_OP_ADD_IDD 3 /* add idd to trace context */ + /* arg: idd or NULL for all */ +#define TRC_OP_DEL_IDD 4 /* remove idd from trace context */ + /* arg: idd or NULL for all */ +#define TRC_OP_SET_FILTER 5 /* set filter for tracing */ + /* arg: filter type */ +#define TRC_OP_RESET_AREA 6 /* reset area state to idle */ +#define TRC_OP_CREATE 7 /* create trc object */ +#define TRC_OP_DESTROY 8 /* destroy trc object */ + +/* error codes */ +#define TRC_E_SUCC 0 /* success */ +#define TRC_E_IDD 1 /* idd operation failed */ +#define TRC_E_NOMEM 2 /* not enough memory */ +#define TRC_E_NOSUCH 3 /* no such error */ +#define TRC_E_NOROOM 4 /* no room in a table */ +#define TRC_E_PARAM 5 /* parameter error */ +#define TRC_E_BUSY 6 /* trace context area busy */ + +/* + * TRC_LOC.H - Line trace module, local definitions + */ + +/* prototypes for internal functions */ +VOID trc__cmd_handler(VOID *idd_1, USHORT chan, ULONG Reserved, IDD_MSG *msg); +INT trc__filter(ULONG filter, CHAR* data, ULONG len); + + +#endif /* _TRC_ */ diff --git a/private/ntos/ndis/digi/pcimac/trc_core.c b/private/ntos/ndis/digi/pcimac/trc_core.c new file mode 100644 index 000000000..4c802ec8c --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/trc_core.c @@ -0,0 +1,357 @@ +/* + * TRC_CORE.C - trace core module + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* local trace context table (NULL=free) */ + +#define CheckNULLTrace(Trace) \ + { \ + if (Trace == NULL) \ + break; \ + } + + +/* register an available idd */ +INT +trc_register_idd(VOID *idd) +{ + IDD_MSG msg; + + D_LOG(D_ENTRY, ("trc_register_idd: entry, idd: 0x%lx", idd)); + + /* add handle to idd command receiver */ + if ( idd_attach(idd, IDD_PORT_CMD_RX, (VOID*)trc__cmd_handler, idd) != IDD_E_SUCC ) + return(TRC_E_IDD); + + /* issue idd command to stop trace */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = CMD_TRC_OFF; + if ( idd_send_msg(idd, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) + return(TRC_E_IDD); + + return(TRC_E_SUCC); +} + +/* deregister an available idd */ +INT +trc_deregister_idd(VOID *idd) +{ + IDD_MSG msg; + + D_LOG(D_ENTRY, ("trc_deregister_idd: entry, idd: 0x%lx", idd)); + + /* issue idd command to stop trace */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = CMD_TRC_OFF; + if ( idd_send_msg(idd, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) + return(TRC_E_IDD); + + /* remove handle from idd command receiver */ + if ( idd_detach(idd, IDD_PORT_CMD_RX, (VOID*)trc__cmd_handler, idd) != IDD_E_SUCC ) + return(TRC_E_IDD); + else + return(TRC_E_SUCC); +} + +/* create a trace object */ +INT +trc_create(VOID **trc_1, ULONG depth) +{ + TRC **ret_trc = (TRC**)trc_1; + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(0xffffffff, 0xffffffff); + TRC *trc; + + D_LOG(D_ENTRY, ("trc_create: entry, ret_trc: 0x%lx, depth: %ld", ret_trc, depth)); + + /* allocate memory object */ + NdisAllocateMemory((PVOID*)&trc, sizeof(*trc), 0, pa); + if ( !trc ) + { + mem_alloc_failed: + D_LOG(D_ALWAYS, ("trc_create: memory allocate failed!")); + return(TRC_E_NOMEM); + } + D_LOG(D_ALWAYS, ("trc_create: trc: 0x%lx", trc)); + NdisZeroMemory(trc, sizeof(*trc)); + + /* allocate buffer memory */ + NdisAllocateMemory((PVOID*)&trc->ent_tbl, sizeof(TRC_ENTRY) * depth, + 0, pa); + if ( !trc->ent_tbl ) + goto mem_alloc_failed; + D_LOG(D_ALWAYS, ("trc_create: trc->ent_tbl: 0x%lx", trc->ent_tbl)); + NdisZeroMemory(trc->ent_tbl, sizeof(TRC_ENTRY) * depth); + + /* setup initial field values */ + trc->stat.state = TRC_ST_STOP; + trc->stat.filter = TRC_FT_NONE; + trc->stat.depth = depth; + + /* return succ */ + *ret_trc = trc; + return(TRC_E_SUCC); +} + +/* delte a trace object */ +INT +trc_destroy(VOID *trc_1) +{ + TRC *trc = (TRC*)trc_1; + + D_LOG(D_ENTRY, ("trc_destroy: entry, trc: 0x%lx", trc)); + + /* free memory */ + NdisFreeMemory(trc->ent_tbl, sizeof(TRC_ENTRY) * trc->stat.depth, 0); + NdisFreeMemory(trc, sizeof(*trc), 0); + + return(TRC_E_SUCC); +} + +/* perform a trace control function */ +INT +trc_control(VOID *idd, ULONG op, ULONG arg) +{ + IDD_MSG msg; + TRC *trc; + INT ret; + + + trc = idd_get_trc(idd); + + D_LOG(D_ENTRY, ("trc_control: idd: 0x%lx trc: 0x%lx, op: 0x%x, arg: 0x%x", idd, trc, op, arg)); + + /* branch on opcode */ + switch ( op ) + { + case TRC_OP_CREATE: + D_LOG(D_ENTRY, ("trc_control: CreateTrace")); + // if no trace object for this idd yet + if (trc == NULL) + { + //create trace object + if ((ret = trc_create(&trc, arg)) != TRC_E_SUCC) + return(TRC_E_IDD); + + // register trace for this idd + if ((ret = trc_register_idd (idd)) != TRC_E_SUCC) + { + trc_destroy(trc); + return(TRC_E_IDD); + } + + idd_set_trc (idd, trc); + + // set ref count + trc->create_ref = 0; + + // set backpointer + trc->idd = idd; + } + // inc ref count + trc->create_ref++; + break; + + case TRC_OP_DESTROY: + D_LOG(D_ENTRY, ("trc_control: DestroyTrace")); + + // if trc == NULL break; + CheckNULLTrace (trc); + + // dec ref count + if (--trc->create_ref) + break; + + trc_deregister_idd(idd); + trc_destroy(trc); + idd_set_trc(idd, NULL); + break; + + case TRC_OP_RESET : + D_LOG(D_ENTRY, ("trc_control: ResetTrace")); + // if trc == NULL break; + CheckNULLTrace (trc); + + trc->stat.state = TRC_ST_STOP; + trc->stat.entries = trc->stat.seq_1st = 0; + trc->ent_put = trc->ent_get = trc->ent_num = trc->ent_seq = 0; + break; + + case TRC_OP_STOP : + D_LOG(D_ENTRY, ("trc_control: StopTrace")); + // if trc == NULL break; + CheckNULLTrace (trc); + + // check start flag + if (--trc->start_ref) + break; + + trc->stat.state = TRC_ST_STOP; + + /* issue idd command to stop trace */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = CMD_TRC_OFF; + if ( idd_send_msg((VOID*)arg, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) + return(TRC_E_IDD); + break; + + case TRC_OP_START : + D_LOG(D_ENTRY, ("trc_control: StartTrace")); + // if trc == NULL break; + CheckNULLTrace (trc); + + trc->stat.state = TRC_ST_RUN; + + // check start flag + if (trc->start_ref++) + break; + + + /* issue idd command to start trace */ + NdisZeroMemory(&msg, sizeof(msg)); + msg.opcode = CMD_TRC_ON; + if ( idd_send_msg((VOID*)arg, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) + return(TRC_E_IDD); + break; + + case TRC_OP_SET_FILTER : + D_LOG(D_ENTRY, ("trc_control: SetTraceFilter")); + // if trc == NULL break; + CheckNULLTrace (trc); + + trc->stat.filter = arg; + break; + + default : + return(TRC_E_PARAM); + } + + /* if here, was successful */ + return(TRC_E_SUCC); +} + +/* get status of a trace context */ +INT +trc_get_status(VOID *trc_1, TRC_STATUS *stat) +{ + TRC *trc = (TRC*)trc_1; + + D_LOG(D_ENTRY, ("trc_get_status: entry, trc: 0x%lx, stat: 0x%lx", trc, stat)); + + // if no obect exit + if (trc == NULL) + return (TRC_E_NOSUCH); + + *stat = trc->stat; + stat->entries = trc->ent_num; + stat->seq_1st = trc->ent_seq; + + return(TRC_E_SUCC); +} + +/* get an entry by sequence number */ +INT +trc_get_entry(VOID *trc_1, ULONG seq, TRC_ENTRY *ent) +{ + TRC *trc = (TRC*)trc_1; + ULONG n, index; + + D_LOG(D_ENTRY, ("trc_get_entry: entry, trc: 0x%lx, seq: %ld, ent: 0x%lx", \ + trc, seq, ent)); + + // if no obect exit + if (trc == NULL) + return(TRC_E_NOSUCH); + + /* find requested sequence number, temp!!!, using search! */ + for ( n = 0 ; n < trc->ent_num ; n++ ) + { + index = (trc->ent_get + n) % trc->stat.depth; + if ( trc->ent_tbl[index].seq == seq ) + { + /* found */ + *ent = trc->ent_tbl[index]; + return(TRC_E_SUCC); + } + } + /* if here not found */ + return(TRC_E_NOSUCH); +} + +/* handler for trace and dump area data packets */ +VOID +trc__cmd_handler(VOID *idd_1, USHORT chan, ULONG Reserved, IDD_MSG *msg) +{ + TRC *trc; + TRC_ENTRY *ent; + IDD *idd = (IDD*)idd_1; + + + D_LOG(D_ENTRY, ("trc__cmd_handler: idd: %lx, chan: %d, msg: %lx", \ + idd, chan, msg)); + D_LOG(D_ENTRY, ("trc__cmd_handler: opcode: 0x%x, buflen: 0x%x, bufptr: %lx", \ + msg->opcode, msg->buflen, msg->bufptr)); + D_LOG(D_ENTRY, ("trc__cmd_handler: bufid: %lx, param: 0x%x", \ + msg->bufid, msg->param)); + + + // Get the trace object for this idd + trc = idd_get_trc(idd); + + // if no obect exit + if (trc == NULL || msg->bufid >= 2) + return; + + /* if here it is a trace frame. param is rx/tx attribute */ + /* establish entry to insert into & update vars */ + + /* check if trace enabled */ + if ( trc->stat.state == TRC_ST_STOP ) + return; + + D_LOG(D_ALWAYS, ("trc__cmd_handler: trc: %lx", trc)); + /* check if frame filters in */ + if ( !trc__filter(trc->stat.filter, msg->bufptr, msg->buflen) ) + return; + + /* frames needs to be buffered, establish entry pointer */ + ent = trc->ent_tbl + trc->ent_put; + trc->ent_put = (trc->ent_put + 1) % trc->stat.depth; + if ( trc->ent_num < trc->stat.depth ) + trc->ent_num++; + + /* fill up entry */ + ent->seq = trc->ent_seq++; + KeQuerySystemTime(&ent->time_stamp); + ent->attr = msg->bufid; + ent->org_len = msg->buflen; + ent->len = MIN(msg->buflen, sizeof(ent->data)); + IddGetDataFromAdapter(idd, + (PUCHAR)ent->data, + (PUCHAR)msg->bufptr, + (USHORT)ent->len); +// NdisMoveMemory (ent->data, msg->bufptr, ent->len); +} + +/* filter trace frame */ +INT +trc__filter(ULONG filter, CHAR *buf, ULONG len) +{ + D_LOG(D_ENTRY, ("trc__filter: entry, filter: %ld, buf: 0x%lx, len: %ld",\ + filter, buf, len)); + + /* not implemented, all frames filter in */ + return(1); +} diff --git a/private/ntos/ndis/digi/pcimac/trc_pub.h b/private/ntos/ndis/digi/pcimac/trc_pub.h new file mode 100644 index 000000000..67655fcf1 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/trc_pub.h @@ -0,0 +1,49 @@ +/* + * TRC_PUB.H - include file for all TRC modules + */ + +#ifndef _TRC_PUB_ +#define _TRC_PUB_ + +/* max values & constants */ +#define TRC_MAX_IDD 40 /* of number of idd's (lines) supported */ +#define TRC_MAX_DATA 256 /* max size of frame data buffered */ + +/* status of trace buffer as reported to user */ +typedef struct +{ + ULONG state; /* state of trace */ +#define TRC_ST_STOP 0 /* - is stopped */ +#define TRC_ST_RUN 1 /* - is running */ + + ULONG filter; /* active filter type */ +#define TRC_FT_NONE 0 /* - no filter, all frames buffered */ +#define TRC_FT_L2 1 /* - only l2 frames accepted */ +#define TRC_FT_L3 2 /* - only l3 frames accepted */ + + ULONG depth; /* depth of trace buffer */ + + + ULONG entries; /* # of entries in buffer now */ + ULONG seq_1st; /* sequence number of first frame in buffer */ + +} TRC_STATUS; + +/* descriptor for a trace entry */ +typedef struct +{ + ULONG seq; /* sequence number for frame */ + LARGE_INTEGER time_stamp; /* some sort of timing information */ + + ULONG attr; /* attribute word */ +#define TRC_AT_RX 0 /* - received frame */ +#define TRC_AT_TX 1 /* - transmit frame */ + + ULONG org_len; /* original frame length */ + ULONG len; /* length of buffered data */ + UCHAR data[TRC_MAX_DATA]; /* frame data */ + +} TRC_ENTRY; + +#endif /* _TRC_PUB_ */ + diff --git a/private/ntos/ndis/digi/pcimac/util.c b/private/ntos/ndis/digi/pcimac/util.c new file mode 100644 index 000000000..448afe990 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/util.c @@ -0,0 +1,146 @@ +/* + * UTIL.C - some utility functions + */ + +#include +#include +#include +#include + +// Total Memory Allocated +ULONG TotalMemory = 0; + +/* constants */ +#define BUF_SIZE 512 + +#if !BINARY_COMPATIBLE +/* get current time, in seconds */ +ULONG +ut_time_now(VOID) +{ + LARGE_INTEGER curr_time; + LARGE_INTEGER sec; + static LARGE_INTEGER base = {0, 0}; + static BOOL first_call = TRUE; + + /* get current system time */ + KeQuerySystemTime(&curr_time); + + /* on first call, store base */ + if ( first_call ) + { + base = curr_time; + first_call = FALSE; + } + /* make relative to base */ + curr_time.QuadPart -= base.QuadPart; + + /* convert to seconds */ + sec.QuadPart = curr_time.QuadPart/10000000L; + + /* return as a ULONG */ + return((ULONG)sec.LowPart); +} +#else +/* get current time, in seconds */ +ULONG +ut_time_now(VOID) +{ + ULONG seconds; + static BOOL first_call = TRUE; + + static ULONG base = 0; + ULONG curr_time; + + + // BUGBUG - Have to get real time somehow + + curr_time = base + 1; + + /* on first call, store base */ + if ( first_call ) + { + base = curr_time; + first_call = FALSE; + } + + /* make relative to base */ + seconds = curr_time - base; + + /* return as a ULONG */ + return(seconds); +} +#endif + +/* allocate a buffer */ +CHAR* +ut_get_buf(VOID) +{ + CHAR *ret; + + NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + + NdisAllocateMemory((PVOID*)&ret, BUF_SIZE, 0, pa); + + return(ret); +} + +/* free buffer */ +VOID +ut_free_buf(CHAR *buf) +{ + if ( buf ) + NdisFreeMemory(buf, BUF_SIZE, 0); +} + +/* init */ +VOID +sema_init(SEMA *s) +{ + s->signalled = FALSE; + NdisAllocateSpinLock (&s->lock); +} + +VOID +sema_term(SEMA *s) +{ + s->signalled = FALSE; + NdisFreeSpinLock (&s->lock); +} + +/* try to get semaphore */ +BOOL +sema_get(SEMA *s) +{ + BOOL ret; +// KIRQL NewIrql, OldIrql; + +// NewIrql = HIGH_LEVEL; + +// KeRaiseIrql (NewIrql, &OldIrql); + + NdisAcquireSpinLock (&s->lock); + + if ( !s->signalled ) + ret = s->signalled = TRUE; + else + ret = FALSE; + + NdisReleaseSpinLock (&s->lock); + +// KeLowerIrql (OldIrql); + + return(ret); +} + +/* free semaphore */ +VOID +sema_free(SEMA *s) +{ + NdisAcquireSpinLock (&s->lock); + + s->signalled = FALSE; + + NdisReleaseSpinLock (&s->lock); +} + diff --git a/private/ntos/ndis/digi/pcimac/util.h b/private/ntos/ndis/digi/pcimac/util.h new file mode 100644 index 000000000..629c49a71 --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/util.h @@ -0,0 +1,27 @@ +/* + * UTIL.H - utility module header + */ + +#ifndef _UTIL_ +#define _UTIL_ + +/* data structure */ +typedef struct +{ + BOOL signalled; + NDIS_SPIN_LOCK lock; +} SEMA; + +/* prototypes */ +VOID sema_init(SEMA* s); +VOID sema_term(SEMA* s); +BOOL sema_get(SEMA* s); +VOID sema_free(SEMA* s); + +ULONG ut_time_now(VOID); +CHAR *ut_get_buf(VOID); +VOID ut_free_buf(CHAR* buf); + +/* macros */ + +#endif /* _UTIL_ */ diff --git a/private/ntos/ndis/digi/pcimac/wan_conn.c b/private/ntos/ndis/digi/pcimac/wan_conn.c new file mode 100644 index 000000000..16172d1ce --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/wan_conn.c @@ -0,0 +1,122 @@ +/* + * WAN_CONN.C - routines for ras connection and disconnection + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +INT +WanLineup(VOID *cm_1, NDIS_HANDLE Endpoint) +{ + CM *cm = (CM*)cm_1; + ADAPTER *Adapter = cm->Adapter; + NDIS_MAC_LINE_UP ISDNLineUp; + MTL *mtl = (MTL*)cm->mtl; + TAPI_LINE_INFO *TapiLineInfo = (TAPI_LINE_INFO*)(cm->TapiLineInfo); + ULONG LinkSpeed; + + D_LOG(D_ENTRY, ("WanLineup: entry, cm: 0x%lx", cm)); + + // + // Get the connection speed and fill + // + mtl_get_conn_speed (mtl, &LinkSpeed); + + D_LOG(D_ALWAYS, ("cm_wanlineup: ConnectSpeed: [%d]", LinkSpeed)); + + ISDNLineUp.LinkSpeed = LinkSpeed / 100; + + // + // fill line quality + // + ISDNLineUp.Quality = NdisWanReliable; + + // + // fill send windows + // + ISDNLineUp.SendWindow = MAX_WANPACKET_XMITS; + + // + // fill the connection wrapper id + // this will need to change (i'm not clear on what is needed here) + // + if (Endpoint) + ISDNLineUp.ConnectionWrapperID = Endpoint; + else + ISDNLineUp.ConnectionWrapperID = (NDIS_HANDLE)cm->htCall; + + // + // fill the link context + // + ISDNLineUp.NdisLinkHandle = (NDIS_HANDLE)mtl; + + // + // clear out link handle since this lineup is for a new connection + // will get back a link handle from wrapper + // + ISDNLineUp.NdisLinkContext = (NDIS_HANDLE)mtl->LinkHandle = NULL; + + // + // Tell the wan wrapper that the connection is now up. + // We have a new link speed, frame size, quality of service. + // + NdisMIndicateStatus( + (NDIS_HANDLE)Adapter->Handle, + NDIS_STATUS_WAN_LINE_UP, // General Status + (PVOID)&ISDNLineUp, // Specific Status (baud rate in 100bps) + sizeof(ISDNLineUp)); + + NdisMIndicateStatusComplete(Adapter->Handle); + + // + // save new link handle + // + cm->LinkHandle = mtl->LinkHandle = ISDNLineUp.NdisLinkContext; + + return(CM_E_SUCC); +} + +INT +WanLinedown(VOID *cm_1) +{ + CM *cm = (CM*)cm_1; + ADAPTER *Adapter = cm->Adapter; + NDIS_MAC_LINE_DOWN ISDNLineDown; + MTL *mtl = (MTL*)cm->mtl; + + D_LOG(D_ENTRY, ("cm_wanlinedown: entry, cm: 0x%lx", cm)); + + ISDNLineDown.NdisLinkContext = mtl->LinkHandle; + + NdisMIndicateStatus( + (NDIS_HANDLE)Adapter->Handle, + NDIS_STATUS_WAN_LINE_DOWN, // General Status + (PVOID)&ISDNLineDown, // Specific Status (baud rate in 100bps) + sizeof(ISDNLineDown)); + + NdisMIndicateStatusComplete(Adapter->Handle); + + // + // clear out link handles + // + cm->LinkHandle = mtl->LinkHandle = NULL; + + // + // flush the mtl's wan packet queue + // + MtlFlushWanPacketTxQueue(mtl); + + return(CM_E_SUCC); +} + + diff --git a/private/ntos/ndis/digi/pcimac/wanoid.c b/private/ntos/ndis/digi/pcimac/wanoid.c new file mode 100644 index 000000000..a3cb1241a --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/wanoid.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +// +// Wan OID's +// +static UINT SupportedWanOids[] = + { + OID_WAN_PERMANENT_ADDRESS, + OID_WAN_CURRENT_ADDRESS, + OID_WAN_QUALITY_OF_SERVICE, + OID_WAN_PROTOCOL_TYPE, + OID_WAN_MEDIUM_SUBTYPE, + OID_WAN_HEADER_FORMAT, + OID_WAN_GET_INFO, + OID_WAN_SET_LINK_INFO, + OID_WAN_GET_LINK_INFO, + OID_WAN_GET_COMP_INFO, + OID_WAN_SET_COMP_INFO, + }; + +#define MAX_SUPPORTED_WAN_OIDS 11 + + + + +NDIS_STATUS +WanOidProc( + NDIS_HANDLE AdapterContext, + NDIS_OID Oid, + PVOID InfoBuffer, + ULONG InfoBufferLen, + PULONG BytesReadWritten, + PULONG BytesNeeded + ) +{ + NDIS_WAN_MEDIUM_SUBTYPE Medium = NdisWanMediumIsdn; + NDIS_WAN_HEADER_FORMAT HeaderFormat = NdisWanHeaderNative; + NDIS_WAN_QUALITY WanQuality = NdisWanReliable; + ADAPTER *Adapter = (ADAPTER*)AdapterContext; + PNDIS_WAN_INFO pWanInfo; + PNDIS_WAN_SET_LINK_INFO pLinkSetInfo; + PNDIS_WAN_GET_LINK_INFO pLinkGetInfo; + NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + MTL* mtl; + CM* cm; + ULONG n, NumIddPerAdapter; + + switch (Oid) + { + case OID_WAN_PERMANENT_ADDRESS: + case OID_WAN_CURRENT_ADDRESS: + if (InfoBufferLen < 6) + { + *BytesNeeded = 6; + return(NDIS_STATUS_INVALID_LENGTH); + } + + cm = (CM*)Adapter->CmTbl[0]; + + NdisMoveMemory(InfoBuffer, + (PVOID)cm->SrcAddr, + 6); + + *BytesNeeded = 0; + *BytesReadWritten = 6; + break; + + case OID_WAN_QUALITY_OF_SERVICE: + NdisMoveMemory(InfoBuffer, + (PVOID)(&WanQuality), + sizeof(NDIS_WAN_QUALITY)); + *BytesNeeded = 0; + *BytesReadWritten = sizeof(NDIS_WAN_QUALITY); + break; + + case OID_WAN_PROTOCOL_TYPE: + break; + + case OID_WAN_MEDIUM_SUBTYPE: + NdisMoveMemory(InfoBuffer, + (PVOID)(&Medium), + sizeof(NDIS_WAN_MEDIUM_SUBTYPE)); + *BytesNeeded = 0; + *BytesReadWritten = sizeof(NDIS_WAN_MEDIUM_SUBTYPE); + break; + + case OID_WAN_HEADER_FORMAT: + NdisMoveMemory(InfoBuffer, + (PVOID)(&HeaderFormat), + sizeof(NDIS_WAN_HEADER_FORMAT)); + *BytesNeeded = 0; + *BytesReadWritten = sizeof(NDIS_WAN_HEADER_FORMAT); + break; + + case OID_WAN_GET_INFO: + pWanInfo = (PNDIS_WAN_INFO)InfoBuffer; + + NumIddPerAdapter = EnumIddPerAdapter(Adapter); + pWanInfo->Endpoints = 2 * NumIddPerAdapter; + pWanInfo->MemoryFlags = 0; + pWanInfo->HighestAcceptableAddress = HighestAcceptableMax; + pWanInfo->MaxTransmit = MAX_WANPACKET_XMITS; + pWanInfo->MaxFrameSize = MAX_WANPACKET_BUFFERSIZE; + pWanInfo->HeaderPadding = MAX_WANPACKET_HEADERPADDING; + pWanInfo->TailPadding = MAX_WANPACKET_TAILPADDING; + pWanInfo->FramingBits = RAS_FRAMING | + PPP_FRAMING | + PPP_COMPRESS_PROTOCOL_FIELD | + MEDIA_NRZ_ENCODING | + TAPI_PROVIDER; + pWanInfo->DesiredACCM = 0; + *BytesNeeded = 0; + *BytesReadWritten = sizeof(NDIS_WAN_INFO); + break; + + case OID_WAN_SET_LINK_INFO: + // + // get pointer to link set info + // + pLinkSetInfo = (PNDIS_WAN_SET_LINK_INFO)InfoBuffer; + + // + // get mtl (Link Context) + // + mtl = (MTL*)pLinkSetInfo->NdisLinkHandle; + + if (!mtl->is_conn) + return (NDIS_STATUS_INVALID_DATA); + + mtl->MaxSendFrameSize = pLinkSetInfo->MaxSendFrameSize; + mtl->MaxRecvFrameSize = pLinkSetInfo->MaxRecvFrameSize; + if (pLinkSetInfo->SendFramingBits) + mtl->SendFramingBits = pLinkSetInfo->SendFramingBits; + mtl->RecvFramingBits = pLinkSetInfo->RecvFramingBits; + mtl->SendCompressionBits = pLinkSetInfo->SendCompressionBits; + mtl->RecvCompressionBits = pLinkSetInfo->RecvCompressionBits; + D_LOG(DIGIWANOID, ("SetLinkInfo: mtl: 0x%lx\n",mtl)); + D_LOG(DIGIWANOID, ("SendFramingBits: 0x%x\n", mtl->SendFramingBits)); + D_LOG(DIGIWANOID, ("RecvFramingBits: 0x%x\n", mtl->RecvFramingBits)); + *BytesNeeded = 0; + *BytesReadWritten = sizeof(NDIS_WAN_SET_LINK_INFO); + + // + // get cm (connection context) + // + cm = (CM*)mtl->cm; + + // + // if this connection was originally a PPP connection + // and now framing has been backed off to RAS we need to + // do some uus negotiation + // + if ((cm->ConnectionType == CM_PPP) && + (mtl->SendFramingBits & RAS_FRAMING)) + { + // + // set flag that will block transmits on this mtl + // + cm->PPPToDKF = 1; + + // + // for all channels (better only be one but???) do uus + // + for (n = 0; n < cm->dprof.chan_num; n++) + { + cm->dprof.chan_tbl[n].ustate = CM_US_UUS_SEND; + cm__tx_uus_pkt(cm->dprof.chan_tbl + n, CM_ASSOC_RQ, 0); + } + mtl->IddTxFrameType = IDD_FRAME_DKF; + } + + break; + + case OID_WAN_GET_LINK_INFO: + // + // get pointer to link set info + // + pLinkGetInfo = (PNDIS_WAN_GET_LINK_INFO)InfoBuffer; + + // + // get mtl (Link Context) + // + mtl = (MTL*)pLinkGetInfo->NdisLinkHandle; + + if (!mtl->is_conn) + return (NDIS_STATUS_INVALID_DATA); + + pLinkGetInfo->MaxSendFrameSize = mtl->MaxSendFrameSize; + pLinkGetInfo->MaxRecvFrameSize = mtl->MaxRecvFrameSize; + pLinkGetInfo->HeaderPadding = mtl->PreamblePadding; + pLinkGetInfo->TailPadding = mtl->PostamblePadding; + pLinkGetInfo->SendFramingBits = mtl->SendFramingBits; + pLinkGetInfo->RecvFramingBits = mtl->RecvFramingBits; + pLinkGetInfo->SendCompressionBits = mtl->SendCompressionBits; + pLinkGetInfo->RecvCompressionBits = mtl->RecvCompressionBits; + D_LOG(DIGIWANOID, ("GetLinkInfo: mtl: 0x%lx\n",mtl)); + D_LOG(DIGIWANOID, ("SendFramingBits: 0x%x\n", mtl->SendFramingBits)); + D_LOG(DIGIWANOID, ("RecvFramingBits: 0x%x\n", mtl->RecvFramingBits)); + *BytesNeeded = 0; + *BytesReadWritten = sizeof(NDIS_WAN_GET_LINK_INFO); + break; + + case OID_WAN_GET_COMP_INFO: + case OID_WAN_SET_COMP_INFO: + return(NDIS_STATUS_INVALID_OID); + + } + + return(NDIS_STATUS_SUCCESS); +} + -- cgit v1.2.3