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