1 /****************************************************************************** 2 * 3 * (C)Copyright 1998,1999 SysKonnect, 4 * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 5 * 6 * See the file "skfddi.c" for further information. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * The information in this file is provided "AS IS" without warranty. 14 * 15 ******************************************************************************/ 16 17 #include "h/types.h" 18 #include "h/fddi.h" 19 #include "h/smc.h" 20 #include "h/smt_p.h" 21 #include <linux/bitrev.h> 22 #include <linux/kernel.h> 23 24 #define KERNEL 25 #include "h/smtstate.h" 26 27 #ifndef lint 28 static const char ID_sccs[] = "@(#)smt.c 2.43 98/11/23 (C) SK " ; 29 #endif 30 31 /* 32 * FC in SMbuf 33 */ 34 #define m_fc(mb) ((mb)->sm_data[0]) 35 36 #define SMT_TID_MAGIC 0x1f0a7b3c 37 38 static const char *const smt_type_name[] = { 39 "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??", 40 "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??", 41 "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??", 42 "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA" 43 } ; 44 45 static const char *const smt_class_name[] = { 46 "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF", 47 "SRF","PMF_GET","PMF_SET","ESF" 48 } ; 49 50 #define LAST_CLASS (SMT_PMF_SET) 51 52 static const struct fddi_addr SMT_Unknown = { 53 { 0,0,0x1f,0,0,0 } 54 } ; 55 56 /* 57 * function prototypes 58 */ 59 #ifdef LITTLE_ENDIAN 60 static int smt_swap_short(u_short s); 61 #endif 62 static int mac_index(struct s_smc *smc, int mac); 63 static int phy_index(struct s_smc *smc, int phy); 64 static int mac_con_resource_index(struct s_smc *smc, int mac); 65 static int phy_con_resource_index(struct s_smc *smc, int phy); 66 static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, 67 int local); 68 static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 69 int fc, u_long tid, int type, int local); 70 static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, 71 u_long tid, int type, int len); 72 static void smt_echo_test(struct s_smc *smc, int dna); 73 static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, 74 u_long tid, int local); 75 static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, 76 u_long tid, int local); 77 #ifdef LITTLE_ENDIAN 78 static void smt_string_swap(char *data, const char *format, int len); 79 #endif 80 static void smt_add_frame_len(SMbuf *mb, int len); 81 static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una); 82 static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde); 83 static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state); 84 static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts); 85 static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy); 86 static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency); 87 static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor); 88 static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path); 89 static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st); 90 static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy); 91 static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers); 92 static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc); 93 static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc); 94 static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc); 95 static void smt_fill_manufacturer(struct s_smc *smc, 96 struct smp_p_manufacturer *man); 97 static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user); 98 static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount); 99 static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, 100 int len); 101 102 static void smt_clear_una_dna(struct s_smc *smc); 103 static void smt_clear_old_una_dna(struct s_smc *smc); 104 #ifdef CONCENTRATOR 105 static int entity_to_index(void); 106 #endif 107 static void update_dac(struct s_smc *smc, int report); 108 static int div_ratio(u_long upper, u_long lower); 109 #ifdef USE_CAN_ADDR 110 static void hwm_conv_can(struct s_smc *smc, char *data, int len); 111 #else 112 #define hwm_conv_can(smc,data,len) 113 #endif 114 115 116 static inline int is_my_addr(const struct s_smc *smc, 117 const struct fddi_addr *addr) 118 { 119 return(*(short *)(&addr->a[0]) == 120 *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0]) 121 && *(short *)(&addr->a[2]) == 122 *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2]) 123 && *(short *)(&addr->a[4]) == 124 *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ; 125 } 126 127 static inline int is_broadcast(const struct fddi_addr *addr) 128 { 129 return *(u_short *)(&addr->a[0]) == 0xffff && 130 *(u_short *)(&addr->a[2]) == 0xffff && 131 *(u_short *)(&addr->a[4]) == 0xffff; 132 } 133 134 static inline int is_individual(const struct fddi_addr *addr) 135 { 136 return !(addr->a[0] & GROUP_ADDR); 137 } 138 139 static inline int is_equal(const struct fddi_addr *addr1, 140 const struct fddi_addr *addr2) 141 { 142 return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) && 143 *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) && 144 *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]); 145 } 146 147 /* 148 * list of mandatory paras in frames 149 */ 150 static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ; 151 152 /* 153 * init SMT agent 154 */ 155 void smt_agent_init(struct s_smc *smc) 156 { 157 int i ; 158 159 /* 160 * get MAC address 161 */ 162 smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ; 163 164 /* 165 * get OUI address from driver (bia == built-in-address) 166 */ 167 smc->mib.fddiSMTStationId.sid_oem[0] = 0 ; 168 smc->mib.fddiSMTStationId.sid_oem[1] = 0 ; 169 driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ; 170 for (i = 0 ; i < 6 ; i ++) { 171 smc->mib.fddiSMTStationId.sid_node.a[i] = 172 bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]); 173 } 174 smc->mib.fddiSMTManufacturerData[0] = 175 smc->mib.fddiSMTStationId.sid_node.a[0] ; 176 smc->mib.fddiSMTManufacturerData[1] = 177 smc->mib.fddiSMTStationId.sid_node.a[1] ; 178 smc->mib.fddiSMTManufacturerData[2] = 179 smc->mib.fddiSMTStationId.sid_node.a[2] ; 180 smc->sm.smt_tid = 0 ; 181 smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ; 182 smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ; 183 #ifndef SLIM_SMT 184 smt_clear_una_dna(smc) ; 185 smt_clear_old_una_dna(smc) ; 186 #endif 187 for (i = 0 ; i < SMT_MAX_TEST ; i++) 188 smc->sm.pend[i] = 0 ; 189 smc->sm.please_reconnect = 0 ; 190 smc->sm.uniq_ticks = 0 ; 191 } 192 193 /* 194 * SMT task 195 * forever 196 * delay 30 seconds 197 * send NIF 198 * check tvu & tvd 199 * end 200 */ 201 void smt_agent_task(struct s_smc *smc) 202 { 203 smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, 204 EV_TOKEN(EVENT_SMT,SM_TIMER)) ; 205 DB_SMT("SMT agent task"); 206 } 207 208 #ifndef SMT_REAL_TOKEN_CT 209 void smt_emulate_token_ct(struct s_smc *smc, int mac_index) 210 { 211 u_long count; 212 u_long time; 213 214 215 time = smt_get_time(); 216 count = ((time - smc->sm.last_tok_time[mac_index]) * 217 100)/TICKS_PER_SECOND; 218 219 /* 220 * Only when ring is up we will have a token count. The 221 * flag is unfortunately a single instance value. This 222 * doesn't matter now, because we currently have only 223 * one MAC instance. 224 */ 225 if (smc->hw.mac_ring_is_up){ 226 smc->mib.m[mac_index].fddiMACToken_Ct += count; 227 } 228 229 /* Remember current time */ 230 smc->sm.last_tok_time[mac_index] = time; 231 232 } 233 #endif 234 235 /*ARGSUSED1*/ 236 void smt_event(struct s_smc *smc, int event) 237 { 238 u_long time ; 239 #ifndef SMT_REAL_TOKEN_CT 240 int i ; 241 #endif 242 243 244 if (smc->sm.please_reconnect) { 245 smc->sm.please_reconnect -- ; 246 if (smc->sm.please_reconnect == 0) { 247 /* Counted down */ 248 queue_event(smc,EVENT_ECM,EC_CONNECT) ; 249 } 250 } 251 252 if (event == SM_FAST) 253 return ; 254 255 /* 256 * timer for periodic cleanup in driver 257 * reset and start the watchdog (FM2) 258 * ESS timer 259 * SBA timer 260 */ 261 smt_timer_poll(smc) ; 262 smt_start_watchdog(smc) ; 263 #ifndef SLIM_SMT 264 #ifndef BOOT 265 #ifdef ESS 266 ess_timer_poll(smc) ; 267 #endif 268 #endif 269 #ifdef SBA 270 sba_timer_poll(smc) ; 271 #endif 272 273 smt_srf_event(smc,0,0,0) ; 274 275 #endif /* no SLIM_SMT */ 276 277 time = smt_get_time() ; 278 279 if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) { 280 /* 281 * Use 8 sec. for the time intervall, it simplifies the 282 * LER estimation. 283 */ 284 struct fddi_mib_m *mib ; 285 u_long upper ; 286 u_long lower ; 287 int cond ; 288 int port; 289 struct s_phy *phy ; 290 /* 291 * calculate LEM bit error rate 292 */ 293 sm_lem_evaluate(smc) ; 294 smc->sm.smt_last_lem = time ; 295 296 /* 297 * check conditions 298 */ 299 #ifndef SLIM_SMT 300 mac_update_counter(smc) ; 301 mib = smc->mib.m ; 302 upper = 303 (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) + 304 (mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ; 305 lower = 306 (mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) + 307 (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ; 308 mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ; 309 310 cond = 311 ((!mib->fddiMACFrameErrorThreshold && 312 mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) || 313 (mib->fddiMACFrameErrorRatio > 314 mib->fddiMACFrameErrorThreshold)) ; 315 316 if (cond != mib->fddiMACFrameErrorFlag) 317 smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR, 318 INDEX_MAC,cond) ; 319 320 upper = 321 (mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ; 322 lower = 323 upper + 324 (mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ; 325 mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ; 326 327 cond = 328 ((!mib->fddiMACNotCopiedThreshold && 329 mib->fddiMACNotCopied_Ct != 330 mib->fddiMACOld_NotCopied_Ct)|| 331 (mib->fddiMACNotCopiedRatio > 332 mib->fddiMACNotCopiedThreshold)) ; 333 334 if (cond != mib->fddiMACNotCopiedFlag) 335 smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED, 336 INDEX_MAC,cond) ; 337 338 /* 339 * set old values 340 */ 341 mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ; 342 mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ; 343 mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ; 344 mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ; 345 mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ; 346 347 /* 348 * Check port EBError Condition 349 */ 350 for (port = 0; port < NUMPHYS; port ++) { 351 phy = &smc->y[port] ; 352 353 if (!phy->mib->fddiPORTHardwarePresent) { 354 continue; 355 } 356 357 cond = (phy->mib->fddiPORTEBError_Ct - 358 phy->mib->fddiPORTOldEBError_Ct > 5) ; 359 360 /* If ratio is more than 5 in 8 seconds 361 * Set the condition. 362 */ 363 smt_srf_event(smc,SMT_COND_PORT_EB_ERROR, 364 (int) (INDEX_PORT+ phy->np) ,cond) ; 365 366 /* 367 * set old values 368 */ 369 phy->mib->fddiPORTOldEBError_Ct = 370 phy->mib->fddiPORTEBError_Ct ; 371 } 372 373 #endif /* no SLIM_SMT */ 374 } 375 376 #ifndef SLIM_SMT 377 378 if (time - smc->sm.smt_last_notify >= (u_long) 379 (smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) { 380 /* 381 * we can either send an announcement or a request 382 * a request will trigger a reply so that we can update 383 * our dna 384 * note: same tid must be used until reply is received 385 */ 386 if (!smc->sm.pend[SMT_TID_NIF]) 387 smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ; 388 smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA, 389 smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ; 390 smc->sm.smt_last_notify = time ; 391 } 392 393 /* 394 * check timer 395 */ 396 if (smc->sm.smt_tvu && 397 time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) { 398 DB_SMT("SMT : UNA expired"); 399 smc->sm.smt_tvu = 0 ; 400 401 if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr, 402 &SMT_Unknown)){ 403 /* Do not update unknown address */ 404 smc->mib.m[MAC0].fddiMACOldUpstreamNbr= 405 smc->mib.m[MAC0].fddiMACUpstreamNbr ; 406 } 407 smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; 408 smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ; 409 /* 410 * Make sure the fddiMACUNDA_Flag = FALSE is 411 * included in the SRF so we don't generate 412 * a separate SRF for the deassertion of this 413 * condition 414 */ 415 update_dac(smc,0) ; 416 smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE, 417 INDEX_MAC,0) ; 418 } 419 if (smc->sm.smt_tvd && 420 time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) { 421 DB_SMT("SMT : DNA expired"); 422 smc->sm.smt_tvd = 0 ; 423 if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr, 424 &SMT_Unknown)){ 425 /* Do not update unknown address */ 426 smc->mib.m[MAC0].fddiMACOldDownstreamNbr= 427 smc->mib.m[MAC0].fddiMACDownstreamNbr ; 428 } 429 smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; 430 smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE, 431 INDEX_MAC,0) ; 432 } 433 434 #endif /* no SLIM_SMT */ 435 436 #ifndef SMT_REAL_TOKEN_CT 437 /* 438 * Token counter emulation section. If hardware supports the token 439 * count, the token counter will be updated in mac_update_counter. 440 */ 441 for (i = MAC0; i < NUMMACS; i++ ){ 442 if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){ 443 smt_emulate_token_ct( smc, i ); 444 } 445 } 446 #endif 447 448 smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L, 449 EV_TOKEN(EVENT_SMT,SM_TIMER)) ; 450 } 451 452 static int div_ratio(u_long upper, u_long lower) 453 { 454 if ((upper<<16L) < upper) 455 upper = 0xffff0000L ; 456 else 457 upper <<= 16L ; 458 if (!lower) 459 return 0; 460 return (int)(upper/lower) ; 461 } 462 463 #ifndef SLIM_SMT 464 465 /* 466 * receive packet handler 467 */ 468 void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs) 469 /* int fs; frame status */ 470 { 471 struct smt_header *sm ; 472 int local ; 473 474 int illegal = 0 ; 475 476 switch (m_fc(mb)) { 477 case FC_SMT_INFO : 478 case FC_SMT_LAN_LOC : 479 case FC_SMT_LOC : 480 case FC_SMT_NSA : 481 break ; 482 default : 483 smt_free_mbuf(smc,mb) ; 484 return ; 485 } 486 487 smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ; 488 sm = smtod(mb,struct smt_header *) ; 489 local = ((fs & L_INDICATOR) != 0) ; 490 hwm_conv_can(smc,(char *)sm,12) ; 491 492 /* check destination address */ 493 if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) { 494 smt_free_mbuf(smc,mb) ; 495 return ; 496 } 497 #if 0 /* for DUP recognition, do NOT filter them */ 498 /* ignore loop back packets */ 499 if (is_my_addr(smc,&sm->smt_source) && !local) { 500 smt_free_mbuf(smc,mb) ; 501 return ; 502 } 503 #endif 504 505 smt_swap_para(sm,(int) mb->sm_len,1) ; 506 DB_SMT("SMT : received packet [%s] at 0x%p", 507 smt_type_name[m_fc(mb) & 0xf], sm); 508 DB_SMT("SMT : version %d, class %s", 509 sm->smt_version, 510 smt_class_name[sm->smt_class > LAST_CLASS ? 0 : sm->smt_class]); 511 512 #ifdef SBA 513 /* 514 * check if NSA frame 515 */ 516 if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF && 517 (sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) { 518 smc->sba.sm = sm ; 519 sba(smc,NIF) ; 520 } 521 #endif 522 523 /* 524 * ignore any packet with NSA and A-indicator set 525 */ 526 if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) { 527 DB_SMT("SMT : ignoring NSA with A-indicator set from %s", 528 addr_to_string(&sm->smt_source)); 529 smt_free_mbuf(smc,mb) ; 530 return ; 531 } 532 533 /* 534 * ignore frames with illegal length 535 */ 536 if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) || 537 ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) { 538 smt_free_mbuf(smc,mb) ; 539 return ; 540 } 541 542 /* 543 * check SMT version 544 */ 545 switch (sm->smt_class) { 546 case SMT_NIF : 547 case SMT_SIF_CONFIG : 548 case SMT_SIF_OPER : 549 case SMT_ECF : 550 if (sm->smt_version != SMT_VID) 551 illegal = 1; 552 break ; 553 default : 554 if (sm->smt_version != SMT_VID_2) 555 illegal = 1; 556 break ; 557 } 558 if (illegal) { 559 DB_SMT("SMT : version = %d, dest = %s", 560 sm->smt_version, addr_to_string(&sm->smt_source)); 561 smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ; 562 smt_free_mbuf(smc,mb) ; 563 return ; 564 } 565 if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) || 566 ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) { 567 DB_SMT("SMT: info length error, len = %d", sm->smt_len); 568 smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ; 569 smt_free_mbuf(smc,mb) ; 570 return ; 571 } 572 switch (sm->smt_class) { 573 case SMT_NIF : 574 if (smt_check_para(smc,sm,plist_nif)) { 575 DB_SMT("SMT: NIF with para problem, ignoring"); 576 break ; 577 } 578 switch (sm->smt_type) { 579 case SMT_ANNOUNCE : 580 case SMT_REQUEST : 581 if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA 582 && is_broadcast(&sm->smt_dest)) { 583 struct smt_p_state *st ; 584 585 /* set my UNA */ 586 if (!is_equal( 587 &smc->mib.m[MAC0].fddiMACUpstreamNbr, 588 &sm->smt_source)) { 589 DB_SMT("SMT : updated my UNA = %s", 590 addr_to_string(&sm->smt_source)); 591 if (!is_equal(&smc->mib.m[MAC0]. 592 fddiMACUpstreamNbr,&SMT_Unknown)){ 593 /* Do not update unknown address */ 594 smc->mib.m[MAC0].fddiMACOldUpstreamNbr= 595 smc->mib.m[MAC0].fddiMACUpstreamNbr ; 596 } 597 598 smc->mib.m[MAC0].fddiMACUpstreamNbr = 599 sm->smt_source ; 600 smt_srf_event(smc, 601 SMT_EVENT_MAC_NEIGHBOR_CHANGE, 602 INDEX_MAC,0) ; 603 smt_echo_test(smc,0) ; 604 } 605 smc->sm.smt_tvu = smt_get_time() ; 606 st = (struct smt_p_state *) 607 sm_to_para(smc,sm,SMT_P_STATE) ; 608 if (st) { 609 smc->mib.m[MAC0].fddiMACUNDA_Flag = 610 (st->st_dupl_addr & SMT_ST_MY_DUPA) ? 611 TRUE : FALSE ; 612 update_dac(smc,1) ; 613 } 614 } 615 if ((sm->smt_type == SMT_REQUEST) && 616 is_individual(&sm->smt_source) && 617 ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) || 618 (m_fc(mb) != FC_SMT_NSA))) { 619 DB_SMT("SMT : replying to NIF request %s", 620 addr_to_string(&sm->smt_source)); 621 smt_send_nif(smc,&sm->smt_source, 622 FC_SMT_INFO, 623 sm->smt_tid, 624 SMT_REPLY,local) ; 625 } 626 break ; 627 case SMT_REPLY : 628 DB_SMT("SMT : received NIF response from %s", 629 addr_to_string(&sm->smt_source)); 630 if (fs & A_INDICATOR) { 631 smc->sm.pend[SMT_TID_NIF] = 0 ; 632 DB_SMT("SMT : duplicate address"); 633 smc->mib.m[MAC0].fddiMACDupAddressTest = 634 DA_FAILED ; 635 smc->r.dup_addr_test = DA_FAILED ; 636 queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; 637 smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ; 638 update_dac(smc,1) ; 639 break ; 640 } 641 if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) { 642 smc->sm.pend[SMT_TID_NIF] = 0 ; 643 /* set my DNA */ 644 if (!is_equal( 645 &smc->mib.m[MAC0].fddiMACDownstreamNbr, 646 &sm->smt_source)) { 647 DB_SMT("SMT : updated my DNA"); 648 if (!is_equal(&smc->mib.m[MAC0]. 649 fddiMACDownstreamNbr, &SMT_Unknown)){ 650 /* Do not update unknown address */ 651 smc->mib.m[MAC0].fddiMACOldDownstreamNbr = 652 smc->mib.m[MAC0].fddiMACDownstreamNbr ; 653 } 654 655 smc->mib.m[MAC0].fddiMACDownstreamNbr = 656 sm->smt_source ; 657 smt_srf_event(smc, 658 SMT_EVENT_MAC_NEIGHBOR_CHANGE, 659 INDEX_MAC,0) ; 660 smt_echo_test(smc,1) ; 661 } 662 smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ; 663 update_dac(smc,1) ; 664 smc->sm.smt_tvd = smt_get_time() ; 665 smc->mib.m[MAC0].fddiMACDupAddressTest = 666 DA_PASSED ; 667 if (smc->r.dup_addr_test != DA_PASSED) { 668 smc->r.dup_addr_test = DA_PASSED ; 669 queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ; 670 } 671 } 672 else if (sm->smt_tid == 673 smc->sm.pend[SMT_TID_NIF_TEST]) { 674 DB_SMT("SMT : NIF test TID ok"); 675 } 676 else { 677 DB_SMT("SMT : expected TID %lx, got %x", 678 smc->sm.pend[SMT_TID_NIF], sm->smt_tid); 679 } 680 break ; 681 default : 682 illegal = 2 ; 683 break ; 684 } 685 break ; 686 case SMT_SIF_CONFIG : /* station information */ 687 if (sm->smt_type != SMT_REQUEST) 688 break ; 689 DB_SMT("SMT : replying to SIF Config request from %s", 690 addr_to_string(&sm->smt_source)); 691 smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ; 692 break ; 693 case SMT_SIF_OPER : /* station information */ 694 if (sm->smt_type != SMT_REQUEST) 695 break ; 696 DB_SMT("SMT : replying to SIF Operation request from %s", 697 addr_to_string(&sm->smt_source)); 698 smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ; 699 break ; 700 case SMT_ECF : /* echo frame */ 701 switch (sm->smt_type) { 702 case SMT_REPLY : 703 smc->mib.priv.fddiPRIVECF_Reply_Rx++ ; 704 DB_SMT("SMT: received ECF reply from %s", 705 addr_to_string(&sm->smt_source)); 706 if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) { 707 DB_SMT("SMT: ECHODATA missing"); 708 break ; 709 } 710 if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) { 711 DB_SMT("SMT : ECF test TID ok"); 712 } 713 else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) { 714 DB_SMT("SMT : ECF test UNA ok"); 715 } 716 else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) { 717 DB_SMT("SMT : ECF test DNA ok"); 718 } 719 else { 720 DB_SMT("SMT : expected TID %lx, got %x", 721 smc->sm.pend[SMT_TID_ECF], 722 sm->smt_tid); 723 } 724 break ; 725 case SMT_REQUEST : 726 smc->mib.priv.fddiPRIVECF_Req_Rx++ ; 727 { 728 if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) { 729 DB_SMT("SMT: ECF with para problem,sending RDF"); 730 smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH, 731 local) ; 732 break ; 733 } 734 DB_SMT("SMT - sending ECF reply to %s", 735 addr_to_string(&sm->smt_source)); 736 737 /* set destination addr. & reply */ 738 sm->smt_dest = sm->smt_source ; 739 sm->smt_type = SMT_REPLY ; 740 dump_smt(smc,sm,"ECF REPLY") ; 741 smc->mib.priv.fddiPRIVECF_Reply_Tx++ ; 742 smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 743 return ; /* DON'T free mbuf */ 744 } 745 default : 746 illegal = 1 ; 747 break ; 748 } 749 break ; 750 #ifndef BOOT 751 case SMT_RAF : /* resource allocation */ 752 #ifdef ESS 753 DB_ESSN(2, "ESS: RAF frame received"); 754 fs = ess_raf_received_pack(smc,mb,sm,fs) ; 755 #endif 756 757 #ifdef SBA 758 DB_SBAN(2,"SBA: RAF frame received\n",0,0) ; 759 sba_raf_received_pack(smc,sm,fs) ; 760 #endif 761 break ; 762 case SMT_RDF : /* request denied */ 763 smc->mib.priv.fddiPRIVRDF_Rx++ ; 764 break ; 765 case SMT_ESF : /* extended service - not supported */ 766 if (sm->smt_type == SMT_REQUEST) { 767 DB_SMT("SMT - received ESF, sending RDF"); 768 smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ; 769 } 770 break ; 771 case SMT_PMF_GET : 772 case SMT_PMF_SET : 773 if (sm->smt_type != SMT_REQUEST) 774 break ; 775 /* update statistics */ 776 if (sm->smt_class == SMT_PMF_GET) 777 smc->mib.priv.fddiPRIVPMF_Get_Rx++ ; 778 else 779 smc->mib.priv.fddiPRIVPMF_Set_Rx++ ; 780 /* 781 * ignore PMF SET with I/G set 782 */ 783 if ((sm->smt_class == SMT_PMF_SET) && 784 !is_individual(&sm->smt_dest)) { 785 DB_SMT("SMT: ignoring PMF-SET with I/G set"); 786 break ; 787 } 788 smt_pmf_received_pack(smc,mb, local) ; 789 break ; 790 case SMT_SRF : 791 dump_smt(smc,sm,"SRF received") ; 792 break ; 793 default : 794 if (sm->smt_type != SMT_REQUEST) 795 break ; 796 /* 797 * For frames with unknown class: 798 * we need to send a RDF frame according to 8.1.3.1.1, 799 * only if it is a REQUEST. 800 */ 801 DB_SMT("SMT : class = %d, send RDF to %s", 802 sm->smt_class, addr_to_string(&sm->smt_source)); 803 804 smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ; 805 break ; 806 #endif 807 } 808 if (illegal) { 809 DB_SMT("SMT: discarding invalid frame, reason = %d", illegal); 810 } 811 smt_free_mbuf(smc,mb) ; 812 } 813 814 static void update_dac(struct s_smc *smc, int report) 815 { 816 int cond ; 817 818 cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag | 819 smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ; 820 if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond)) 821 smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ; 822 else 823 smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ; 824 } 825 826 /* 827 * send SMT frame 828 * set source address 829 * set station ID 830 * send frame 831 */ 832 void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local) 833 /* SMbuf *mb; buffer to send */ 834 /* int fc; FC value */ 835 { 836 struct smt_header *sm ; 837 838 if (!smc->r.sm_ma_avail && !local) { 839 smt_free_mbuf(smc,mb) ; 840 return ; 841 } 842 sm = smtod(mb,struct smt_header *) ; 843 sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ; 844 sm->smt_sid = smc->mib.fddiSMTStationId ; 845 846 smt_swap_para(sm,(int) mb->sm_len,0) ; /* swap para & header */ 847 hwm_conv_can(smc,(char *)sm,12) ; /* convert SA and DA */ 848 smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ; 849 smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ; 850 } 851 852 /* 853 * generate and send RDF 854 */ 855 static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason, 856 int local) 857 /* SMbuf *rej; mbuf of offending frame */ 858 /* int fc; FC of denied frame */ 859 /* int reason; reason code */ 860 { 861 SMbuf *mb ; 862 struct smt_header *sm ; /* header of offending frame */ 863 struct smt_rdf *rdf ; 864 int len ; 865 int frame_len ; 866 867 sm = smtod(rej,struct smt_header *) ; 868 if (sm->smt_type != SMT_REQUEST) 869 return ; 870 871 DB_SMT("SMT: sending RDF to %s,reason = 0x%x", 872 addr_to_string(&sm->smt_source), reason); 873 874 875 /* 876 * note: get framelength from MAC length, NOT from SMT header 877 * smt header length is included in sm_len 878 */ 879 frame_len = rej->sm_len ; 880 881 if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf)))) 882 return ; 883 rdf = smtod(mb,struct smt_rdf *) ; 884 rdf->smt.smt_tid = sm->smt_tid ; /* use TID from sm */ 885 rdf->smt.smt_dest = sm->smt_source ; /* set dest = source */ 886 887 /* set P12 */ 888 rdf->reason.para.p_type = SMT_P_REASON ; 889 rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ; 890 rdf->reason.rdf_reason = reason ; 891 892 /* set P14 */ 893 rdf->version.para.p_type = SMT_P_VERSION ; 894 rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ; 895 rdf->version.v_pad = 0 ; 896 rdf->version.v_n = 1 ; 897 rdf->version.v_index = 1 ; 898 rdf->version.v_version[0] = SMT_VID_2 ; 899 rdf->version.v_pad2 = 0 ; 900 901 /* set P13 */ 902 if ((unsigned int) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) + 903 2*sizeof(struct smt_header)) 904 len = frame_len ; 905 else 906 len = SMT_MAX_INFO_LEN - sizeof(*rdf) + 907 2*sizeof(struct smt_header) ; 908 /* make length multiple of 4 */ 909 len &= ~3 ; 910 rdf->refused.para.p_type = SMT_P_REFUSED ; 911 /* length of para is smt_frame + ref_fc */ 912 rdf->refused.para.p_len = len + 4 ; 913 rdf->refused.ref_fc = fc ; 914 915 /* swap it back */ 916 smt_swap_para(sm,frame_len,0) ; 917 918 memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ; 919 920 len -= sizeof(struct smt_header) ; 921 mb->sm_len += len ; 922 rdf->smt.smt_len += len ; 923 924 dump_smt(smc,(struct smt_header *)rdf,"RDF") ; 925 smc->mib.priv.fddiPRIVRDF_Tx++ ; 926 smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 927 } 928 929 /* 930 * generate and send NIF 931 */ 932 static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 933 int fc, u_long tid, int type, int local) 934 /* struct fddi_addr *dest; dest address */ 935 /* int fc; frame control */ 936 /* u_long tid; transaction id */ 937 /* int type; frame type */ 938 { 939 struct smt_nif *nif ; 940 SMbuf *mb ; 941 942 if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif)))) 943 return ; 944 nif = smtod(mb, struct smt_nif *) ; 945 smt_fill_una(smc,&nif->una) ; /* set UNA */ 946 smt_fill_sde(smc,&nif->sde) ; /* set station descriptor */ 947 smt_fill_state(smc,&nif->state) ; /* set state information */ 948 #ifdef SMT6_10 949 smt_fill_fsc(smc,&nif->fsc) ; /* set frame status cap. */ 950 #endif 951 nif->smt.smt_dest = *dest ; /* destination address */ 952 nif->smt.smt_tid = tid ; /* transaction ID */ 953 dump_smt(smc,(struct smt_header *)nif,"NIF") ; 954 smt_send_frame(smc,mb,fc,local) ; 955 } 956 957 #ifdef DEBUG 958 /* 959 * send NIF request (test purpose) 960 */ 961 static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest) 962 { 963 smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ; 964 smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST], 965 SMT_REQUEST,0) ; 966 } 967 968 /* 969 * send ECF request (test purpose) 970 */ 971 static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest, 972 int len) 973 { 974 smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ; 975 smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF], 976 SMT_REQUEST,len) ; 977 } 978 #endif 979 980 /* 981 * echo test 982 */ 983 static void smt_echo_test(struct s_smc *smc, int dna) 984 { 985 u_long tid ; 986 987 smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] = 988 tid = smt_get_tid(smc) ; 989 smt_send_ecf(smc, dna ? 990 &smc->mib.m[MAC0].fddiMACDownstreamNbr : 991 &smc->mib.m[MAC0].fddiMACUpstreamNbr, 992 FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ; 993 } 994 995 /* 996 * generate and send ECF 997 */ 998 static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc, 999 u_long tid, int type, int len) 1000 /* struct fddi_addr *dest; dest address */ 1001 /* int fc; frame control */ 1002 /* u_long tid; transaction id */ 1003 /* int type; frame type */ 1004 /* int len; frame length */ 1005 { 1006 struct smt_ecf *ecf ; 1007 SMbuf *mb ; 1008 1009 if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len))) 1010 return ; 1011 ecf = smtod(mb, struct smt_ecf *) ; 1012 1013 smt_fill_echo(smc,&ecf->ec_echo,tid,len) ; /* set ECHO */ 1014 ecf->smt.smt_dest = *dest ; /* destination address */ 1015 ecf->smt.smt_tid = tid ; /* transaction ID */ 1016 smc->mib.priv.fddiPRIVECF_Req_Tx++ ; 1017 smt_send_frame(smc,mb,fc,0) ; 1018 } 1019 1020 /* 1021 * generate and send SIF config response 1022 */ 1023 1024 static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest, 1025 u_long tid, int local) 1026 /* struct fddi_addr *dest; dest address */ 1027 /* u_long tid; transaction id */ 1028 { 1029 struct smt_sif_config *sif ; 1030 SMbuf *mb ; 1031 int len ; 1032 if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY, 1033 SIZEOF_SMT_SIF_CONFIG))) 1034 return ; 1035 1036 sif = smtod(mb, struct smt_sif_config *) ; 1037 smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */ 1038 smt_fill_sde(smc,&sif->sde) ; /* set station descriptor */ 1039 smt_fill_version(smc,&sif->version) ; /* set version information */ 1040 smt_fill_state(smc,&sif->state) ; /* set state information */ 1041 smt_fill_policy(smc,&sif->policy) ; /* set station policy */ 1042 smt_fill_latency(smc,&sif->latency); /* set station latency */ 1043 smt_fill_neighbor(smc,&sif->neighbor); /* set station neighbor */ 1044 smt_fill_setcount(smc,&sif->setcount) ; /* set count */ 1045 len = smt_fill_path(smc,&sif->path); /* set station path descriptor*/ 1046 sif->smt.smt_dest = *dest ; /* destination address */ 1047 sif->smt.smt_tid = tid ; /* transaction ID */ 1048 smt_add_frame_len(mb,len) ; /* adjust length fields */ 1049 dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ; 1050 smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 1051 } 1052 1053 /* 1054 * generate and send SIF operation response 1055 */ 1056 1057 static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest, 1058 u_long tid, int local) 1059 /* struct fddi_addr *dest; dest address */ 1060 /* u_long tid; transaction id */ 1061 { 1062 struct smt_sif_operation *sif ; 1063 SMbuf *mb ; 1064 int ports ; 1065 int i ; 1066 1067 ports = NUMPHYS ; 1068 #ifndef CONCENTRATOR 1069 if (smc->s.sas == SMT_SAS) 1070 ports = 1 ; 1071 #endif 1072 1073 if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY, 1074 SIZEOF_SMT_SIF_OPERATION+ports*sizeof(struct smt_p_lem)))) 1075 return ; 1076 sif = smtod(mb, struct smt_sif_operation *) ; 1077 smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */ 1078 smt_fill_mac_status(smc,&sif->status) ; /* set mac status */ 1079 smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */ 1080 smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */ 1081 smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */ 1082 smt_fill_user(smc,&sif->user) ; /* set user field */ 1083 smt_fill_setcount(smc,&sif->setcount) ; /* set count */ 1084 /* 1085 * set link error mon information 1086 */ 1087 if (ports == 1) { 1088 smt_fill_lem(smc,sif->lem,PS) ; 1089 } 1090 else { 1091 for (i = 0 ; i < ports ; i++) { 1092 smt_fill_lem(smc,&sif->lem[i],i) ; 1093 } 1094 } 1095 1096 sif->smt.smt_dest = *dest ; /* destination address */ 1097 sif->smt.smt_tid = tid ; /* transaction ID */ 1098 dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ; 1099 smt_send_frame(smc,mb,FC_SMT_INFO,local) ; 1100 } 1101 1102 /* 1103 * get and initialize SMT frame 1104 */ 1105 SMbuf *smt_build_frame(struct s_smc *smc, int class, int type, 1106 int length) 1107 { 1108 SMbuf *mb ; 1109 struct smt_header *smt ; 1110 1111 #if 0 1112 if (!smc->r.sm_ma_avail) { 1113 return 0; 1114 } 1115 #endif 1116 if (!(mb = smt_get_mbuf(smc))) 1117 return mb; 1118 1119 mb->sm_len = length ; 1120 smt = smtod(mb, struct smt_header *) ; 1121 smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */ 1122 smt->smt_class = class ; 1123 smt->smt_type = type ; 1124 switch (class) { 1125 case SMT_NIF : 1126 case SMT_SIF_CONFIG : 1127 case SMT_SIF_OPER : 1128 case SMT_ECF : 1129 smt->smt_version = SMT_VID ; 1130 break ; 1131 default : 1132 smt->smt_version = SMT_VID_2 ; 1133 break ; 1134 } 1135 smt->smt_tid = smt_get_tid(smc) ; /* set transaction ID */ 1136 smt->smt_pad = 0 ; 1137 smt->smt_len = length - sizeof(struct smt_header) ; 1138 return mb; 1139 } 1140 1141 static void smt_add_frame_len(SMbuf *mb, int len) 1142 { 1143 struct smt_header *smt ; 1144 1145 smt = smtod(mb, struct smt_header *) ; 1146 smt->smt_len += len ; 1147 mb->sm_len += len ; 1148 } 1149 1150 1151 1152 /* 1153 * fill values in UNA parameter 1154 */ 1155 static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una) 1156 { 1157 SMTSETPARA(una,SMT_P_UNA) ; 1158 una->una_pad = 0 ; 1159 una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ; 1160 } 1161 1162 /* 1163 * fill values in SDE parameter 1164 */ 1165 static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde) 1166 { 1167 SMTSETPARA(sde,SMT_P_SDE) ; 1168 sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ; 1169 sde->sde_master = smc->mib.fddiSMTMaster_Ct ; 1170 sde->sde_mac_count = NUMMACS ; /* only 1 MAC */ 1171 #ifdef CONCENTRATOR 1172 sde->sde_type = SMT_SDE_CONCENTRATOR ; 1173 #else 1174 sde->sde_type = SMT_SDE_STATION ; 1175 #endif 1176 } 1177 1178 /* 1179 * fill in values in station state parameter 1180 */ 1181 static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state) 1182 { 1183 int top ; 1184 int twist ; 1185 1186 SMTSETPARA(state,SMT_P_STATE) ; 1187 state->st_pad = 0 ; 1188 1189 /* determine topology */ 1190 top = 0 ; 1191 if (smc->mib.fddiSMTPeerWrapFlag) { 1192 top |= SMT_ST_WRAPPED ; /* state wrapped */ 1193 } 1194 #ifdef CONCENTRATOR 1195 if (cfm_status_unattached(smc)) { 1196 top |= SMT_ST_UNATTACHED ; /* unattached concentrator */ 1197 } 1198 #endif 1199 if ((twist = pcm_status_twisted(smc)) & 1) { 1200 top |= SMT_ST_TWISTED_A ; /* twisted cable */ 1201 } 1202 if (twist & 2) { 1203 top |= SMT_ST_TWISTED_B ; /* twisted cable */ 1204 } 1205 #ifdef OPT_SRF 1206 top |= SMT_ST_SRF ; 1207 #endif 1208 if (pcm_rooted_station(smc)) 1209 top |= SMT_ST_ROOTED_S ; 1210 if (smc->mib.a[0].fddiPATHSbaPayload != 0) 1211 top |= SMT_ST_SYNC_SERVICE ; 1212 state->st_topology = top ; 1213 state->st_dupl_addr = 1214 ((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) | 1215 (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ; 1216 } 1217 1218 /* 1219 * fill values in timestamp parameter 1220 */ 1221 static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts) 1222 { 1223 1224 SMTSETPARA(ts,SMT_P_TIMESTAMP) ; 1225 smt_set_timestamp(smc,ts->ts_time) ; 1226 } 1227 1228 void smt_set_timestamp(struct s_smc *smc, u_char *p) 1229 { 1230 u_long time ; 1231 u_long utime ; 1232 1233 /* 1234 * timestamp is 64 bits long ; resolution is 80 nS 1235 * our clock resolution is 10mS 1236 * 10mS/80ns = 125000 ~ 2^17 = 131072 1237 */ 1238 utime = smt_get_time() ; 1239 time = utime * 100 ; 1240 time /= TICKS_PER_SECOND ; 1241 p[0] = 0 ; 1242 p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ; 1243 p[2] = (u_char)(time>>(8+8+8-1)) ; 1244 p[3] = (u_char)(time>>(8+8-1)) ; 1245 p[4] = (u_char)(time>>(8-1)) ; 1246 p[5] = (u_char)(time<<1) ; 1247 p[6] = (u_char)(smc->sm.uniq_ticks>>8) ; 1248 p[7] = (u_char)smc->sm.uniq_ticks ; 1249 /* 1250 * make sure we don't wrap: restart whenever the upper digits change 1251 */ 1252 if (utime != smc->sm.uniq_time) { 1253 smc->sm.uniq_ticks = 0 ; 1254 } 1255 smc->sm.uniq_ticks++ ; 1256 smc->sm.uniq_time = utime ; 1257 } 1258 1259 /* 1260 * fill values in station policy parameter 1261 */ 1262 static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy) 1263 { 1264 int i ; 1265 const u_char *map ; 1266 u_short in ; 1267 u_short out ; 1268 1269 /* 1270 * MIB para 101b (fddiSMTConnectionPolicy) coding 1271 * is different from 0005 coding 1272 */ 1273 static const u_char ansi_weirdness[16] = { 1274 0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15 1275 } ; 1276 SMTSETPARA(policy,SMT_P_POLICY) ; 1277 1278 out = 0 ; 1279 in = smc->mib.fddiSMTConnectionPolicy ; 1280 for (i = 0, map = ansi_weirdness ; i < 16 ; i++) { 1281 if (in & 1) 1282 out |= (1<<*map) ; 1283 in >>= 1 ; 1284 map++ ; 1285 } 1286 policy->pl_config = smc->mib.fddiSMTConfigPolicy ; 1287 policy->pl_connect = out ; 1288 } 1289 1290 /* 1291 * fill values in latency equivalent parameter 1292 */ 1293 static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency) 1294 { 1295 SMTSETPARA(latency,SMT_P_LATENCY) ; 1296 1297 latency->lt_phyout_idx1 = phy_index(smc,0) ; 1298 latency->lt_latency1 = 10 ; /* in octets (byte clock) */ 1299 /* 1300 * note: latency has two phy entries by definition 1301 * for a SAS, the 2nd one is null 1302 */ 1303 if (smc->s.sas == SMT_DAS) { 1304 latency->lt_phyout_idx2 = phy_index(smc,1) ; 1305 latency->lt_latency2 = 10 ; /* in octets (byte clock) */ 1306 } 1307 else { 1308 latency->lt_phyout_idx2 = 0 ; 1309 latency->lt_latency2 = 0 ; 1310 } 1311 } 1312 1313 /* 1314 * fill values in MAC neighbors parameter 1315 */ 1316 static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor) 1317 { 1318 SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ; 1319 1320 neighbor->nb_mib_index = INDEX_MAC ; 1321 neighbor->nb_mac_index = mac_index(smc,1) ; 1322 neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ; 1323 neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ; 1324 } 1325 1326 /* 1327 * fill values in path descriptor 1328 */ 1329 #ifdef CONCENTRATOR 1330 #define ALLPHYS NUMPHYS 1331 #else 1332 #define ALLPHYS ((smc->s.sas == SMT_SAS) ? 1 : 2) 1333 #endif 1334 1335 static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path) 1336 { 1337 SK_LOC_DECL(int,type) ; 1338 SK_LOC_DECL(int,state) ; 1339 SK_LOC_DECL(int,remote) ; 1340 SK_LOC_DECL(int,mac) ; 1341 int len ; 1342 int p ; 1343 int physp ; 1344 struct smt_phy_rec *phy ; 1345 struct smt_mac_rec *pd_mac ; 1346 1347 len = PARA_LEN + 1348 sizeof(struct smt_mac_rec) * NUMMACS + 1349 sizeof(struct smt_phy_rec) * ALLPHYS ; 1350 path->para.p_type = SMT_P_PATH ; 1351 path->para.p_len = len - PARA_LEN ; 1352 1353 /* PHYs */ 1354 for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) { 1355 physp = p ; 1356 #ifndef CONCENTRATOR 1357 if (smc->s.sas == SMT_SAS) 1358 physp = PS ; 1359 #endif 1360 pcm_status_state(smc,physp,&type,&state,&remote,&mac) ; 1361 #ifdef LITTLE_ENDIAN 1362 phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ; 1363 #else 1364 phy->phy_mib_index = p+INDEX_PORT ; 1365 #endif 1366 phy->phy_type = type ; 1367 phy->phy_connect_state = state ; 1368 phy->phy_remote_type = remote ; 1369 phy->phy_remote_mac = mac ; 1370 phy->phy_resource_idx = phy_con_resource_index(smc,p) ; 1371 } 1372 1373 /* MAC */ 1374 pd_mac = (struct smt_mac_rec *) phy ; 1375 pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ; 1376 pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ; 1377 return len; 1378 } 1379 1380 /* 1381 * fill values in mac status 1382 */ 1383 static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st) 1384 { 1385 SMTSETPARA(st,SMT_P_MAC_STATUS) ; 1386 1387 st->st_mib_index = INDEX_MAC ; 1388 st->st_mac_index = mac_index(smc,1) ; 1389 1390 mac_update_counter(smc) ; 1391 /* 1392 * timer values are represented in SMT as 2's complement numbers 1393 * units : internal : 2's complement BCLK 1394 */ 1395 st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ; 1396 st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ; 1397 st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ; 1398 st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ; 1399 st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ; 1400 1401 st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ; 1402 st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ; 1403 st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ; 1404 st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ; 1405 } 1406 1407 /* 1408 * fill values in LEM status 1409 */ 1410 static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy) 1411 { 1412 struct fddi_mib_p *mib ; 1413 1414 mib = smc->y[phy].mib ; 1415 1416 SMTSETPARA(lem,SMT_P_LEM) ; 1417 lem->lem_mib_index = phy+INDEX_PORT ; 1418 lem->lem_phy_index = phy_index(smc,phy) ; 1419 lem->lem_pad2 = 0 ; 1420 lem->lem_cutoff = mib->fddiPORTLer_Cutoff ; 1421 lem->lem_alarm = mib->fddiPORTLer_Alarm ; 1422 /* long term bit error rate */ 1423 lem->lem_estimate = mib->fddiPORTLer_Estimate ; 1424 /* # of rejected connections */ 1425 lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ; 1426 lem->lem_ct = mib->fddiPORTLem_Ct ; /* total number of errors */ 1427 } 1428 1429 /* 1430 * fill version parameter 1431 */ 1432 static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers) 1433 { 1434 SK_UNUSED(smc) ; 1435 SMTSETPARA(vers,SMT_P_VERSION) ; 1436 vers->v_pad = 0 ; 1437 vers->v_n = 1 ; /* one version is enough .. */ 1438 vers->v_index = 1 ; 1439 vers->v_version[0] = SMT_VID_2 ; 1440 vers->v_pad2 = 0 ; 1441 } 1442 1443 #ifdef SMT6_10 1444 /* 1445 * fill frame status capabilities 1446 */ 1447 /* 1448 * note: this para 200B is NOT in swap table, because it's also set in 1449 * PMF add_para 1450 */ 1451 static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc) 1452 { 1453 SK_UNUSED(smc) ; 1454 SMTSETPARA(fsc,SMT_P_FSC) ; 1455 fsc->fsc_pad0 = 0 ; 1456 fsc->fsc_mac_index = INDEX_MAC ; /* this is MIB ; MIB is NOT 1457 * mac_index ()i ! 1458 */ 1459 fsc->fsc_pad1 = 0 ; 1460 fsc->fsc_value = FSC_TYPE0 ; /* "normal" node */ 1461 #ifdef LITTLE_ENDIAN 1462 fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ; 1463 fsc->fsc_value = smt_swap_short(FSC_TYPE0) ; 1464 #endif 1465 } 1466 #endif 1467 1468 /* 1469 * fill mac counter field 1470 */ 1471 static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc) 1472 { 1473 SMTSETPARA(mc,SMT_P_MAC_COUNTER) ; 1474 mc->mc_mib_index = INDEX_MAC ; 1475 mc->mc_index = mac_index(smc,1) ; 1476 mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ; 1477 mc->mc_transmit_ct = smc->mib.m[MAC0].fddiMACTransmit_Ct ; 1478 } 1479 1480 /* 1481 * fill mac frame not copied counter 1482 */ 1483 static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc) 1484 { 1485 SMTSETPARA(fnc,SMT_P_MAC_FNC) ; 1486 fnc->nc_mib_index = INDEX_MAC ; 1487 fnc->nc_index = mac_index(smc,1) ; 1488 fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ; 1489 } 1490 1491 1492 /* 1493 * fill manufacturer field 1494 */ 1495 static void smt_fill_manufacturer(struct s_smc *smc, 1496 struct smp_p_manufacturer *man) 1497 { 1498 SMTSETPARA(man,SMT_P_MANUFACTURER) ; 1499 memcpy((char *) man->mf_data, 1500 (char *) smc->mib.fddiSMTManufacturerData, 1501 sizeof(man->mf_data)) ; 1502 } 1503 1504 /* 1505 * fill user field 1506 */ 1507 static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user) 1508 { 1509 SMTSETPARA(user,SMT_P_USER) ; 1510 memcpy((char *) user->us_data, 1511 (char *) smc->mib.fddiSMTUserData, 1512 sizeof(user->us_data)) ; 1513 } 1514 1515 /* 1516 * fill set count 1517 */ 1518 static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount) 1519 { 1520 SK_UNUSED(smc) ; 1521 SMTSETPARA(setcount,SMT_P_SETCOUNT) ; 1522 setcount->count = smc->mib.fddiSMTSetCount.count ; 1523 memcpy((char *)setcount->timestamp, 1524 (char *)smc->mib.fddiSMTSetCount.timestamp,8) ; 1525 } 1526 1527 /* 1528 * fill echo data 1529 */ 1530 static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed, 1531 int len) 1532 { 1533 u_char *p ; 1534 1535 SK_UNUSED(smc) ; 1536 SMTSETPARA(echo,SMT_P_ECHODATA) ; 1537 echo->para.p_len = len ; 1538 for (p = echo->ec_data ; len ; len--) { 1539 *p++ = (u_char) seed ; 1540 seed += 13 ; 1541 } 1542 } 1543 1544 /* 1545 * clear DNA and UNA 1546 * called from CFM if configuration changes 1547 */ 1548 static void smt_clear_una_dna(struct s_smc *smc) 1549 { 1550 smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ; 1551 smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ; 1552 } 1553 1554 static void smt_clear_old_una_dna(struct s_smc *smc) 1555 { 1556 smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ; 1557 smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ; 1558 } 1559 1560 u_long smt_get_tid(struct s_smc *smc) 1561 { 1562 u_long tid ; 1563 while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0) 1564 ; 1565 return tid & 0x3fffffffL; 1566 } 1567 1568 1569 /* 1570 * table of parameter lengths 1571 */ 1572 static const struct smt_pdef { 1573 int ptype ; 1574 int plen ; 1575 const char *pswap ; 1576 } smt_pdef[] = { 1577 { SMT_P_UNA, sizeof(struct smt_p_una) , 1578 SWAP_SMT_P_UNA } , 1579 { SMT_P_SDE, sizeof(struct smt_p_sde) , 1580 SWAP_SMT_P_SDE } , 1581 { SMT_P_STATE, sizeof(struct smt_p_state) , 1582 SWAP_SMT_P_STATE } , 1583 { SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) , 1584 SWAP_SMT_P_TIMESTAMP } , 1585 { SMT_P_POLICY, sizeof(struct smt_p_policy) , 1586 SWAP_SMT_P_POLICY } , 1587 { SMT_P_LATENCY, sizeof(struct smt_p_latency) , 1588 SWAP_SMT_P_LATENCY } , 1589 { SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) , 1590 SWAP_SMT_P_NEIGHBORS } , 1591 { SMT_P_PATH, sizeof(struct smt_p_path) , 1592 SWAP_SMT_P_PATH } , 1593 { SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) , 1594 SWAP_SMT_P_MAC_STATUS } , 1595 { SMT_P_LEM, sizeof(struct smt_p_lem) , 1596 SWAP_SMT_P_LEM } , 1597 { SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) , 1598 SWAP_SMT_P_MAC_COUNTER } , 1599 { SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) , 1600 SWAP_SMT_P_MAC_FNC } , 1601 { SMT_P_PRIORITY,sizeof(struct smt_p_priority) , 1602 SWAP_SMT_P_PRIORITY } , 1603 { SMT_P_EB,sizeof(struct smt_p_eb) , 1604 SWAP_SMT_P_EB } , 1605 { SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) , 1606 SWAP_SMT_P_MANUFACTURER } , 1607 { SMT_P_REASON, sizeof(struct smt_p_reason) , 1608 SWAP_SMT_P_REASON } , 1609 { SMT_P_REFUSED, sizeof(struct smt_p_refused) , 1610 SWAP_SMT_P_REFUSED } , 1611 { SMT_P_VERSION, sizeof(struct smt_p_version) , 1612 SWAP_SMT_P_VERSION } , 1613 #ifdef ESS 1614 { SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } , 1615 { SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } , 1616 { SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } , 1617 { SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } , 1618 { SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } , 1619 { SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } , 1620 { SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } , 1621 { SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } , 1622 { SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } , 1623 #endif 1624 #if 0 1625 { SMT_P_FSC, sizeof(struct smt_p_fsc) , 1626 SWAP_SMT_P_FSC } , 1627 #endif 1628 1629 { SMT_P_SETCOUNT,0, SWAP_SMT_P_SETCOUNT } , 1630 { SMT_P1048, 0, SWAP_SMT_P1048 } , 1631 { SMT_P208C, 0, SWAP_SMT_P208C } , 1632 { SMT_P208D, 0, SWAP_SMT_P208D } , 1633 { SMT_P208E, 0, SWAP_SMT_P208E } , 1634 { SMT_P208F, 0, SWAP_SMT_P208F } , 1635 { SMT_P2090, 0, SWAP_SMT_P2090 } , 1636 #ifdef ESS 1637 { SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } , 1638 { SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } , 1639 { SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } , 1640 #endif 1641 { SMT_P4050, 0, SWAP_SMT_P4050 } , 1642 { SMT_P4051, 0, SWAP_SMT_P4051 } , 1643 { SMT_P4052, 0, SWAP_SMT_P4052 } , 1644 { SMT_P4053, 0, SWAP_SMT_P4053 } , 1645 } ; 1646 1647 #define N_SMT_PLEN ARRAY_SIZE(smt_pdef) 1648 1649 int smt_check_para(struct s_smc *smc, struct smt_header *sm, 1650 const u_short list[]) 1651 { 1652 const u_short *p = list ; 1653 while (*p) { 1654 if (!sm_to_para(smc,sm,(int) *p)) { 1655 DB_SMT("SMT: smt_check_para - missing para %hx", *p); 1656 return -1; 1657 } 1658 p++ ; 1659 } 1660 return 0; 1661 } 1662 1663 void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para) 1664 { 1665 char *p ; 1666 int len ; 1667 int plen ; 1668 void *found = NULL; 1669 1670 SK_UNUSED(smc) ; 1671 1672 len = sm->smt_len ; 1673 p = (char *)(sm+1) ; /* pointer to info */ 1674 while (len > 0 ) { 1675 if (((struct smt_para *)p)->p_type == para) 1676 found = (void *) p ; 1677 plen = ((struct smt_para *)p)->p_len + PARA_LEN ; 1678 p += plen ; 1679 len -= plen ; 1680 if (len < 0) { 1681 DB_SMT("SMT : sm_to_para - length error %d", plen); 1682 return NULL; 1683 } 1684 if ((plen & 3) && (para != SMT_P_ECHODATA)) { 1685 DB_SMT("SMT : sm_to_para - odd length %d", plen); 1686 return NULL; 1687 } 1688 if (found) 1689 return found; 1690 } 1691 return NULL; 1692 } 1693 1694 #if 0 1695 /* 1696 * send ANTC data test frame 1697 */ 1698 void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest) 1699 { 1700 SK_UNUSED(smc) ; 1701 SK_UNUSED(dest) ; 1702 #if 0 1703 SMbuf *mb ; 1704 struct smt_header *smt ; 1705 int i ; 1706 char *p ; 1707 1708 mb = smt_get_mbuf() ; 1709 mb->sm_len = 3000+12 ; 1710 p = smtod(mb, char *) + 12 ; 1711 for (i = 0 ; i < 3000 ; i++) 1712 *p++ = 1 << (i&7) ; 1713 1714 smt = smtod(mb, struct smt_header *) ; 1715 smt->smt_dest = *dest ; 1716 smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ; 1717 smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ; 1718 #endif 1719 } 1720 #endif 1721 1722 #ifdef DEBUG 1723 char *addr_to_string(struct fddi_addr *addr) 1724 { 1725 int i ; 1726 static char string[6*3] = "****" ; 1727 1728 for (i = 0 ; i < 6 ; i++) { 1729 string[i * 3] = hex_asc_hi(addr->a[i]); 1730 string[i * 3 + 1] = hex_asc_lo(addr->a[i]); 1731 string[i * 3 + 2] = ':'; 1732 } 1733 string[5 * 3 + 2] = 0; 1734 return string; 1735 } 1736 #endif 1737 1738 /* 1739 * return static mac index 1740 */ 1741 static int mac_index(struct s_smc *smc, int mac) 1742 { 1743 SK_UNUSED(mac) ; 1744 #ifdef CONCENTRATOR 1745 SK_UNUSED(smc) ; 1746 return NUMPHYS + 1; 1747 #else 1748 return (smc->s.sas == SMT_SAS) ? 2 : 3; 1749 #endif 1750 } 1751 1752 /* 1753 * return static phy index 1754 */ 1755 static int phy_index(struct s_smc *smc, int phy) 1756 { 1757 SK_UNUSED(smc) ; 1758 return phy + 1; 1759 } 1760 1761 /* 1762 * return dynamic mac connection resource index 1763 */ 1764 static int mac_con_resource_index(struct s_smc *smc, int mac) 1765 { 1766 #ifdef CONCENTRATOR 1767 SK_UNUSED(smc) ; 1768 SK_UNUSED(mac) ; 1769 return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC)); 1770 #else 1771 SK_UNUSED(mac) ; 1772 switch (smc->mib.fddiSMTCF_State) { 1773 case SC9_C_WRAP_A : 1774 case SC5_THRU_B : 1775 case SC11_C_WRAP_S : 1776 return 1; 1777 case SC10_C_WRAP_B : 1778 case SC4_THRU_A : 1779 return 2; 1780 } 1781 return smc->s.sas == SMT_SAS ? 2 : 3; 1782 #endif 1783 } 1784 1785 /* 1786 * return dynamic phy connection resource index 1787 */ 1788 static int phy_con_resource_index(struct s_smc *smc, int phy) 1789 { 1790 #ifdef CONCENTRATOR 1791 return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ; 1792 #else 1793 switch (smc->mib.fddiSMTCF_State) { 1794 case SC9_C_WRAP_A : 1795 return phy == PA ? 3 : 2; 1796 case SC10_C_WRAP_B : 1797 return phy == PA ? 1 : 3; 1798 case SC4_THRU_A : 1799 return phy == PA ? 3 : 1; 1800 case SC5_THRU_B : 1801 return phy == PA ? 2 : 3; 1802 case SC11_C_WRAP_S : 1803 return 2; 1804 } 1805 return phy; 1806 #endif 1807 } 1808 1809 #ifdef CONCENTRATOR 1810 static int entity_to_index(struct s_smc *smc, int e) 1811 { 1812 if (e == ENTITY_MAC) 1813 return mac_index(smc, 1); 1814 else 1815 return phy_index(smc, e - ENTITY_PHY(0)); 1816 } 1817 #endif 1818 1819 #ifdef LITTLE_ENDIAN 1820 static int smt_swap_short(u_short s) 1821 { 1822 return ((s>>8)&0xff) | ((s&0xff)<<8); 1823 } 1824 1825 void smt_swap_para(struct smt_header *sm, int len, int direction) 1826 /* int direction; 0 encode 1 decode */ 1827 { 1828 struct smt_para *pa ; 1829 const struct smt_pdef *pd ; 1830 char *p ; 1831 int plen ; 1832 int type ; 1833 int i ; 1834 1835 /* printf("smt_swap_para sm %x len %d dir %d\n", 1836 sm,len,direction) ; 1837 */ 1838 smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ; 1839 1840 /* swap args */ 1841 len -= sizeof(struct smt_header) ; 1842 1843 p = (char *) (sm + 1) ; 1844 while (len > 0) { 1845 pa = (struct smt_para *) p ; 1846 plen = pa->p_len ; 1847 type = pa->p_type ; 1848 pa->p_type = smt_swap_short(pa->p_type) ; 1849 pa->p_len = smt_swap_short(pa->p_len) ; 1850 if (direction) { 1851 plen = pa->p_len ; 1852 type = pa->p_type ; 1853 } 1854 /* 1855 * note: paras can have 0 length ! 1856 */ 1857 if (plen < 0) 1858 break ; 1859 plen += PARA_LEN ; 1860 for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) { 1861 if (pd->ptype == type) 1862 break ; 1863 } 1864 if (i && pd->pswap) { 1865 smt_string_swap(p+PARA_LEN,pd->pswap,len) ; 1866 } 1867 len -= plen ; 1868 p += plen ; 1869 } 1870 } 1871 1872 static void smt_string_swap(char *data, const char *format, int len) 1873 { 1874 const char *open_paren = NULL ; 1875 int x ; 1876 1877 while (len > 0 && *format) { 1878 switch (*format) { 1879 case '[' : 1880 open_paren = format ; 1881 break ; 1882 case ']' : 1883 format = open_paren ; 1884 break ; 1885 case '1' : 1886 case '2' : 1887 case '3' : 1888 case '4' : 1889 case '5' : 1890 case '6' : 1891 case '7' : 1892 case '8' : 1893 case '9' : 1894 data += *format - '0' ; 1895 len -= *format - '0' ; 1896 break ; 1897 case 'c': 1898 data++ ; 1899 len-- ; 1900 break ; 1901 case 's' : 1902 x = data[0] ; 1903 data[0] = data[1] ; 1904 data[1] = x ; 1905 data += 2 ; 1906 len -= 2 ; 1907 break ; 1908 case 'l' : 1909 x = data[0] ; 1910 data[0] = data[3] ; 1911 data[3] = x ; 1912 x = data[1] ; 1913 data[1] = data[2] ; 1914 data[2] = x ; 1915 data += 4 ; 1916 len -= 4 ; 1917 break ; 1918 } 1919 format++ ; 1920 } 1921 } 1922 #else 1923 void smt_swap_para(struct smt_header *sm, int len, int direction) 1924 /* int direction; 0 encode 1 decode */ 1925 { 1926 SK_UNUSED(sm) ; 1927 SK_UNUSED(len) ; 1928 SK_UNUSED(direction) ; 1929 } 1930 #endif 1931 1932 /* 1933 * PMF actions 1934 */ 1935 int smt_action(struct s_smc *smc, int class, int code, int index) 1936 { 1937 int event ; 1938 int port ; 1939 DB_SMT("SMT: action %d code %d", class, code); 1940 switch(class) { 1941 case SMT_STATION_ACTION : 1942 switch(code) { 1943 case SMT_STATION_ACTION_CONNECT : 1944 smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ; 1945 queue_event(smc,EVENT_ECM,EC_CONNECT) ; 1946 break ; 1947 case SMT_STATION_ACTION_DISCONNECT : 1948 queue_event(smc,EVENT_ECM,EC_DISCONNECT) ; 1949 smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ; 1950 RS_SET(smc,RS_DISCONNECT) ; 1951 AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 1952 FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT, 1953 smt_get_event_word(smc)); 1954 break ; 1955 case SMT_STATION_ACTION_PATHTEST : 1956 AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 1957 FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST, 1958 smt_get_event_word(smc)); 1959 break ; 1960 case SMT_STATION_ACTION_SELFTEST : 1961 AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long) 1962 FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST, 1963 smt_get_event_word(smc)); 1964 break ; 1965 case SMT_STATION_ACTION_DISABLE_A : 1966 if (smc->y[PA].pc_mode == PM_PEER) { 1967 RS_SET(smc,RS_EVENT) ; 1968 queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ; 1969 } 1970 break ; 1971 case SMT_STATION_ACTION_DISABLE_B : 1972 if (smc->y[PB].pc_mode == PM_PEER) { 1973 RS_SET(smc,RS_EVENT) ; 1974 queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ; 1975 } 1976 break ; 1977 case SMT_STATION_ACTION_DISABLE_M : 1978 for (port = 0 ; port < NUMPHYS ; port++) { 1979 if (smc->mib.p[port].fddiPORTMy_Type != TM) 1980 continue ; 1981 RS_SET(smc,RS_EVENT) ; 1982 queue_event(smc,EVENT_PCM+port,PC_DISABLE) ; 1983 } 1984 break ; 1985 default : 1986 return 1; 1987 } 1988 break ; 1989 case SMT_PORT_ACTION : 1990 switch(code) { 1991 case SMT_PORT_ACTION_ENABLE : 1992 event = PC_ENABLE ; 1993 break ; 1994 case SMT_PORT_ACTION_DISABLE : 1995 event = PC_DISABLE ; 1996 break ; 1997 case SMT_PORT_ACTION_MAINT : 1998 event = PC_MAINT ; 1999 break ; 2000 case SMT_PORT_ACTION_START : 2001 event = PC_START ; 2002 break ; 2003 case SMT_PORT_ACTION_STOP : 2004 event = PC_STOP ; 2005 break ; 2006 default : 2007 return 1; 2008 } 2009 queue_event(smc,EVENT_PCM+index,event) ; 2010 break ; 2011 default : 2012 return 1; 2013 } 2014 return 0; 2015 } 2016 2017 /* 2018 * canonical conversion of <len> bytes beginning form *data 2019 */ 2020 #ifdef USE_CAN_ADDR 2021 static void hwm_conv_can(struct s_smc *smc, char *data, int len) 2022 { 2023 int i ; 2024 2025 SK_UNUSED(smc) ; 2026 2027 for (i = len; i ; i--, data++) 2028 *data = bitrev8(*data); 2029 } 2030 #endif 2031 2032 #endif /* no SLIM_SMT */ 2033 2034