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