OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [802/] [cl2llc.c] - Diff between revs 1275 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1275 Rev 1765
/*
/*
 * NET          An implementation of the IEEE 802.2 LLC protocol for the
 * NET          An implementation of the IEEE 802.2 LLC protocol for the
 *              LINUX operating system.  LLC is implemented as a set of
 *              LINUX operating system.  LLC is implemented as a set of
 *              state machines and callbacks for higher networking layers.
 *              state machines and callbacks for higher networking layers.
 *
 *
 *              Class 2 llc algorithm.
 *              Class 2 llc algorithm.
 *              Pseudocode interpreter, transition table lookup,
 *              Pseudocode interpreter, transition table lookup,
 *                      data_request & indicate primitives...
 *                      data_request & indicate primitives...
 *
 *
 *              Code for initialization, termination, registration and
 *              Code for initialization, termination, registration and
 *              MAC layer glue.
 *              MAC layer glue.
 *
 *
 *              Copyright Tim Alpaerts,
 *              Copyright Tim Alpaerts,
 *                      <Tim_Alpaerts@toyota-motor-europe.com>
 *                      <Tim_Alpaerts@toyota-motor-europe.com>
 *
 *
 *              This program is free software; you can redistribute it and/or
 *              This program is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *              2 of the License, or (at your option) any later version.
 *
 *
 *      Changes
 *      Changes
 *              Alan Cox        :       Chainsawed into Linux format
 *              Alan Cox        :       Chainsawed into Linux format
 *                                      Modified to use llc_ names
 *                                      Modified to use llc_ names
 *                                      Changed callbacks
 *                                      Changed callbacks
 *
 *
 *      This file must be processed by sed before it can be compiled.
 *      This file must be processed by sed before it can be compiled.
 */
 */
 
 
#include <linux/types.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <net/p8022.h>
#include <net/p8022.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <asm/byteorder.h>
#include <asm/byteorder.h>
 
 
#include "pseudo/pseudocode.h"
#include "pseudo/pseudocode.h"
#include "transit/pdutr.h"
#include "transit/pdutr.h"
#include "transit/timertr.h"
#include "transit/timertr.h"
#include <net/llc_frame.h>
#include <net/llc_frame.h>
#include <net/llc.h>
#include <net/llc.h>
 
 
/*
/*
 *      Data_request() is called by the client to present a data unit
 *      Data_request() is called by the client to present a data unit
 *      to the llc for transmission.
 *      to the llc for transmission.
 *      In the future this function should also check if the transmit window
 *      In the future this function should also check if the transmit window
 *      allows the sending of another pdu, and if not put the skb on the atq
 *      allows the sending of another pdu, and if not put the skb on the atq
 *      for deferred sending.
 *      for deferred sending.
 */
 */
 
 
