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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [skfp/] [pmf.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/******************************************************************************
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
        Parameter Management Frame processing for SMT 7.2
19
*/
20
 
21
#include "h/types.h"
22
#include "h/fddi.h"
23
#include "h/smc.h"
24
#include "h/smt_p.h"
25
 
26
#define KERNEL
27
#include "h/smtstate.h"
28
 
29
#ifndef SLIM_SMT
30
 
31
#ifndef lint
32
static const char ID_sccs[] = "@(#)pmf.c        1.37 97/08/04 (C) SK " ;
33
#endif
34
 
35
static int smt_authorize(struct s_smc *smc, struct smt_header *sm);
36
static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm);
37
static const struct s_p_tab* smt_get_ptab(u_short para);
38
static int smt_mib_phys(struct s_smc *smc);
39
static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
40
                        int local, int set);
41
void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
42
                  int index, int local);
43
static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
44
                                     int set, int local);
45
static int port_to_mib(struct s_smc *smc, int p);
46
 
47
#define MOFFSS(e)       ((int)&(((struct fddi_mib *)0)->e))
48
#define MOFFSA(e)       ((int) (((struct fddi_mib *)0)->e))
49
 
50
#define MOFFMS(e)       ((int)&(((struct fddi_mib_m *)0)->e))
51
#define MOFFMA(e)       ((int) (((struct fddi_mib_m *)0)->e))
52
 
53
#define MOFFAS(e)       ((int)&(((struct fddi_mib_a *)0)->e))
54
#define MOFFAA(e)       ((int) (((struct fddi_mib_a *)0)->e))
55
 
56
#define MOFFPS(e)       ((int)&(((struct fddi_mib_p *)0)->e))
57
#define MOFFPA(e)       ((int) (((struct fddi_mib_p *)0)->e))
58
 
59
 
