summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/digi/pcimac
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/digi/pcimac')
-rw-r--r--private/ntos/ndis/digi/pcimac/adapter.h223
-rw-r--r--private/ntos/ndis/digi/pcimac/ansihelp.c487
-rw-r--r--private/ntos/ndis/digi/pcimac/ansihelp.h109
-rw-r--r--private/ntos/ndis/digi/pcimac/cm.h162
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_chan.c106
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_conn.c323
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_init.c488
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_prof.c51
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_pub.h134
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_q931.c943
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_stat.c31
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_state.c757
-rw-r--r--private/ntos/ndis/digi/pcimac/cm_timer.c78
-rw-r--r--private/ntos/ndis/digi/pcimac/cnf.h13
-rw-r--r--private/ntos/ndis/digi/pcimac/dgbrip.h33
-rw-r--r--private/ntos/ndis/digi/pcimac/disp.c105
-rw-r--r--private/ntos/ndis/digi/pcimac/disp.h147
-rw-r--r--private/ntos/ndis/digi/pcimac/event.h31
-rw-r--r--private/ntos/ndis/digi/pcimac/frame.h196
-rw-r--r--private/ntos/ndis/digi/pcimac/idd.h440
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_init.c894
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_io.c672
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_msg.c168
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_nv.c140
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_proc.c988
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_pub.h59
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_run.c868
-rw-r--r--private/ntos/ndis/digi/pcimac/io.h27
-rw-r--r--private/ntos/ndis/digi/pcimac/io_core.c435
-rw-r--r--private/ntos/ndis/digi/pcimac/io_pub.h153
-rw-r--r--private/ntos/ndis/digi/pcimac/lanoid.c240
-rw-r--r--private/ntos/ndis/digi/pcimac/makefile6
-rw-r--r--private/ntos/ndis/digi/pcimac/mtl.h306
-rw-r--r--private/ntos/ndis/digi/pcimac/mtl_init.c195
-rw-r--r--private/ntos/ndis/digi/pcimac/mtl_rx.c840
-rw-r--r--private/ntos/ndis/digi/pcimac/mtl_set.c228
-rw-r--r--private/ntos/ndis/digi/pcimac/mtl_tick.c47
-rw-r--r--private/ntos/ndis/digi/pcimac/mtl_tx.c1092
-rw-r--r--private/ntos/ndis/digi/pcimac/mydefs.h376
-rw-r--r--private/ntos/ndis/digi/pcimac/mytypes.h39
-rw-r--r--private/ntos/ndis/digi/pcimac/opcodes.h152
-rw-r--r--private/ntos/ndis/digi/pcimac/pcimac.c2385
-rw-r--r--private/ntos/ndis/digi/pcimac/pcimac.rc28
-rw-r--r--private/ntos/ndis/digi/pcimac/res.h52
-rw-r--r--private/ntos/ndis/digi/pcimac/res_core.c261
-rw-r--r--private/ntos/ndis/digi/pcimac/sema.h8
-rw-r--r--private/ntos/ndis/digi/pcimac/sources74
-rw-r--r--private/ntos/ndis/digi/pcimac/tapioid.c2535
-rw-r--r--private/ntos/ndis/digi/pcimac/tapioid.h440
-rw-r--r--private/ntos/ndis/digi/pcimac/trc.h71
-rw-r--r--private/ntos/ndis/digi/pcimac/trc_core.c357
-rw-r--r--private/ntos/ndis/digi/pcimac/trc_pub.h49
-rw-r--r--private/ntos/ndis/digi/pcimac/util.c146
-rw-r--r--private/ntos/ndis/digi/pcimac/util.h27
-rw-r--r--private/ntos/ndis/digi/pcimac/wan_conn.c122
-rw-r--r--private/ntos/ndis/digi/pcimac/wanoid.c226
56 files changed, 19563 insertions, 0 deletions
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 <ndis.h>
+//#include <ansihelp.h>
+
+#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<count) && (buffer[len] != chr)) {
+ len++;
+ }
+
+ return ((len<count)?(buffer+len):NULL);
+} // end of __memchr
+
+
+
+/******************************************************************************
+
+ @doc INTERNAL
+
+ @internal PUCHAR | __strchr | search for char within a string
+
+ @parm PUCHAR | str1 | source string.
+
+ @parm CHAR | chr | chr
+
+ @rdesc PUCHAR |
+
+******************************************************************************/
+PUCHAR
+__strchr(PUCHAR str1, CHAR chr)
+{
+ ULONG len = 0;
+
+ if (str1 == NULL) {
+ return(NULL);
+ }
+
+ while ((str1[len] != '\0') && (str1[len] != chr)) {
+ len++;
+ }
+
+ return ((str1[len])?(str1+len):NULL);
+} // end of __strchr
+
+
+
+/******************************************************************************
+
+ @doc INTERNAL
+
+ @internal PUCHAR | __strrchr | reverse search for char within a string
+
+ @parm PUCHAR | str1 | source string.
+
+ @parm CHAR | chr | chr
+
+ @rdesc PUCHAR |
+
+******************************************************************************/
+PUCHAR
+__strrchr(PUCHAR str1, CHAR chr)
+{
+ ULONG len = 0;
+
+ return(NULL);
+
+} // end of __strrchr
+
+
+
+/******************************************************************************
+
+ @doc INTERNAL
+
+ @internal PUCHAR | __strlwr | convert a string to lowercase
+
+ @parm PUCHAR | str1 | source string.
+
+ @rdesc PUCHAR |
+
+******************************************************************************/
+PUCHAR
+__strlwr(PUCHAR str1)
+{
+ for( ; str1 != NULL, *str1 != '\0'; str1++ )
+ *str1 = tolower( *str1 );
+
+ return( str1 );
+} // end of __strlwr
+
+ULONG
+__strtoul (const CHAR *s, INT base)
+{
+ return(__Stoul (s, (CHAR **)NULL, base));
+}
+
+ULONG
+__Stoul (const CHAR *s, CHAR **endptr, INT base)
+{
+ const CHAR *sc, *sd;
+ const CHAR *s1, *s2;
+ CHAR sign;
+ LONG n;
+ ULONG x, y;
+
+ for (sc = s; isspace (*sc); ++sc);
+
+ sign = *sc == '-' || *sc == '+' ? *sc++ : '+';
+
+ if (base < 0 || base == 1 || BASE_MAX < base)
+ {
+ if (endptr)
+ *endptr = (CHAR *)s;
+ return( (ULONG)-1 );
+ }
+ else if (base)
+ {
+ if (base == 16 && *sc == '0' && (sc[1] == 'x' || sc[1] == 'X'))
+ sc += 2;
+ }
+ else if (*sc != '0')
+ base = 10;
+ else if (sc[1] == 'x' || sc[1] == 'X')
+ {
+ base = 16;
+ sc += 2;
+ }
+ else
+ base = 8;
+ for (s1 = sc; *sc == '0'; ++sc );
+ x = 0;
+ for (s2 = sc; (sd = memchr (digits, (INT)tolower(*sc), (UINT)base)) != NULL; ++sc)
+ {
+ y = x;
+ x = x * base + (sd - digits);
+ }
+ if (s1 == sc)
+ {
+ if (endptr)
+ *endptr = (CHAR *)s;
+ return( (ULONG)-1 );
+ }
+ n = sc - s2 - ndigs[base];
+ if (n < 0)
+ ;
+ else if (0 < n || x < x - sc[-1] || (x - sc[-1]) / base != y)
+ {
+ // overflow
+ x = 0xFFFFFFFF;
+ }
+ if (sign == '-')
+ x = (ULONG)(0 - x);
+ if (endptr)
+ *endptr = (CHAR *)sc;
+ return(x);
+}
+
+INT
+__isspace (INT c)
+{
+ return(_Ctype[(INT)c] & (_CN | _SP | _XS));
+}
+
+PCHAR
+__vsprintf()
+{
+ return( NULL );
+}
+
+
diff --git a/private/ntos/ndis/digi/pcimac/ansihelp.h b/private/ntos/ndis/digi/pcimac/ansihelp.h
new file mode 100644
index 000000000..c358f7247
--- /dev/null
+++ b/private/ntos/ndis/digi/pcimac/ansihelp.h
@@ -0,0 +1,109 @@
+#if !BINARY_COMPATIBLE
+// Building for NT
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 <ndistapi.h>
+#include <cm_pub.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <trc.h>
+#include <io.h>
+#include <tapioid.h>
+
+/* 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 <idd,lterm,cid> */
+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 <idd,bchan> */
+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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+#include <ansihelp.h>
+
+/* (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, "<unknown>");
+
+ 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mydefs.h>
+#include <mytypes.h>
+#include <stdarg.h>
+#include <ansihelp.h>
+#include <util.h>
+#include <adapter.h>
+#include <idd.h>
+#include <cm.h>
+#include <mtl.h>
+#include <trc.h>
+#include <io.h>
+
+#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_pub.h>
+
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <ndistapi.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <res.h>
+#include <trc.h>
+#include <io.h>
+
+#include <ansihelp.h>
+
+
+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 <ndis.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <idd.h>
+#include <res.h>
+
+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 <ndis.h>
+#include <mydefs.h>
+#include <mytypes.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <idd.h>
+
+/* 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 <ndis.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <idd.h>
+#include <res.h>
+
+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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <res.h>
+
+#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 <ndis.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <idd.h>
+#include <res.h>
+
+/* 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 <io_pub.h>
+
+// 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 <ndis.h>
+#include <ndiswan.h>
+#include <mydefs.h>
+#include <mytypes.h>
+#include <util.h>
+#include <disp.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <trc.h>
+#include <io.h>
+
+#include <dgatlas.h>
+#include <dgbrip.h>
+
+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 <ndis.h>
+#include <ndiswan.h>
+#include <stdio.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <adapter.h>
+#include <util.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <res.h>
+#include <trc.h>
+#include <io.h>
+
+
+#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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+#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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <trc.h>
+#include <io.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+
+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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <opcodes.h>
+#include <disp.h>
+#include <adapter.h>
+#include <util.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <tapioid.h>
+#include <res.h>
+#include <trc.h>
+#include <io.h>
+
+#include <ansihelp.h>
+
+
+/* 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( &paramTable[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,
+ &paramTable[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 <winver.h>
+#else
+#include <windows.h>
+#endif
+
+#include <ntverp.h>
+
+#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 <ndis.h>
+#include <ndiswan.h>
+#include <mydefs.h>
+#include <mytypes.h>
+#include <util.h>
+#include <adapter.h>
+#include <idd.h>
+#include <cm.h>
+#include <mtl.h>
+#include <res.h>
+#include <disp.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <adapter.h>
+#include <util.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <res.h>
+#include <trc.h>
+#include <io.h>
+#include <tapioid.h>
+
+#include <ansihelp.h>
+
+
+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
+ // <media name>\0<device name>\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 <trc_pub.h>
+
+/* 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 <ndis.h>
+#include <ndiswan.h>
+#include <mydefs.h>
+#include <mytypes.h>
+#include <util.h>
+#include <opcodes.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <trc.h>
+#include <disp.h>
+
+/* 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 <ndis.h>
+#include <mydefs.h>
+#include <mytypes.h>
+#include <util.h>
+
+// 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 <ndis.h>
+#include <ndiswan.h>
+#include <mydefs.h>
+#include <mytypes.h>
+#include <util.h>
+#include <adapter.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <tapioid.h>
+#include <disp.h>
+
+
+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 <ndis.h>
+#include <ndiswan.h>
+#include <mytypes.h>
+#include <mydefs.h>
+#include <disp.h>
+#include <adapter.h>
+#include <util.h>
+#include <idd.h>
+#include <mtl.h>
+#include <cm.h>
+#include <res.h>
+#include <trc.h>
+#include <io.h>
+
+#include <ansihelp.h>
+
+
+//
+// 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);
+}
+