int llc_data_request(llcptr lp, struct sk_buff *skb)
int llc_data_request(llcptr lp, struct sk_buff *skb)
{
{
        if (skb_headroom(skb) < (lp->dev->hard_header_len +4)){
        if (skb_headroom(skb) < (lp->dev->hard_header_len +4)){
                printk("cl2llc: data_request() not enough headroom in skb\n");
                printk("cl2llc: data_request() not enough headroom in skb\n");
                return -1;
                return -1;
        };
        };
 
 
        skb_push(skb, 4);
        skb_push(skb, 4);
 
 
        if ((lp->state != NORMAL) && (lp->state != BUSY) && (lp->state != REJECT))
        if ((lp->state != NORMAL) && (lp->state != BUSY) && (lp->state != REJECT))
        {
        {
                printk("cl2llc: data_request() while no llc connection\n");
                printk("cl2llc: data_request() while no llc connection\n");
                return -1;
                return -1;
        }
        }
 
 
        if (lp->remote_busy)
        if (lp->remote_busy)
        {     /* if the remote llc is BUSY, */
        {     /* if the remote llc is BUSY, */
                ADD_TO_ATQ(skb);      /* save skb in the await transmit queue */
                ADD_TO_ATQ(skb);      /* save skb in the await transmit queue */
                return 0;
                return 0;
        }
        }
        else
        else
        {
        {
                /*
                /*
                 *      Else proceed with xmit
                 *      Else proceed with xmit
                 */
                 */
 
 
                switch(lp->state)
                switch(lp->state)
                {
                {
                        case NORMAL:
                        case NORMAL:
                                if(lp->p_flag)
                                if(lp->p_flag)
                                        llc_interpret_pseudo_code(lp, NORMAL2, skb, NO_FRAME);
                                        llc_interpret_pseudo_code(lp, NORMAL2, skb, NO_FRAME);
                                else
                                else
                                        llc_interpret_pseudo_code(lp, NORMAL1, skb, NO_FRAME);
                                        llc_interpret_pseudo_code(lp, NORMAL1, skb, NO_FRAME);
                                break;
                                break;
                        case BUSY:
                        case BUSY:
                                if (lp->p_flag)
                                if (lp->p_flag)
                                        llc_interpret_pseudo_code(lp, BUSY2, skb, NO_FRAME);
                                        llc_interpret_pseudo_code(lp, BUSY2, skb, NO_FRAME);
                                else
                                else
                                        llc_interpret_pseudo_code(lp, BUSY1, skb, NO_FRAME);
                                        llc_interpret_pseudo_code(lp, BUSY1, skb, NO_FRAME);
                                break;
                                break;
                        case REJECT:
                        case REJECT:
                                if (lp->p_flag)
                                if (lp->p_flag)
                                        llc_interpret_pseudo_code(lp, REJECT2, skb, NO_FRAME);
                                        llc_interpret_pseudo_code(lp, REJECT2, skb, NO_FRAME);
                                else
                                else
                                        llc_interpret_pseudo_code(lp, REJECT1, skb, NO_FRAME);
                                        llc_interpret_pseudo_code(lp, REJECT1, skb, NO_FRAME);
                                break;
                                break;
                        default:;
                        default:;
                }
                }
                if(lp->llc_callbacks)
                if(lp->llc_callbacks)
                {
                {
                        lp->llc_event(lp);
                        lp->llc_event(lp);
                        lp->llc_callbacks=0;
                        lp->llc_callbacks=0;
                }
                }
                return 0;
                return 0;
        }
        }
}
}
 
 
 
 
 
 
/*
/*
 *      Disconnect_request() requests that the llc to terminate a connection
 *      Disconnect_request() requests that the llc to terminate a connection
 */
 */
 
 
void disconnect_request(llcptr lp)
void disconnect_request(llcptr lp)
{
{
        if ((lp->state == NORMAL) ||
        if ((lp->state == NORMAL) ||
                (lp->state == BUSY) ||
                (lp->state == BUSY) ||
                (lp->state == REJECT) ||
                (lp->state == REJECT) ||
                (lp->state == AWAIT) ||
                (lp->state == AWAIT) ||
                (lp->state == AWAIT_BUSY) ||
                (lp->state == AWAIT_BUSY) ||
                (lp->state == AWAIT_REJECT))
                (lp->state == AWAIT_REJECT))
        {
        {
                lp->state = D_CONN;
                lp->state = D_CONN;
                llc_interpret_pseudo_code(lp, SH1, NULL, NO_FRAME);
                llc_interpret_pseudo_code(lp, SH1, NULL, NO_FRAME);
                if(lp->llc_callbacks)
                if(lp->llc_callbacks)
                {
                {
                        lp->llc_event(lp);
                        lp->llc_event(lp);
                        lp->llc_callbacks=0;
                        lp->llc_callbacks=0;
                }
                }
                /*
                /*
                 *      lp may be invalid after the callback
                 *      lp may be invalid after the callback
                 */
                 */
        }
        }
}
}
 
 
 
 
/*
/*
 *      Connect_request() requests that the llc to start a connection
 *      Connect_request() requests that the llc to start a connection
 */
 */
 
 
void connect_request(llcptr lp)
void connect_request(llcptr lp)
{
{
        if (lp->state == ADM)
        if (lp->state == ADM)
        {
        {
                lp->state = SETUP;
                lp->state = SETUP;
                llc_interpret_pseudo_code(lp, ADM1, NULL, NO_FRAME);
                llc_interpret_pseudo_code(lp, ADM1, NULL, NO_FRAME);
                if(lp->llc_callbacks)
                if(lp->llc_callbacks)
                {
                {
                        lp->llc_event(lp);
                        lp->llc_event(lp);
                        lp->llc_callbacks=0;
                        lp->llc_callbacks=0;
                }
                }
                /*
                /*
                 *      lp may be invalid after the callback
                 *      lp may be invalid after the callback
                 */
                 */
        }
        }
}
}
 
 
 
 
/*
/*
 *      Interpret_pseudo_code() executes the actions in the connection component
 *      Interpret_pseudo_code() executes the actions in the connection component
 *      state transition table. Table 4 in document on p88.
 *      state transition table. Table 4 in document on p88.
 *
 *
 *      If this function is called to handle an incoming pdu, skb will point
 *      If this function is called to handle an incoming pdu, skb will point
 *      to the buffer with the pdu and type will contain the decoded pdu type.
 *      to the buffer with the pdu and type will contain the decoded pdu type.
 *
 *
 *      If called by data_request skb points to an skb that was skb_alloc-ed by
 *      If called by data_request skb points to an skb that was skb_alloc-ed by
 *      the llc client to hold the information unit to be transmitted, there is
 *      the llc client to hold the information unit to be transmitted, there is
 *      no valid type in this case.
 *      no valid type in this case.
 *
 *
 *      If called because a timer expired no skb is passed, and there is no
 *      If called because a timer expired no skb is passed, and there is no
 *      type.
 *      type.
 */
 */
 
 