60
#define AC_G    0x01            /* Get */
61
#define AC_GR   0x02            /* Get/Set */
62
#define AC_S    0x04            /* Set */
63
#define AC_NA   0x08
64
#define AC_GROUP        0x10            /* Group */
65
#define MS2BCLK(x)      ((x)*12500L)
66
/*
67
        F       LFag (byte)
68
        B       byte
69
        S       u_short 16 bit
70
        C       Counter 32 bit
71
        L       Long 32 bit
72
        T       Timer_2 32 bit
73
        P       TimeStamp ;
74
        A       LongAddress (6 byte)
75
        E       Enum 16 bit
76
        R       ResId 16 Bit
77
*/
78
static const struct s_p_tab {
79
        u_short p_num ;         /* parameter code */
80
        u_char  p_access ;      /* access rights */
81
        u_short p_offset ;      /* offset in mib */
82
        char    p_swap[3] ;     /* format string */
83
} p_tab[] = {
84
        /* StationIdGrp */
85
        { SMT_P100A,AC_GROUP    } ,
86
        { SMT_P100B,AC_G,       MOFFSS(fddiSMTStationId),       "8"     } ,
87
        { SMT_P100D,AC_G,       MOFFSS(fddiSMTOpVersionId),     "S"     } ,
88
        { SMT_P100E,AC_G,       MOFFSS(fddiSMTHiVersionId),     "S"     } ,
89
        { SMT_P100F,AC_G,       MOFFSS(fddiSMTLoVersionId),     "S"     } ,
90
        { SMT_P1010,AC_G,       MOFFSA(fddiSMTManufacturerData), "D" } ,
91
        { SMT_P1011,AC_GR,      MOFFSA(fddiSMTUserData),        "D"     } ,
92
        { SMT_P1012,AC_G,       MOFFSS(fddiSMTMIBVersionId),    "S"     } ,
93
 
94
        /* StationConfigGrp */
95
        { SMT_P1014,AC_GROUP    } ,
96
        { SMT_P1015,AC_G,       MOFFSS(fddiSMTMac_Ct),          "B"     } ,
97
        { SMT_P1016,AC_G,       MOFFSS(fddiSMTNonMaster_Ct),    "B"     } ,
98
        { SMT_P1017,AC_G,       MOFFSS(fddiSMTMaster_Ct),       "B"     } ,
99
        { SMT_P1018,AC_G,       MOFFSS(fddiSMTAvailablePaths),  "B"     } ,
100
        { SMT_P1019,AC_G,       MOFFSS(fddiSMTConfigCapabilities),"S"   } ,
101
        { SMT_P101A,AC_GR,      MOFFSS(fddiSMTConfigPolicy),    "wS"    } ,
102
        { SMT_P101B,AC_GR,      MOFFSS(fddiSMTConnectionPolicy),"wS"    } ,
103
        { SMT_P101D,AC_GR,      MOFFSS(fddiSMTTT_Notify),       "wS"    } ,
104
        { SMT_P101E,AC_GR,      MOFFSS(fddiSMTStatRptPolicy),   "bB"    } ,
105
        { SMT_P101F,AC_GR,      MOFFSS(fddiSMTTrace_MaxExpiration),"lL" } ,
106
        { SMT_P1020,AC_G,       MOFFSA(fddiSMTPORTIndexes),     "II"    } ,
107
        { SMT_P1021,AC_G,       MOFFSS(fddiSMTMACIndexes),      "I"     } ,
108
        { SMT_P1022,AC_G,       MOFFSS(fddiSMTBypassPresent),   "F"     } ,
109
 
110
        /* StatusGrp */
111
        { SMT_P1028,AC_GROUP    } ,
112
        { SMT_P1029,AC_G,       MOFFSS(fddiSMTECMState),        "E"     } ,
113
        { SMT_P102A,AC_G,       MOFFSS(fddiSMTCF_State),        "E"     } ,
114
        { SMT_P102C,AC_G,       MOFFSS(fddiSMTRemoteDisconnectFlag),"F" } ,
115
        { SMT_P102D,AC_G,       MOFFSS(fddiSMTStationStatus),   "E"     } ,
116
        { SMT_P102E,AC_G,       MOFFSS(fddiSMTPeerWrapFlag),    "F"     } ,
117
 
118
        /* MIBOperationGrp */
119
        { SMT_P1032,AC_GROUP    } ,
120
        { SMT_P1033,AC_G,       MOFFSA(fddiSMTTimeStamp),"P"            } ,
121
        { SMT_P1034,AC_G,       MOFFSA(fddiSMTTransitionTimeStamp),"P"  } ,
122
        /* NOTE : SMT_P1035 is already swapped ! SMT_P_SETCOUNT */
123
        { SMT_P1035,AC_G,       MOFFSS(fddiSMTSetCount),"4P"            } ,
124
        { SMT_P1036,AC_G,       MOFFSS(fddiSMTLastSetStationId),"8"     } ,
125
 
126
        { SMT_P103C,AC_S,       0,                               "wS"    } ,
127
 
128
        /*
129
         * PRIVATE EXTENSIONS
130
         * only accessible locally to get/set passwd
131
         */
132
        { SMT_P10F0,AC_GR,      MOFFSA(fddiPRPMFPasswd),        "8"     } ,
133
        { SMT_P10F1,AC_GR,      MOFFSS(fddiPRPMFStation),       "8"     } ,
134
#ifdef  ESS
135
        { SMT_P10F2,AC_GR,      MOFFSS(fddiESSPayload),         "lL"    } ,
136
        { SMT_P10F3,AC_GR,      MOFFSS(fddiESSOverhead),        "lL"    } ,
137
        { SMT_P10F4,AC_GR,      MOFFSS(fddiESSMaxTNeg),         "lL"    } ,
138
        { SMT_P10F5,AC_GR,      MOFFSS(fddiESSMinSegmentSize),  "lL"    } ,
139
        { SMT_P10F6,AC_GR,      MOFFSS(fddiESSCategory),        "lL"    } ,
140
        { SMT_P10F7,AC_GR,      MOFFSS(fddiESSSynchTxMode),     "wS"    } ,
141
#endif
142
#ifdef  SBA
143
        { SMT_P10F8,AC_GR,      MOFFSS(fddiSBACommand),         "bF"    } ,
144
        { SMT_P10F9,AC_GR,      MOFFSS(fddiSBAAvailable),       "bF"    } ,
145
#endif
146
        /* MAC Attributes */
147
        { SMT_P200A,AC_GROUP    } ,
148
        { SMT_P200B,AC_G,       MOFFMS(fddiMACFrameStatusFunctions),"S" } ,
149
        { SMT_P200D,AC_G,       MOFFMS(fddiMACT_MaxCapabilitiy),"T"     } ,
150
        { SMT_P200E,AC_G,       MOFFMS(fddiMACTVXCapabilitiy),"T"       } ,
151
 
152
        /* ConfigGrp */
153
        { SMT_P2014,AC_GROUP    } ,
154
        { SMT_P2016,AC_G,       MOFFMS(fddiMACAvailablePaths),  "B"     } ,
155
        { SMT_P2017,AC_G,       MOFFMS(fddiMACCurrentPath),     "S"     } ,
156
        { SMT_P2018,AC_G,       MOFFMS(fddiMACUpstreamNbr),     "A"     } ,
157
        { SMT_P2019,AC_G,       MOFFMS(fddiMACDownstreamNbr),   "A"     } ,
158
        { SMT_P201A,AC_G,       MOFFMS(fddiMACOldUpstreamNbr),  "A"     } ,
159
        { SMT_P201B,AC_G,       MOFFMS(fddiMACOldDownstreamNbr),"A"     } ,
160
        { SMT_P201D,AC_G,       MOFFMS(fddiMACDupAddressTest),  "E"     } ,
161
        { SMT_P2020,AC_GR,      MOFFMS(fddiMACRequestedPaths),  "wS"    } ,
162
        { SMT_P2021,AC_G,       MOFFMS(fddiMACDownstreamPORTType),"E"   } ,
163
        { SMT_P2022,AC_G,       MOFFMS(fddiMACIndex),           "S"     } ,
164
 
165
        /* AddressGrp */
166
        { SMT_P2028,AC_GROUP    } ,
167
        { SMT_P2029,AC_G,       MOFFMS(fddiMACSMTAddress),      "A"     } ,
168
 
169
        /* OperationGrp */
170
        { SMT_P2032,AC_GROUP    } ,
171
        { SMT_P2033,AC_G,       MOFFMS(fddiMACT_Req),           "T"     } ,
172
        { SMT_P2034,AC_G,       MOFFMS(fddiMACT_Neg),           "T"     } ,
173
        { SMT_P2035,AC_G,       MOFFMS(fddiMACT_Max),           "T"     } ,
174
        { SMT_P2036,AC_G,       MOFFMS(fddiMACTvxValue),        "T"     } ,
175
        { SMT_P2038,AC_G,       MOFFMS(fddiMACT_Pri0),          "T"     } ,
176
        { SMT_P2039,AC_G,       MOFFMS(fddiMACT_Pri1),          "T"     } ,
177
        { SMT_P203A,AC_G,       MOFFMS(fddiMACT_Pri2),          "T"     } ,
178
        { SMT_P203B,AC_G,       MOFFMS(fddiMACT_Pri3),          "T"     } ,
179
        { SMT_P203C,AC_G,       MOFFMS(fddiMACT_Pri4),          "T"     } ,
180
        { SMT_P203D,AC_G,       MOFFMS(fddiMACT_Pri5),          "T"     } ,
181
        { SMT_P203E,AC_G,       MOFFMS(fddiMACT_Pri6),          "T"     } ,
182
 
183
 
184
        /* CountersGrp */
185
        { SMT_P2046,AC_GROUP    } ,
186
        { SMT_P2047,AC_G,       MOFFMS(fddiMACFrame_Ct),        "C"     } ,
187
        { SMT_P2048,AC_G,       MOFFMS(fddiMACCopied_Ct),       "C"     } ,
188
        { SMT_P2049,AC_G,       MOFFMS(fddiMACTransmit_Ct),     "C"     } ,
189
        { SMT_P204A,AC_G,       MOFFMS(fddiMACToken_Ct),        "C"     } ,
190
        { SMT_P2051,AC_G,       MOFFMS(fddiMACError_Ct),        "C"     } ,
191
        { SMT_P2052,AC_G,       MOFFMS(fddiMACLost_Ct),         "C"     } ,
192
        { SMT_P2053,AC_G,       MOFFMS(fddiMACTvxExpired_Ct),   "C"     } ,
193
        { SMT_P2054,AC_G,       MOFFMS(fddiMACNotCopied_Ct),    "C"     } ,
194
        { SMT_P2056,AC_G,       MOFFMS(fddiMACRingOp_Ct),       "C"     } ,
195
 
196
        /* FrameErrorConditionGrp */
197
        { SMT_P205A,AC_GROUP    } ,
198
        { SMT_P205F,AC_GR,      MOFFMS(fddiMACFrameErrorThreshold),"wS" } ,
199
        { SMT_P2060,AC_G,       MOFFMS(fddiMACFrameErrorRatio), "S"     } ,
200
 
201
        /* NotCopiedConditionGrp */
202
        { SMT_P2064,AC_GROUP    } ,
203
        { SMT_P2067,AC_GR,      MOFFMS(fddiMACNotCopiedThreshold),"wS"  } ,
204
        { SMT_P2069,AC_G,       MOFFMS(fddiMACNotCopiedRatio),  "S"     } ,
205
 
206
        /* StatusGrp */
207
        { SMT_P206E,AC_GROUP    } ,
208
        { SMT_P206F,AC_G,       MOFFMS(fddiMACRMTState),        "S"     } ,
209
        { SMT_P2070,AC_G,       MOFFMS(fddiMACDA_Flag), "F"     } ,
210
        { SMT_P2071,AC_G,       MOFFMS(fddiMACUNDA_Flag),       "F"     } ,
211
        { SMT_P2072,AC_G,       MOFFMS(fddiMACFrameErrorFlag),  "F"     } ,
212
        { SMT_P2073,AC_G,       MOFFMS(fddiMACNotCopiedFlag),   "F"     } ,
213
        { SMT_P2074,AC_G,       MOFFMS(fddiMACMA_UnitdataAvailable),"F" } ,
214
        { SMT_P2075,AC_G,       MOFFMS(fddiMACHardwarePresent), "F"     } ,
215
        { SMT_P2076,AC_GR,      MOFFMS(fddiMACMA_UnitdataEnable),"bF"   } ,
216
 
217
        /*
218
         * PRIVATE EXTENSIONS
219
         * only accessible locally to get/set TMIN
220
         */
221
        { SMT_P20F0,AC_NA                                               } ,
222
        { SMT_P20F1,AC_GR,      MOFFMS(fddiMACT_Min),           "lT"    } ,
223
 
224
        /* Path Attributes */
225
        /*
226
         * DON't swap 320B,320F,3210: they are already swapped in swap_para()
227
         */
228
        { SMT_P320A,AC_GROUP    } ,
229
        { SMT_P320B,AC_G,       MOFFAS(fddiPATHIndex),          "r"     } ,
230
        { SMT_P320F,AC_GR,      MOFFAS(fddiPATHSbaPayload),     "l4"    } ,
231
        { SMT_P3210,AC_GR,      MOFFAS(fddiPATHSbaOverhead),    "l4"    } ,
232
        /* fddiPATHConfiguration */
233
        { SMT_P3212,AC_G,       0,                               ""      } ,
234
        { SMT_P3213,AC_GR,      MOFFAS(fddiPATHT_Rmode),        "lT"    } ,
235
        { SMT_P3214,AC_GR,      MOFFAS(fddiPATHSbaAvailable),   "lL"    } ,
236
        { SMT_P3215,AC_GR,      MOFFAS(fddiPATHTVXLowerBound),  "lT"    } ,
237
        { SMT_P3216,AC_GR,      MOFFAS(fddiPATHT_MaxLowerBound),"lT"    } ,
238
        { SMT_P3217,AC_GR,      MOFFAS(fddiPATHMaxT_Req),       "lT"    } ,
239
 
240
        /* Port Attributes */
241
        /* ConfigGrp */
242
        { SMT_P400A,AC_GROUP    } ,
243
        { SMT_P400C,AC_G,       MOFFPS(fddiPORTMy_Type),        "E"     } ,
244
        { SMT_P400D,AC_G,       MOFFPS(fddiPORTNeighborType),   "E"     } ,
245
        { SMT_P400E,AC_GR,      MOFFPS(fddiPORTConnectionPolicies),"bB" } ,
246
        { SMT_P400F,AC_G,       MOFFPS(fddiPORTMacIndicated),   "2"     } ,
247
        { SMT_P4010,AC_G,       MOFFPS(fddiPORTCurrentPath),    "E"     } ,
248
        { SMT_P4011,AC_GR,      MOFFPA(fddiPORTRequestedPaths), "l4"    } ,
249
        { SMT_P4012,AC_G,       MOFFPS(fddiPORTMACPlacement),   "S"     } ,
250
        { SMT_P4013,AC_G,       MOFFPS(fddiPORTAvailablePaths), "B"     } ,
251
        { SMT_P4016,AC_G,       MOFFPS(fddiPORTPMDClass),       "E"     } ,
252
        { SMT_P4017,AC_G,       MOFFPS(fddiPORTConnectionCapabilities), "B"} ,
253
        { SMT_P401D,AC_G,       MOFFPS(fddiPORTIndex),          "R"     } ,
254
 
255
        /* OperationGrp */
256
        { SMT_P401E,AC_GROUP    } ,
257
        { SMT_P401F,AC_GR,      MOFFPS(fddiPORTMaint_LS),       "wE"    } ,
258
        { SMT_P4021,AC_G,       MOFFPS(fddiPORTBS_Flag),        "F"     } ,
259
        { SMT_P4022,AC_G,       MOFFPS(fddiPORTPC_LS),          "E"     } ,
260
 
261
        /* ErrorCtrsGrp */
262
        { SMT_P4028,AC_GROUP    } ,
263
        { SMT_P4029,AC_G,       MOFFPS(fddiPORTEBError_Ct),     "C"     } ,
264
        { SMT_P402A,AC_G,       MOFFPS(fddiPORTLCTFail_Ct),     "C"     } ,
265
 
266
        /* LerGrp */
267
        { SMT_P4032,AC_GROUP    } ,
268
        { SMT_P4033,AC_G,       MOFFPS(fddiPORTLer_Estimate),   "F"     } ,
269
        { SMT_P4034,AC_G,       MOFFPS(fddiPORTLem_Reject_Ct),  "C"     } ,
270
        { SMT_P4035,AC_G,       MOFFPS(fddiPORTLem_Ct),         "C"     } ,
271
        { SMT_P403A,AC_GR,      MOFFPS(fddiPORTLer_Cutoff),     "bB"    } ,
272
        { SMT_P403B,AC_GR,      MOFFPS(fddiPORTLer_Alarm),      "bB"    } ,
273
 
274
        /* StatusGrp */
275
        { SMT_P403C,AC_GROUP    } ,
276
        { SMT_P403D,AC_G,       MOFFPS(fddiPORTConnectState),   "E"     } ,
277
        { SMT_P403E,AC_G,       MOFFPS(fddiPORTPCMStateX),      "E"     } ,
278
        { SMT_P403F,AC_G,       MOFFPS(fddiPORTPC_Withhold),    "E"     } ,
279
        { SMT_P4040,AC_G,       MOFFPS(fddiPORTLerFlag),        "F"     } ,
280
        { SMT_P4041,AC_G,       MOFFPS(fddiPORTHardwarePresent),"F"     } ,
281
 
282
        { SMT_P4046,AC_S,       0,                               "wS"    } ,
283
 
284
        { 0,     AC_GROUP        } ,
285
        { 0 }
286
} ;
287
 
