linux/drivers/net/fddi/skfp/srf.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 *      (C)Copyright 1998,1999 SysKonnect,
   4 *      a business unit of Schneider & Koch & Co. Datensysteme GmbH.
   5 *
   6 *      See the file "skfddi.c" for further information.
   7 *
   8 *      This program is free software; you can redistribute it and/or modify
   9 *      it under the terms of the GNU General Public License as published by
  10 *      the Free Software Foundation; either version 2 of the License, or
  11 *      (at your option) any later version.
  12 *
  13 *      The information in this file is provided "AS IS" without warranty.
  14 *
  15 ******************************************************************************/
  16
  17/*
  18        SMT 7.2 Status Response Frame Implementation
  19        SRF state machine and frame generation
  20*/
  21
  22#include "h/types.h"
  23#include "h/fddi.h"
  24#include "h/smc.h"
  25#include "h/smt_p.h"
  26
  27#define KERNEL
  28#include "h/smtstate.h"
  29
  30#ifndef SLIM_SMT
  31#ifndef BOOT
  32
  33#ifndef lint
  34static const char ID_sccs[] = "@(#)srf.c        1.18 97/08/04 (C) SK " ;
  35#endif
  36
  37
  38/*
  39 * function declarations
  40 */
  41static void clear_all_rep(struct s_smc *smc);
  42static void clear_reported(struct s_smc *smc);
  43static void smt_send_srf(struct s_smc *smc);
  44static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
  45
  46#define MAX_EVCS        ARRAY_SIZE(smc->evcs)
  47
  48struct evc_init {
  49        u_char code ;
  50        u_char index ;
  51        u_char n ;
  52        u_short para ;
  53}  ;
  54
  55static const struct evc_init evc_inits[] = {
  56        { SMT_COND_SMT_PEER_WRAP,               0,1,SMT_P1048   } ,
  57
  58        { SMT_COND_MAC_DUP_ADDR,                INDEX_MAC, NUMMACS,SMT_P208C } ,
  59        { SMT_COND_MAC_FRAME_ERROR,             INDEX_MAC, NUMMACS,SMT_P208D } ,
  60        { SMT_COND_MAC_NOT_COPIED,              INDEX_MAC, NUMMACS,SMT_P208E } ,
  61        { SMT_EVENT_MAC_NEIGHBOR_CHANGE,        INDEX_MAC, NUMMACS,SMT_P208F } ,
  62        { SMT_EVENT_MAC_PATH_CHANGE,            INDEX_MAC, NUMMACS,SMT_P2090 } ,
  63
  64        { SMT_COND_PORT_LER,                    INDEX_PORT,NUMPHYS,SMT_P4050 } ,
  65        { SMT_COND_PORT_EB_ERROR,               INDEX_PORT,NUMPHYS,SMT_P4052 } ,
  66        { SMT_EVENT_PORT_CONNECTION,            INDEX_PORT,NUMPHYS,SMT_P4051 } ,
  67        { SMT_EVENT_PORT_PATH_CHANGE,           INDEX_PORT,NUMPHYS,SMT_P4053 } ,
  68} ;
  69
  70#define MAX_INIT_EVC    ARRAY_SIZE(evc_inits)
  71
  72void smt_init_evc(struct s_smc *smc)
  73{
  74        struct s_srf_evc        *evc ;
  75        const struct evc_init   *init ;
  76        unsigned int            i ;
  77        int                     index ;
  78        int                     offset ;
  79
  80        static u_char           fail_safe = FALSE ;
  81
  82        memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
  83
  84        evc = smc->evcs ;
  85        init = evc_inits ;
  86
  87        for (i = 0 ; i < MAX_INIT_EVC ; i++) {
  88                for (index = 0 ; index < init->n ; index++) {
  89                        evc->evc_code = init->code ;
  90                        evc->evc_para = init->para ;
  91                        evc->evc_index = init->index + index ;
  92#ifndef DEBUG
  93                        evc->evc_multiple = &fail_safe ;
  94                        evc->evc_cond_state = &fail_safe ;
  95#endif
  96                        evc++ ;
  97                }
  98                init++ ;
  99        }
 100
 101        if ((unsigned int) (evc - smc->evcs) > MAX_EVCS) {
 102                SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
 103        }
 104
 105        /*
 106         * conditions
 107         */
 108        smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
 109        smc->evcs[1].evc_cond_state =
 110                &smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
 111        smc->evcs[2].evc_cond_state =
 112                &smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
 113        smc->evcs[3].evc_cond_state =
 114                &smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
 115
 116        /*
 117         * events
 118         */
 119        smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
 120        smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
 121
 122        offset = 6 ;
 123        for (i = 0 ; i < NUMPHYS ; i++) {
 124                /*
 125                 * conditions
 126                 */
 127                smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
 128                        &smc->mib.p[i].fddiPORTLerFlag ;
 129                smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
 130                        &smc->mib.p[i].fddiPORTEB_Condition ;
 131
 132                /*
 133                 * events
 134                 */
 135                smc->evcs[offset + 2*NUMPHYS].evc_multiple =
 136                        &smc->mib.p[i].fddiPORTMultiple_U ;
 137                smc->evcs[offset + 3*NUMPHYS].evc_multiple =
 138                        &smc->mib.p[i].fddiPORTMultiple_P ;
 139                offset++ ;
 140        }
 141#ifdef  DEBUG
 142        for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
 143                if (SMT_IS_CONDITION(evc->evc_code)) {
 144                        if (!evc->evc_cond_state) {
 145                                SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
 146                        }
 147                        evc->evc_multiple = &fail_safe ;
 148                }
 149                else {
 150                        if (!evc->evc_multiple) {
 151                                SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
 152                        }
 153                        evc->evc_cond_state = &fail_safe ;
 154                }
 155        }
 156#endif
 157        smc->srf.TSR = smt_get_time() ;
 158        smc->srf.sr_state = SR0_WAIT ;
 159}
 160
 161static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
 162{
 163        unsigned int            i ;
 164        struct s_srf_evc        *evc ;
 165
 166        for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
 167                if (evc->evc_code == code && evc->evc_index == index)
 168                        return evc;
 169        }
 170        return NULL;
 171}
 172
 173#define THRESHOLD_2     (2*TICKS_PER_SECOND)
 174#define THRESHOLD_32    (32*TICKS_PER_SECOND)
 175
 176#ifdef  DEBUG
 177static const char * const srf_names[] = {
 178        "None","MACPathChangeEvent",    "MACNeighborChangeEvent",
 179        "PORTPathChangeEvent",          "PORTUndesiredConnectionAttemptEvent",
 180        "SMTPeerWrapCondition",         "SMTHoldCondition",
 181        "MACFrameErrorCondition",       "MACDuplicateAddressCondition",
 182        "MACNotCopiedCondition",        "PORTEBErrorCondition",
 183        "PORTLerCondition"
 184} ;
 185#endif
 186
 187void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
 188{
 189        struct s_srf_evc        *evc ;
 190        int                     cond_asserted = 0 ;
 191        int                     cond_deasserted = 0 ;
 192        int                     event_occurred = 0 ;
 193        int                     tsr ;
 194        int                     T_Limit = 2*TICKS_PER_SECOND ;
 195
 196        if (code == SMT_COND_MAC_DUP_ADDR && cond) {
 197                RS_SET(smc,RS_DUPADDR) ;
 198        }
 199
 200        if (code) {
 201                DB_SMT("SRF: %s index %d\n",srf_names[code],index) ;
 202
 203                if (!(evc = smt_get_evc(smc,code,index))) {
 204                        DB_SMT("SRF : smt_get_evc() failed\n",0,0) ;
 205                        return ;
 206                }
 207                /*
 208                 * ignore condition if no change
 209                 */
 210                if (SMT_IS_CONDITION(code)) {
 211                        if (*evc->evc_cond_state == cond)
 212                                return ;
 213                }
 214
 215                /*
 216                 * set transition time stamp
 217                 */
 218                smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
 219                if (SMT_IS_CONDITION(code)) {
 220                        DB_SMT("SRF: condition is %s\n",cond ? "ON":"OFF",0) ;
 221                        if (cond) {
 222                                *evc->evc_cond_state = TRUE ;
 223                                evc->evc_rep_required = TRUE ;
 224                                smc->srf.any_report = TRUE ;
 225                                cond_asserted = TRUE ;
 226                        }
 227                        else {
 228                                *evc->evc_cond_state = FALSE ;
 229                                cond_deasserted = TRUE ;
 230                        }
 231                }
 232                else {
 233                        if (evc->evc_rep_required) {
 234                                *evc->evc_multiple  = TRUE ;
 235                        }
 236                        else {
 237                                evc->evc_rep_required = TRUE ;
 238                                *evc->evc_multiple  = FALSE ;
 239                        }
 240                        smc->srf.any_report = TRUE ;
 241                        event_occurred = TRUE ;
 242                }
 243#ifdef  FDDI_MIB
 244                snmp_srf_event(smc,evc) ;
 245#endif  /* FDDI_MIB */
 246        }
 247        tsr = smt_get_time() - smc->srf.TSR ;
 248
 249        switch (smc->srf.sr_state) {
 250        case SR0_WAIT :
 251                /* SR01a */
 252                if (cond_asserted && tsr < T_Limit) {
 253                        smc->srf.SRThreshold = THRESHOLD_2 ;
 254                        smc->srf.sr_state = SR1_HOLDOFF ;
 255                        break ;
 256                }
 257                /* SR01b */
 258                if (cond_deasserted && tsr < T_Limit) {
 259                        smc->srf.sr_state = SR1_HOLDOFF ;
 260                        break ;
 261                }
 262                /* SR01c */
 263                if (event_occurred && tsr < T_Limit) {
 264                        smc->srf.sr_state = SR1_HOLDOFF ;
 265                        break ;
 266                }
 267                /* SR00b */
 268                if (cond_asserted && tsr >= T_Limit) {
 269                        smc->srf.SRThreshold = THRESHOLD_2 ;
 270                        smc->srf.TSR = smt_get_time() ;
 271                        smt_send_srf(smc) ;
 272                        break ;
 273                }
 274                /* SR00c */
 275                if (cond_deasserted && tsr >= T_Limit) {
 276                        smc->srf.TSR = smt_get_time() ;
 277                        smt_send_srf(smc) ;
 278                        break ;
 279                }
 280                /* SR00d */
 281                if (event_occurred && tsr >= T_Limit) {
 282                        smc->srf.TSR = smt_get_time() ;
 283                        smt_send_srf(smc) ;
 284                        break ;
 285                }
 286                /* SR00e */
 287                if (smc->srf.any_report && (u_long) tsr >=
 288                        smc->srf.SRThreshold) {
 289                        smc->srf.SRThreshold *= 2 ;
 290                        if (smc->srf.SRThreshold > THRESHOLD_32)
 291                                smc->srf.SRThreshold = THRESHOLD_32 ;
 292                        smc->srf.TSR = smt_get_time() ;
 293                        smt_send_srf(smc) ;
 294                        break ;
 295                }
 296                /* SR02 */
 297                if (!smc->mib.fddiSMTStatRptPolicy) {
 298                        smc->srf.sr_state = SR2_DISABLED ;
 299                        break ;
 300                }
 301                break ;
 302        case SR1_HOLDOFF :
 303                /* SR10b */
 304                if (tsr >= T_Limit) {
 305                        smc->srf.sr_state = SR0_WAIT ;
 306                        smc->srf.TSR = smt_get_time() ;
 307                        smt_send_srf(smc) ;
 308                        break ;
 309                }
 310                /* SR11a */
 311                if (cond_asserted) {
 312                        smc->srf.SRThreshold = THRESHOLD_2 ;
 313                }
 314                /* SR11b */
 315                /* SR11c */
 316                /* handled above */
 317                /* SR12 */
 318                if (!smc->mib.fddiSMTStatRptPolicy) {
 319                        smc->srf.sr_state = SR2_DISABLED ;
 320                        break ;
 321                }
 322                break ;
 323        case SR2_DISABLED :
 324                if (smc->mib.fddiSMTStatRptPolicy) {
 325                        smc->srf.sr_state = SR0_WAIT ;
 326                        smc->srf.TSR = smt_get_time() ;
 327                        smc->srf.SRThreshold = THRESHOLD_2 ;
 328                        clear_all_rep(smc) ;
 329                        break ;
 330                }
 331                break ;
 332        }
 333}
 334
 335static void clear_all_rep(struct s_smc *smc)
 336{
 337        struct s_srf_evc        *evc ;
 338        unsigned int            i ;
 339
 340        for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
 341                evc->evc_rep_required = FALSE ;
 342                if (SMT_IS_CONDITION(evc->evc_code))
 343                        *evc->evc_cond_state = FALSE ;
 344        }
 345        smc->srf.any_report = FALSE ;
 346}
 347
 348static void clear_reported(struct s_smc *smc)
 349{
 350        struct s_srf_evc        *evc ;
 351        unsigned int            i ;
 352
 353        smc->srf.any_report = FALSE ;
 354        for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
 355                if (SMT_IS_CONDITION(evc->evc_code)) {
 356                        if (*evc->evc_cond_state == FALSE)
 357                                evc->evc_rep_required = FALSE ;
 358                        else
 359                                smc->srf.any_report = TRUE ;
 360                }
 361                else {
 362                        evc->evc_rep_required = FALSE ;
 363                        *evc->evc_multiple = FALSE ;
 364                }
 365        }
 366}
 367
 368/*
 369 * build and send SMT SRF frame
 370 */
 371static void smt_send_srf(struct s_smc *smc)
 372{
 373
 374        struct smt_header       *smt ;
 375        struct s_srf_evc        *evc ;
 376        SK_LOC_DECL(struct s_pcon,pcon) ;
 377        SMbuf                   *mb ;
 378        unsigned int            i ;
 379
 380        static const struct fddi_addr SMT_SRF_DA = {
 381                { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
 382        } ;
 383
 384        /*
 385         * build SMT header
 386         */
 387        if (!smc->r.sm_ma_avail)
 388                return ;
 389        if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
 390                return ;
 391
 392        RS_SET(smc,RS_SOFTERROR) ;
 393
 394        smt = smtod(mb, struct smt_header *) ;
 395        smt->smt_dest = SMT_SRF_DA ;            /* DA == SRF multicast */
 396
 397        /*
 398         * setup parameter status
 399         */
 400        pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
 401        pcon.pc_err = 0 ;                       /* no error */
 402        pcon.pc_badset = 0 ;                    /* no bad set count */
 403        pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
 404
 405        smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
 406        smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
 407
 408        for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
 409                if (evc->evc_rep_required) {
 410                        smt_add_para(smc,&pcon,evc->evc_para,
 411                                (int)evc->evc_index,0) ;
 412                }
 413        }
 414        smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
 415        mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
 416
 417        DB_SMT("SRF: sending SRF at %x, len %d\n",smt,mb->sm_len) ;
 418        DB_SMT("SRF: state SR%d Threshold %d\n",
 419                smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ;
 420#ifdef  DEBUG
 421        dump_smt(smc,smt,"SRF Send") ;
 422#endif
 423        smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
 424        clear_reported(smc) ;
 425}
 426
 427#endif  /* no BOOT */
 428#endif  /* no SLIM_SMT */
 429
 430