void llc_interpret_pseudo_code(llcptr lp, int pc_label, struct sk_buff *skb,
void llc_interpret_pseudo_code(llcptr lp, int pc_label, struct sk_buff *skb,
                char type)
                char type)
{
{
        short int pc;   /* program counter in pseudo code array */
        short int pc;   /* program counter in pseudo code array */
        char p_flag_received;
        char p_flag_received;
        frameptr fr;
        frameptr fr;
        int resend_count;   /* number of pdus resend by llc_resend_ipdu() */
        int resend_count;   /* number of pdus resend by llc_resend_ipdu() */
        int ack_count;      /* number of pdus acknowledged */
        int ack_count;      /* number of pdus acknowledged */
        struct sk_buff *skb2;
        struct sk_buff *skb2;
 
 
        if (skb != NULL)
        if (skb != NULL)
        {
        {
                fr = (frameptr) skb->data;
                fr = (frameptr) skb->data;
        }
        }
        else
        else
                fr = NULL;
                fr = NULL;
 
 
        pc = pseudo_code_idx[pc_label];
        pc = pseudo_code_idx[pc_label];
        while(pseudo_code[pc])
        while(pseudo_code[pc])
        {
        {
                switch(pseudo_code[pc])
                switch(pseudo_code[pc])
                {
                {
                        case 9:
                        case 9:
                                if ((type != I_CMD) || (fr->i_hdr.i_pflag == 0))
                                if ((type != I_CMD) || (fr->i_hdr.i_pflag == 0))
                                        break;
                                        break;
                        case 1:
                        case 1:
                                lp->remote_busy = 0;
                                lp->remote_busy = 0;
                                llc_stop_timer(lp, BUSY_TIMER);
                                llc_stop_timer(lp, BUSY_TIMER);
                                if ((lp->state == NORMAL) ||
                                if ((lp->state == NORMAL) ||
                                        (lp->state == REJECT) ||
                                        (lp->state == REJECT) ||
                                        (lp->state == BUSY))
                                        (lp->state == BUSY))
                                {
                                {
                                        skb2 = llc_pull_from_atq(lp);
                                        skb2 = llc_pull_from_atq(lp);
                                        if (skb2 != NULL)
                                        if (skb2 != NULL)
                                                llc_start_timer(lp, ACK_TIMER);
                                                llc_start_timer(lp, ACK_TIMER);
                                        while (skb2 != NULL)
                                        while (skb2 != NULL)
                                        {
                                        {
                                                llc_sendipdu( lp, I_CMD, 0, skb2);
                                                llc_sendipdu( lp, I_CMD, 0, skb2);
                                                skb2 = llc_pull_from_atq(lp);
                                                skb2 = llc_pull_from_atq(lp);
                                        }
                                        }
                                }
                                }
                                break;
                                break;
                        case 2:
                        case 2:
                                lp->state = NORMAL;  /* needed to eliminate connect_response() */
                                lp->state = NORMAL;  /* needed to eliminate connect_response() */
                                lp->llc_mode = MODE_ABM;
                                lp->llc_mode = MODE_ABM;
                                lp->llc_callbacks|=LLC_CONN_INDICATION;
                                lp->llc_callbacks|=LLC_CONN_INDICATION;
                                break;
                                break;
                        case 3:
                        case 3:
                                lp->llc_mode = MODE_ABM;
                                lp->llc_mode = MODE_ABM;
                                lp->llc_callbacks|=LLC_CONN_CONFIRM;
                                lp->llc_callbacks|=LLC_CONN_CONFIRM;
                                break;
                                break;
                        case 4:
                        case 4:
                                skb_pull(skb, 4);
                                skb_pull(skb, 4);
                                lp->inc_skb=skb;
                                lp->inc_skb=skb;
                                lp->llc_callbacks|=LLC_DATA_INDIC;
                                lp->llc_callbacks|=LLC_DATA_INDIC;
                                break;
                                break;
                        case 5:
                        case 5:
                                lp->llc_mode = MODE_ADM;
                                lp->llc_mode = MODE_ADM;
                                lp->llc_callbacks|=LLC_DISC_INDICATION;
                                lp->llc_callbacks|=LLC_DISC_INDICATION;
                                break;
                                break;
                        case 70:
                        case 70:
                                lp->llc_callbacks|=LLC_RESET_INDIC_LOC;
                                lp->llc_callbacks|=LLC_RESET_INDIC_LOC;
                                break;
                                break;
                        case 71:
                        case 71:
                                lp->llc_callbacks|=LLC_RESET_INDIC_REM;
                                lp->llc_callbacks|=LLC_RESET_INDIC_REM;
                                break;
                                break;
                        case 7:
                        case 7:
                                lp->llc_callbacks|=LLC_RST_CONFIRM;
                                lp->llc_callbacks|=LLC_RST_CONFIRM;
                                break;
                                break;
                        case 66:
                        case 66:
                                lp->llc_callbacks|=LLC_FRMR_RECV;
                                lp->llc_callbacks|=LLC_FRMR_RECV;
                                break;
                                break;
                        case 67:
                        case 67:
                                lp->llc_callbacks|=LLC_FRMR_SENT;
                                lp->llc_callbacks|=LLC_FRMR_SENT;
                                break;
                                break;
                        case 68:
                        case 68:
                                lp->llc_callbacks|=LLC_REMOTE_BUSY;
                                lp->llc_callbacks|=LLC_REMOTE_BUSY;
                                break;
                                break;
                        case 69:
                        case 69:
                                lp->llc_callbacks|=LLC_REMOTE_NOTBUSY;
                                lp->llc_callbacks|=LLC_REMOTE_NOTBUSY;
                                break;
                                break;
                        case 11:
                        case 11:
                                llc_sendpdu(lp, DISC_CMD, lp->f_flag, 0, NULL);
                                llc_sendpdu(lp, DISC_CMD, lp->f_flag, 0, NULL);
                                break;
                                break;
                        case 12:
                        case 12:
                                llc_sendpdu(lp, DM_RSP, 0, 0, NULL);
                                llc_sendpdu(lp, DM_RSP, 0, 0, NULL);
                                break;
                                break;
                        case 13:
                        case 13:
                                lp->frmr_info_fld.cntl1 = fr->pdu_cntl.byte1;
                                lp->frmr_info_fld.cntl1 = fr->pdu_cntl.byte1;
                                lp->frmr_info_fld.cntl2 = fr->pdu_cntl.byte2;
                                lp->frmr_info_fld.cntl2 = fr->pdu_cntl.byte2;
                                lp->frmr_info_fld.vs = lp->vs;
                                lp->frmr_info_fld.vs = lp->vs;
                                lp->frmr_info_fld.vr_cr = lp->vr;
                                lp->frmr_info_fld.vr_cr = lp->vr;
                                llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
                                llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
                                break;
                                break;
                        case 14:
                        case 14:
                                llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
                                llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
                                break;
                                break;
                        case 15:
                        case 15:
                                llc_sendpdu(lp, FRMR_RSP, lp->p_flag,
                                llc_sendpdu(lp, FRMR_RSP, lp->p_flag,
                                        5, (char *) &lp->frmr_info_fld);
                                        5, (char *) &lp->frmr_info_fld);
                                break;
                                break;
                        case 16:
                        case 16:
                                llc_sendipdu(lp, I_CMD, 1, skb);
                                llc_sendipdu(lp, I_CMD, 1, skb);
                                break;
                                break;
                        case 17:
                        case 17:
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
                                break;
                                break;
                        case 18:
                        case 18:
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
                                if (resend_count == 0)
                                if (resend_count == 0)
                                {
                                {
                                        llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
                                        llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
                                }
                                }
                                break;
                                break;
                        case 19:
                        case 19:
                                llc_sendipdu(lp, I_CMD, 0, skb);
                                llc_sendipdu(lp, I_CMD, 0, skb);
                                break;
                                break;
                        case 20:
                        case 20:
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
                                break;
                                break;
                        case 21:
                        case 21:
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
                                if (resend_count == 0)
                                if (resend_count == 0)
                                {
                                {
                                        llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
                                        llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
                                }
                                }
                                break;
                                break;
                        case 22:
                        case 22:
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_RSP, 1);
                                resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_RSP, 1);
                                break;
                                break;
                        case 23:
                        case 23:
                                llc_sendpdu(lp, REJ_CMD, 1, 0, NULL);
                                llc_sendpdu(lp, REJ_CMD, 1, 0, NULL);
                                break;
                                break;
                        case 24:
                        case 24:
                                llc_sendpdu(lp, REJ_RSP, 1, 0, NULL);
                                llc_sendpdu(lp, REJ_RSP, 1, 0, NULL);
                                break;
                                break;
                        case 25:
                        case 25:
                                if (IS_RSP(fr))
                                if (IS_RSP(fr))
                                        llc_sendpdu(lp, REJ_CMD, 0, 0, NULL);
                                        llc_sendpdu(lp, REJ_CMD, 0, 0, NULL);
                                else
                                else
                                        llc_sendpdu(lp, REJ_RSP, 0, 0, NULL);
                                        llc_sendpdu(lp, REJ_RSP, 0, 0, NULL);
                                break;
                                break;
                        case 26:
                        case 26:
                                llc_sendpdu(lp, RNR_CMD, 1, 0, NULL);
                                llc_sendpdu(lp, RNR_CMD, 1, 0, NULL);
                                break;
                                break;
                        case 27:
                        case 27:
                                llc_sendpdu(lp, RNR_RSP, 1, 0, NULL);
                                llc_sendpdu(lp, RNR_RSP, 1, 0, NULL);
                                break;
                                break;
                        case 28:
                        case 28:
                                if (IS_RSP(fr))
                                if (IS_RSP(fr))
                                        llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
                                        llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
                                else
                                else
                                        llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
                                        llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
                                break;
                                break;
                        case 29:
                        case 29:
                                if (lp->remote_busy == 0)
                                if (lp->remote_busy == 0)
                                {
                                {
                                        lp->remote_busy = 1;
                                        lp->remote_busy = 1;
                                        llc_start_timer(lp, BUSY_TIMER);
                                        llc_start_timer(lp, BUSY_TIMER);
                                        lp->llc_callbacks|=LLC_REMOTE_BUSY;
                                        lp->llc_callbacks|=LLC_REMOTE_BUSY;
                                }
                                }
                                else if (lp->timer_state[BUSY_TIMER] == TIMER_IDLE)
                                else if (lp->timer_state[BUSY_TIMER] == TIMER_IDLE)
                                {
                                {
                                        llc_start_timer(lp, BUSY_TIMER);
                                        llc_start_timer(lp, BUSY_TIMER);
                                }
                                }
                                break;
                                break;
                        case 30:
                        case 30:
                                if (IS_RSP(fr))
                                if (IS_RSP(fr))
                                        llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
                                        llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
                                else
                                else
                                        llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
                                        llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
                                break;
                                break;
                        case 31:
                        case 31:
                                llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
                                llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
                                break;
                                break;
                        case 32:
                        case 32:
                                llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
                                llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
                                break;
                                break;
                        case 33:
                        case 33:
                                llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
                                llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
                                break;
                                break;
                        case 34:
                        case 34:
                                llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
                                llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
                                break;
                                break;
                        case 35:
                        case 35:
                                llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
                                llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
                                break;
                                break;
                        case 36:
                        case 36:
                                if (IS_RSP(fr))
                                if (IS_RSP(fr))
                                        llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
                                        llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
                                else
                                else
                                        llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
                                        llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
                                break;
                                break;
                        case 37:
                        case 37:
                                llc_sendpdu(lp, SABME_CMD, 0, 0, NULL);
                                llc_sendpdu(lp, SABME_CMD, 0, 0, NULL);
                                lp->f_flag = 0;
                                lp->f_flag = 0;
                                break;
                                break;
                        case 38:
                        case 38:
                                llc_sendpdu(lp, UA_RSP, lp->f_flag, 0, NULL);
                                llc_sendpdu(lp, UA_RSP, lp->f_flag, 0, NULL);
                                break;
                                break;
                        case 39:
                        case 39:
                                lp->s_flag = 0;
                                lp->s_flag = 0;
                                break;
                                break;
                        case 40:
                        case 40:
                                lp->s_flag = 1;
                                lp->s_flag = 1;
                                break;
                                break;
                        case 41:
                        case 41:
                                if(lp->timer_state[P_TIMER] == TIMER_RUNNING)
                                if(lp->timer_state[P_TIMER] == TIMER_RUNNING)
                                        llc_stop_timer(lp, P_TIMER);
                                        llc_stop_timer(lp, P_TIMER);
                                llc_start_timer(lp, P_TIMER);
                                llc_start_timer(lp, P_TIMER);
                                if (lp->p_flag == 0)
                                if (lp->p_flag == 0)
                                {
                                {
                                        lp->retry_count = 0;
                                        lp->retry_count = 0;
                                        lp->p_flag = 1;
                                        lp->p_flag = 1;
                                }
                                }
                                break;
                                break;
                        case 44:
                        case 44:
                                if (lp->timer_state[ACK_TIMER] == TIMER_IDLE)
                                if (lp->timer_state[ACK_TIMER] == TIMER_IDLE)
                                        llc_start_timer(lp, ACK_TIMER);
                                        llc_start_timer(lp, ACK_TIMER);
                                break;
                                break;
                        case 42:
                        case 42:
                                llc_start_timer(lp, ACK_TIMER);
                                llc_start_timer(lp, ACK_TIMER);
                                break;
                                break;
                        case 43:
                        case 43:
                                llc_start_timer(lp, REJ_TIMER);
                                llc_start_timer(lp, REJ_TIMER);
                                break;
                                break;
                        case 45:
                        case 45:
                                llc_stop_timer(lp, ACK_TIMER);
                                llc_stop_timer(lp, ACK_TIMER);
                                break;
                                break;
                        case 46:
                        case 46:
                                llc_stop_timer(lp, ACK_TIMER);
                                llc_stop_timer(lp, ACK_TIMER);
                                lp->p_flag = 0;
                                lp->p_flag = 0;
                                break;
                                break;
                        case 10:
                        case 10:
                                if (lp->data_flag == 2)
                                if (lp->data_flag == 2)
                                        llc_stop_timer(lp, REJ_TIMER);
                                        llc_stop_timer(lp, REJ_TIMER);
                                break;
                                break;
                        case 47:
                        case 47:
                                llc_stop_timer(lp, REJ_TIMER);
                                llc_stop_timer(lp, REJ_TIMER);
                                break;
                                break;
                        case 48:
                        case 48:
                                llc_stop_timer(lp, ACK_TIMER);
                                llc_stop_timer(lp, ACK_TIMER);
                                llc_stop_timer(lp, P_TIMER);
                                llc_stop_timer(lp, P_TIMER);
                                llc_stop_timer(lp, REJ_TIMER);
                                llc_stop_timer(lp, REJ_TIMER);
                                llc_stop_timer(lp, BUSY_TIMER);
                                llc_stop_timer(lp, BUSY_TIMER);
                                break;
                                break;
                        case 49:
                        case 49:
                                llc_stop_timer(lp, P_TIMER);
                                llc_stop_timer(lp, P_TIMER);
                                llc_stop_timer(lp, REJ_TIMER);
                                llc_stop_timer(lp, REJ_TIMER);
                                llc_stop_timer(lp, BUSY_TIMER);
                                llc_stop_timer(lp, BUSY_TIMER);
                                break;
                                break;
                        case 50:
                        case 50:
                                ack_count = llc_free_acknowledged_skbs(lp,
                                ack_count = llc_free_acknowledged_skbs(lp,
                                        (unsigned char) fr->s_hdr.nr);
                                        (unsigned char) fr->s_hdr.nr);
                                if (ack_count > 0)
                                if (ack_count > 0)
                                {
                                {
                                        lp->retry_count = 0;
                                        lp->retry_count = 0;
                                        llc_stop_timer(lp, ACK_TIMER);
                                        llc_stop_timer(lp, ACK_TIMER);
                                        if (skb_peek(&lp->rtq) != NULL)
                                        if (skb_peek(&lp->rtq) != NULL)
                                        {
                                        {
                                                /*
                                                /*
                                                 *      Re-transmit queue not empty
                                                 *      Re-transmit queue not empty
                                                 */
                                                 */
                                                llc_start_timer(lp, ACK_TIMER);
                                                llc_start_timer(lp, ACK_TIMER);
                                        }
                                        }
                                }
                                }
                                break;
                                break;
                        case 51:
                        case 51:
                                if (IS_UFRAME(fr))
                                if (IS_UFRAME(fr))
                                        p_flag_received = fr->u_hdr.u_pflag;
                                        p_flag_received = fr->u_hdr.u_pflag;
                                else
                                else
                                        p_flag_received = fr->i_hdr.i_pflag;
                                        p_flag_received = fr->i_hdr.i_pflag;
                                if ((fr->pdu_hdr.ssap & 0x01) && (p_flag_received))
                                if ((fr->pdu_hdr.ssap & 0x01) && (p_flag_received))
                                {
                                {
                                        lp->p_flag = 0;
                                        lp->p_flag = 0;
                                        llc_stop_timer(lp, P_TIMER);
                                        llc_stop_timer(lp, P_TIMER);
                                }
                                }
                                break;
                                break;
                        case 52:
                        case 52:
                                lp->data_flag = 2;
                                lp->data_flag = 2;
                                break;
                                break;
                        case 53:
                        case 53:
                                lp->data_flag = 0;
                                lp->data_flag = 0;
                                break;
                                break;
                        case 54:
                        case 54:
                                lp->data_flag = 1;
                                lp->data_flag = 1;
                                break;
                                break;
                        case 55:
                        case 55:
                                if (lp->data_flag == 0)
                                if (lp->data_flag == 0)
                                        lp->data_flag = 1;
                                        lp->data_flag = 1;
                                break;
                                break;
                        case 56:
                        case 56:
                                lp->p_flag = 0;
                                lp->p_flag = 0;
                                break;
                                break;
                        case 57:
                        case 57:
                                lp->p_flag = lp->f_flag;
                                lp->p_flag = lp->f_flag;
                                break;
                                break;
                        case 58:
                        case 58:
                                lp->remote_busy = 0;
                                lp->remote_busy = 0;
                                break;
                                break;
                        case 59:
                        case 59:
                                lp->retry_count = 0;
                                lp->retry_count = 0;
                                break;
                                break;
                        case 60:
                        case 60:
                                lp->retry_count++;
                                lp->retry_count++;
                                break;
                                break;
                        case 61:
                        case 61:
                                lp->vr = 0;
                                lp->vr = 0;
                                break;
                                break;
                        case 62:
                        case 62:
                                lp->vr++;
                                lp->vr++;
                                break;
                                break;
                        case 63:
                        case 63:
                                lp->vs = 0;
                                lp->vs = 0;
                                break;
                                break;
                        case 64:
                        case 64:
                                lp->vs = fr->i_hdr.nr;
                                lp->vs = fr->i_hdr.nr;
                                break;
                                break;
                        case 65:
                        case 65:
                                if (IS_UFRAME(fr))
                                if (IS_UFRAME(fr))
                                        lp->f_flag = fr->u_hdr.u_pflag;
                                        lp->f_flag = fr->u_hdr.u_pflag;
                                else
                                else
                                        lp->f_flag = fr->i_hdr.i_pflag;
                                        lp->f_flag = fr->i_hdr.i_pflag;
                                break;
                                break;
                        default:;
                        default:;
                }
                }
                pc++;
                pc++;
        }
        }
}
}
 
 
 
 
/*
/*
 *      Process_otype2_frame will handle incoming frames
 *      Process_otype2_frame will handle incoming frames
 *      for 802.2 Type 2 Procedure.
 *      for 802.2 Type 2 Procedure.
 */
 */
 
 