288
void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local)
289
{
290
        struct smt_header       *sm ;
291
        SMbuf           *reply ;
292
 
293
        sm = smtod(mb,struct smt_header *) ;
294
        DB_SMT("SMT: processing PMF frame at %x len %d\n",sm,mb->sm_len) ;
295
#ifdef  DEBUG
296
        dump_smt(smc,sm,"PMF Received") ;
297
#endif
298
        /*
299
         * Start the watchdog: It may be a long, long packet and
300
         * maybe the watchdog occurs ...
301
         */
302
        smt_start_watchdog(smc) ;
303
 
304
        if (sm->smt_class == SMT_PMF_GET ||
305
            sm->smt_class == SMT_PMF_SET) {
306
                reply = smt_build_pmf_response(smc,sm,
307
                        sm->smt_class == SMT_PMF_SET,local) ;
308
                if (reply) {
309
                        sm = smtod(reply,struct smt_header *) ;
310
#ifdef  DEBUG
311
                        dump_smt(smc,sm,"PMF Reply") ;
312
#endif
313
                        smt_send_frame(smc,reply,FC_SMT_INFO,local) ;
314
                }
315
        }
316
}
317
 
318
static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
319
                                     int set, int local)
320
{
321
        SMbuf                   *mb ;
322
        struct smt_header       *smt ;
323
        struct smt_para         *pa ;
324
        struct smt_p_reason     *res ;
325
        const struct s_p_tab    *pt ;
326
        int                     len ;
327
        int                     index ;
328
        int                     idx_end ;
329
        int                     error ;
330
        int                     range ;
331
        SK_LOC_DECL(struct s_pcon,pcon) ;
332
        SK_LOC_DECL(struct s_pcon,set_pcon) ;
333
 
334
        /*
335
         * build SMT header
336
         */
337
        if (!(mb = smt_get_mbuf(smc)))
338
                return(mb) ;
339
 
340
        smt = smtod(mb, struct smt_header *) ;
341
        smt->smt_dest = req->smt_source ;       /* DA == source of request */
342
        smt->smt_class = req->smt_class ;       /* same class (GET/SET) */
343
        smt->smt_type = SMT_REPLY ;
344
        smt->smt_version = SMT_VID_2 ;
345
        smt->smt_tid = req->smt_tid ;           /* same TID */
346
        smt->smt_pad = 0 ;
347
        smt->smt_len = 0 ;
348
 
349
        /*
350
         * setup parameter status
351
         */
352
        pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
353
        pcon.pc_err = 0 ;                        /* no error */
354
        pcon.pc_badset = 0 ;                     /* no bad set count */
355
        pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
356
 
357
        /*
358
         * check authoriziation and set count
359
         */
360
        error = 0 ;
361
        if (set) {
362
                if (!local && smt_authorize(smc,req))
363
                        error = SMT_RDF_AUTHOR ;
364
                else if (smt_check_set_count(smc,req))
365
                        pcon.pc_badset = SMT_RDF_BADSET ;
366
        }
367
        /*
368
         * add reason code and all mandatory parameters
369
         */
370
        res = (struct smt_p_reason *) pcon.pc_p ;
371
        smt_add_para(smc,&pcon,(u_short) SMT_P_REASON,0,0) ;
372
        smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
373
        /* update 1035 and 1036 later if set */
374
        set_pcon = pcon ;
375
        smt_add_para(smc,&pcon,(u_short) SMT_P1035,0,0) ;
376
        smt_add_para(smc,&pcon,(u_short) SMT_P1036,0,0) ;
377
 
378
        pcon.pc_err = error ;
379
        len = req->smt_len ;
380
        pa = (struct smt_para *) (req + 1) ;
381
        /*
382
         * process list of paras
383
         */
384
        while (!pcon.pc_err && len > 0 ) {
385
                if (((u_short)len < pa->p_len + PARA_LEN) || (pa->p_len & 3)) {
386
                        pcon.pc_err = SMT_RDF_LENGTH ;
387
                        break ;
388
                }
389
 
390
                if (((range = (pa->p_type & 0xf000)) == 0x2000) ||
391
                        range == 0x3000 || range == 0x4000) {
392
                        /*
393
                         * get index for PART,MAC ad PATH group
394
                         */
395
                        index = *((u_char *)pa + PARA_LEN + 3) ;/* index */
396
                        idx_end = index ;
397
                        if (!set && (pa->p_len != 4)) {
398
                                pcon.pc_err = SMT_RDF_LENGTH ;
399
                                break ;
400
                        }
401
                        if (!index && !set) {
402
                                switch (range) {
403
                                case 0x2000 :
404
                                        index = INDEX_MAC ;
405
                                        idx_end = index - 1 + NUMMACS ;
406
                                        break ;
407
                                case 0x3000 :
408
                                        index = INDEX_PATH ;
409
                                        idx_end = index - 1 + NUMPATHS ;
410
                                        break ;
411
                                case 0x4000 :
412
                                        index = INDEX_PORT ;
413
                                        idx_end = index - 1 + NUMPHYS ;
414
#ifndef CONCENTRATOR
415
                                        if (smc->s.sas == SMT_SAS)
416
                                                idx_end = INDEX_PORT ;
417
#endif
418
                                        break ;
419
                                }
420
                        }
421
                }
422
                else {
423
                        /*
424
                         * smt group has no index
425
                         */
426
                        if (!set && (pa->p_len != 0)) {
427
                                pcon.pc_err = SMT_RDF_LENGTH ;
428
                                break ;
429
                        }
430
                        index = 0 ;
431
                        idx_end = 0 ;
432
                }
433
                while (index <= idx_end) {
434
                        /*
435
                         * if group
436
                         *      add all paras of group
437
                         */
438
                        pt = smt_get_ptab(pa->p_type) ;
439
                        if (pt && pt->p_access == AC_GROUP && !set) {
440
                                pt++ ;
441
                                while (pt->p_access == AC_G ||
442
                                        pt->p_access == AC_GR) {
443
                                        smt_add_para(smc,&pcon,pt->p_num,
444
                                                index,local);
445
                                        pt++ ;
446
                                }
447
                        }
448
                        /*
449
                         * ignore
450
                         *      AUTHORIZATION in get/set
451
                         *      SET COUNT in set
452
                         */
453
                        else if (pa->p_type != SMT_P_AUTHOR &&
454
                                 (!set || (pa->p_type != SMT_P1035))) {
455
                                int     st ;
456
                                if (pcon.pc_badset) {
457
                                        smt_add_para(smc,&pcon,pa->p_type,
458
                                                index,local) ;
459
                                }
460
                                else if (set) {
461
                                        st = smt_set_para(smc,pa,index,local,1);
462
                                        /*
463
                                         * return para even if error
464
                                         */
465
                                        smt_add_para(smc,&pcon,pa->p_type,
466
                                                index,local) ;
467
                                        pcon.pc_err = st ;
468
                                }
469
                                else {
470
                                        if (pt && pt->p_access == AC_S) {
471
                                                pcon.pc_err =
472
                                                        SMT_RDF_ILLEGAL ;
473
                                        }
474
                                        smt_add_para(smc,&pcon,pa->p_type,
475
                                                index,local) ;
476
                                }
477
                        }
478
                        if (pcon.pc_err)
479
                                break ;
480
                        index++ ;
481
                }
482
                len -= pa->p_len + PARA_LEN ;
483
                pa = (struct smt_para *) ((char *)pa + pa->p_len + PARA_LEN) ;
484
        }
485
        smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
486
        mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
487
 
488
        /* update reason code */
489
        res->rdf_reason = pcon.pc_badset ? pcon.pc_badset :
490
                        pcon.pc_err ? pcon.pc_err : SMT_RDF_SUCCESS ;
491
        if (set && (res->rdf_reason == SMT_RDF_SUCCESS)) {
492
                /*
493
                 * increment set count
494
                 * set time stamp
495
                 * store station id of last set
496
                 */
497
                smc->mib.fddiSMTSetCount.count++ ;
498
                smt_set_timestamp(smc,smc->mib.fddiSMTSetCount.timestamp) ;
499
                smc->mib.fddiSMTLastSetStationId = req->smt_sid ;
500
                smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
501
                smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
502
        }
503
        return(mb) ;
504
}
505
 
