cfm.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:16k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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