/drivers/net/fddi/skfp/cfm.c

http://github.com/mirrors/linux · C · 621 lines · 441 code · 46 blank · 134 comment · 126 complexity · bd4a0de096ac3f44176e741c83092143 MD5 · raw file

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