1 /******************************************************************************
3 * (C)Copyright 1998,1999 SysKonnect,
4 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
6 * See the file "skfddi.c" for further information.
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.
13 * The information in this file is provided "AS IS" without warranty.
15 ******************************************************************************/
23 #include "h/smtstate.h"
26 static const char ID_sccs
[] = "@(#)smt.c 2.43 98/11/23 (C) SK " ;
29 extern const u_char canonical
[256] ;
34 #define m_fc(mb) ((mb)->sm_data[0])
36 #define SMT_TID_MAGIC 0x1f0a7b3c
39 static const char *const smt_type_name
[] = {
40 "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??",
41 "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??",
42 "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??",
43 "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"
46 static const char *const smt_class_name
[] = {
47 "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF",
48 "SRF","PMF_GET","PMF_SET","ESF"
51 #define LAST_CLASS (SMT_PMF_SET)
53 static const struct fddi_addr SMT_Unknown
= {
60 extern const struct fddi_addr fddi_broadcast
;
65 int pcm_status_twisted(struct s_smc
*smc
);
71 static int smt_swap_short(u_short s
);
73 static int mac_index(struct s_smc
*smc
, int mac
);
74 static int phy_index(struct s_smc
*smc
, int phy
);
75 static int mac_con_resource_index(struct s_smc
*smc
, int mac
);
76 static int phy_con_resource_index(struct s_smc
*smc
, int phy
);
77 static void smt_send_rdf(struct s_smc
*smc
, SMbuf
*rej
, int fc
, int reason
,
79 static void smt_send_nif(struct s_smc
*smc
, const struct fddi_addr
*dest
,
80 int fc
, u_long tid
, int type
, int local
);
81 static void smt_send_ecf(struct s_smc
*smc
, struct fddi_addr
*dest
, int fc
,
82 u_long tid
, int type
, int len
);
83 static void smt_echo_test(struct s_smc
*smc
, int dna
);
84 static void smt_send_sif_config(struct s_smc
*smc
, struct fddi_addr
*dest
,
85 u_long tid
, int local
);
86 static void smt_send_sif_operation(struct s_smc
*smc
, struct fddi_addr
*dest
,
87 u_long tid
, int local
);
89 static void smt_string_swap(void);
91 static void smt_add_frame_len(SMbuf
*mb
, int len
);
92 static void smt_fill_una(struct s_smc
*smc
, struct smt_p_una
*una
);
93 static void smt_fill_sde(struct s_smc
*smc
, struct smt_p_sde
*sde
);
94 static void smt_fill_state(struct s_smc
*smc
, struct smt_p_state
*state
);
95 static void smt_fill_timestamp(struct s_smc
*smc
, struct smt_p_timestamp
*ts
);
96 static void smt_fill_policy(struct s_smc
*smc
, struct smt_p_policy
*policy
);
97 static void smt_fill_latency(struct s_smc
*smc
, struct smt_p_latency
*latency
);
98 static void smt_fill_neighbor(struct s_smc
*smc
, struct smt_p_neighbor
*neighbor
);
99 static int smt_fill_path(struct s_smc
*smc
, struct smt_p_path
*path
);
100 static void smt_fill_mac_status(struct s_smc
*smc
, struct smt_p_mac_status
*st
);
101 static void smt_fill_lem(struct s_smc
*smc
, struct smt_p_lem
*lem
, int phy
);
102 static void smt_fill_version(struct s_smc
*smc
, struct smt_p_version
*vers
);
103 static void smt_fill_fsc(struct s_smc
*smc
, struct smt_p_fsc
*fsc
);
104 static void smt_fill_mac_counter(struct s_smc
*smc
, struct smt_p_mac_counter
*mc
);
105 static void smt_fill_mac_fnc(struct s_smc
*smc
, struct smt_p_mac_fnc
*fnc
);
106 static void smt_fill_manufacturer(struct s_smc
*smc
,
107 struct smp_p_manufacturer
*man
);
108 static void smt_fill_user(struct s_smc
*smc
, struct smp_p_user
*user
);
109 static void smt_fill_setcount(struct s_smc
*smc
, struct smt_p_setcount
*setcount
);
110 static void smt_fill_echo(struct s_smc
*smc
, struct smt_p_echo
*echo
, u_long seed
,
113 void smt_clear_una_dna(struct s_smc
*smc
);
114 static void smt_clear_old_una_dna(struct s_smc
*smc
);
116 static int entity_to_index(void);
118 static void update_dac(struct s_smc
*smc
, int report
);
119 static int div_ratio(u_long upper
, u_long lower
);
121 void hwm_conv_can(struct s_smc
*smc
, char *data
, int len
);
123 #define hwm_conv_can(smc,data,len)
127 static inline int is_my_addr(const struct s_smc
*smc
,
128 const struct fddi_addr
*addr
)
130 return(*(short *)(&addr
->a
[0]) ==
131 *(short *)(&smc
->mib
.m
[MAC0
].fddiMACSMTAddress
.a
[0])
132 && *(short *)(&addr
->a
[2]) ==
133 *(short *)(&smc
->mib
.m
[MAC0
].fddiMACSMTAddress
.a
[2])
134 && *(short *)(&addr
->a
[4]) ==
135 *(short *)(&smc
->mib
.m
[MAC0
].fddiMACSMTAddress
.a
[4])) ;
138 static inline int is_broadcast(const struct fddi_addr
*addr
)
140 return(*(u_short
*)(&addr
->a
[0]) == 0xffff &&
141 *(u_short
*)(&addr
->a
[2]) == 0xffff &&
142 *(u_short
*)(&addr
->a
[4]) == 0xffff ) ;
145 static inline int is_individual(const struct fddi_addr
*addr
)
147 return(!(addr
->a
[0] & GROUP_ADDR
)) ;
150 static inline int is_equal(const struct fddi_addr
*addr1
,
151 const struct fddi_addr
*addr2
)
153 return(*(u_short
*)(&addr1
->a
[0]) == *(u_short
*)(&addr2
->a
[0]) &&
154 *(u_short
*)(&addr1
->a
[2]) == *(u_short
*)(&addr2
->a
[2]) &&
155 *(u_short
*)(&addr1
->a
[4]) == *(u_short
*)(&addr2
->a
[4]) ) ;
159 * list of mandatory paras in frames
161 static const u_short plist_nif
[] = { SMT_P_UNA
,SMT_P_SDE
,SMT_P_STATE
,0 } ;
166 void smt_agent_init(struct s_smc
*smc
)
173 smc
->mib
.m
[MAC0
].fddiMACSMTAddress
= smc
->hw
.fddi_home_addr
;
176 * get OUI address from driver (bia == built-in-address)
178 smc
->mib
.fddiSMTStationId
.sid_oem
[0] = 0 ;
179 smc
->mib
.fddiSMTStationId
.sid_oem
[1] = 0 ;
180 driver_get_bia(smc
,&smc
->mib
.fddiSMTStationId
.sid_node
) ;
181 for (i
= 0 ; i
< 6 ; i
++) {
182 smc
->mib
.fddiSMTStationId
.sid_node
.a
[i
] =
183 canonical
[smc
->mib
.fddiSMTStationId
.sid_node
.a
[i
]] ;
185 smc
->mib
.fddiSMTManufacturerData
[0] =
186 smc
->mib
.fddiSMTStationId
.sid_node
.a
[0] ;
187 smc
->mib
.fddiSMTManufacturerData
[1] =
188 smc
->mib
.fddiSMTStationId
.sid_node
.a
[1] ;
189 smc
->mib
.fddiSMTManufacturerData
[2] =
190 smc
->mib
.fddiSMTStationId
.sid_node
.a
[2] ;
191 smc
->sm
.smt_tid
= 0 ;
192 smc
->mib
.m
[MAC0
].fddiMACDupAddressTest
= DA_NONE
;
193 smc
->mib
.m
[MAC0
].fddiMACUNDA_Flag
= FALSE
;
195 smt_clear_una_dna(smc
) ;
196 smt_clear_old_una_dna(smc
) ;
198 for (i
= 0 ; i
< SMT_MAX_TEST
; i
++)
199 smc
->sm
.pend
[i
] = 0 ;
200 smc
->sm
.please_reconnect
= 0 ;
201 smc
->sm
.uniq_ticks
= 0 ;
212 void smt_agent_task(struct s_smc
*smc
)
214 smt_timer_start(smc
,&smc
->sm
.smt_timer
, (u_long
)1000000L,
215 EV_TOKEN(EVENT_SMT
,SM_TIMER
)) ;
216 DB_SMT("SMT agent task\n",0,0) ;
219 void smt_please_reconnect(struct s_smc
*smc
, int reconn_time
)
220 /* struct s_smc *smc; Pointer to SMT context */
221 /* int reconn_time; Wait for reconnect time in seconds */
224 * The please reconnect variable is used as a timer.
225 * It is decremented each time smt_event is called.
226 * This happens every second or when smt_force_irq is called.
227 * Note: smt_force_irq () is called on some packet receives and
228 * when a multicast address is changed. Since nothing
229 * is received during the disconnect and the multicast
230 * address changes can be viewed as not very often and
231 * the timer runs out close to its given value
234 smc
->sm
.please_reconnect
= reconn_time
;
237 #ifndef SMT_REAL_TOKEN_CT
238 void smt_emulate_token_ct(struct s_smc
*smc
, int mac_index
)
244 time
= smt_get_time();
245 count
= ((time
- smc
->sm
.last_tok_time
[mac_index
]) *
246 100)/TICKS_PER_SECOND
;
249 * Only when ring is up we will have a token count. The
250 * flag is unfortunatly a single instance value. This
251 * doesn't matter now, because we currently have only
254 if (smc
->hw
.mac_ring_is_up
){
255 smc
->mib
.m
[mac_index
].fddiMACToken_Ct
+= count
;
258 /* Remember current time */
259 smc
->sm
.last_tok_time
[mac_index
] = time
;
265 void smt_event(struct s_smc
*smc
, int event
)
268 #ifndef SMT_REAL_TOKEN_CT
273 if (smc
->sm
.please_reconnect
) {
274 smc
->sm
.please_reconnect
-- ;
275 if (smc
->sm
.please_reconnect
== 0) {
277 queue_event(smc
,EVENT_ECM
,EC_CONNECT
) ;
281 if (event
== SM_FAST
)
285 * timer for periodic cleanup in driver
286 * reset and start the watchdog (FM2)
290 smt_timer_poll(smc
) ;
291 smt_start_watchdog(smc
) ;
295 ess_timer_poll(smc
) ;
299 sba_timer_poll(smc
) ;
302 smt_srf_event(smc
,0,0,0) ;
304 #endif /* no SLIM_SMT */
306 time
= smt_get_time() ;
308 if (time
- smc
->sm
.smt_last_lem
>= TICKS_PER_SECOND
*8) {
310 * Use 8 sec. for the time intervall, it simplifies the
313 struct fddi_mib_m
*mib
;
320 * calculate LEM bit error rate
322 sm_lem_evaluate(smc
) ;
323 smc
->sm
.smt_last_lem
= time
;
329 mac_update_counter(smc
) ;
332 (mib
->fddiMACLost_Ct
- mib
->fddiMACOld_Lost_Ct
) +
333 (mib
->fddiMACError_Ct
- mib
->fddiMACOld_Error_Ct
) ;
335 (mib
->fddiMACFrame_Ct
- mib
->fddiMACOld_Frame_Ct
) +
336 (mib
->fddiMACLost_Ct
- mib
->fddiMACOld_Lost_Ct
) ;
337 mib
->fddiMACFrameErrorRatio
= div_ratio(upper
,lower
) ;
340 ((!mib
->fddiMACFrameErrorThreshold
&&
341 mib
->fddiMACError_Ct
!= mib
->fddiMACOld_Error_Ct
) ||
342 (mib
->fddiMACFrameErrorRatio
>
343 mib
->fddiMACFrameErrorThreshold
)) ;
345 if (cond
!= mib
->fddiMACFrameErrorFlag
)
346 smt_srf_event(smc
,SMT_COND_MAC_FRAME_ERROR
,
350 (mib
->fddiMACNotCopied_Ct
- mib
->fddiMACOld_NotCopied_Ct
) ;
353 (mib
->fddiMACCopied_Ct
- mib
->fddiMACOld_Copied_Ct
) ;
354 mib
->fddiMACNotCopiedRatio
= div_ratio(upper
,lower
) ;
357 ((!mib
->fddiMACNotCopiedThreshold
&&
358 mib
->fddiMACNotCopied_Ct
!=
359 mib
->fddiMACOld_NotCopied_Ct
)||
360 (mib
->fddiMACNotCopiedRatio
>
361 mib
->fddiMACNotCopiedThreshold
)) ;
363 if (cond
!= mib
->fddiMACNotCopiedFlag
)
364 smt_srf_event(smc
,SMT_COND_MAC_NOT_COPIED
,
370 mib
->fddiMACOld_Frame_Ct
= mib
->fddiMACFrame_Ct
;
371 mib
->fddiMACOld_Copied_Ct
= mib
->fddiMACCopied_Ct
;
372 mib
->fddiMACOld_Error_Ct
= mib
->fddiMACError_Ct
;
373 mib
->fddiMACOld_Lost_Ct
= mib
->fddiMACLost_Ct
;
374 mib
->fddiMACOld_NotCopied_Ct
= mib
->fddiMACNotCopied_Ct
;
377 * Check port EBError Condition
379 for (port
= 0; port
< NUMPHYS
; port
++) {
380 phy
= &smc
->y
[port
] ;
382 if (!phy
->mib
->fddiPORTHardwarePresent
) {
386 cond
= (phy
->mib
->fddiPORTEBError_Ct
-
387 phy
->mib
->fddiPORTOldEBError_Ct
> 5) ;
389 /* If ratio is more than 5 in 8 seconds
392 smt_srf_event(smc
,SMT_COND_PORT_EB_ERROR
,
393 (int) (INDEX_PORT
+ phy
->np
) ,cond
) ;
398 phy
->mib
->fddiPORTOldEBError_Ct
=
399 phy
->mib
->fddiPORTEBError_Ct
;
402 #endif /* no SLIM_SMT */
407 if (time
- smc
->sm
.smt_last_notify
>= (u_long
)
408 (smc
->mib
.fddiSMTTT_Notify
* TICKS_PER_SECOND
) ) {
410 * we can either send an announcement or a request
411 * a request will trigger a reply so that we can update
413 * note: same tid must be used until reply is received
415 if (!smc
->sm
.pend
[SMT_TID_NIF
])
416 smc
->sm
.pend
[SMT_TID_NIF
] = smt_get_tid(smc
) ;
417 smt_send_nif(smc
,&fddi_broadcast
, FC_SMT_NSA
,
418 smc
->sm
.pend
[SMT_TID_NIF
], SMT_REQUEST
,0) ;
419 smc
->sm
.smt_last_notify
= time
;
425 if (smc
->sm
.smt_tvu
&&
426 time
- smc
->sm
.smt_tvu
> 228*TICKS_PER_SECOND
) {
427 DB_SMT("SMT : UNA expired\n",0,0) ;
428 smc
->sm
.smt_tvu
= 0 ;
430 if (!is_equal(&smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
,
432 /* Do not update unknown address */
433 smc
->mib
.m
[MAC0
].fddiMACOldUpstreamNbr
=
434 smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
;
436 smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
= SMT_Unknown
;
437 smc
->mib
.m
[MAC0
].fddiMACUNDA_Flag
= FALSE
;
439 * Make sure the fddiMACUNDA_Flag = FALSE is
440 * included in the SRF so we don't generate
441 * a separate SRF for the deassertion of this
445 smt_srf_event(smc
, SMT_EVENT_MAC_NEIGHBOR_CHANGE
,
448 if (smc
->sm
.smt_tvd
&&
449 time
- smc
->sm
.smt_tvd
> 228*TICKS_PER_SECOND
) {
450 DB_SMT("SMT : DNA expired\n",0,0) ;
451 smc
->sm
.smt_tvd
= 0 ;
452 if (!is_equal(&smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
,
454 /* Do not update unknown address */
455 smc
->mib
.m
[MAC0
].fddiMACOldDownstreamNbr
=
456 smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
;
458 smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
= SMT_Unknown
;
459 smt_srf_event(smc
, SMT_EVENT_MAC_NEIGHBOR_CHANGE
,
463 #endif /* no SLIM_SMT */
465 #ifndef SMT_REAL_TOKEN_CT
467 * Token counter emulation section. If hardware supports the token
468 * count, the token counter will be updated in mac_update_counter.
470 for (i
= MAC0
; i
< NUMMACS
; i
++ ){
471 if (time
- smc
->sm
.last_tok_time
[i
] > 2*TICKS_PER_SECOND
){
472 smt_emulate_token_ct( smc
, i
);
477 smt_timer_start(smc
,&smc
->sm
.smt_timer
, (u_long
)1000000L,
478 EV_TOKEN(EVENT_SMT
,SM_TIMER
)) ;
481 static int div_ratio(u_long upper
, u_long lower
)
483 if ((upper
<<16L) < upper
)
484 upper
= 0xffff0000L
;
489 return((int)(upper
/lower
)) ;
495 * receive packet handler
497 void smt_received_pack(struct s_smc
*smc
, SMbuf
*mb
, int fs
)
498 /* int fs; frame status */
500 struct smt_header
*sm
;
507 case FC_SMT_LAN_LOC
:
512 smt_free_mbuf(smc
,mb
) ;
516 smc
->mib
.m
[MAC0
].fddiMACSMTCopied_Ct
++ ;
517 sm
= smtod(mb
,struct smt_header
*) ;
518 local
= ((fs
& L_INDICATOR
) != 0) ;
519 hwm_conv_can(smc
,(char *)sm
,12) ;
521 /* check destination address */
522 if (is_individual(&sm
->smt_dest
) && !is_my_addr(smc
,&sm
->smt_dest
)) {
523 smt_free_mbuf(smc
,mb
) ;
526 #if 0 /* for DUP recognition, do NOT filter them */
527 /* ignore loop back packets */
528 if (is_my_addr(smc
,&sm
->smt_source
) && !local
) {
529 smt_free_mbuf(smc
,mb
) ;
534 smt_swap_para(sm
,(int) mb
->sm_len
,1) ;
535 DB_SMT("SMT : received packet [%s] at 0x%x\n",
536 smt_type_name
[m_fc(mb
) & 0xf],sm
) ;
537 DB_SMT("SMT : version %d, class %s\n",sm
->smt_version
,
538 smt_class_name
[(sm
->smt_class
>LAST_CLASS
)?0 : sm
->smt_class
]) ;
544 if (m_fc(mb
) == FC_SMT_NSA
&& sm
->smt_class
== SMT_NIF
&&
545 (sm
->smt_type
== SMT_ANNOUNCE
|| sm
->smt_type
== SMT_REQUEST
)) {
552 * ignore any packet with NSA and A-indicator set
554 if ( (fs
& A_INDICATOR
) && m_fc(mb
) == FC_SMT_NSA
) {
555 DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n",
556 addr_to_string(&sm
->smt_source
),0) ;
557 smt_free_mbuf(smc
,mb
) ;
562 * ignore frames with illegal length
564 if (((sm
->smt_class
== SMT_ECF
) && (sm
->smt_len
> SMT_MAX_ECHO_LEN
)) ||
565 ((sm
->smt_class
!= SMT_ECF
) && (sm
->smt_len
> SMT_MAX_INFO_LEN
))) {
566 smt_free_mbuf(smc
,mb
) ;
573 switch (sm
->smt_class
) {
575 case SMT_SIF_CONFIG
:
578 if (sm
->smt_version
!= SMT_VID
)
582 if (sm
->smt_version
!= SMT_VID_2
)
587 DB_SMT("SMT : version = %d, dest = %s\n",
588 sm
->smt_version
,addr_to_string(&sm
->smt_source
)) ;
589 smt_send_rdf(smc
,mb
,m_fc(mb
),SMT_RDF_VERSION
,local
) ;
590 smt_free_mbuf(smc
,mb
) ;
593 if ((sm
->smt_len
> mb
->sm_len
- sizeof(struct smt_header
)) ||
594 ((sm
->smt_len
& 3) && (sm
->smt_class
!= SMT_ECF
))) {
595 DB_SMT("SMT: info length error, len = %d\n",sm
->smt_len
,0) ;
596 smt_send_rdf(smc
,mb
,m_fc(mb
),SMT_RDF_LENGTH
,local
) ;
597 smt_free_mbuf(smc
,mb
) ;
600 switch (sm
->smt_class
) {
602 if (smt_check_para(smc
,sm
,plist_nif
)) {
603 DB_SMT("SMT: NIF with para problem, ignoring\n",0,0) ;
606 switch (sm
->smt_type
) {
609 if (!(fs
& C_INDICATOR
) && m_fc(mb
) == FC_SMT_NSA
610 && is_broadcast(&sm
->smt_dest
)) {
611 struct smt_p_state
*st
;
615 &smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
,
617 DB_SMT("SMT : updated my UNA = %s\n",
618 addr_to_string(&sm
->smt_source
),0) ;
619 if (!is_equal(&smc
->mib
.m
[MAC0
].
620 fddiMACUpstreamNbr
,&SMT_Unknown
)){
621 /* Do not update unknown address */
622 smc
->mib
.m
[MAC0
].fddiMACOldUpstreamNbr
=
623 smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
;
626 smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
=
629 SMT_EVENT_MAC_NEIGHBOR_CHANGE
,
631 smt_echo_test(smc
,0) ;
633 smc
->sm
.smt_tvu
= smt_get_time() ;
634 st
= (struct smt_p_state
*)
635 sm_to_para(smc
,sm
,SMT_P_STATE
) ;
637 smc
->mib
.m
[MAC0
].fddiMACUNDA_Flag
=
638 (st
->st_dupl_addr
& SMT_ST_MY_DUPA
) ?
643 if ((sm
->smt_type
== SMT_REQUEST
) &&
644 is_individual(&sm
->smt_source
) &&
645 ((!(fs
& A_INDICATOR
) && m_fc(mb
) == FC_SMT_NSA
) ||
646 (m_fc(mb
) != FC_SMT_NSA
))) {
647 DB_SMT("SMT : replying to NIF request %s\n",
648 addr_to_string(&sm
->smt_source
),0) ;
649 smt_send_nif(smc
,&sm
->smt_source
,
656 DB_SMT("SMT : received NIF response from %s\n",
657 addr_to_string(&sm
->smt_source
),0) ;
658 if (fs
& A_INDICATOR
) {
659 smc
->sm
.pend
[SMT_TID_NIF
] = 0 ;
660 DB_SMT("SMT : duplicate address\n",0,0) ;
661 smc
->mib
.m
[MAC0
].fddiMACDupAddressTest
=
663 smc
->r
.dup_addr_test
= DA_FAILED
;
664 queue_event(smc
,EVENT_RMT
,RM_DUP_ADDR
) ;
665 smc
->mib
.m
[MAC0
].fddiMACDA_Flag
= TRUE
;
669 if (sm
->smt_tid
== smc
->sm
.pend
[SMT_TID_NIF
]) {
670 smc
->sm
.pend
[SMT_TID_NIF
] = 0 ;
673 &smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
,
675 DB_SMT("SMT : updated my DNA\n",0,0) ;
676 if (!is_equal(&smc
->mib
.m
[MAC0
].
677 fddiMACDownstreamNbr
, &SMT_Unknown
)){
678 /* Do not update unknown address */
679 smc
->mib
.m
[MAC0
].fddiMACOldDownstreamNbr
=
680 smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
;
683 smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
=
686 SMT_EVENT_MAC_NEIGHBOR_CHANGE
,
688 smt_echo_test(smc
,1) ;
690 smc
->mib
.m
[MAC0
].fddiMACDA_Flag
= FALSE
;
692 smc
->sm
.smt_tvd
= smt_get_time() ;
693 smc
->mib
.m
[MAC0
].fddiMACDupAddressTest
=
695 if (smc
->r
.dup_addr_test
!= DA_PASSED
) {
696 smc
->r
.dup_addr_test
= DA_PASSED
;
697 queue_event(smc
,EVENT_RMT
,RM_DUP_ADDR
) ;
700 else if (sm
->smt_tid
==
701 smc
->sm
.pend
[SMT_TID_NIF_TEST
]) {
702 DB_SMT("SMT : NIF test TID ok\n",0,0) ;
705 DB_SMT("SMT : expected TID %lx, got %lx\n",
706 smc
->sm
.pend
[SMT_TID_NIF
],sm
->smt_tid
) ;
714 case SMT_SIF_CONFIG
: /* station information */
715 if (sm
->smt_type
!= SMT_REQUEST
)
717 DB_SMT("SMT : replying to SIF Config request from %s\n",
718 addr_to_string(&sm
->smt_source
),0) ;
719 smt_send_sif_config(smc
,&sm
->smt_source
,sm
->smt_tid
,local
) ;
721 case SMT_SIF_OPER
: /* station information */
722 if (sm
->smt_type
!= SMT_REQUEST
)
724 DB_SMT("SMT : replying to SIF Operation request from %s\n",
725 addr_to_string(&sm
->smt_source
),0) ;
726 smt_send_sif_operation(smc
,&sm
->smt_source
,sm
->smt_tid
,local
) ;
728 case SMT_ECF
: /* echo frame */
729 switch (sm
->smt_type
) {
731 smc
->mib
.priv
.fddiPRIVECF_Reply_Rx
++ ;
732 DB_SMT("SMT: received ECF reply from %s\n",
733 addr_to_string(&sm
->smt_source
),0) ;
734 if (sm_to_para(smc
,sm
,SMT_P_ECHODATA
) == 0) {
735 DB_SMT("SMT: ECHODATA missing\n",0,0) ;
738 if (sm
->smt_tid
== smc
->sm
.pend
[SMT_TID_ECF
]) {
739 DB_SMT("SMT : ECF test TID ok\n",0,0) ;
741 else if (sm
->smt_tid
== smc
->sm
.pend
[SMT_TID_ECF_UNA
]) {
742 DB_SMT("SMT : ECF test UNA ok\n",0,0) ;
744 else if (sm
->smt_tid
== smc
->sm
.pend
[SMT_TID_ECF_DNA
]) {
745 DB_SMT("SMT : ECF test DNA ok\n",0,0) ;
748 DB_SMT("SMT : expected TID %lx, got %lx\n",
749 smc
->sm
.pend
[SMT_TID_ECF
],
754 smc
->mib
.priv
.fddiPRIVECF_Req_Rx
++ ;
756 if (sm
->smt_len
&& !sm_to_para(smc
,sm
,SMT_P_ECHODATA
)) {
757 DB_SMT("SMT: ECF with para problem,sending RDF\n",0,0) ;
758 smt_send_rdf(smc
,mb
,m_fc(mb
),SMT_RDF_LENGTH
,
762 DB_SMT("SMT - sending ECF reply to %s\n",
763 addr_to_string(&sm
->smt_source
),0) ;
765 /* set destination addr. & reply */
766 sm
->smt_dest
= sm
->smt_source
;
767 sm
->smt_type
= SMT_REPLY
;
768 dump_smt(smc
,sm
,"ECF REPLY") ;
769 smc
->mib
.priv
.fddiPRIVECF_Reply_Tx
++ ;
770 smt_send_frame(smc
,mb
,FC_SMT_INFO
,local
) ;
771 return ; /* DON'T free mbuf */
779 case SMT_RAF
: /* resource allocation */
781 DB_ESSN(2,"ESS: RAF frame received\n",0,0) ;
782 fs
= ess_raf_received_pack(smc
,mb
,sm
,fs
) ;
786 DB_SBAN(2,"SBA: RAF frame received\n",0,0) ;
787 sba_raf_received_pack(smc
,sm
,fs
) ;
790 case SMT_RDF
: /* request denied */
791 smc
->mib
.priv
.fddiPRIVRDF_Rx
++ ;
793 case SMT_ESF
: /* extended service - not supported */
794 if (sm
->smt_type
== SMT_REQUEST
) {
795 DB_SMT("SMT - received ESF, sending RDF\n",0,0) ;
796 smt_send_rdf(smc
,mb
,m_fc(mb
),SMT_RDF_CLASS
,local
) ;
801 if (sm
->smt_type
!= SMT_REQUEST
)
803 /* update statistics */
804 if (sm
->smt_class
== SMT_PMF_GET
)
805 smc
->mib
.priv
.fddiPRIVPMF_Get_Rx
++ ;
807 smc
->mib
.priv
.fddiPRIVPMF_Set_Rx
++ ;
809 * ignore PMF SET with I/G set
811 if ((sm
->smt_class
== SMT_PMF_SET
) &&
812 !is_individual(&sm
->smt_dest
)) {
813 DB_SMT("SMT: ignoring PMF-SET with I/G set\n",0,0) ;
816 smt_pmf_received_pack(smc
,mb
, local
) ;
819 dump_smt(smc
,sm
,"SRF received") ;
822 if (sm
->smt_type
!= SMT_REQUEST
)
825 * For frames with unknown class:
826 * we need to send a RDF frame according to 8.1.3.1.1,
827 * only if it is a REQUEST.
829 DB_SMT("SMT : class = %d, send RDF to %s\n",
830 sm
->smt_class
, addr_to_string(&sm
->smt_source
)) ;
832 smt_send_rdf(smc
,mb
,m_fc(mb
),SMT_RDF_CLASS
,local
) ;
837 DB_SMT("SMT: discarding invalid frame, reason = %d\n",
840 smt_free_mbuf(smc
,mb
) ;
843 static void update_dac(struct s_smc
*smc
, int report
)
847 cond
= ( smc
->mib
.m
[MAC0
].fddiMACUNDA_Flag
|
848 smc
->mib
.m
[MAC0
].fddiMACDA_Flag
) != 0 ;
849 if (report
&& (cond
!= smc
->mib
.m
[MAC0
].fddiMACDuplicateAddressCond
))
850 smt_srf_event(smc
, SMT_COND_MAC_DUP_ADDR
,INDEX_MAC
,cond
) ;
852 smc
->mib
.m
[MAC0
].fddiMACDuplicateAddressCond
= cond
;
861 void smt_send_frame(struct s_smc
*smc
, SMbuf
*mb
, int fc
, int local
)
862 /* SMbuf *mb; buffer to send */
863 /* int fc; FC value */
865 struct smt_header
*sm
;
867 if (!smc
->r
.sm_ma_avail
&& !local
) {
868 smt_free_mbuf(smc
,mb
) ;
871 sm
= smtod(mb
,struct smt_header
*) ;
872 sm
->smt_source
= smc
->mib
.m
[MAC0
].fddiMACSMTAddress
;
873 sm
->smt_sid
= smc
->mib
.fddiSMTStationId
;
875 smt_swap_para(sm
,(int) mb
->sm_len
,0) ; /* swap para & header */
876 hwm_conv_can(smc
,(char *)sm
,12) ; /* convert SA and DA */
877 smc
->mib
.m
[MAC0
].fddiMACSMTTransmit_Ct
++ ;
878 smt_send_mbuf(smc
,mb
,local
? FC_SMT_LOC
: fc
) ;
882 * generate and send RDF
884 static void smt_send_rdf(struct s_smc
*smc
, SMbuf
*rej
, int fc
, int reason
,
886 /* SMbuf *rej; mbuf of offending frame */
887 /* int fc; FC of denied frame */
888 /* int reason; reason code */
891 struct smt_header
*sm
; /* header of offending frame */
892 struct smt_rdf
*rdf
;
896 sm
= smtod(rej
,struct smt_header
*) ;
897 if (sm
->smt_type
!= SMT_REQUEST
)
900 DB_SMT("SMT: sending RDF to %s,reason = 0x%x\n",
901 addr_to_string(&sm
->smt_source
),reason
) ;
905 * note: get framelength from MAC length, NOT from SMT header
906 * smt header length is included in sm_len
908 frame_len
= rej
->sm_len
;
910 if (!(mb
=smt_build_frame(smc
,SMT_RDF
,SMT_REPLY
,sizeof(struct smt_rdf
))))
912 rdf
= smtod(mb
,struct smt_rdf
*) ;
913 rdf
->smt
.smt_tid
= sm
->smt_tid
; /* use TID from sm */
914 rdf
->smt
.smt_dest
= sm
->smt_source
; /* set dest = source */
917 rdf
->reason
.para
.p_type
= SMT_P_REASON
;
918 rdf
->reason
.para
.p_len
= sizeof(struct smt_p_reason
) - PARA_LEN
;
919 rdf
->reason
.rdf_reason
= reason
;
922 rdf
->version
.para
.p_type
= SMT_P_VERSION
;
923 rdf
->version
.para
.p_len
= sizeof(struct smt_p_version
) - PARA_LEN
;
924 rdf
->version
.v_pad
= 0 ;
925 rdf
->version
.v_n
= 1 ;
926 rdf
->version
.v_index
= 1 ;
927 rdf
->version
.v_version
[0] = SMT_VID_2
;
928 rdf
->version
.v_pad2
= 0 ;
931 if ((unsigned) frame_len
<= SMT_MAX_INFO_LEN
- sizeof(*rdf
) +
932 2*sizeof(struct smt_header
))
935 len
= SMT_MAX_INFO_LEN
- sizeof(*rdf
) +
936 2*sizeof(struct smt_header
) ;
937 /* make length multiple of 4 */
939 rdf
->refused
.para
.p_type
= SMT_P_REFUSED
;
940 /* length of para is smt_frame + ref_fc */
941 rdf
->refused
.para
.p_len
= len
+ 4 ;
942 rdf
->refused
.ref_fc
= fc
;
945 smt_swap_para(sm
,frame_len
,0) ;
947 memcpy((char *) &rdf
->refused
.ref_header
,(char *) sm
,len
) ;
949 len
-= sizeof(struct smt_header
) ;
951 rdf
->smt
.smt_len
+= len
;
953 dump_smt(smc
,(struct smt_header
*)rdf
,"RDF") ;
954 smc
->mib
.priv
.fddiPRIVRDF_Tx
++ ;
955 smt_send_frame(smc
,mb
,FC_SMT_INFO
,local
) ;
959 * generate and send NIF
961 static void smt_send_nif(struct s_smc
*smc
, const struct fddi_addr
*dest
,
962 int fc
, u_long tid
, int type
, int local
)
963 /* struct fddi_addr *dest; dest address */
964 /* int fc; frame control */
965 /* u_long tid; transaction id */
966 /* int type; frame type */
968 struct smt_nif
*nif
;
971 if (!(mb
= smt_build_frame(smc
,SMT_NIF
,type
,sizeof(struct smt_nif
))))
973 nif
= smtod(mb
, struct smt_nif
*) ;
974 smt_fill_una(smc
,&nif
->una
) ; /* set UNA */
975 smt_fill_sde(smc
,&nif
->sde
) ; /* set station descriptor */
976 smt_fill_state(smc
,&nif
->state
) ; /* set state information */
978 smt_fill_fsc(smc
,&nif
->fsc
) ; /* set frame status cap. */
980 nif
->smt
.smt_dest
= *dest
; /* destination address */
981 nif
->smt
.smt_tid
= tid
; /* transaction ID */
982 dump_smt(smc
,(struct smt_header
*)nif
,"NIF") ;
983 smt_send_frame(smc
,mb
,fc
,local
) ;
988 * send NIF request (test purpose)
990 static void smt_send_nif_request(struct s_smc
*smc
, struct fddi_addr
*dest
)
992 smc
->sm
.pend
[SMT_TID_NIF_TEST
] = smt_get_tid(smc
) ;
993 smt_send_nif(smc
,dest
, FC_SMT_INFO
, smc
->sm
.pend
[SMT_TID_NIF_TEST
],
998 * send ECF request (test purpose)
1000 static void smt_send_ecf_request(struct s_smc
*smc
, struct fddi_addr
*dest
,
1003 smc
->sm
.pend
[SMT_TID_ECF
] = smt_get_tid(smc
) ;
1004 smt_send_ecf(smc
,dest
, FC_SMT_INFO
, smc
->sm
.pend
[SMT_TID_ECF
],
1012 static void smt_echo_test(struct s_smc
*smc
, int dna
)
1016 smc
->sm
.pend
[dna
? SMT_TID_ECF_DNA
: SMT_TID_ECF_UNA
] =
1017 tid
= smt_get_tid(smc
) ;
1018 smt_send_ecf(smc
, dna
?
1019 &smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
:
1020 &smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
,
1021 FC_SMT_INFO
,tid
, SMT_REQUEST
, (SMT_TEST_ECHO_LEN
& ~3)-8) ;
1025 * generate and send ECF
1027 static void smt_send_ecf(struct s_smc
*smc
, struct fddi_addr
*dest
, int fc
,
1028 u_long tid
, int type
, int len
)
1029 /* struct fddi_addr *dest; dest address */
1030 /* int fc; frame control */
1031 /* u_long tid; transaction id */
1032 /* int type; frame type */
1033 /* int len; frame length */
1035 struct smt_ecf
*ecf
;
1038 if (!(mb
= smt_build_frame(smc
,SMT_ECF
,type
,SMT_ECF_LEN
+ len
)))
1040 ecf
= smtod(mb
, struct smt_ecf
*) ;
1042 smt_fill_echo(smc
,&ecf
->ec_echo
,tid
,len
) ; /* set ECHO */
1043 ecf
->smt
.smt_dest
= *dest
; /* destination address */
1044 ecf
->smt
.smt_tid
= tid
; /* transaction ID */
1045 smc
->mib
.priv
.fddiPRIVECF_Req_Tx
++ ;
1046 smt_send_frame(smc
,mb
,fc
,0) ;
1050 * generate and send SIF config response
1053 static void smt_send_sif_config(struct s_smc
*smc
, struct fddi_addr
*dest
,
1054 u_long tid
, int local
)
1055 /* struct fddi_addr *dest; dest address */
1056 /* u_long tid; transaction id */
1058 struct smt_sif_config
*sif
;
1061 if (!(mb
= smt_build_frame(smc
,SMT_SIF_CONFIG
,SMT_REPLY
,
1062 SIZEOF_SMT_SIF_CONFIG
)))
1065 sif
= smtod(mb
, struct smt_sif_config
*) ;
1066 smt_fill_timestamp(smc
,&sif
->ts
) ; /* set time stamp */
1067 smt_fill_sde(smc
,&sif
->sde
) ; /* set station descriptor */
1068 smt_fill_version(smc
,&sif
->version
) ; /* set version information */
1069 smt_fill_state(smc
,&sif
->state
) ; /* set state information */
1070 smt_fill_policy(smc
,&sif
->policy
) ; /* set station policy */
1071 smt_fill_latency(smc
,&sif
->latency
); /* set station latency */
1072 smt_fill_neighbor(smc
,&sif
->neighbor
); /* set station neighbor */
1073 smt_fill_setcount(smc
,&sif
->setcount
) ; /* set count */
1074 len
= smt_fill_path(smc
,&sif
->path
); /* set station path descriptor*/
1075 sif
->smt
.smt_dest
= *dest
; /* destination address */
1076 sif
->smt
.smt_tid
= tid
; /* transaction ID */
1077 smt_add_frame_len(mb
,len
) ; /* adjust length fields */
1078 dump_smt(smc
,(struct smt_header
*)sif
,"SIF Configuration Reply") ;
1079 smt_send_frame(smc
,mb
,FC_SMT_INFO
,local
) ;
1083 * generate and send SIF operation response
1086 static void smt_send_sif_operation(struct s_smc
*smc
, struct fddi_addr
*dest
,
1087 u_long tid
, int local
)
1088 /* struct fddi_addr *dest; dest address */
1089 /* u_long tid; transaction id */
1091 struct smt_sif_operation
*sif
;
1097 #ifndef CONCENTRATOR
1098 if (smc
->s
.sas
== SMT_SAS
)
1102 if (!(mb
= smt_build_frame(smc
,SMT_SIF_OPER
,SMT_REPLY
,
1103 SIZEOF_SMT_SIF_OPERATION
+ports
*sizeof(struct smt_p_lem
))))
1105 sif
= smtod(mb
, struct smt_sif_operation
*) ;
1106 smt_fill_timestamp(smc
,&sif
->ts
) ; /* set time stamp */
1107 smt_fill_mac_status(smc
,&sif
->status
) ; /* set mac status */
1108 smt_fill_mac_counter(smc
,&sif
->mc
) ; /* set mac counter field */
1109 smt_fill_mac_fnc(smc
,&sif
->fnc
) ; /* set frame not copied counter */
1110 smt_fill_manufacturer(smc
,&sif
->man
) ; /* set manufacturer field */
1111 smt_fill_user(smc
,&sif
->user
) ; /* set user field */
1112 smt_fill_setcount(smc
,&sif
->setcount
) ; /* set count */
1114 * set link error mon information
1117 smt_fill_lem(smc
,sif
->lem
,PS
) ;
1120 for (i
= 0 ; i
< ports
; i
++) {
1121 smt_fill_lem(smc
,&sif
->lem
[i
],i
) ;
1125 sif
->smt
.smt_dest
= *dest
; /* destination address */
1126 sif
->smt
.smt_tid
= tid
; /* transaction ID */
1127 dump_smt(smc
,(struct smt_header
*)sif
,"SIF Operation Reply") ;
1128 smt_send_frame(smc
,mb
,FC_SMT_INFO
,local
) ;
1132 * get and initialize SMT frame
1134 SMbuf
*smt_build_frame(struct s_smc
*smc
, int class, int type
,
1138 struct smt_header
*smt
;
1141 if (!smc
->r
.sm_ma_avail
) {
1145 if (!(mb
= smt_get_mbuf(smc
)))
1148 mb
->sm_len
= length
;
1149 smt
= smtod(mb
, struct smt_header
*) ;
1150 smt
->smt_dest
= fddi_broadcast
; /* set dest = broadcast */
1151 smt
->smt_class
= class ;
1152 smt
->smt_type
= type
;
1155 case SMT_SIF_CONFIG
:
1158 smt
->smt_version
= SMT_VID
;
1161 smt
->smt_version
= SMT_VID_2
;
1164 smt
->smt_tid
= smt_get_tid(smc
) ; /* set transaction ID */
1166 smt
->smt_len
= length
- sizeof(struct smt_header
) ;
1170 static void smt_add_frame_len(SMbuf
*mb
, int len
)
1172 struct smt_header
*smt
;
1174 smt
= smtod(mb
, struct smt_header
*) ;
1175 smt
->smt_len
+= len
;
1182 * fill values in UNA parameter
1184 static void smt_fill_una(struct s_smc
*smc
, struct smt_p_una
*una
)
1186 SMTSETPARA(una
,SMT_P_UNA
) ;
1188 una
->una_node
= smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
;
1192 * fill values in SDE parameter
1194 static void smt_fill_sde(struct s_smc
*smc
, struct smt_p_sde
*sde
)
1196 SMTSETPARA(sde
,SMT_P_SDE
) ;
1197 sde
->sde_non_master
= smc
->mib
.fddiSMTNonMaster_Ct
;
1198 sde
->sde_master
= smc
->mib
.fddiSMTMaster_Ct
;
1199 sde
->sde_mac_count
= NUMMACS
; /* only 1 MAC */
1201 sde
->sde_type
= SMT_SDE_CONCENTRATOR
;
1203 sde
->sde_type
= SMT_SDE_STATION
;
1208 * fill in values in station state parameter
1210 static void smt_fill_state(struct s_smc
*smc
, struct smt_p_state
*state
)
1215 SMTSETPARA(state
,SMT_P_STATE
) ;
1218 /* determine topology */
1220 if (smc
->mib
.fddiSMTPeerWrapFlag
) {
1221 top
|= SMT_ST_WRAPPED
; /* state wrapped */
1224 if (cfm_status_unattached(smc
)) {
1225 top
|= SMT_ST_UNATTACHED
; /* unattached concentrator */
1228 if ((twist
= pcm_status_twisted(smc
)) & 1) {
1229 top
|= SMT_ST_TWISTED_A
; /* twisted cable */
1232 top
|= SMT_ST_TWISTED_B
; /* twisted cable */
1237 if (pcm_rooted_station(smc
))
1238 top
|= SMT_ST_ROOTED_S
;
1239 if (smc
->mib
.a
[0].fddiPATHSbaPayload
!= 0)
1240 top
|= SMT_ST_SYNC_SERVICE
;
1241 state
->st_topology
= top
;
1242 state
->st_dupl_addr
=
1243 ((smc
->mib
.m
[MAC0
].fddiMACDA_Flag
? SMT_ST_MY_DUPA
: 0 ) |
1244 (smc
->mib
.m
[MAC0
].fddiMACUNDA_Flag
? SMT_ST_UNA_DUPA
: 0)) ;
1248 * fill values in timestamp parameter
1250 static void smt_fill_timestamp(struct s_smc
*smc
, struct smt_p_timestamp
*ts
)
1253 SMTSETPARA(ts
,SMT_P_TIMESTAMP
) ;
1254 smt_set_timestamp(smc
,ts
->ts_time
) ;
1257 void smt_set_timestamp(struct s_smc
*smc
, u_char
*p
)
1263 * timestamp is 64 bits long ; resolution is 80 nS
1264 * our clock resolution is 10mS
1265 * 10mS/80ns = 125000 ~ 2^17 = 131072
1267 utime
= smt_get_time() ;
1268 time
= utime
* 100 ;
1269 time
/= TICKS_PER_SECOND
;
1271 p
[1] = (u_char
)((time
>>(8+8+8+8-1)) & 1) ;
1272 p
[2] = (u_char
)(time
>>(8+8+8-1)) ;
1273 p
[3] = (u_char
)(time
>>(8+8-1)) ;
1274 p
[4] = (u_char
)(time
>>(8-1)) ;
1275 p
[5] = (u_char
)(time
<<1) ;
1276 p
[6] = (u_char
)(smc
->sm
.uniq_ticks
>>8) ;
1277 p
[7] = (u_char
)smc
->sm
.uniq_ticks
;
1279 * make sure we don't wrap: restart whenever the upper digits change
1281 if (utime
!= smc
->sm
.uniq_time
) {
1282 smc
->sm
.uniq_ticks
= 0 ;
1284 smc
->sm
.uniq_ticks
++ ;
1285 smc
->sm
.uniq_time
= utime
;
1289 * fill values in station policy parameter
1291 static void smt_fill_policy(struct s_smc
*smc
, struct smt_p_policy
*policy
)
1299 * MIB para 101b (fddiSMTConnectionPolicy) coding
1300 * is different from 0005 coding
1302 static u_char ansi_weirdness
[16] = {
1303 0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15
1305 SMTSETPARA(policy
,SMT_P_POLICY
) ;
1308 in
= smc
->mib
.fddiSMTConnectionPolicy
;
1309 for (i
= 0, map
= ansi_weirdness
; i
< 16 ; i
++) {
1315 policy
->pl_config
= smc
->mib
.fddiSMTConfigPolicy
;
1316 policy
->pl_connect
= out
;
1320 * fill values in latency equivalent parameter
1322 static void smt_fill_latency(struct s_smc
*smc
, struct smt_p_latency
*latency
)
1324 SMTSETPARA(latency
,SMT_P_LATENCY
) ;
1326 latency
->lt_phyout_idx1
= phy_index(smc
,0) ;
1327 latency
->lt_latency1
= 10 ; /* in octets (byte clock) */
1329 * note: latency has two phy entries by definition
1330 * for a SAS, the 2nd one is null
1332 if (smc
->s
.sas
== SMT_DAS
) {
1333 latency
->lt_phyout_idx2
= phy_index(smc
,1) ;
1334 latency
->lt_latency2
= 10 ; /* in octets (byte clock) */
1337 latency
->lt_phyout_idx2
= 0 ;
1338 latency
->lt_latency2
= 0 ;
1343 * fill values in MAC neighbors parameter
1345 static void smt_fill_neighbor(struct s_smc
*smc
, struct smt_p_neighbor
*neighbor
)
1347 SMTSETPARA(neighbor
,SMT_P_NEIGHBORS
) ;
1349 neighbor
->nb_mib_index
= INDEX_MAC
;
1350 neighbor
->nb_mac_index
= mac_index(smc
,1) ;
1351 neighbor
->nb_una
= smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
;
1352 neighbor
->nb_dna
= smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
;
1356 * fill values in path descriptor
1359 #define ALLPHYS NUMPHYS
1361 #define ALLPHYS ((smc->s.sas == SMT_SAS) ? 1 : 2)
1364 static int smt_fill_path(struct s_smc
*smc
, struct smt_p_path
*path
)
1366 SK_LOC_DECL(int,type
) ;
1367 SK_LOC_DECL(int,state
) ;
1368 SK_LOC_DECL(int,remote
) ;
1369 SK_LOC_DECL(int,mac
) ;
1373 struct smt_phy_rec
*phy
;
1374 struct smt_mac_rec
*pd_mac
;
1377 sizeof(struct smt_mac_rec
) * NUMMACS
+
1378 sizeof(struct smt_phy_rec
) * ALLPHYS
;
1379 path
->para
.p_type
= SMT_P_PATH
;
1380 path
->para
.p_len
= len
- PARA_LEN
;
1383 for (p
= 0,phy
= path
->pd_phy
; p
< ALLPHYS
; p
++, phy
++) {
1385 #ifndef CONCENTRATOR
1386 if (smc
->s
.sas
== SMT_SAS
)
1389 pcm_status_state(smc
,physp
,&type
,&state
,&remote
,&mac
) ;
1390 #ifdef LITTLE_ENDIAN
1391 phy
->phy_mib_index
= smt_swap_short((u_short
)p
+INDEX_PORT
) ;
1393 phy
->phy_mib_index
= p
+INDEX_PORT
;
1395 phy
->phy_type
= type
;
1396 phy
->phy_connect_state
= state
;
1397 phy
->phy_remote_type
= remote
;
1398 phy
->phy_remote_mac
= mac
;
1399 phy
->phy_resource_idx
= phy_con_resource_index(smc
,p
) ;
1403 pd_mac
= (struct smt_mac_rec
*) phy
;
1404 pd_mac
->mac_addr
= smc
->mib
.m
[MAC0
].fddiMACSMTAddress
;
1405 pd_mac
->mac_resource_idx
= mac_con_resource_index(smc
,1) ;
1410 * fill values in mac status
1412 static void smt_fill_mac_status(struct s_smc
*smc
, struct smt_p_mac_status
*st
)
1414 SMTSETPARA(st
,SMT_P_MAC_STATUS
) ;
1416 st
->st_mib_index
= INDEX_MAC
;
1417 st
->st_mac_index
= mac_index(smc
,1) ;
1419 mac_update_counter(smc
) ;
1421 * timer values are represented in SMT as 2's complement numbers
1422 * units : internal : 2's complement BCLK
1424 st
->st_t_req
= smc
->mib
.m
[MAC0
].fddiMACT_Req
;
1425 st
->st_t_neg
= smc
->mib
.m
[MAC0
].fddiMACT_Neg
;
1426 st
->st_t_max
= smc
->mib
.m
[MAC0
].fddiMACT_Max
;
1427 st
->st_tvx_value
= smc
->mib
.m
[MAC0
].fddiMACTvxValue
;
1428 st
->st_t_min
= smc
->mib
.m
[MAC0
].fddiMACT_Min
;
1430 st
->st_sba
= smc
->mib
.a
[PATH0
].fddiPATHSbaPayload
;
1431 st
->st_frame_ct
= smc
->mib
.m
[MAC0
].fddiMACFrame_Ct
;
1432 st
->st_error_ct
= smc
->mib
.m
[MAC0
].fddiMACError_Ct
;
1433 st
->st_lost_ct
= smc
->mib
.m
[MAC0
].fddiMACLost_Ct
;
1437 * fill values in LEM status
1439 static void smt_fill_lem(struct s_smc
*smc
, struct smt_p_lem
*lem
, int phy
)
1441 struct fddi_mib_p
*mib
;
1443 mib
= smc
->y
[phy
].mib
;
1445 SMTSETPARA(lem
,SMT_P_LEM
) ;
1446 lem
->lem_mib_index
= phy
+INDEX_PORT
;
1447 lem
->lem_phy_index
= phy_index(smc
,phy
) ;
1449 lem
->lem_cutoff
= mib
->fddiPORTLer_Cutoff
;
1450 lem
->lem_alarm
= mib
->fddiPORTLer_Alarm
;
1451 /* long term bit error rate */
1452 lem
->lem_estimate
= mib
->fddiPORTLer_Estimate
;
1453 /* # of rejected connections */
1454 lem
->lem_reject_ct
= mib
->fddiPORTLem_Reject_Ct
;
1455 lem
->lem_ct
= mib
->fddiPORTLem_Ct
; /* total number of errors */
1459 * fill version parameter
1461 static void smt_fill_version(struct s_smc
*smc
, struct smt_p_version
*vers
)
1464 SMTSETPARA(vers
,SMT_P_VERSION
) ;
1466 vers
->v_n
= 1 ; /* one version is enough .. */
1468 vers
->v_version
[0] = SMT_VID_2
;
1474 * fill frame status capabilities
1477 * note: this para 200B is NOT in swap table, because it's also set in
1480 static void smt_fill_fsc(struct s_smc
*smc
, struct smt_p_fsc
*fsc
)
1483 SMTSETPARA(fsc
,SMT_P_FSC
) ;
1485 fsc
->fsc_mac_index
= INDEX_MAC
; /* this is MIB ; MIB is NOT
1489 fsc
->fsc_value
= FSC_TYPE0
; /* "normal" node */
1490 #ifdef LITTLE_ENDIAN
1491 fsc
->fsc_mac_index
= smt_swap_short(INDEX_MAC
) ;
1492 fsc
->fsc_value
= smt_swap_short(FSC_TYPE0
) ;
1498 * fill mac counter field
1500 static void smt_fill_mac_counter(struct s_smc
*smc
, struct smt_p_mac_counter
*mc
)
1502 SMTSETPARA(mc
,SMT_P_MAC_COUNTER
) ;
1503 mc
->mc_mib_index
= INDEX_MAC
;
1504 mc
->mc_index
= mac_index(smc
,1) ;
1505 mc
->mc_receive_ct
= smc
->mib
.m
[MAC0
].fddiMACCopied_Ct
;
1506 mc
->mc_transmit_ct
= smc
->mib
.m
[MAC0
].fddiMACTransmit_Ct
;
1510 * fill mac frame not copied counter
1512 static void smt_fill_mac_fnc(struct s_smc
*smc
, struct smt_p_mac_fnc
*fnc
)
1514 SMTSETPARA(fnc
,SMT_P_MAC_FNC
) ;
1515 fnc
->nc_mib_index
= INDEX_MAC
;
1516 fnc
->nc_index
= mac_index(smc
,1) ;
1517 fnc
->nc_counter
= smc
->mib
.m
[MAC0
].fddiMACNotCopied_Ct
;
1522 * fill manufacturer field
1524 static void smt_fill_manufacturer(struct s_smc
*smc
,
1525 struct smp_p_manufacturer
*man
)
1527 SMTSETPARA(man
,SMT_P_MANUFACTURER
) ;
1528 memcpy((char *) man
->mf_data
,
1529 (char *) smc
->mib
.fddiSMTManufacturerData
,
1530 sizeof(man
->mf_data
)) ;
1536 static void smt_fill_user(struct s_smc
*smc
, struct smp_p_user
*user
)
1538 SMTSETPARA(user
,SMT_P_USER
) ;
1539 memcpy((char *) user
->us_data
,
1540 (char *) smc
->mib
.fddiSMTUserData
,
1541 sizeof(user
->us_data
)) ;
1547 static void smt_fill_setcount(struct s_smc
*smc
, struct smt_p_setcount
*setcount
)
1550 SMTSETPARA(setcount
,SMT_P_SETCOUNT
) ;
1551 setcount
->count
= smc
->mib
.fddiSMTSetCount
.count
;
1552 memcpy((char *)setcount
->timestamp
,
1553 (char *)smc
->mib
.fddiSMTSetCount
.timestamp
,8) ;
1559 static void smt_fill_echo(struct s_smc
*smc
, struct smt_p_echo
*echo
, u_long seed
,
1565 SMTSETPARA(echo
,SMT_P_ECHODATA
) ;
1566 echo
->para
.p_len
= len
;
1567 for (p
= echo
->ec_data
; len
; len
--) {
1568 *p
++ = (u_char
) seed
;
1575 * called from CFM if configuration changes
1577 void smt_clear_una_dna(struct s_smc
*smc
)
1579 smc
->mib
.m
[MAC0
].fddiMACUpstreamNbr
= SMT_Unknown
;
1580 smc
->mib
.m
[MAC0
].fddiMACDownstreamNbr
= SMT_Unknown
;
1583 static void smt_clear_old_una_dna(struct s_smc
*smc
)
1585 smc
->mib
.m
[MAC0
].fddiMACOldUpstreamNbr
= SMT_Unknown
;
1586 smc
->mib
.m
[MAC0
].fddiMACOldDownstreamNbr
= SMT_Unknown
;
1589 u_long
smt_get_tid(struct s_smc
*smc
)
1592 while ((tid
= ++(smc
->sm
.smt_tid
) ^ SMT_TID_MAGIC
) == 0)
1594 return(tid
& 0x3fffffffL
) ;
1599 * table of parameter lengths
1601 static const struct smt_pdef
{
1606 { SMT_P_UNA
, sizeof(struct smt_p_una
) ,
1608 { SMT_P_SDE
, sizeof(struct smt_p_sde
) ,
1610 { SMT_P_STATE
, sizeof(struct smt_p_state
) ,
1611 SWAP_SMT_P_STATE
} ,
1612 { SMT_P_TIMESTAMP
,sizeof(struct smt_p_timestamp
) ,
1613 SWAP_SMT_P_TIMESTAMP
} ,
1614 { SMT_P_POLICY
, sizeof(struct smt_p_policy
) ,
1615 SWAP_SMT_P_POLICY
} ,
1616 { SMT_P_LATENCY
, sizeof(struct smt_p_latency
) ,
1617 SWAP_SMT_P_LATENCY
} ,
1618 { SMT_P_NEIGHBORS
,sizeof(struct smt_p_neighbor
) ,
1619 SWAP_SMT_P_NEIGHBORS
} ,
1620 { SMT_P_PATH
, sizeof(struct smt_p_path
) ,
1622 { SMT_P_MAC_STATUS
,sizeof(struct smt_p_mac_status
) ,
1623 SWAP_SMT_P_MAC_STATUS
} ,
1624 { SMT_P_LEM
, sizeof(struct smt_p_lem
) ,
1626 { SMT_P_MAC_COUNTER
,sizeof(struct smt_p_mac_counter
) ,
1627 SWAP_SMT_P_MAC_COUNTER
} ,
1628 { SMT_P_MAC_FNC
,sizeof(struct smt_p_mac_fnc
) ,
1629 SWAP_SMT_P_MAC_FNC
} ,
1630 { SMT_P_PRIORITY
,sizeof(struct smt_p_priority
) ,
1631 SWAP_SMT_P_PRIORITY
} ,
1632 { SMT_P_EB
,sizeof(struct smt_p_eb
) ,
1634 { SMT_P_MANUFACTURER
,sizeof(struct smp_p_manufacturer
) ,
1635 SWAP_SMT_P_MANUFACTURER
} ,
1636 { SMT_P_REASON
, sizeof(struct smt_p_reason
) ,
1637 SWAP_SMT_P_REASON
} ,
1638 { SMT_P_REFUSED
, sizeof(struct smt_p_refused
) ,
1639 SWAP_SMT_P_REFUSED
} ,
1640 { SMT_P_VERSION
, sizeof(struct smt_p_version
) ,
1641 SWAP_SMT_P_VERSION
} ,
1643 { SMT_P0015
, sizeof(struct smt_p_0015
) , SWAP_SMT_P0015
} ,
1644 { SMT_P0016
, sizeof(struct smt_p_0016
) , SWAP_SMT_P0016
} ,
1645 { SMT_P0017
, sizeof(struct smt_p_0017
) , SWAP_SMT_P0017
} ,
1646 { SMT_P0018
, sizeof(struct smt_p_0018
) , SWAP_SMT_P0018
} ,
1647 { SMT_P0019
, sizeof(struct smt_p_0019
) , SWAP_SMT_P0019
} ,
1648 { SMT_P001A
, sizeof(struct smt_p_001a
) , SWAP_SMT_P001A
} ,
1649 { SMT_P001B
, sizeof(struct smt_p_001b
) , SWAP_SMT_P001B
} ,
1650 { SMT_P001C
, sizeof(struct smt_p_001c
) , SWAP_SMT_P001C
} ,
1651 { SMT_P001D
, sizeof(struct smt_p_001d
) , SWAP_SMT_P001D
} ,
1654 { SMT_P_FSC
, sizeof(struct smt_p_fsc
) ,
1658 { SMT_P_SETCOUNT
,0, SWAP_SMT_P_SETCOUNT
} ,
1659 { SMT_P1048
, 0, SWAP_SMT_P1048
} ,
1660 { SMT_P208C
, 0, SWAP_SMT_P208C
} ,
1661 { SMT_P208D
, 0, SWAP_SMT_P208D
} ,
1662 { SMT_P208E
, 0, SWAP_SMT_P208E
} ,
1663 { SMT_P208F
, 0, SWAP_SMT_P208F
} ,
1664 { SMT_P2090
, 0, SWAP_SMT_P2090
} ,
1666 { SMT_P320B
, sizeof(struct smt_p_320b
) , SWAP_SMT_P320B
} ,
1667 { SMT_P320F
, sizeof(struct smt_p_320f
) , SWAP_SMT_P320F
} ,
1668 { SMT_P3210
, sizeof(struct smt_p_3210
) , SWAP_SMT_P3210
} ,
1670 { SMT_P4050
, 0, SWAP_SMT_P4050
} ,
1671 { SMT_P4051
, 0, SWAP_SMT_P4051
} ,
1672 { SMT_P4052
, 0, SWAP_SMT_P4052
} ,
1673 { SMT_P4053
, 0, SWAP_SMT_P4053
} ,
1676 #define N_SMT_PLEN (sizeof(smt_pdef)/sizeof(smt_pdef[0]))
1678 int smt_check_para(struct s_smc
*smc
, struct smt_header
*sm
,
1679 const u_short list
[])
1681 const u_short
*p
= list
;
1683 if (!sm_to_para(smc
,sm
,(int) *p
)) {
1684 DB_SMT("SMT: smt_check_para - missing para %x\n",*p
,0);
1692 void *sm_to_para(struct s_smc
*smc
, struct smt_header
*sm
, int para
)
1702 p
= (char *)(sm
+1) ; /* pointer to info */
1704 if (((struct smt_para
*)p
)->p_type
== para
)
1705 found
= (void *) p
;
1706 plen
= ((struct smt_para
*)p
)->p_len
+ PARA_LEN
;
1710 DB_SMT("SMT : sm_to_para - length error %d\n",plen
,0) ;
1713 if ((plen
& 3) && (para
!= SMT_P_ECHODATA
)) {
1714 DB_SMT("SMT : sm_to_para - odd length %d\n",plen
,0) ;
1725 * send ANTC data test frame
1727 void fddi_send_antc(struct s_smc
*smc
, struct fddi_addr
*dest
)
1733 struct smt_header
*smt
;
1737 mb
= smt_get_mbuf() ;
1738 mb
->sm_len
= 3000+12 ;
1739 p
= smtod(mb
, char *) + 12 ;
1740 for (i
= 0 ; i
< 3000 ; i
++)
1743 smt
= smtod(mb
, struct smt_header
*) ;
1744 smt
->smt_dest
= *dest
;
1745 smt
->smt_source
= smc
->mib
.m
[MAC0
].fddiMACSMTAddress
;
1746 smt_send_mbuf(smc
,mb
,FC_ASYNC_LLC
) ;
1752 #define hextoasc(x) "0123456789abcdef"[x]
1754 char *addr_to_string(struct fddi_addr
*addr
)
1757 static char string
[6*3] = "****" ;
1759 for (i
= 0 ; i
< 6 ; i
++) {
1760 string
[i
*3] = hextoasc((addr
->a
[i
]>>4)&0xf) ;
1761 string
[i
*3+1] = hextoasc((addr
->a
[i
])&0xf) ;
1762 string
[i
*3+2] = ':' ;
1770 smt_ifconfig(int argc
, char *argv
[])
1772 if (argc
>= 2 && !strcmp(argv
[0],"opt_bypass") &&
1773 !strcmp(argv
[1],"yes")) {
1774 smc
->mib
.fddiSMTBypassPresent
= 1 ;
1777 return(amdfddi_config(0,argc
,argv
)) ;
1782 * return static mac index
1784 static int mac_index(struct s_smc
*smc
, int mac
)
1791 return((smc
->s
.sas
== SMT_SAS
) ? 2 : 3) ;
1796 * return static phy index
1798 static int phy_index(struct s_smc
*smc
, int phy
)
1805 * return dynamic mac connection resource index
1807 static int mac_con_resource_index(struct s_smc
*smc
, int mac
)
1812 return(entity_to_index(smc
,cem_get_downstream(smc
,ENTITY_MAC
))) ;
1815 switch (smc
->mib
.fddiSMTCF_State
) {
1818 case SC11_C_WRAP_S
:
1820 case SC10_C_WRAP_B
:
1824 return(smc
->s
.sas
== SMT_SAS
? 2 : 3) ;
1829 * return dynamic phy connection resource index
1831 static int phy_con_resource_index(struct s_smc
*smc
, int phy
)
1834 return(entity_to_index(smc
,cem_get_downstream(smc
,ENTITY_PHY(phy
)))) ;
1836 switch (smc
->mib
.fddiSMTCF_State
) {
1838 return(phy
== PA
? 3 : 2) ;
1839 case SC10_C_WRAP_B
:
1840 return(phy
== PA
? 1 : 3) ;
1842 return(phy
== PA
? 3 : 1) ;
1844 return(phy
== PA
? 2 : 3) ;
1845 case SC11_C_WRAP_S
:
1853 static int entity_to_index(struct s_smc
*smc
, int e
)
1855 if (e
== ENTITY_MAC
)
1856 return(mac_index(smc
,1)) ;
1858 return(phy_index(smc
,e
- ENTITY_PHY(0))) ;
1862 #ifdef LITTLE_ENDIAN
1863 static int smt_swap_short(u_short s
)
1865 return(((s
>>8)&0xff)|((s
&0xff)<<8)) ;
1868 void smt_swap_para(struct smt_header
*sm
, int len
, int direction
)
1869 /* int direction; 0 encode 1 decode */
1871 struct smt_para
*pa
;
1872 const struct smt_pdef
*pd
;
1878 /* printf("smt_swap_para sm %x len %d dir %d\n",
1881 smt_string_swap((char *)sm
,SWAP_SMTHEADER
,len
) ;
1884 len
-= sizeof(struct smt_header
) ;
1886 p
= (char *) (sm
+ 1) ;
1888 pa
= (struct smt_para
*) p
;
1891 pa
->p_type
= smt_swap_short(pa
->p_type
) ;
1892 pa
->p_len
= smt_swap_short(pa
->p_len
) ;
1898 * note: paras can have 0 length !
1903 for (i
= N_SMT_PLEN
, pd
= smt_pdef
; i
; i
--,pd
++) {
1904 if (pd
->ptype
== type
)
1907 if (i
&& pd
->pswap
) {
1908 smt_string_swap(p
+PARA_LEN
,pd
->pswap
,len
) ;
1915 static void smt_string_swap(char *data
, const char *format
, int len
)
1917 const char *open_paren
= 0 ;
1920 while (len
> 0 && *format
) {
1923 open_paren
= format
;
1926 format
= open_paren
;
1937 data
+= *format
- '0' ;
1938 len
-= *format
- '0' ;
1966 void smt_swap_para(struct smt_header
*sm
, int len
, int direction
)
1967 /* int direction; 0 encode 1 decode */
1971 SK_UNUSED(direction
) ;
1978 int smt_action(struct s_smc
*smc
, int class, int code
, int index
)
1982 DB_SMT("SMT: action %d code %d\n",class,code
) ;
1984 case SMT_STATION_ACTION
:
1986 case SMT_STATION_ACTION_CONNECT
:
1987 smc
->mib
.fddiSMTRemoteDisconnectFlag
= FALSE
;
1988 queue_event(smc
,EVENT_ECM
,EC_CONNECT
) ;
1990 case SMT_STATION_ACTION_DISCONNECT
:
1991 queue_event(smc
,EVENT_ECM
,EC_DISCONNECT
) ;
1992 smc
->mib
.fddiSMTRemoteDisconnectFlag
= TRUE
;
1993 RS_SET(smc
,RS_DISCONNECT
) ;
1994 AIX_EVENT(smc
, (u_long
) FDDI_RING_STATUS
, (u_long
)
1995 FDDI_SMT_EVENT
, (u_long
) FDDI_REMOTE_DISCONNECT
,
1996 smt_get_event_word(smc
));
1998 case SMT_STATION_ACTION_PATHTEST
:
1999 AIX_EVENT(smc
, (u_long
) FDDI_RING_STATUS
, (u_long
)
2000 FDDI_SMT_EVENT
, (u_long
) FDDI_PATH_TEST
,
2001 smt_get_event_word(smc
));
2003 case SMT_STATION_ACTION_SELFTEST
:
2004 AIX_EVENT(smc
, (u_long
) FDDI_RING_STATUS
, (u_long
)
2005 FDDI_SMT_EVENT
, (u_long
) FDDI_REMOTE_SELF_TEST
,
2006 smt_get_event_word(smc
));
2008 case SMT_STATION_ACTION_DISABLE_A
:
2009 if (smc
->y
[PA
].pc_mode
== PM_PEER
) {
2010 RS_SET(smc
,RS_EVENT
) ;
2011 queue_event(smc
,EVENT_PCM
+PA
,PC_DISABLE
) ;
2014 case SMT_STATION_ACTION_DISABLE_B
:
2015 if (smc
->y
[PB
].pc_mode
== PM_PEER
) {
2016 RS_SET(smc
,RS_EVENT
) ;
2017 queue_event(smc
,EVENT_PCM
+PB
,PC_DISABLE
) ;
2020 case SMT_STATION_ACTION_DISABLE_M
:
2021 for (port
= 0 ; port
< NUMPHYS
; port
++) {
2022 if (smc
->mib
.p
[port
].fddiPORTMy_Type
!= TM
)
2024 RS_SET(smc
,RS_EVENT
) ;
2025 queue_event(smc
,EVENT_PCM
+port
,PC_DISABLE
) ;
2032 case SMT_PORT_ACTION
:
2034 case SMT_PORT_ACTION_ENABLE
:
2037 case SMT_PORT_ACTION_DISABLE
:
2038 event
= PC_DISABLE
;
2040 case SMT_PORT_ACTION_MAINT
:
2043 case SMT_PORT_ACTION_START
:
2046 case SMT_PORT_ACTION_STOP
:
2052 queue_event(smc
,EVENT_PCM
+index
,event
) ;
2062 * set T_Req in MIB (Path Attribute)
2063 * calculate new values for MAC
2064 * if change required
2069 void smt_change_t_neg(struct s_smc
*smc
, u_long tneg
)
2071 smc
->mib
.a
[PATH0
].fddiPATHMaxT_Req
= tneg
;
2073 if (smt_set_mac_opvalues(smc
)) {
2074 RS_SET(smc
,RS_EVENT
) ;
2075 smc
->sm
.please_reconnect
= 1 ;
2076 queue_event(smc
,EVENT_ECM
,EC_DISCONNECT
) ;
2081 * canonical conversion of <len> bytes beginning form *data
2084 void hwm_conv_can(struct s_smc
*smc
, char *data
, int len
)
2090 for (i
= len
; i
; i
--, data
++) {
2091 *data
= canonical
[*(u_char
*)data
] ;
2096 #endif /* no SLIM_SMT */