506
static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
507
{
508
        struct smt_para *pa ;
509
        int             i ;
510
        char            *p ;
511
 
512
        /*
513
         * check source station id if not zero
514
         */
515
        p = (char *) &smc->mib.fddiPRPMFStation ;
516
        for (i = 0 ; i < 8 && !p[i] ; i++)
517
                ;
518
        if (i != 8) {
519
                if (memcmp((char *) &sm->smt_sid,
520
                        (char *) &smc->mib.fddiPRPMFStation,8))
521
                        return(1) ;
522
        }
523
        /*
524
         * check authoriziation parameter if passwd not zero
525
         */
526
        p = (char *) smc->mib.fddiPRPMFPasswd ;
527
        for (i = 0 ; i < 8 && !p[i] ; i++)
528
                ;
529
        if (i != 8) {
530
                pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ;
531
                if (!pa)
532
                        return(1) ;
533
                if (pa->p_len != 8)
534
                        return(1) ;
535
                if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8))
536
                        return(1) ;
537
        }
538
        return(0) ;
539
}
540
 
541
static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
542
{
543
        struct smt_para *pa ;
544
        struct smt_p_setcount   *sc ;
545
 
546
        pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P1035) ;
547
        if (pa) {
548
                sc = (struct smt_p_setcount *) pa ;
549
                if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
550
                        memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
551
                        (char *)sc->timestamp,8))
552
                        return(1) ;
553
        }
554
        return(0) ;
555
}
556
 
557
void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
558
                  int index, int local)
