diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/pcimac/cm_conn.c | 324 |
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); +} + + |