/*
 * (llc_stat.c)-Implementation of LLC station component state machine transitions
 *
 * Copyright (c) 1997 by Procom Technology,Inc.
 *
 * This program can be redistributed or modified under the terms of the 
 * GNU General Public License as published by the Free Software Foundation.
 * This program is distributed without any warranty or implied warranty
 * of merchantability or fitness for a particular purpose.
 *
 * See the GNU General Public License for more details.
 *
 */
 

#define LLC_STAT_C


#include <net/cm_types.h>
#include <net/cm_mm.h>
#include <net/cm_dll.h>
#include <net/cm_frame.h>
#include <net/llc_if.h>
#include <net/llc_sap.h>
#include <net/llc_conn.h>
#include <net/llc_main.h>
#include <net/llc_evnt.h>
#include <net/llc_actn.h>
#include <net/llc_stat.h>
#include <net/llc_glob.h>
#include <net/llc_dbg.h>

#ifdef LLC_STAT_DBG
  #define  DBG_MSG(body) { printk body; }
#else
  #define  DBG_MSG(body)  ;
#endif

/* ------------------- COMMON STATION STATE transitions ------------------ */

/* dummy last-transition indicator; common to all state transition groups */
static station_state_transition_t	stat_state_transition_n =
{
	NULL, 0, NULL			/* last entry for this state */
};

/* ------------------------ DOWN STATE transitions ----------------------- */

/* state transition for STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK event */
static station_action_t			stat_down_state_actions_1 [] =
{
	station_ac_start_ack_timer,
	station_ac_set_retry_count_0,
	station_ac_set_xid_r_count_0,
	station_ac_send_null_dsap_xid_c,
	NULL
};

static station_state_transition_t	stat_down_state_transition_1 =
{
	stat_ev_enable_with_dup_addr_check,
					STATION_STATE_DUP_ADDR_CHK,   
					stat_down_state_actions_1
};


/* state transition for STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK event */
static station_action_t			stat_down_state_actions_2 [] =
{
	station_ac_report_status,	/* STATION UP */
	NULL
};

static station_state_transition_t	stat_down_state_transition_2 =
{
	stat_ev_enable_without_dup_addr_check,
					STATION_STATE_UP,   
					stat_down_state_actions_2
};

/* array of pointers; one to each transition */
static station_state_transition_t *	stat_dwn_state_transitions [] =
{
	&stat_down_state_transition_1,
	&stat_down_state_transition_2,
	&stat_state_transition_n
};

/* ------------------------- UP STATE transitions ------------------------ */

/* state transition for STATION_EV_DISABLE_REQUEST event */
static station_action_t			stat_up_state_actions_1 [] =
{
	station_ac_report_status,	/* STATION DOWN */
	NULL
};

static station_state_transition_t	stat_up_state_transition_1 =
{
	stat_ev_disable_request,	STATION_STATE_DOWN,   
					stat_up_state_actions_1
};


/* state transition for STATION_EV_RX_NULL_DSAP_XID_C event */
static station_action_t			stat_up_state_actions_2 [] =
{
	station_ac_send_xid_r,
	NULL
};

static station_state_transition_t	stat_up_state_transition_2 =
{
	stat_ev_rx_null_dsap_xid_c,	STATION_STATE_UP,   
					stat_up_state_actions_2
};


/* state transition for STATION_EV_RX_NULL_DSAP_TEST_C event */
static station_action_t			stat_up_state_actions_3 [] =
{
	station_ac_send_test_r,
	NULL
};

static station_state_transition_t	stat_up_state_transition_3 =
{
	stat_ev_rx_null_dsap_test_c,	STATION_STATE_UP,   
					stat_up_state_actions_3
};


/* array of pointers; one to each transition */
static station_state_transition_t *	stat_up_state_transitions [] =
{
	&stat_up_state_transition_1,
	&stat_up_state_transition_2,
	&stat_up_state_transition_3,
	&stat_state_transition_n
};