559
{
560
        struct smt_para *pa ;
561
        const struct s_p_tab    *pt ;
562
        struct fddi_mib_m *mib_m = NULL;
563
        struct fddi_mib_p *mib_p = NULL;
564
        int             len ;
565
        int             plen ;
566
        char            *from ;
567
        char            *to ;
568
        const char      *swap ;
569
        char            c ;
570
        int             range ;
571
        char            *mib_addr ;
572
        int             mac ;
573
        int             path ;
574
        int             port ;
575
        int             sp_len ;
576
 
577
        /*
578
         * skip if error
579
         */
580
        if (pcon->pc_err)
581
                return ;
582
 
583
        /*
584
         * actions don't have a value
585
         */
586
        pt = smt_get_ptab(para) ;
587
        if (pt && pt->p_access == AC_S)
588
                return ;
589
 
590
        to = (char *) (pcon->pc_p) ;    /* destination pointer */
591
        len = pcon->pc_len ;            /* free space */
592
        plen = len ;                    /* remember start length */
593
        pa = (struct smt_para *) to ;   /* type/length pointer */
594
        to += PARA_LEN ;                /* skip smt_para */
595
        len -= PARA_LEN ;
596
        /*
597
         * set index if required
598
         */
599
        if (((range = (para & 0xf000)) == 0x2000) ||
600
                range == 0x3000 || range == 0x4000) {
601
                if (len < 4)
602
                        goto wrong_error ;
603
                to[0] = 0 ;
604
                to[1] = 0 ;
605
                to[2] = 0 ;
606
                to[3] = index ;
607
                len -= 4 ;
608
                to += 4 ;
609
        }
610
        mac = index - INDEX_MAC ;
611
        path = index - INDEX_PATH ;
612
        port = index - INDEX_PORT ;
613
        /*
614
         * get pointer to mib
615
         */
616
        switch (range) {
617
        case 0x1000 :
618
        default :
619
                mib_addr = (char *) (&smc->mib) ;
620
                break ;
621
        case 0x2000 :
622
                if (mac < 0 || mac >= NUMMACS) {
623
                        pcon->pc_err = SMT_RDF_NOPARAM ;
624
                        return ;
625
                }
626
                mib_addr = (char *) (&smc->mib.m[mac]) ;
627
                mib_m = (struct fddi_mib_m *) mib_addr ;
628
                break ;
629
        case 0x3000 :
630
                if (path < 0 || path >= NUMPATHS) {
631
                        pcon->pc_err = SMT_RDF_NOPARAM ;
632
                        return ;
633
                }
634
                mib_addr = (char *) (&smc->mib.a[path]) ;
635
                break ;
636
        case 0x4000 :
637
                if (port < 0 || port >= smt_mib_phys(smc)) {
638
                        pcon->pc_err = SMT_RDF_NOPARAM ;
639
                        return ;
640
                }
641
                mib_addr = (char *) (&smc->mib.p[port_to_mib(smc,port)]) ;
642
                mib_p = (struct fddi_mib_p *) mib_addr ;
643
                break ;
644
        }
645
        /*
646
         * check special paras
647
         */
648
        swap = NULL;
649
        switch (para) {
650
        case SMT_P10F0 :
651
        case SMT_P10F1 :
652
#ifdef  ESS
653
        case SMT_P10F2 :
654
        case SMT_P10F3 :
655
        case SMT_P10F4 :
656
        case SMT_P10F5 :
657
        case SMT_P10F6 :
658
        case SMT_P10F7 :
659
#endif
660
#ifdef  SBA
661
        case SMT_P10F8 :
662
        case SMT_P10F9 :
663
#endif
664
        case SMT_P20F1 :
665
                if (!local) {
666
                        pcon->pc_err = SMT_RDF_NOPARAM ;
667
                        return ;
668
                }
669
                break ;
670
        case SMT_P2034 :
671
        case SMT_P2046 :
672
        case SMT_P2047 :
673
        case SMT_P204A :
674
        case SMT_P2051 :
675
        case SMT_P2052 :
676
                mac_update_counter(smc) ;
677
                break ;
678
        case SMT_P4022:
679
                mib_p->fddiPORTPC_LS = LS2MIB(
680
                        sm_pm_get_ls(smc,port_to_mib(smc,port))) ;
681
                break ;
682
        case SMT_P_REASON :
683
                * (u_long *) to = 0 ;
684
                sp_len = 4 ;
685
                goto sp_done ;
686
        case SMT_P1033 :                        /* time stamp */
687
                smt_set_timestamp(smc,smc->mib.fddiSMTTimeStamp) ;
688
                break ;
689
 
690
        case SMT_P1020:                         /* port indexes */
691
#if     NUMPHYS == 12
692
                swap = "IIIIIIIIIIII" ;
693
#else
694
#if     NUMPHYS == 2
695
                if (smc->s.sas == SMT_SAS)
696
                        swap = "I" ;
697
                else
698
                        swap = "II" ;
699
#else
700
#if     NUMPHYS == 24
701
                swap = "IIIIIIIIIIIIIIIIIIIIIIII" ;
702
#else
703
        ????
704
#endif
705
#endif
706
#endif
707
                break ;
708
        case SMT_P3212 :
709
                {
710
                        sp_len = cem_build_path(smc,to,path) ;
711
                        goto sp_done ;
712
                }
713
        case SMT_P1048 :                /* peer wrap condition */
714
                {
715
                        struct smt_p_1048       *sp ;
716
                        sp = (struct smt_p_1048 *) to ;
717
                        sp->p1048_flag = smc->mib.fddiSMTPeerWrapFlag ;
718
                        sp->p1048_cf_state = smc->mib.fddiSMTCF_State ;
719
                        sp_len = sizeof(struct smt_p_1048) ;
720
                        goto sp_done ;
721
                }
722
        case SMT_P208C :
723
                {
724
                        struct smt_p_208c       *sp ;
725
                        sp = (struct smt_p_208c *) to ;
726
                        sp->p208c_flag =
727
                                smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
728
                        sp->p208c_dupcondition =
729
                                (mib_m->fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0) |
730
                                (mib_m->fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0);
731
                        sp->p208c_fddilong =
732
                                mib_m->fddiMACSMTAddress ;
733
                        sp->p208c_fddiunalong =
734
                                mib_m->fddiMACUpstreamNbr ;
735
                        sp->p208c_pad = 0 ;
736
                        sp_len = sizeof(struct smt_p_208c) ;
737
                        goto sp_done ;
738
                }
739
        case SMT_P208D :                /* frame error condition */
740
                {
741
                        struct smt_p_208d       *sp ;
742
                        sp = (struct smt_p_208d *) to ;
743
                        sp->p208d_flag =
744
                                mib_m->fddiMACFrameErrorFlag ;
745
                        sp->p208d_frame_ct =
746
                                mib_m->fddiMACFrame_Ct ;
747
                        sp->p208d_error_ct =
748
                                mib_m->fddiMACError_Ct ;
749
                        sp->p208d_lost_ct =
750
                                mib_m->fddiMACLost_Ct ;
751
                        sp->p208d_ratio =
752
                                mib_m->fddiMACFrameErrorRatio ;
753
                        sp_len = sizeof(struct smt_p_208d) ;
754
                        goto sp_done ;
755
                }
756
        case SMT_P208E :                /* not copied condition */
757
                {
758
                        struct smt_p_208e       *sp ;
759
                        sp = (struct smt_p_208e *) to ;
760
                        sp->p208e_flag =
761
                                mib_m->fddiMACNotCopiedFlag ;
762
                        sp->p208e_not_copied =
763
                                mib_m->fddiMACNotCopied_Ct ;
764
                        sp->p208e_copied =
765
                                mib_m->fddiMACCopied_Ct ;
766
                        sp->p208e_not_copied_ratio =
767
                                mib_m->fddiMACNotCopiedRatio ;
768
                        sp_len = sizeof(struct smt_p_208e) ;
769
                        goto sp_done ;
770
                }
771
        case SMT_P208F :        /* neighbor change event */
772
                {
773
                        struct smt_p_208f       *sp ;
774
                        sp = (struct smt_p_208f *) to ;
775
                        sp->p208f_multiple =
776
                                mib_m->fddiMACMultiple_N ;
777
                        sp->p208f_nacondition =
778
                                mib_m->fddiMACDuplicateAddressCond ;
779
                        sp->p208f_old_una =
780
                                mib_m->fddiMACOldUpstreamNbr ;
781
                        sp->p208f_new_una =
782
                                mib_m->fddiMACUpstreamNbr ;
783
                        sp->p208f_old_dna =
784
                                mib_m->fddiMACOldDownstreamNbr ;
785
                        sp->p208f_new_dna =
786
                                mib_m->fddiMACDownstreamNbr ;
787
                        sp->p208f_curren_path =
788
                                mib_m->fddiMACCurrentPath ;
789
                        sp->p208f_smt_address =
790
                                mib_m->fddiMACSMTAddress ;
791
                        sp_len = sizeof(struct smt_p_208f) ;
792
                        goto sp_done ;
793
                }
794
        case SMT_P2090 :
795
                {
796
                        struct smt_p_2090       *sp ;
797
                        sp = (struct smt_p_2090 *) to ;
798
                        sp->p2090_multiple =
799
                                mib_m->fddiMACMultiple_P ;
800
                        sp->p2090_availablepaths =
801
                                mib_m->fddiMACAvailablePaths ;
802
                        sp->p2090_currentpath =
803
                                mib_m->fddiMACCurrentPath ;
804
                        sp->p2090_requestedpaths =
805
                                mib_m->fddiMACRequestedPaths ;
806
                        sp_len = sizeof(struct smt_p_2090) ;
807
                        goto sp_done ;
808
                }
809
        case SMT_P4050 :
810
                {
811
                        struct smt_p_4050       *sp ;
812
                        sp = (struct smt_p_4050 *) to ;
813
                        sp->p4050_flag =
814
                                mib_p->fddiPORTLerFlag ;
815
                        sp->p4050_pad = 0 ;
816
                        sp->p4050_cutoff =
817
                                mib_p->fddiPORTLer_Cutoff ; ;
818
                        sp->p4050_alarm =
819
                                mib_p->fddiPORTLer_Alarm ; ;
820
                        sp->p4050_estimate =
821
                                mib_p->fddiPORTLer_Estimate ;
822
                        sp->p4050_reject_ct =
823
                                mib_p->fddiPORTLem_Reject_Ct ;
824
                        sp->p4050_ct =
825
                                mib_p->fddiPORTLem_Ct ;
826
                        sp_len = sizeof(struct smt_p_4050) ;
827
                        goto sp_done ;
828
                }
829
 
830
        case SMT_P4051 :
831
                {
832
                        struct smt_p_4051       *sp ;
833
                        sp = (struct smt_p_4051 *) to ;
834
                        sp->p4051_multiple =
835
                                mib_p->fddiPORTMultiple_U ;
836
                        sp->p4051_porttype =
837
                                mib_p->fddiPORTMy_Type ;
838
                        sp->p4051_connectstate =
839
                                mib_p->fddiPORTConnectState ; ;
840
                        sp->p4051_pc_neighbor =
841
                                mib_p->fddiPORTNeighborType ;
842
                        sp->p4051_pc_withhold =
843
                                mib_p->fddiPORTPC_Withhold ;
844
                        sp_len = sizeof(struct smt_p_4051) ;
845
                        goto sp_done ;
846
                }
847
        case SMT_P4052 :
848
                {
849
                        struct smt_p_4052       *sp ;
850
                        sp = (struct smt_p_4052 *) to ;
851
                        sp->p4052_flag =
852
                                mib_p->fddiPORTEB_Condition ;
853
                        sp->p4052_eberrorcount =
854
                                mib_p->fddiPORTEBError_Ct ;
855
                        sp_len = sizeof(struct smt_p_4052) ;
856
                        goto sp_done ;
857
                }
858
        case SMT_P4053 :
859
                {
860
                        struct smt_p_4053       *sp ;
861
                        sp = (struct smt_p_4053 *) to ;
862
                        sp->p4053_multiple =
863
                                mib_p->fddiPORTMultiple_P ; ;
864
                        sp->p4053_availablepaths =
865
                                mib_p->fddiPORTAvailablePaths ;
866
                        sp->p4053_currentpath =
867
                                mib_p->fddiPORTCurrentPath ;
868
                        memcpy( (char *) &sp->p4053_requestedpaths,
869
                                (char *) mib_p->fddiPORTRequestedPaths,4) ;
870
                        sp->p4053_mytype =
871
                                mib_p->fddiPORTMy_Type ;
872
                        sp->p4053_neighbortype =
873
                                mib_p->fddiPORTNeighborType ;
874
                        sp_len = sizeof(struct smt_p_4053) ;
875
                        goto sp_done ;
876
                }
877
        default :
878
                break ;
879
        }
880
        /*
881
         * in table ?
882
         */
883
        if (!pt) {
884
                pcon->pc_err = (para & 0xff00) ? SMT_RDF_NOPARAM :
885
                                                SMT_RDF_ILLEGAL ;
886
                return ;
887
        }
888
        /*
889
         * check access rights
890
         */
891
        switch (pt->p_access) {
892
        case AC_G :
893
        case AC_GR :
894
                break ;
895
        default :
896
                pcon->pc_err = SMT_RDF_ILLEGAL ;
897
                return ;
898
        }
899
        from = mib_addr + pt->p_offset ;
900
        if (!swap)
901
                swap = pt->p_swap ;             /* pointer to swap string */
902
 
903
        /*
904
         * copy values
905
         */
906
        while ((c = *swap++)) {
907
                switch(c) {
908
                case 'b' :
909
                case 'w' :
910
                case 'l' :
911
                        break ;
912
                case 'S' :
913
                case 'E' :
914
                case 'R' :
915
                case 'r' :
916
                        if (len < 4)
917
                                goto len_error ;
918
                        to[0] = 0 ;
919
                        to[1] = 0 ;
920
#ifdef  LITTLE_ENDIAN
921
                        if (c == 'r') {
922
                                to[2] = *from++ ;
923
                                to[3] = *from++ ;
924
                        }
925
                        else {
926
                                to[3] = *from++ ;
927
                                to[2] = *from++ ;
928
                        }
929
#else
930
                        to[2] = *from++ ;
931
                        to[3] = *from++ ;
932
#endif
933
                        to += 4 ;
934
                        len -= 4 ;
935
                        break ;
936
                case 'I' :              /* for SET of port indexes */
937
                        if (len < 2)
938
                                goto len_error ;
939
#ifdef  LITTLE_ENDIAN
940
                        to[1] = *from++ ;
941
                        to[0] = *from++ ;
942
#else
943
                        to[0] = *from++ ;
944
                        to[1] = *from++ ;
945
#endif
946
                        to += 2 ;
947
                        len -= 2 ;
948
                        break ;
949
                case 'F' :
950
                case 'B' :
951
                        if (len < 4)
952
                                goto len_error ;
953
                        len -= 4 ;
954
                        to[0] = 0 ;
955
                        to[1] = 0 ;
956
                        to[2] = 0 ;
957
                        to[3] = *from++ ;
958
                        to += 4 ;
959
                        break ;
960
                case 'C' :
961
                case 'T' :
962
                case 'L' :
963
                        if (len < 4)
964
                                goto len_error ;
965
#ifdef  LITTLE_ENDIAN
966
                        to[3] = *from++ ;
967
                        to[2] = *from++ ;
968
                        to[1] = *from++ ;
969
                        to[0] = *from++ ;
970
#else
971
                        to[0] = *from++ ;
972
                        to[1] = *from++ ;
973
                        to[2] = *from++ ;
974
                        to[3] = *from++ ;
975
#endif
976
                        len -= 4 ;
977
                        to += 4 ;
978
                        break ;
979
                case '2' :              /* PortMacIndicated */
980
                        if (len < 4)
981
                                goto len_error ;
982
                        to[0] = 0 ;
983
                        to[1] = 0 ;
984
                        to[2] = *from++ ;
985
                        to[3] = *from++ ;
986
                        len -= 4 ;
987
                        to += 4 ;
988
                        break ;
989
                case '4' :
990
                        if (len < 4)
991
                                goto len_error ;
992
                        to[0] = *from++ ;
993
                        to[1] = *from++ ;
994
                        to[2] = *from++ ;
995
                        to[3] = *from++ ;
996
                        len -= 4 ;
997
                        to += 4 ;
998
                        break ;
999
                case 'A' :
1000
                        if (len < 8)
1001
                                goto len_error ;
1002
                        to[0] = 0 ;
1003
                        to[1] = 0 ;
1004
                        memcpy((char *) to+2,(char *) from,6) ;
1005
                        to += 8 ;
1006
                        from += 8 ;
1007
                        len -= 8 ;
1008
                        break ;
1009
                case '8' :
1010
                        if (len < 8)
1011
                                goto len_error ;
1012
                        memcpy((char *) to,(char *) from,8) ;
1013
                        to += 8 ;
1014
                        from += 8 ;
1015
                        len -= 8 ;
1016
                        break ;
1017
                case 'D' :
1018
                        if (len < 32)
1019
                                goto len_error ;
1020
                        memcpy((char *) to,(char *) from,32) ;
1021
                        to += 32 ;
1022
                        from += 32 ;
1023
                        len -= 32 ;
1024
                        break ;
1025
                case 'P' :              /* timestamp is NOT swapped */
1026
                        if (len < 8)
1027
                                goto len_error ;
1028
                        to[0] = *from++ ;
1029
                        to[1] = *from++ ;
1030
                        to[2] = *from++ ;
1031
                        to[3] = *from++ ;
1032
                        to[4] = *from++ ;
1033
                        to[5] = *from++ ;
1034
                        to[6] = *from++ ;
1035
                        to[7] = *from++ ;
1036
                        to += 8 ;
1037
                        len -= 8 ;
1038
                        break ;
1039
                default :
1040
                        SMT_PANIC(smc,SMT_E0119, SMT_E0119_MSG) ;
1041
                        break ;
1042
                }
1043
        }
1044
 
1045
done:
1046
        /*
1047
         * make it even (in case of 'I' encoding)
1048
         * note: len is DECREMENTED
1049
         */
1050
        if (len & 3) {
1051
                to[0] = 0 ;
1052
                to[1] = 0 ;
1053
                to += 4 - (len & 3 ) ;
1054
                len = len & ~ 3 ;
1055
        }
1056
 
1057
        /* set type and length */
1058
        pa->p_type = para ;
1059
        pa->p_len = plen - len - PARA_LEN ;
1060
        /* return values */
1061
        pcon->pc_p = (void *) to ;
1062
        pcon->pc_len = len ;
1063
        return ;
1064
 
1065
sp_done:
1066
        len -= sp_len ;
1067
        to += sp_len ;
1068
        goto done ;
1069
 
1070
len_error:
1071
        /* parameter does not fit in frame */
1072
        pcon->pc_err = SMT_RDF_TOOLONG ;
1073
        return ;
1074
 
1075
wrong_error:
1076
        pcon->pc_err = SMT_RDF_LENGTH ;
1077
}
1078
 
