summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/pcimac/cm_init.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/pcimac/cm_init.c489
1 files changed, 489 insertions, 0 deletions
diff --git a/private/ntos/ndis/pcimac/cm_init.c b/private/ntos/ndis/pcimac/cm_init.c
new file mode 100644
index 000000000..79ae7fe81
--- /dev/null
+++ b/private/ntos/ndis/pcimac/cm_init.c
@@ -0,0 +1,489 @@
+/*
+ * CM_INIT.H - initialization code for CM objects
+ */
+
+#include <ndis.h>
+//#include <ndismini.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"));
+
+ 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"));
+
+ 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%p", 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%p", 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%p", 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!"));
+ NdisWriteErrorLogEntry (AdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 0);
+ return(CM_E_NOMEM);
+ }
+ D_LOG(D_ALWAYS, ("cm_create: cm: 0x%x", *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%p", 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%p, lterm: 0x%x, cid: 0x%p", 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%p, bchan: 0x%x", \
+ 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]", \
+ 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]", \
+ 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]);
+}