/* ---------------------- DUP ADDR CHK STATE transitions ----------------- */

/*
 * state transition for STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_COUNT_EQ
 * event
 */
static station_action_t			stat_dupaddr_state_actions_1 [] =
{
	station_ac_increment_xid_r_count_by_1,
	NULL
};

static station_state_transition_t	stat_dupaddr_state_transition_1 =
{
	stat_ev_rx_null_dsap_0_xid_r_xid_r_count_eq,
					STATION_STATE_DUP_ADDR_CHK,
					stat_dupaddr_state_actions_1
};


/*
 * state transition for STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_COUNT_EQ
 * event
 */
static station_action_t    		stat_dupaddr_state_actions_2 [] =
{
	station_ac_report_status,	/* DUPLICATE ADDRESS FOUND */
	NULL
};

static station_state_transition_t	stat_dupaddr_state_transition_2 =
{
	stat_ev_rx_null_dsap_1_xid_r_xid_r_count_eq, 
					STATION_STATE_DOWN,
					stat_dupaddr_state_actions_2
};


/* state transition for STATION_EV_RX_NULL_DSAP_XID_C event */
static station_action_t			stat_dupaddr_state_actions_3 [] =
{
	station_ac_send_xid_r,
	NULL
};

static station_state_transition_t	stat_dupaddr_state_transition_3 =
{
	stat_ev_rx_null_dsap_xid_c,	STATION_STATE_DUP_ADDR_CHK,
					stat_dupaddr_state_actions_3
};


/*
 * state transition for STATION_EV_ACK_TIMER_EXPIRED_LT_RETRY_COUNT_MAX_RETRY
 * event 
 */
static station_action_t			stat_dupaddr_state_actions_4 [] =
{
	station_ac_start_ack_timer,
	station_ac_increment_retry_count_by_1,
	station_ac_set_xid_r_count_0,
	station_ac_send_null_dsap_xid_c,
	NULL
};

static station_state_transition_t	stat_dupaddr_state_transition_4 =
{
	stat_ev_ack_timer_expired_lt_retry_count_max_retry,
					STATION_STATE_DUP_ADDR_CHK,
					stat_dupaddr_state_actions_4
};


/*
 * state transition for STATION_EV_ACK_TIMER_EXPIRED_EQ_RETRY_COUNT_MAX_RETRY
 * event 
 */
static station_action_t			stat_dupaddr_state_actions_5 [] =
{
	station_ac_report_status,	/* STATION UP */
	NULL
};

static station_state_transition_t	stat_dupaddr_state_transition_5 =
{
	stat_ev_ack_timer_expired_eq_retry_count_max_retry,
					STATION_STATE_UP,
					stat_dupaddr_state_actions_5
};


/* state transition for STATION_EV_DISABLE_REQUEST event */
static station_action_t			stat_dupaddr_state_actions_6 [] =
{
	station_ac_report_status,	/* STATION DOWN */
	NULL
};

static station_state_transition_t	stat_dupaddr_state_transition_6 =
{
	stat_ev_disable_request,	STATION_STATE_DOWN,
					stat_dupaddr_state_actions_6
};


/* array of pointers; one to each transition */
static station_state_transition_t *	stat_dupaddr_state_transitions [] =
{
	&stat_dupaddr_state_transition_6,	// Request

	&stat_dupaddr_state_transition_4,	// Timer
	&stat_dupaddr_state_transition_5,

	&stat_dupaddr_state_transition_1,	// Receive frame
	&stat_dupaddr_state_transition_2,
	&stat_dupaddr_state_transition_3,

	&stat_state_transition_n
};


station_state_t		Station_state_table [NBR_STATION_STATES] =
{
	{ STATION_STATE_DOWN,		stat_dwn_state_transitions        },
	{ STATION_STATE_DUP_ADDR_CHK,	stat_dupaddr_state_transitions    },
	{ STATION_STATE_UP,		stat_up_state_transitions         }
};


