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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [802/] [llc_utility.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.
 *
 *
 *              Small utilities, Linux timer handling.
 *              Small utilities, Linux timer handling.
 *
 *
 *              Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
 *              Written by Tim Alpaerts, 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 form.
 *              Alan Cox        :       Chainsawed into Linux form.
 *                                      Added llc_ function name prefixes.
 *                                      Added llc_ function name prefixes.
 *                                      Fixed bug in stop/start timer.
 *                                      Fixed bug in stop/start timer.
 *                                      Added llc_cancel_timers for closing
 *                                      Added llc_cancel_timers for closing
 *                                              down an llc
 *                                              down an llc
 */
 */
 
 
#include <linux/types.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <net/llc_frame.h>
#include <net/llc_frame.h>
#include <net/llc.h>
#include <net/llc.h>
 
 
int llc_decode_frametype(frameptr fr)
int llc_decode_frametype(frameptr fr)
{
{
        if (IS_UFRAME(fr))
        if (IS_UFRAME(fr))
        {      /* unnumbered cmd/rsp */
        {      /* unnumbered cmd/rsp */
                switch(fr->u_mm.mm & 0x3B)
                switch(fr->u_mm.mm & 0x3B)
                {
                {
                        case 0x1B:
                        case 0x1B:
                            return(SABME_CMD);
                            return(SABME_CMD);
                            break;
                            break;
                        case 0x10:
                        case 0x10:
                            return(DISC_CMD);
                            return(DISC_CMD);
                            break;
                            break;
                        case 0x18:
                        case 0x18:
                            return(UA_RSP);
                            return(UA_RSP);
                            break;
                            break;
                        case 0x03:
                        case 0x03:
                            return(DM_RSP);
                            return(DM_RSP);
                            break;
                            break;
                        case 0x21:
                        case 0x21:
                            return(FRMR_RSP);
                            return(FRMR_RSP);
                            break;
                            break;
                        case 0x00:
                        case 0x00:
                            return(UI_CMD);
                            return(UI_CMD);
                            break;
                            break;
                        case 0x2B:
                        case 0x2B:
                            if (IS_RSP(fr))
                            if (IS_RSP(fr))
                                return(XID_RSP);
                                return(XID_RSP);
                            else
                            else
                                return(XID_CMD);
                                return(XID_CMD);
                            break;
                            break;
                        case 0x38:
                        case 0x38:
                            if (IS_RSP(fr))
                            if (IS_RSP(fr))
                                return(TEST_RSP);
                                return(TEST_RSP);
                            else
                            else
                                return(TEST_CMD);
                                return(TEST_CMD);
                            break;
                            break;
                        default:
                        default:
                            return(BAD_FRAME);
                            return(BAD_FRAME);
                }
                }
        }
        }
        else if (IS_SFRAME(fr))
        else if (IS_SFRAME(fr))
        {  /* supervisory cmd/rsp */
        {  /* supervisory cmd/rsp */
                switch(fr->s_hdr.ss)
                switch(fr->s_hdr.ss)
                {
                {
                        case 0x00:
                        case 0x00:
                            if (IS_RSP(fr))
                            if (IS_RSP(fr))
                                return(RR_RSP);
                                return(RR_RSP);
                            else
                            else
                                return(RR_CMD);
                                return(RR_CMD);
                            break;
                            break;
                        case 0x02:
                        case 0x02:
                            if (IS_RSP(fr))
                            if (IS_RSP(fr))
                                return(REJ_RSP);
                                return(REJ_RSP);
                            else
                            else
                                return(REJ_CMD);
                                return(REJ_CMD);
                            break;
                            break;
                        case 0x01:
                        case 0x01:
                            if (IS_RSP(fr))
                            if (IS_RSP(fr))
                                return(RNR_RSP);
                                return(RNR_RSP);
                            else
                            else
                                return(RNR_CMD);
                                return(RNR_CMD);
                            break;
                            break;
                        default:
                        default:
                            return(BAD_FRAME);
                            return(BAD_FRAME);
                }
                }
        }
        }
        else
        else
        {                         /* information xfer */
        {                         /* information xfer */
                if (IS_RSP(fr))
                if (IS_RSP(fr))
                        return(I_RSP);
                        return(I_RSP);
                else
                else
                        return(I_CMD);
                        return(I_CMD);
        }
        }
}
}
 
 
 
 
/*
/*
 *      Validate_seq_nos will check N(S) and N(R) to see if they are
 *      Validate_seq_nos will check N(S) and N(R) to see if they are
 *      invalid or unexpected.
 *      invalid or unexpected.
 *      "unexpected" is explained on p44 Send State Variable.
 *      "unexpected" is explained on p44 Send State Variable.
 *      The return value is:
 *      The return value is:
 *              4 * invalid N(R) +
 *              4 * invalid N(R) +
 *              2 * invalid N(S) +
 *              2 * invalid N(S) +
 *              1 * unexpected N(S)
 *              1 * unexpected N(S)
 */
 */
 
 
int llc_validate_seq_nos(llcptr lp, frameptr fr)
int llc_validate_seq_nos(llcptr lp, frameptr fr)
{
{
        int res;
        int res;
 
 
        /*
        /*
         *      A U-frame is always good
         *      A U-frame is always good
         */
         */
 
 
        if (IS_UFRAME(fr))
        if (IS_UFRAME(fr))
                return(0);
                return(0);
 
 
        /*
        /*
         *      For S- and I-frames check N(R):
         *      For S- and I-frames check N(R):
         */
         */
 
 
        if (fr->i_hdr.nr == lp->vs)
        if (fr->i_hdr.nr == lp->vs)
        {       /* if N(R) = V(S)  */
        {       /* if N(R) = V(S)  */
                res = 0;                        /* N(R) is good */
                res = 0;                        /* N(R) is good */
        }
        }
        else
        else
        {                               /* lp->k = transmit window size */
        {                               /* lp->k = transmit window size */
                if (lp->vs >= lp->k)
                if (lp->vs >= lp->k)
                {       /* if window not wrapped around 127 */
                {       /* if window not wrapped around 127 */
                        if ((fr->i_hdr.nr < lp->vs) &&
                        if ((fr->i_hdr.nr < lp->vs) &&
                                (fr->i_hdr.nr > (lp->vs - lp->k)))
                                (fr->i_hdr.nr > (lp->vs - lp->k)))
                                res = 0;
                                res = 0;
                        else
                        else
                                res = 4;                /* N(R) invalid */
                                res = 4;                /* N(R) invalid */
                }
                }
                else
                else
                {       /* window wraps around 127 */
                {       /* window wraps around 127 */
                        if ((fr->i_hdr.nr < lp->vs) ||
                        if ((fr->i_hdr.nr < lp->vs) ||
                                (fr->i_hdr.nr > (128 + lp->vs - lp->k)))
                                (fr->i_hdr.nr > (128 + lp->vs - lp->k)))
                                res = 0;
                                res = 0;
                        else
                        else
                                res = 4;                /* N(R) invalid */
                                res = 4;                /* N(R) invalid */
                }
                }
        }
        }
 
 
        /*
        /*
         *      For an I-frame, must check N(S) also:
         *      For an I-frame, must check N(S) also:
         */
         */
 
 
        if (IS_IFRAME(fr))
        if (IS_IFRAME(fr))
        {
        {
                if (fr->i_hdr.ns == lp->vr)
                if (fr->i_hdr.ns == lp->vr)
                        return res;   /* N(S) good */
                        return res;   /* N(S) good */
                if (lp->vr >= lp->rw)
                if (lp->vr >= lp->rw)
                {
                {
                        /* if receive window not wrapped */
                        /* if receive window not wrapped */
 
 
                        if ((fr->i_hdr.ns < lp->vr) &&
                        if ((fr->i_hdr.ns < lp->vr) &&
                                (fr->i_hdr.ns > (lp->vr - lp->k)))
                                (fr->i_hdr.ns > (lp->vr - lp->k)))
                                res = res +1;           /* N(S) unexpected */
                                res = res +1;           /* N(S) unexpected */
                        else
                        else
                                res = res +2;         /* N(S) invalid */
                                res = res +2;         /* N(S) invalid */
                }
                }
                else
                else
                {
                {
                        /* Window wraps around 127 */
                        /* Window wraps around 127 */
 
 
                        if ((fr->i_hdr.ns < lp->vr) ||
                        if ((fr->i_hdr.ns < lp->vr) ||
                                (fr->i_hdr.ns > (128 + lp->vr - lp->k)))
                                (fr->i_hdr.ns > (128 + lp->vr - lp->k)))
                                res = res +1;           /* N(S) unexpected */
                                res = res +1;           /* N(S) unexpected */
                        else
                        else
                                res = res +2;         /* N(S) invalid */
                                res = res +2;         /* N(S) invalid */
                }
                }
        }
        }
        return(res);
        return(res);
}
}
 
 
/* **************** timer management routines ********************* */
/* **************** timer management routines ********************* */
 
 
static void llc_p_timer_expired(unsigned long ulp)
static void llc_p_timer_expired(unsigned long ulp)
{
{
        llc_timer_expired((llcptr) ulp, P_TIMER);
        llc_timer_expired((llcptr) ulp, P_TIMER);
}
}
 
 
static void llc_rej_timer_expired(unsigned long ulp)
static void llc_rej_timer_expired(unsigned long ulp)
{
{
        llc_timer_expired((llcptr) ulp, REJ_TIMER);
        llc_timer_expired((llcptr) ulp, REJ_TIMER);
}
}
 
 
static void llc_ack_timer_expired(unsigned long ulp)
static void llc_ack_timer_expired(unsigned long ulp)
{
{
        llc_timer_expired((llcptr) ulp, ACK_TIMER);
        llc_timer_expired((llcptr) ulp, ACK_TIMER);
}
}
 
 
static void llc_busy_timer_expired(unsigned long ulp)
static void llc_busy_timer_expired(unsigned long ulp)
{
{
        llc_timer_expired((llcptr) ulp, BUSY_TIMER);
        llc_timer_expired((llcptr) ulp, BUSY_TIMER);
}
}
 
 
/* exp_fcn is an array holding the 4 entry points of the
/* exp_fcn is an array holding the 4 entry points of the
   timer expiry routines above.
   timer expiry routines above.
   It is required to keep start_timer() generic.
   It is required to keep start_timer() generic.
   Thank you cdecl.
   Thank you cdecl.
 */
 */
 
 
static void (* exp_fcn[])(unsigned long) =
static void (* exp_fcn[])(unsigned long) =
{
{
        llc_p_timer_expired,
        llc_p_timer_expired,
        llc_rej_timer_expired,
        llc_rej_timer_expired,
        llc_ack_timer_expired,
        llc_ack_timer_expired,
        llc_busy_timer_expired
        llc_busy_timer_expired
};
};
 
 
void llc_start_timer(llcptr lp, int t)
void llc_start_timer(llcptr lp, int t)
{
{
        if (lp->timer_state[t] == TIMER_IDLE)
        if (lp->timer_state[t] == TIMER_IDLE)
        {
        {
                lp->tl[t].expires = jiffies + lp->timer_interval[t];
                lp->tl[t].expires = jiffies + lp->timer_interval[t];
                lp->tl[t].data = (unsigned long) lp;
                lp->tl[t].data = (unsigned long) lp;
                lp->tl[t].function = exp_fcn[t];
                lp->tl[t].function = exp_fcn[t];
                add_timer(&lp->tl[t]);
                add_timer(&lp->tl[t]);
                lp->timer_state[t] = TIMER_RUNNING;
                lp->timer_state[t] = TIMER_RUNNING;
        }
        }
}
}
 
 
void llc_stop_timer(llcptr lp, int t)
void llc_stop_timer(llcptr lp, int t)
{
{
        if (lp->timer_state[t] == TIMER_RUNNING)
        if (lp->timer_state[t] == TIMER_RUNNING)
        {
        {
                del_timer(&lp->tl[t]);
                del_timer(&lp->tl[t]);
                lp->timer_state[t] = TIMER_IDLE;
                lp->timer_state[t] = TIMER_IDLE;
        }
        }
}
}
 
 
void llc_cancel_timers(llcptr lp)
void llc_cancel_timers(llcptr lp)
{
{
        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, ACK_TIMER);
        llc_stop_timer(lp, ACK_TIMER);
        llc_stop_timer(lp, BUSY_TIMER);
        llc_stop_timer(lp, BUSY_TIMER);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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