1079
/*
1080
 * set parameter
1081
 */
1082
static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
1083
                        int local, int set)
1084
{
1085
#define IFSET(x)        if (set) (x)
1086
 
1087
        const struct s_p_tab    *pt ;
1088
        int             len ;
1089
        char            *from ;
1090
        char            *to ;
1091
        const char      *swap ;
1092
        char            c ;
1093
        char            *mib_addr ;
1094
        struct fddi_mib *mib ;
1095
        struct fddi_mib_m       *mib_m = NULL;
1096
        struct fddi_mib_a       *mib_a = NULL;
1097
        struct fddi_mib_p       *mib_p = NULL;
1098
        int             mac ;
1099
        int             path ;
1100
        int             port ;
1101
        SK_LOC_DECL(u_char,byte_val) ;
1102
        SK_LOC_DECL(u_short,word_val) ;
1103
        SK_LOC_DECL(u_long,long_val) ;
1104
 
1105
        mac = index - INDEX_MAC ;
1106
        path = index - INDEX_PATH ;
1107
        port = index - INDEX_PORT ;
1108
        len = pa->p_len ;
1109
        from = (char *) (pa + 1 ) ;
1110
 
1111
        mib = &smc->mib ;
1112
        switch (pa->p_type & 0xf000) {
1113
        case 0x1000 :
1114
        default :
1115
                mib_addr = (char *) mib ;
1116
                break ;
1117
        case 0x2000 :
1118
                if (mac < 0 || mac >= NUMMACS) {
1119
                        return(SMT_RDF_NOPARAM) ;
1120
                }
1121
                mib_m = &smc->mib.m[mac] ;
1122
                mib_addr = (char *) mib_m ;
1123
                from += 4 ;             /* skip index */
1124
                len -= 4 ;
1125
                break ;
1126
        case 0x3000 :
1127
                if (path < 0 || path >= NUMPATHS) {
1128
                        return(SMT_RDF_NOPARAM) ;
1129
                }
1130
                mib_a = &smc->mib.a[path] ;
1131
                mib_addr = (char *) mib_a ;
1132
                from += 4 ;             /* skip index */
1133
                len -= 4 ;
1134
                break ;
1135
        case 0x4000 :
1136
                if (port < 0 || port >= smt_mib_phys(smc)) {
1137
                        return(SMT_RDF_NOPARAM) ;
1138
                }
1139
                mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
1140
                mib_addr = (char *) mib_p ;
1141
                from += 4 ;             /* skip index */
1142
                len -= 4 ;
1143
                break ;
1144
        }
1145
        switch (pa->p_type) {
1146
        case SMT_P10F0 :
1147
        case SMT_P10F1 :
1148
#ifdef  ESS
1149
        case SMT_P10F2 :
1150
        case SMT_P10F3 :
1151
        case SMT_P10F4 :
1152
        case SMT_P10F5 :
1153
        case SMT_P10F6 :
1154
        case SMT_P10F7 :
1155
#endif
1156
#ifdef  SBA
1157
        case SMT_P10F8 :
1158
        case SMT_P10F9 :
1159
#endif
1160
        case SMT_P20F1 :
1161
                if (!local) {
1162
                        return(SMT_RDF_NOPARAM) ;
1163
                }
1164
                break ;
1165
        }
1166
        pt = smt_get_ptab(pa->p_type) ;
1167
        if (!pt) {
1168
                return( (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
1169
                                                SMT_RDF_ILLEGAL ) ;
1170
        }
1171
        switch (pt->p_access) {
1172
        case AC_GR :
1173
        case AC_S :
1174
                break ;
1175
        default :
1176
                return(SMT_RDF_ILLEGAL) ;
1177
        }
1178
        to = mib_addr + pt->p_offset ;
1179
        swap = pt->p_swap ;             /* pointer to swap string */
1180
 
1181
        while (swap && (c = *swap++)) {
1182
                switch(c) {
1183
                case 'b' :
1184
                        to = (char *) &byte_val ;
1185
                        break ;
1186
                case 'w' :
1187
                        to = (char *) &word_val ;
1188
                        break ;
1189
                case 'l' :
1190
                        to = (char *) &long_val ;
1191
                        break ;
1192
                case 'S' :
1193
                case 'E' :
1194
                case 'R' :
1195
                case 'r' :
1196
                        if (len < 4) {
1197
                                goto len_error ;
1198
                        }
1199
                        if (from[0] | from[1])
1200
                                goto val_error ;
1201
#ifdef  LITTLE_ENDIAN
1202
                        if (c == 'r') {
1203
                                to[0] = from[2] ;
1204
                                to[1] = from[3] ;
1205
                        }
1206
                        else {
1207
                                to[1] = from[2] ;
1208
                                to[0] = from[3] ;
1209
                        }
1210
#else
1211
                        to[0] = from[2] ;
1212
                        to[1] = from[3] ;
1213
#endif
1214
                        from += 4 ;
1215
                        to += 2 ;
1216
                        len -= 4 ;
1217
                        break ;
1218
                case 'F' :
1219
                case 'B' :
1220
                        if (len < 4) {
1221
                                goto len_error ;
1222
                        }
1223
                        if (from[0] | from[1] | from[2])
1224
                                goto val_error ;
1225
                        to[0] = from[3] ;
1226
                        len -= 4 ;
1227
                        from += 4 ;
1228
                        to += 4 ;
1229
                        break ;
1230
                case 'C' :
1231
                case 'T' :
1232
                case 'L' :
1233
                        if (len < 4) {
1234
                                goto len_error ;
1235
                        }
1236
#ifdef  LITTLE_ENDIAN
1237
                        to[3] = *from++ ;
1238
                        to[2] = *from++ ;
1239
                        to[1] = *from++ ;
1240
                        to[0] = *from++ ;
1241
#else
1242
                        to[0] = *from++ ;
1243
                        to[1] = *from++ ;
1244
                        to[2] = *from++ ;
1245
                        to[3] = *from++ ;
1246
#endif
1247
                        len -= 4 ;
1248
                        to += 4 ;
1249
                        break ;
1250
                case 'A' :
1251
                        if (len < 8)
1252
                                goto len_error ;
1253
                        if (set)
1254
                                memcpy((char *) to,(char *) from+2,6) ;
1255
                        to += 8 ;
1256
                        from += 8 ;
1257
                        len -= 8 ;
1258
                        break ;
1259
                case '4' :
1260
                        if (len < 4)
1261
                                goto len_error ;
1262
                        if (set)
1263
                                memcpy((char *) to,(char *) from,4) ;
1264
                        to += 4 ;
1265
                        from += 4 ;
1266
                        len -= 4 ;
1267
                        break ;
1268
                case '8' :
1269
                        if (len < 8)
1270
                                goto len_error ;
1271
                        if (set)
1272
                                memcpy((char *) to,(char *) from,8) ;
1273
                        to += 8 ;
1274
                        from += 8 ;
1275
                        len -= 8 ;
1276
                        break ;
1277
                case 'D' :
1278
                        if (len < 32)
1279
                                goto len_error ;
1280
                        if (set)
1281
                                memcpy((char *) to,(char *) from,32) ;
1282
                        to += 32 ;
1283
                        from += 32 ;
1284
                        len -= 32 ;
1285
                        break ;
1286
                case 'P' :              /* timestamp is NOT swapped */
1287
                        if (set) {
1288
                                to[0] = *from++ ;
1289
                                to[1] = *from++ ;
1290
                                to[2] = *from++ ;
1291
                                to[3] = *from++ ;
1292
                                to[4] = *from++ ;
1293
                                to[5] = *from++ ;
1294
                                to[6] = *from++ ;
1295
                                to[7] = *from++ ;
1296
                        }
1297
                        to += 8 ;
1298
                        len -= 8 ;
1299
                        break ;
1300
                default :
1301
                        SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ;
1302
                        return(SMT_RDF_ILLEGAL) ;
1303
                }
1304
        }
1305
        /*
1306
         * actions and internal updates
1307
         */
1308
        switch (pa->p_type) {
1309
        case SMT_P101A:                 /* fddiSMTConfigPolicy */
1310
                if (word_val & ~1)
1311
                        goto val_error ;
1312
                IFSET(mib->fddiSMTConfigPolicy = word_val) ;
1313
                break ;
1314
        case SMT_P101B :                /* fddiSMTConnectionPolicy */
1315
                if (!(word_val & POLICY_MM))
1316
                        goto val_error ;
1317
                IFSET(mib->fddiSMTConnectionPolicy = word_val) ;
1318
                break ;
1319
        case SMT_P101D :                /* fddiSMTTT_Notify */
1320
                if (word_val < 2 || word_val > 30)
1321
                        goto val_error ;
1322
                IFSET(mib->fddiSMTTT_Notify = word_val) ;
1323
                break ;
1324
        case SMT_P101E :                /* fddiSMTStatRptPolicy */
1325
                if (byte_val & ~1)
1326
                        goto val_error ;
1327
                IFSET(mib->fddiSMTStatRptPolicy = byte_val) ;
1328
                break ;
1329
        case SMT_P101F :                /* fddiSMTTrace_MaxExpiration */
1330
                /*
1331
                 * note: lower limit trace_max = 6.001773... s
1332
                 * NO upper limit
1333
                 */
1334
                if (long_val < (long)0x478bf51L)
1335
                        goto val_error ;
1336
                IFSET(mib->fddiSMTTrace_MaxExpiration = long_val) ;
1337
                break ;
1338
#ifdef  ESS
1339
        case SMT_P10F2 :                /* fddiESSPayload */
1340
                if (long_val > 1562)
1341
                        goto val_error ;
1342
                if (set && smc->mib.fddiESSPayload != long_val) {
1343
                        smc->ess.raf_act_timer_poll = TRUE ;
1344
                        smc->mib.fddiESSPayload = long_val ;
1345
                }
1346
                break ;
1347
        case SMT_P10F3 :                /* fddiESSOverhead */
1348
                if (long_val < 50 || long_val > 5000)
1349
                        goto val_error ;
1350
                if (set && smc->mib.fddiESSPayload &&
1351
                        smc->mib.fddiESSOverhead != long_val) {
1352
                        smc->ess.raf_act_timer_poll = TRUE ;
1353
                        smc->mib.fddiESSOverhead = long_val ;
1354
                }
1355
                break ;
1356
        case SMT_P10F4 :                /* fddiESSMaxTNeg */
1357
                if (long_val > -MS2BCLK(5) || long_val < -MS2BCLK(165))
1358
                        goto val_error ;
1359
                IFSET(mib->fddiESSMaxTNeg = long_val) ;
1360
                break ;
1361
        case SMT_P10F5 :                /* fddiESSMinSegmentSize */
1362
                if (long_val < 1 || long_val > 4478)
1363
                        goto val_error ;
1364
                IFSET(mib->fddiESSMinSegmentSize = long_val) ;
1365
                break ;
1366
        case SMT_P10F6 :                /* fddiESSCategory */
1367
                if ((long_val & 0xffff) != 1)
1368
                        goto val_error ;
1369
                IFSET(mib->fddiESSCategory = long_val) ;
1370
                break ;
1371
        case SMT_P10F7 :                /* fddiESSSyncTxMode */
1372
                if (word_val > 1)
1373
                        goto val_error ;
1374
                IFSET(mib->fddiESSSynchTxMode = word_val) ;
1375
                break ;
1376
#endif
1377
#ifdef  SBA
1378
        case SMT_P10F8 :                /* fddiSBACommand */
1379
                if (byte_val != SB_STOP && byte_val != SB_START)
1380
                        goto val_error ;
1381
                IFSET(mib->fddiSBACommand = byte_val) ;
1382
                break ;
1383
        case SMT_P10F9 :                /* fddiSBAAvailable */
1384
                if (byte_val > 100)
1385
                        goto val_error ;
1386
                IFSET(mib->fddiSBAAvailable = byte_val) ;
1387
                break ;
1388
#endif
1389
        case SMT_P2020 :                /* fddiMACRequestedPaths */
1390
                if ((word_val & (MIB_P_PATH_PRIM_PREFER |
1391
                        MIB_P_PATH_PRIM_ALTER)) == 0 )
1392
                        goto val_error ;
1393
                IFSET(mib_m->fddiMACRequestedPaths = word_val) ;
1394
                break ;
1395
        case SMT_P205F :                /* fddiMACFrameErrorThreshold */
1396
                /* 0 .. ffff acceptable */
1397
                IFSET(mib_m->fddiMACFrameErrorThreshold = word_val) ;
1398
                break ;
1399
        case SMT_P2067 :                /* fddiMACNotCopiedThreshold */
1400
                /* 0 .. ffff acceptable */
1401
                IFSET(mib_m->fddiMACNotCopiedThreshold = word_val) ;
1402
                break ;
1403
        case SMT_P2076:                 /* fddiMACMA_UnitdataEnable */
1404
                if (byte_val & ~1)
1405
                        goto val_error ;
1406
                if (set) {
1407
                        mib_m->fddiMACMA_UnitdataEnable = byte_val ;
1408
                        queue_event(smc,EVENT_RMT,RM_ENABLE_FLAG) ;
1409
                }
1410
                break ;
1411
        case SMT_P20F1 :                /* fddiMACT_Min */
1412
                IFSET(mib_m->fddiMACT_Min = long_val) ;
1413
                break ;
1414
        case SMT_P320F :
1415
                if (long_val > 1562)
1416
                        goto val_error ;
1417
                IFSET(mib_a->fddiPATHSbaPayload = long_val) ;
1418
#ifdef  ESS
1419
                if (set)
1420
                        ess_para_change(smc) ;
1421
#endif
1422
                break ;
1423
        case SMT_P3210 :
1424
                if (long_val > 5000)
1425
                        goto val_error ;
1426
 
1427
                if (long_val != 0 && mib_a->fddiPATHSbaPayload == 0)
1428
                        goto val_error ;
1429
 
1430
                IFSET(mib_a->fddiPATHSbaOverhead = long_val) ;
1431
#ifdef  ESS
1432
                if (set)
1433
                        ess_para_change(smc) ;
1434
#endif
1435
                break ;
1436
        case SMT_P3213:                 /* fddiPATHT_Rmode */
1437
                /* no limit :
1438
                 * 0 .. 343.597 => 0 .. 2e32 * 80nS
1439
                 */
1440
                if (set) {
1441
                        mib_a->fddiPATHT_Rmode = long_val ;
1442
                        rtm_set_timer(smc) ;
1443
                }
1444
                break ;
1445
        case SMT_P3214 :                /* fddiPATHSbaAvailable */
1446
                if (long_val > 0x00BEBC20L)
1447
                        goto val_error ;
1448
#ifdef SBA 
1449
                if (set && mib->fddiSBACommand == SB_STOP)
1450
                        goto val_error ;
1451
#endif
1452
                IFSET(mib_a->fddiPATHSbaAvailable = long_val) ;
1453
                break ;
1454
        case SMT_P3215 :                /* fddiPATHTVXLowerBound */
1455
                IFSET(mib_a->fddiPATHTVXLowerBound = long_val) ;
1456
                goto change_mac_para ;
1457
        case SMT_P3216 :                /* fddiPATHT_MaxLowerBound */
1458
                IFSET(mib_a->fddiPATHT_MaxLowerBound = long_val) ;
1459
                goto change_mac_para ;
1460
        case SMT_P3217 :                /* fddiPATHMaxT_Req */
1461
                IFSET(mib_a->fddiPATHMaxT_Req = long_val) ;
1462
 
1463
change_mac_para:
1464
                if (set && smt_set_mac_opvalues(smc)) {
1465
                        RS_SET(smc,RS_EVENT) ;
1466
                        smc->sm.please_reconnect = 1 ;
1467
                        queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
1468
                }
1469
                break ;
1470
        case SMT_P400E :                /* fddiPORTConnectionPolicies */
1471
                if (byte_val > 1)
1472
                        goto val_error ;
1473
                IFSET(mib_p->fddiPORTConnectionPolicies = byte_val) ;
1474
                break ;
1475
        case SMT_P4011 :                /* fddiPORTRequestedPaths */
1476
                /* all 3*8 bits allowed */
1477
                IFSET(memcpy((char *)mib_p->fddiPORTRequestedPaths,
1478
                        (char *)&long_val,4)) ;
1479
                break ;
1480
        case SMT_P401F:                 /* fddiPORTMaint_LS */
1481
                if (word_val > 4)
1482
                        goto val_error ;
1483
                IFSET(mib_p->fddiPORTMaint_LS = word_val) ;
1484
                break ;
1485
        case SMT_P403A :                /* fddiPORTLer_Cutoff */
1486
                if (byte_val < 4 || byte_val > 15)
1487
                        goto val_error ;
1488
                IFSET(mib_p->fddiPORTLer_Cutoff = byte_val) ;
1489
                break ;
1490
        case SMT_P403B :                /* fddiPORTLer_Alarm */
1491
                if (byte_val < 4 || byte_val > 15)
1492
                        goto val_error ;
1493
                IFSET(mib_p->fddiPORTLer_Alarm = byte_val) ;
1494
                break ;
1495
 
1496
        /*
1497
         * Actions
1498
         */
1499
        case SMT_P103C :                /* fddiSMTStationAction */
1500
                if (smt_action(smc,SMT_STATION_ACTION, (int) word_val, 0))
1501
                        goto val_error ;
1502
                break ;
1503
        case SMT_P4046:                 /* fddiPORTAction */
1504
                if (smt_action(smc,SMT_PORT_ACTION, (int) word_val,
1505
                        port_to_mib(smc,port)))
1506
                        goto val_error ;
1507
                break ;
1508
        default :
1509
                break ;
1510
        }
1511
        return(0) ;
1512
 
1513
val_error:
1514
        /* parameter value in frame is out of range */
1515
        return(SMT_RDF_RANGE) ;
1516
 
1517
len_error:
1518
        /* parameter value in frame is too short */
1519
        return(SMT_RDF_LENGTH) ;
1520
 
1521
#if     0
1522
no_author_error:
1523
        /* parameter not setable, because the SBA is not active
1524
         * Please note: we give the return code 'not authorizeed
1525
         *  because SBA denied is not a valid return code in the
1526
         * PMF protocol.
1527
         */
1528
        return(SMT_RDF_AUTHOR) ;
1529
#endif
1530
}
1531
 
1532
static const struct s_p_tab *smt_get_ptab(u_short para)
1533
{
1534
        const struct s_p_tab    *pt ;
1535
        for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
1536
                ;
1537
        return(pt->p_num ? pt : NULL) ;
1538
}
1539
 
1540
static int smt_mib_phys(struct s_smc *smc)
1541
{
1542
#ifdef  CONCENTRATOR
1543
        SK_UNUSED(smc) ;
1544
 
1545
        return(NUMPHYS) ;
1546
#else
1547
        if (smc->s.sas == SMT_SAS)
1548
                return(1) ;
1549
        return(NUMPHYS) ;
1550
#endif
1551
}
1552
 
1553
static int port_to_mib(struct s_smc *smc, int p)
1554
{
1555
#ifdef  CONCENTRATOR
1556
        SK_UNUSED(smc) ;
1557
 
1558
        return(p) ;
1559
#else
1560
        if (smc->s.sas == SMT_SAS)
1561
                return(PS) ;
1562
        return(p) ;
1563
#endif
1564
}
1565
 
1566
 
1567
#ifdef  DEBUG
1568
#ifndef BOOT
1569
void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text)
1570
{
1571
        int     len ;
1572
        struct smt_para *pa ;
1573
        char    *c ;
1574
        int     n ;
1575
        int     nn ;
1576
#ifdef  LITTLE_ENDIAN
1577
        int     smtlen ;
1578
#endif
1579
 
1580
        SK_UNUSED(smc) ;
1581
 
1582
#ifdef  DEBUG_BRD
1583
        if (smc->debug.d_smtf < 2)
1584
#else
1585
        if (debug.d_smtf < 2)
1586
#endif
1587
                return ;
1588
#ifdef  LITTLE_ENDIAN
1589
        smtlen = sm->smt_len + sizeof(struct smt_header) ;
1590
#endif
1591
        printf("SMT Frame [%s]:\nDA  ",text) ;
1592
        dump_hex((char *) &sm->smt_dest,6) ;
1593
        printf("\tSA ") ;
1594
        dump_hex((char *) &sm->smt_source,6) ;
1595
        printf(" Class %x Type %x Version %x\n",
1596
                sm->smt_class,sm->smt_type,sm->smt_version)  ;
1597
        printf("TID %lx\t\tSID ",sm->smt_tid) ;
1598
        dump_hex((char *) &sm->smt_sid,8) ;
1599
        printf(" LEN %x\n",sm->smt_len) ;
1600
 
1601
        len = sm->smt_len ;
1602
        pa = (struct smt_para *) (sm + 1) ;
1603
        while (len > 0 ) {
1604
                int     plen ;
1605
#ifdef UNIX
1606
                printf("TYPE %x LEN %x VALUE\t",pa->p_type,pa->p_len) ;
1607
#else
1608
                printf("TYPE %04x LEN %2x VALUE\t",pa->p_type,pa->p_len) ;
1609
#endif
1610
                n = pa->p_len ;
1611
                if ( (n < 0 ) || (n > (int)(len - PARA_LEN))) {
1612
                        n = len - PARA_LEN ;
1613
                        printf(" BAD LENGTH\n") ;
1614
                        break ;
1615
                }
1616
#ifdef  LITTLE_ENDIAN
1617
                smt_swap_para(sm,smtlen,0) ;
1618
#endif
1619
                if (n < 24) {
1620
                        dump_hex((char *)(pa+1),(int) n) ;
1621
                        printf("\n") ;
1622
                }
1623
                else {
1624
                        int     first = 0 ;
1625
                        c = (char *)(pa+1) ;
1626
                        dump_hex(c,16) ;
1627
                        printf("\n") ;
1628
                        n -= 16 ;
1629
                        c += 16 ;
1630
                        while (n > 0) {
1631
                                nn = (n > 16) ? 16 : n ;
1632
                                if (n > 64) {
1633
                                        if (first == 0)
1634
                                                printf("\t\t\t...\n") ;
1635
                                        first = 1 ;
1636
                                }
1637
                                else {
1638
                                        printf("\t\t\t") ;
1639
                                        dump_hex(c,nn) ;
1640
                                        printf("\n") ;
1641
                                }
1642
                                n -= nn ;
1643
                                c += 16 ;
1644
                        }
1645
                }
1646
#ifdef  LITTLE_ENDIAN
1647
                smt_swap_para(sm,smtlen,1) ;
1648
#endif
1649
                plen = (pa->p_len + PARA_LEN + 3) & ~3 ;
1650
                len -= plen ;
1651
                pa = (struct smt_para *)((char *)pa + plen) ;
1652
        }
1653
        printf("-------------------------------------------------\n\n") ;
1654
}
1655
 
1656
void dump_hex(char *p, int len)
1657
{
1658
        int     n = 0 ;
1659
        while (len--) {
1660
                n++ ;
1661
#ifdef UNIX
1662
                printf("%x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
1663
#else
1664
                printf("%02x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
1665
#endif
1666
        }
1667
}
1668
#endif  /* no BOOT */
1669
#endif  /* DEBUG */
1670
 
1671
 
1672
#endif  /* no SLIM_SMT */

powered by: WebSVN 2.1.0

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