summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/pcimac/cm_conn.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/pcimac/cm_conn.c')
-rw-r--r--private/ntos/ndis/pcimac/cm_conn.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/private/ntos/ndis/pcimac/cm_conn.c b/private/ntos/ndis/pcimac/cm_conn.c
new file mode 100644
index 000000000..7420b3d0a
--- /dev/null
+++ b/private/ntos/ndis/pcimac/cm_conn.c
@@ -0,0 +1,324 @@
+/*
+ * CM_CONN.C - connection managment code
+ */
+
+#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>
+
+/* 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%p", 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%p", 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%p", 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, ("cm__initiate_conn: entry, cm: 0x%p", 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%p", 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%p", 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);
+}
+
+