void llc_process_otype2_frame(llcptr lp, struct sk_buff *skb, char type)
void llc_process_otype2_frame(llcptr lp, struct sk_buff *skb, char type)
{
{
        int idx;                /*      index in transition table */
        int idx;                /*      index in transition table */
        int pc_label;           /*      action to perform, from tr tbl */
        int pc_label;           /*      action to perform, from tr tbl */
        int validation;         /*      result of validate_seq_nos */
        int validation;         /*      result of validate_seq_nos */
        int p_flag_received;    /*      p_flag in received frame */
        int p_flag_received;    /*      p_flag in received frame */
        frameptr fr;
        frameptr fr;
 
 
        fr = (frameptr) skb->data;
        fr = (frameptr) skb->data;
 
 
        if (IS_UFRAME(fr))
        if (IS_UFRAME(fr))
                p_flag_received = fr->u_hdr.u_pflag;
                p_flag_received = fr->u_hdr.u_pflag;
        else
        else
                p_flag_received = fr->i_hdr.i_pflag;
                p_flag_received = fr->i_hdr.i_pflag;
 
 
        switch(lp->state)
        switch(lp->state)
        {
        {
                /*      Compute index in transition table: */
                /*      Compute index in transition table: */
                case ADM:
                case ADM:
                        idx = type;
                        idx = type;
                        idx = (idx << 1) + p_flag_received;
                        idx = (idx << 1) + p_flag_received;
                        break;
                        break;
                case CONN:
                case CONN:
                case RESET_WAIT:
                case RESET_WAIT:
                case RESET_CHECK:
                case RESET_CHECK:
                case ERROR:
                case ERROR:
                        idx = type;
                        idx = type;
                        break;
                        break;
                case SETUP:
                case SETUP:
                case RESET:
                case RESET:
                case D_CONN:
                case D_CONN:
                        idx = type;
                        idx = type;
                        idx = (idx << 1) + lp->p_flag;
                        idx = (idx << 1) + lp->p_flag;
                        break;
                        break;
                case NORMAL:
                case NORMAL:
                case BUSY:
                case BUSY:
                case REJECT:
                case REJECT:
                case AWAIT:
                case AWAIT:
                case AWAIT_BUSY:
                case AWAIT_BUSY:
                case AWAIT_REJECT:
                case AWAIT_REJECT:
                        validation = llc_validate_seq_nos(lp, fr);
                        validation = llc_validate_seq_nos(lp, fr);
                        if (validation > 3)
                        if (validation > 3)
                                type = BAD_FRAME;
                                type = BAD_FRAME;
                        idx = type;
                        idx = type;
                        idx = (idx << 1);
                        idx = (idx << 1);
                        if (validation & 1)
                        if (validation & 1)
                                idx = idx +1;
                                idx = idx +1;
                        idx = (idx << 1) + p_flag_received;
                        idx = (idx << 1) + p_flag_received;
                        idx = (idx << 1) + lp->p_flag;
                        idx = (idx << 1) + lp->p_flag;
                default:
                default:
                        printk("llc_proc: bad state\n");
                        printk("llc_proc: bad state\n");
                        return;
                        return;
        }
        }
        idx = (idx << 1) + pdutr_offset[lp->state];
        idx = (idx << 1) + pdutr_offset[lp->state];
        lp->state = pdutr_entry[idx +1];
        lp->state = pdutr_entry[idx +1];
        pc_label = pdutr_entry[idx];
        pc_label = pdutr_entry[idx];
        if (pc_label != 0)
        if (pc_label != 0)
        {
        {
                llc_interpret_pseudo_code(lp, pc_label, skb, type);
                llc_interpret_pseudo_code(lp, pc_label, skb, type);
                if(lp->llc_callbacks)
                if(lp->llc_callbacks)
                {
                {
                        lp->llc_event(lp);
                        lp->llc_event(lp);
                        lp->llc_callbacks=0;
                        lp->llc_callbacks=0;
                }
                }
                /*
                /*
                 *      lp may no longer be valid after this point. Be
                 *      lp may no longer be valid after this point. Be
                 *      careful what is added!
                 *      careful what is added!
                 */
                 */
        }
        }
}
}
 
 
 
 
void llc_timer_expired(llcptr lp, int t)
void llc_timer_expired(llcptr lp, int t)
{
{
        int idx;                /* index in transition table    */
        int idx;                /* index in transition table    */
        int pc_label;           /* action to perform, from tr tbl */
        int pc_label;           /* action to perform, from tr tbl */
 
 
        lp->timer_state[t] = TIMER_EXPIRED;
        lp->timer_state[t] = TIMER_EXPIRED;
        idx = lp->state;            /* Compute index in transition table: */
        idx = lp->state;            /* Compute index in transition table: */
        idx = (idx << 2) + t;
        idx = (idx << 2) + t;
        idx = idx << 1;
        idx = idx << 1;
        if (lp->retry_count >= lp->n2)
        if (lp->retry_count >= lp->n2)
                idx = idx + 1;
                idx = idx + 1;
        idx = (idx << 1) + lp->s_flag;
        idx = (idx << 1) + lp->s_flag;
        idx = (idx << 1) + lp->p_flag;
        idx = (idx << 1) + lp->p_flag;
        idx = idx << 1;             /* 2 bytes per entry: action & newstate */
        idx = idx << 1;             /* 2 bytes per entry: action & newstate */
 
 
        pc_label = timertr_entry[idx];
        pc_label = timertr_entry[idx];
        if (pc_label != 0)
        if (pc_label != 0)
        {
        {
                llc_interpret_pseudo_code(lp, pc_label, NULL, NO_FRAME);
                llc_interpret_pseudo_code(lp, pc_label, NULL, NO_FRAME);
                lp->state = timertr_entry[idx +1];
                lp->state = timertr_entry[idx +1];
        }
        }
        lp->timer_state[t] = TIMER_IDLE;
        lp->timer_state[t] = TIMER_IDLE;
        if(lp->llc_callbacks)
        if(lp->llc_callbacks)
        {
        {
                lp->llc_event(lp);
                lp->llc_event(lp);
                lp->llc_callbacks=0;
                lp->llc_callbacks=0;
        }
        }
        /*
        /*
         *      And lp may have vanished in the event callback
         *      And lp may have vanished in the event callback
         */
         */
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.