cfm.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  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. SMT CFM
  18. Configuration Management
  19. DAS with single MAC
  20. */
  21. /*
  22. * Hardware independent state machine implemantation
  23. * The following external SMT functions are referenced :
  24. *
  25. * queue_event()
  26. *
  27. * The following external HW dependent functions are referenced :
  28. * config_mux()
  29. *
  30. * The following HW dependent events are required :
  31. * NONE
  32. */
  33. #include "h/types.h"
  34. #include "h/fddi.h"
  35. #include "h/smc.h"
  36. #define KERNEL
  37. #include "h/smtstate.h"
  38. #ifndef lint
  39. static const char ID_sccs[] = "@(#)cfm.c 2.18 98/10/06 (C) SK " ;
  40. #endif
  41. /*
  42. * FSM Macros
  43. */
  44. #define AFLAG 0x10
  45. #define GO_STATE(x) (smc->mib.fddiSMTCF_State = (x)|AFLAG)
  46. #define ACTIONS_DONE() (smc->mib.fddiSMTCF_State &= ~AFLAG)
  47. #define ACTIONS(x) (x|AFLAG)
  48. /*
  49. * symbolic state names
  50. */
  51. static const char * const cfm_states[] = {
  52. "SC0_ISOLATED","CF1","CF2","CF3","CF4",
  53. "SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S",
  54. "SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A"
  55. } ;
  56. /*
  57. * symbolic event names
  58. */
  59. static const char * const cfm_events[] = {
  60. "NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B"
  61. } ;
  62. /*
  63. * map from state to downstream port type
  64. */
  65. static const unsigned char cf_to_ptype[] = {
  66. TNONE,TNONE,TNONE,TNONE,TNONE,
  67. TNONE,TB,TB,TS,
  68. TA,TB,TS,TB
  69. } ;
  70. /*
  71. * CEM port states
  72. */
  73. #define CEM_PST_DOWN 0
  74. #define CEM_PST_UP 1
  75. #define CEM_PST_HOLD 2
  76. /* define portstate array only for A and B port */
  77. /* Do this within the smc structure (use in multiple cards) */
  78. /*
  79. * all Globals are defined in smc.h
  80. * struct s_cfm
  81. */
  82. /*
  83. * function declarations
  84. */
  85. static void cfm_fsm(struct s_smc *smc, int cmd);
  86. /*
  87. init CFM state machine
  88. clear all CFM vars and flags
  89. */
  90. void cfm_init(struct s_smc *smc)
  91. {
  92. smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ;
  93. smc->r.rm_join = 0 ;
  94. smc->r.rm_loop = 0 ;
  95. smc->y[PA].scrub = 0 ;
  96. smc->y[PB].scrub = 0 ;
  97. smc->y[PA].cem_pst = CEM_PST_DOWN ;
  98. smc->y[PB].cem_pst = CEM_PST_DOWN ;
  99. }
  100. /* Some terms conditions used by the selection criteria */
  101. #define THRU_ENABLED(smc) (smc->y[PA].pc_mode != PM_TREE && \
  102. smc->y[PB].pc_mode != PM_TREE)
  103. /* Selection criteria for the ports */
  104. static void selection_criteria (struct s_smc *smc, struct s_phy *phy)
  105. {
  106. switch (phy->mib->fddiPORTMy_Type) {
  107. case TA:
  108. if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) {
  109. phy->wc_flag = TRUE ;
  110. } else {
  111. phy->wc_flag = FALSE ;
  112. }
  113. break;
  114. case TB:
  115. /* take precedence over PA */
  116. phy->wc_flag = FALSE ;
  117. break;
  118. case TS:
  119. phy->wc_flag = FALSE ;
  120. break;
  121. case TM:
  122. phy->wc_flag = FALSE ;
  123. break;
  124. }
  125. }
  126. void all_selection_criteria(struct s_smc *smc)
  127. {
  128. struct s_phy *phy ;
  129. int p ;
  130. for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) {
  131. /* Do the selection criteria */
  132. selection_criteria (smc,phy);
  133. }
  134. }
  135. static void cem_priv_state(struct s_smc *smc, int event)
  136. /* State machine for private PORT states: used to optimize dual homing */
  137. {
  138. int np; /* Number of the port */
  139. int i;
  140. /* Do this only in a DAS */
  141. if (smc->s.sas != SMT_DAS )
  142. return ;
  143. np = event - CF_JOIN;
  144. if (np != PA && np != PB) {
  145. return ;
  146. }
  147. /* Change the port state according to the event (portnumber) */
  148. if (smc->y[np].cf_join) {
  149. smc->y[np].cem_pst = CEM_PST_UP ;
  150. } else if (!smc->y[np].wc_flag) {
  151. /* set the port to done only if it is not withheld */
  152. smc->y[np].cem_pst = CEM_PST_DOWN ;
  153. }
  154. /* Don't set an hold port to down */
  155. /* Check all ports of restart conditions */
  156. for (i = 0 ; i < 2 ; i ++ ) {
  157. /* Check all port for PORT is on hold and no withhold is done */
  158. if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) {
  159. smc->y[i].cem_pst = CEM_PST_DOWN;
  160. queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
  161. }
  162. if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) {
  163. smc->y[i].cem_pst = CEM_PST_HOLD;
  164. queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
  165. }
  166. if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) {
  167. /*
  168. * The port must be restarted when the wc_flag
  169. * will be reset. So set the port on hold.
  170. */
  171. smc->y[i].cem_pst = CEM_PST_HOLD;
  172. }
  173. }
  174. return ;
  175. }
  176. /*
  177. CFM state machine
  178. called by dispatcher
  179. do
  180. display state change
  181. process event
  182. until SM is stable
  183. */
  184. void cfm(struct s_smc *smc, int event)
  185. {
  186. int state ; /* remember last state */
  187. int cond ;
  188. int oldstate ;
  189. /* We will do the following: */
  190. /* - compute the variable WC_Flag for every port (This is where */
  191. /* we can extend the requested path checking !!) */
  192. /* - do the old (SMT 6.2 like) state machine */
  193. /* - do the resulting station states */
  194. all_selection_criteria (smc);
  195. /* We will check now whether a state transition is allowed or not */
  196. /* - change the portstates */
  197. cem_priv_state (smc, event);
  198. oldstate = smc->mib.fddiSMTCF_State ;
  199. do {
  200. DB_CFM("CFM : state %s%s event %s",
  201. smc->mib.fddiSMTCF_State & AFLAG ? "ACTIONS " : "",
  202. cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG],
  203. cfm_events[event]);
  204. state = smc->mib.fddiSMTCF_State ;
  205. cfm_fsm(smc,event) ;
  206. event = 0 ;
  207. } while (state != smc->mib.fddiSMTCF_State) ;
  208. #ifndef SLIM_SMT
  209. /*
  210. * check peer wrap condition
  211. */
  212. cond = FALSE ;
  213. if ( (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A &&
  214. smc->y[PA].pc_mode == PM_PEER) ||
  215. (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B &&
  216. smc->y[PB].pc_mode == PM_PEER) ||
  217. (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S &&
  218. smc->y[PS].pc_mode == PM_PEER &&
  219. smc->y[PS].mib->fddiPORTNeighborType != TS ) ) {
  220. cond = TRUE ;
  221. }
  222. if (cond != smc->mib.fddiSMTPeerWrapFlag)
  223. smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ;
  224. #if 0
  225. /*
  226. * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired
  227. * to the primary path.
  228. */
  229. /*
  230. * path change
  231. */
  232. if (smc->mib.fddiSMTCF_State != oldstate) {
  233. smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ;
  234. }
  235. #endif
  236. #endif /* no SLIM_SMT */
  237. /*
  238. * set MAC port type
  239. */
  240. smc->mib.m[MAC0].fddiMACDownstreamPORTType =
  241. cf_to_ptype[smc->mib.fddiSMTCF_State] ;
  242. cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ;
  243. }
  244. /*
  245. process CFM event
  246. */
  247. /*ARGSUSED1*/
  248. static void cfm_fsm(struct s_smc *smc, int cmd)
  249. {
  250. switch(smc->mib.fddiSMTCF_State) {
  251. case ACTIONS(SC0_ISOLATED) :
  252. smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
  253. smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
  254. smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
  255. smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
  256. smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;
  257. config_mux(smc,MUX_ISOLATE) ; /* configure PHY Mux */
  258. smc->r.rm_loop = FALSE ;
  259. smc->r.rm_join = FALSE ;
  260. queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
  261. /* Don't do the WC-Flag changing here */
  262. ACTIONS_DONE() ;
  263. DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
  264. break;
  265. case SC0_ISOLATED :
  266. /*SC07*/
  267. /*SAS port can be PA or PB ! */
  268. if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop ||
  269. smc->y[PB].cf_join || smc->y[PB].cf_loop)) {
  270. GO_STATE(SC11_C_WRAP_S) ;
  271. break ;
  272. }
  273. /*SC01*/
  274. if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join &&
  275. !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) {
  276. GO_STATE(SC9_C_WRAP_A) ;
  277. break ;
  278. }
  279. /*SC02*/
  280. if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join &&
  281. !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) {
  282. GO_STATE(SC10_C_WRAP_B) ;
  283. break ;
  284. }
  285. break ;
  286. case ACTIONS(SC9_C_WRAP_A) :
  287. smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
  288. smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
  289. smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
  290. smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
  291. smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
  292. config_mux(smc,MUX_WRAPA) ; /* configure PHY mux */
  293. if (smc->y[PA].cf_loop) {
  294. smc->r.rm_join = FALSE ;
  295. smc->r.rm_loop = TRUE ;
  296. queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
  297. }
  298. if (smc->y[PA].cf_join) {
  299. smc->r.rm_loop = FALSE ;
  300. smc->r.rm_join = TRUE ;
  301. queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
  302. }
  303. ACTIONS_DONE() ;
  304. DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
  305. break ;
  306. case SC9_C_WRAP_A :
  307. /*SC10*/
  308. if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) &&
  309. !smc->y[PA].cf_loop ) {
  310. GO_STATE(SC0_ISOLATED) ;
  311. break ;
  312. }
  313. /*SC12*/
  314. else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join &&
  315. smc->y[PA].cem_pst == CEM_PST_UP) ||
  316. ((smc->y[PB].cf_loop ||
  317. (smc->y[PB].cf_join &&
  318. smc->y[PB].cem_pst == CEM_PST_UP)) &&
  319. (smc->y[PA].pc_mode == PM_TREE ||
  320. smc->y[PB].pc_mode == PM_TREE))) {
  321. smc->y[PA].scrub = TRUE ;
  322. GO_STATE(SC10_C_WRAP_B) ;
  323. break ;
  324. }
  325. /*SC14*/
  326. else if (!smc->s.attach_s &&
  327. smc->y[PA].cf_join &&
  328. smc->y[PA].cem_pst == CEM_PST_UP &&
  329. smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join &&
  330. smc->y[PB].cem_pst == CEM_PST_UP &&
  331. smc->y[PB].pc_mode == PM_PEER) {
  332. smc->y[PA].scrub = TRUE ;
  333. smc->y[PB].scrub = TRUE ;
  334. GO_STATE(SC4_THRU_A) ;
  335. break ;
  336. }
  337. /*SC15*/
  338. else if ( smc->s.attach_s &&
  339. smc->y[PA].cf_join &&
  340. smc->y[PA].cem_pst == CEM_PST_UP &&
  341. smc->y[PA].pc_mode == PM_PEER &&
  342. smc->y[PB].cf_join &&
  343. smc->y[PB].cem_pst == CEM_PST_UP &&
  344. smc->y[PB].pc_mode == PM_PEER) {
  345. smc->y[PA].scrub = TRUE ;
  346. smc->y[PB].scrub = TRUE ;
  347. GO_STATE(SC5_THRU_B) ;
  348. break ;
  349. }
  350. break ;
  351. case ACTIONS(SC10_C_WRAP_B) :
  352. smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
  353. smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
  354. smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
  355. smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
  356. smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
  357. config_mux(smc,MUX_WRAPB) ; /* configure PHY mux */
  358. if (smc->y[PB].cf_loop) {
  359. smc->r.rm_join = FALSE ;
  360. smc->r.rm_loop = TRUE ;
  361. queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
  362. }
  363. if (smc->y[PB].cf_join) {
  364. smc->r.rm_loop = FALSE ;
  365. smc->r.rm_join = TRUE ;
  366. queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
  367. }
  368. ACTIONS_DONE() ;
  369. DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
  370. break ;
  371. case SC10_C_WRAP_B :
  372. /*SC20*/
  373. if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) {
  374. GO_STATE(SC0_ISOLATED) ;
  375. break ;
  376. }
  377. /*SC21*/
  378. else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER &&
  379. smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
  380. smc->y[PB].scrub = TRUE ;
  381. GO_STATE(SC9_C_WRAP_A) ;
  382. break ;
  383. }
  384. /*SC24*/
  385. else if (!smc->s.attach_s &&
  386. smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
  387. smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
  388. smc->y[PA].scrub = TRUE ;
  389. smc->y[PB].scrub = TRUE ;
  390. GO_STATE(SC4_THRU_A) ;
  391. break ;
  392. }
  393. /*SC25*/
  394. else if ( smc->s.attach_s &&
  395. smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
  396. smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
  397. smc->y[PA].scrub = TRUE ;
  398. smc->y[PB].scrub = TRUE ;
  399. GO_STATE(SC5_THRU_B) ;
  400. break ;
  401. }
  402. break ;
  403. case ACTIONS(SC4_THRU_A) :
  404. smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
  405. smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
  406. smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
  407. smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
  408. smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
  409. config_mux(smc,MUX_THRUA) ; /* configure PHY mux */
  410. smc->r.rm_loop = FALSE ;
  411. smc->r.rm_join = TRUE ;
  412. queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
  413. ACTIONS_DONE() ;
  414. DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
  415. break ;
  416. case SC4_THRU_A :
  417. /*SC41*/
  418. if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) {
  419. smc->y[PA].scrub = TRUE ;
  420. GO_STATE(SC9_C_WRAP_A) ;
  421. break ;
  422. }
  423. /*SC42*/
  424. else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
  425. smc->y[PB].scrub = TRUE ;
  426. GO_STATE(SC10_C_WRAP_B) ;
  427. break ;
  428. }
  429. /*SC45*/
  430. else if (smc->s.attach_s) {
  431. smc->y[PB].scrub = TRUE ;
  432. GO_STATE(SC5_THRU_B) ;
  433. break ;
  434. }
  435. break ;
  436. case ACTIONS(SC5_THRU_B) :
  437. smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
  438. smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
  439. smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
  440. smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
  441. smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
  442. config_mux(smc,MUX_THRUB) ; /* configure PHY mux */
  443. smc->r.rm_loop = FALSE ;
  444. smc->r.rm_join = TRUE ;
  445. queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
  446. ACTIONS_DONE() ;
  447. DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
  448. break ;
  449. case SC5_THRU_B :
  450. /*SC51*/
  451. if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) {
  452. smc->y[PA].scrub = TRUE ;
  453. GO_STATE(SC9_C_WRAP_A) ;
  454. break ;
  455. }
  456. /*SC52*/
  457. else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
  458. smc->y[PB].scrub = TRUE ;
  459. GO_STATE(SC10_C_WRAP_B) ;
  460. break ;
  461. }
  462. /*SC54*/
  463. else if (!smc->s.attach_s) {
  464. smc->y[PA].scrub = TRUE ;
  465. GO_STATE(SC4_THRU_A) ;
  466. break ;
  467. }
  468. break ;
  469. case ACTIONS(SC11_C_WRAP_S) :
  470. smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
  471. smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ;
  472. smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
  473. config_mux(smc,MUX_WRAPS) ; /* configure PHY mux */
  474. if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) {
  475. smc->r.rm_join = FALSE ;
  476. smc->r.rm_loop = TRUE ;
  477. queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
  478. }
  479. if (smc->y[PA].cf_join || smc->y[PB].cf_join) {
  480. smc->r.rm_loop = FALSE ;
  481. smc->r.rm_join = TRUE ;
  482. queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
  483. }
  484. ACTIONS_DONE() ;
  485. DB_CFMN(1, "CFM : %s", cfm_states[smc->mib.fddiSMTCF_State]);
  486. break ;
  487. case SC11_C_WRAP_S :
  488. /*SC70*/
  489. if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop &&
  490. !smc->y[PB].cf_join && !smc->y[PB].cf_loop) {
  491. GO_STATE(SC0_ISOLATED) ;
  492. break ;
  493. }
  494. break ;
  495. default:
  496. SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ;
  497. break;
  498. }
  499. }
  500. /*
  501. * get MAC's input Port
  502. * return :
  503. * PA or PB
  504. */
  505. int cfm_get_mac_input(struct s_smc *smc)
  506. {
  507. return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
  508. smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA;
  509. }
  510. /*
  511. * get MAC's output Port
  512. * return :
  513. * PA or PB
  514. */
  515. int cfm_get_mac_output(struct s_smc *smc)
  516. {
  517. return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
  518. smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA;
  519. }
  520. static char path_iso[] = {
  521. 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO,
  522. 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
  523. 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
  524. } ;
  525. static char path_wrap_a[] = {
  526. 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
  527. 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
  528. 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
  529. } ;
  530. static char path_wrap_b[] = {
  531. 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM,
  532. 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
  533. 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO
  534. } ;
  535. static char path_thru[] = {
  536. 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
  537. 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
  538. 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM
  539. } ;
  540. static char path_wrap_s[] = {
  541. 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_PRIM,
  542. 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
  543. } ;
  544. static char path_iso_s[] = {
  545. 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_ISO,
  546. 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
  547. } ;
  548. int cem_build_path(struct s_smc *smc, char *to, int path_index)
  549. {
  550. char *path ;
  551. int len ;
  552. switch (smc->mib.fddiSMTCF_State) {
  553. default :
  554. case SC0_ISOLATED :
  555. path = smc->s.sas ? path_iso_s : path_iso ;
  556. len = smc->s.sas ? sizeof(path_iso_s) : sizeof(path_iso) ;
  557. break ;
  558. case SC9_C_WRAP_A :
  559. path = path_wrap_a ;
  560. len = sizeof(path_wrap_a) ;
  561. break ;
  562. case SC10_C_WRAP_B :
  563. path = path_wrap_b ;
  564. len = sizeof(path_wrap_b) ;
  565. break ;
  566. case SC4_THRU_A :
  567. path = path_thru ;
  568. len = sizeof(path_thru) ;
  569. break ;
  570. case SC11_C_WRAP_S :
  571. path = path_wrap_s ;
  572. len = sizeof(path_wrap_s) ;
  573. break ;
  574. }
  575. memcpy(to,path,len) ;
  576. LINT_USE(path_index);
  577. return len;
  578. }