1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * (C)Copyright 1998,1999 SysKonnect,
5*4882a593Smuzhiyun * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * See the file "skfddi.c" for further information.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * The information in this file is provided "AS IS" without warranty.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun ******************************************************************************/
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun SMT ECM
15*4882a593Smuzhiyun Entity Coordination Management
16*4882a593Smuzhiyun Hardware independent state machine
17*4882a593Smuzhiyun */
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun * Hardware independent state machine implemantation
21*4882a593Smuzhiyun * The following external SMT functions are referenced :
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * queue_event()
24*4882a593Smuzhiyun * smt_timer_start()
25*4882a593Smuzhiyun * smt_timer_stop()
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * The following external HW dependent functions are referenced :
28*4882a593Smuzhiyun * sm_pm_bypass_req()
29*4882a593Smuzhiyun * sm_pm_get_ls()
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * The following HW dependent events are required :
32*4882a593Smuzhiyun * NONE
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include "h/types.h"
37*4882a593Smuzhiyun #include "h/fddi.h"
38*4882a593Smuzhiyun #include "h/smc.h"
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define KERNEL
41*4882a593Smuzhiyun #include "h/smtstate.h"
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #ifndef lint
44*4882a593Smuzhiyun static const char ID_sccs[] = "@(#)ecm.c 2.7 99/08/05 (C) SK " ;
45*4882a593Smuzhiyun #endif
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun * FSM Macros
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun #define AFLAG 0x10
51*4882a593Smuzhiyun #define GO_STATE(x) (smc->mib.fddiSMTECMState = (x)|AFLAG)
52*4882a593Smuzhiyun #define ACTIONS_DONE() (smc->mib.fddiSMTECMState &= ~AFLAG)
53*4882a593Smuzhiyun #define ACTIONS(x) (x|AFLAG)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #define EC0_OUT 0 /* not inserted */
56*4882a593Smuzhiyun #define EC1_IN 1 /* inserted */
57*4882a593Smuzhiyun #define EC2_TRACE 2 /* tracing */
58*4882a593Smuzhiyun #define EC3_LEAVE 3 /* leaving the ring */
59*4882a593Smuzhiyun #define EC4_PATH_TEST 4 /* performing path test */
60*4882a593Smuzhiyun #define EC5_INSERT 5 /* bypass being turned on */
61*4882a593Smuzhiyun #define EC6_CHECK 6 /* checking bypass */
62*4882a593Smuzhiyun #define EC7_DEINSERT 7 /* bypass being turnde off */
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /*
65*4882a593Smuzhiyun * symbolic state names
66*4882a593Smuzhiyun */
67*4882a593Smuzhiyun static const char * const ecm_states[] = {
68*4882a593Smuzhiyun "EC0_OUT","EC1_IN","EC2_TRACE","EC3_LEAVE","EC4_PATH_TEST",
69*4882a593Smuzhiyun "EC5_INSERT","EC6_CHECK","EC7_DEINSERT"
70*4882a593Smuzhiyun } ;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /*
73*4882a593Smuzhiyun * symbolic event names
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun static const char * const ecm_events[] = {
76*4882a593Smuzhiyun "NONE","EC_CONNECT","EC_DISCONNECT","EC_TRACE_PROP","EC_PATH_TEST",
77*4882a593Smuzhiyun "EC_TIMEOUT_TD","EC_TIMEOUT_TMAX",
78*4882a593Smuzhiyun "EC_TIMEOUT_IMAX","EC_TIMEOUT_INMAX","EC_TEST_DONE"
79*4882a593Smuzhiyun } ;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun * all Globals are defined in smc.h
83*4882a593Smuzhiyun * struct s_ecm
84*4882a593Smuzhiyun */
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /*
87*4882a593Smuzhiyun * function declarations
88*4882a593Smuzhiyun */
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun static void ecm_fsm(struct s_smc *smc, int cmd);
91*4882a593Smuzhiyun static void start_ecm_timer(struct s_smc *smc, u_long value, int event);
92*4882a593Smuzhiyun static void stop_ecm_timer(struct s_smc *smc);
93*4882a593Smuzhiyun static void prop_actions(struct s_smc *smc);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun init ECM state machine
97*4882a593Smuzhiyun clear all ECM vars and flags
98*4882a593Smuzhiyun */
ecm_init(struct s_smc * smc)99*4882a593Smuzhiyun void ecm_init(struct s_smc *smc)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun smc->e.path_test = PT_PASSED ;
102*4882a593Smuzhiyun smc->e.trace_prop = 0 ;
103*4882a593Smuzhiyun smc->e.sb_flag = 0 ;
104*4882a593Smuzhiyun smc->mib.fddiSMTECMState = ACTIONS(EC0_OUT) ;
105*4882a593Smuzhiyun smc->e.ecm_line_state = FALSE ;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /*
109*4882a593Smuzhiyun ECM state machine
110*4882a593Smuzhiyun called by dispatcher
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun do
113*4882a593Smuzhiyun display state change
114*4882a593Smuzhiyun process event
115*4882a593Smuzhiyun until SM is stable
116*4882a593Smuzhiyun */
ecm(struct s_smc * smc,int event)117*4882a593Smuzhiyun void ecm(struct s_smc *smc, int event)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun int state ;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun do {
122*4882a593Smuzhiyun DB_ECM("ECM : state %s%s event %s",
123*4882a593Smuzhiyun smc->mib.fddiSMTECMState & AFLAG ? "ACTIONS " : "",
124*4882a593Smuzhiyun ecm_states[smc->mib.fddiSMTECMState & ~AFLAG],
125*4882a593Smuzhiyun ecm_events[event]);
126*4882a593Smuzhiyun state = smc->mib.fddiSMTECMState ;
127*4882a593Smuzhiyun ecm_fsm(smc,event) ;
128*4882a593Smuzhiyun event = 0 ;
129*4882a593Smuzhiyun } while (state != smc->mib.fddiSMTECMState) ;
130*4882a593Smuzhiyun ecm_state_change(smc,(int)smc->mib.fddiSMTECMState) ;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /*
134*4882a593Smuzhiyun process ECM event
135*4882a593Smuzhiyun */
ecm_fsm(struct s_smc * smc,int cmd)136*4882a593Smuzhiyun static void ecm_fsm(struct s_smc *smc, int cmd)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun int ls_a ; /* current line state PHY A */
139*4882a593Smuzhiyun int ls_b ; /* current line state PHY B */
140*4882a593Smuzhiyun int p ; /* ports */
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
144*4882a593Smuzhiyun if (cmd == EC_CONNECT)
145*4882a593Smuzhiyun smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* For AIX event notification: */
148*4882a593Smuzhiyun /* Is a disconnect command remotely issued ? */
149*4882a593Smuzhiyun if (cmd == EC_DISCONNECT &&
150*4882a593Smuzhiyun smc->mib.fddiSMTRemoteDisconnectFlag == TRUE)
151*4882a593Smuzhiyun AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
152*4882a593Smuzhiyun FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
153*4882a593Smuzhiyun smt_get_error_word(smc) );
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/
156*4882a593Smuzhiyun if (cmd == EC_CONNECT) {
157*4882a593Smuzhiyun smc->e.DisconnectFlag = FALSE ;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT) {
160*4882a593Smuzhiyun smc->e.DisconnectFlag = TRUE ;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun switch(smc->mib.fddiSMTECMState) {
164*4882a593Smuzhiyun case ACTIONS(EC0_OUT) :
165*4882a593Smuzhiyun /*
166*4882a593Smuzhiyun * We do not perform a path test
167*4882a593Smuzhiyun */
168*4882a593Smuzhiyun smc->e.path_test = PT_PASSED ;
169*4882a593Smuzhiyun smc->e.ecm_line_state = FALSE ;
170*4882a593Smuzhiyun stop_ecm_timer(smc) ;
171*4882a593Smuzhiyun ACTIONS_DONE() ;
172*4882a593Smuzhiyun break ;
173*4882a593Smuzhiyun case EC0_OUT:
174*4882a593Smuzhiyun /*EC01*/
175*4882a593Smuzhiyun if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
176*4882a593Smuzhiyun && smc->e.path_test==PT_PASSED) {
177*4882a593Smuzhiyun GO_STATE(EC1_IN) ;
178*4882a593Smuzhiyun break ;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun /*EC05*/
181*4882a593Smuzhiyun else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
182*4882a593Smuzhiyun smc->mib.fddiSMTBypassPresent &&
183*4882a593Smuzhiyun (smc->s.sas == SMT_DAS)) {
184*4882a593Smuzhiyun GO_STATE(EC5_INSERT) ;
185*4882a593Smuzhiyun break ;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun break;
188*4882a593Smuzhiyun case ACTIONS(EC1_IN) :
189*4882a593Smuzhiyun stop_ecm_timer(smc) ;
190*4882a593Smuzhiyun smc->e.trace_prop = 0 ;
191*4882a593Smuzhiyun sm_ma_control(smc,MA_TREQ) ;
192*4882a593Smuzhiyun for (p = 0 ; p < NUMPHYS ; p++)
193*4882a593Smuzhiyun if (smc->mib.p[p].fddiPORTHardwarePresent)
194*4882a593Smuzhiyun queue_event(smc,EVENT_PCMA+p,PC_START) ;
195*4882a593Smuzhiyun ACTIONS_DONE() ;
196*4882a593Smuzhiyun break ;
197*4882a593Smuzhiyun case EC1_IN:
198*4882a593Smuzhiyun /*EC12*/
199*4882a593Smuzhiyun if (cmd == EC_TRACE_PROP) {
200*4882a593Smuzhiyun prop_actions(smc) ;
201*4882a593Smuzhiyun GO_STATE(EC2_TRACE) ;
202*4882a593Smuzhiyun break ;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun /*EC13*/
205*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT) {
206*4882a593Smuzhiyun GO_STATE(EC3_LEAVE) ;
207*4882a593Smuzhiyun break ;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun break;
210*4882a593Smuzhiyun case ACTIONS(EC2_TRACE) :
211*4882a593Smuzhiyun start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
212*4882a593Smuzhiyun EC_TIMEOUT_TMAX) ;
213*4882a593Smuzhiyun ACTIONS_DONE() ;
214*4882a593Smuzhiyun break ;
215*4882a593Smuzhiyun case EC2_TRACE :
216*4882a593Smuzhiyun /*EC22*/
217*4882a593Smuzhiyun if (cmd == EC_TRACE_PROP) {
218*4882a593Smuzhiyun prop_actions(smc) ;
219*4882a593Smuzhiyun GO_STATE(EC2_TRACE) ;
220*4882a593Smuzhiyun break ;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun /*EC23a*/
223*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT) {
224*4882a593Smuzhiyun smc->e.path_test = PT_EXITING ;
225*4882a593Smuzhiyun GO_STATE(EC3_LEAVE) ;
226*4882a593Smuzhiyun break ;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun /*EC23b*/
229*4882a593Smuzhiyun else if (smc->e.path_test == PT_PENDING) {
230*4882a593Smuzhiyun GO_STATE(EC3_LEAVE) ;
231*4882a593Smuzhiyun break ;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun /*EC23c*/
234*4882a593Smuzhiyun else if (cmd == EC_TIMEOUT_TMAX) {
235*4882a593Smuzhiyun /* Trace_Max is expired */
236*4882a593Smuzhiyun /* -> send AIX_EVENT */
237*4882a593Smuzhiyun AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
238*4882a593Smuzhiyun (u_long) FDDI_SMT_ERROR, (u_long)
239*4882a593Smuzhiyun FDDI_TRACE_MAX, smt_get_error_word(smc));
240*4882a593Smuzhiyun smc->e.path_test = PT_PENDING ;
241*4882a593Smuzhiyun GO_STATE(EC3_LEAVE) ;
242*4882a593Smuzhiyun break ;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun break ;
245*4882a593Smuzhiyun case ACTIONS(EC3_LEAVE) :
246*4882a593Smuzhiyun start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
247*4882a593Smuzhiyun for (p = 0 ; p < NUMPHYS ; p++)
248*4882a593Smuzhiyun queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
249*4882a593Smuzhiyun ACTIONS_DONE() ;
250*4882a593Smuzhiyun break ;
251*4882a593Smuzhiyun case EC3_LEAVE:
252*4882a593Smuzhiyun /*EC30*/
253*4882a593Smuzhiyun if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
254*4882a593Smuzhiyun (smc->e.path_test != PT_PENDING)) {
255*4882a593Smuzhiyun GO_STATE(EC0_OUT) ;
256*4882a593Smuzhiyun break ;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun /*EC34*/
259*4882a593Smuzhiyun else if (cmd == EC_TIMEOUT_TD &&
260*4882a593Smuzhiyun (smc->e.path_test == PT_PENDING)) {
261*4882a593Smuzhiyun GO_STATE(EC4_PATH_TEST) ;
262*4882a593Smuzhiyun break ;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun /*EC31*/
265*4882a593Smuzhiyun else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
266*4882a593Smuzhiyun GO_STATE(EC1_IN) ;
267*4882a593Smuzhiyun break ;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun /*EC33*/
270*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT &&
271*4882a593Smuzhiyun smc->e.path_test == PT_PENDING) {
272*4882a593Smuzhiyun smc->e.path_test = PT_EXITING ;
273*4882a593Smuzhiyun /*
274*4882a593Smuzhiyun * stay in state - state will be left via timeout
275*4882a593Smuzhiyun */
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun /*EC37*/
278*4882a593Smuzhiyun else if (cmd == EC_TIMEOUT_TD &&
279*4882a593Smuzhiyun smc->mib.fddiSMTBypassPresent &&
280*4882a593Smuzhiyun smc->e.path_test != PT_PENDING) {
281*4882a593Smuzhiyun GO_STATE(EC7_DEINSERT) ;
282*4882a593Smuzhiyun break ;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun break ;
285*4882a593Smuzhiyun case ACTIONS(EC4_PATH_TEST) :
286*4882a593Smuzhiyun stop_ecm_timer(smc) ;
287*4882a593Smuzhiyun smc->e.path_test = PT_TESTING ;
288*4882a593Smuzhiyun start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
289*4882a593Smuzhiyun /* now perform path test ... just a simulation */
290*4882a593Smuzhiyun ACTIONS_DONE() ;
291*4882a593Smuzhiyun break ;
292*4882a593Smuzhiyun case EC4_PATH_TEST :
293*4882a593Smuzhiyun /* path test done delay */
294*4882a593Smuzhiyun if (cmd == EC_TEST_DONE)
295*4882a593Smuzhiyun smc->e.path_test = PT_PASSED ;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (smc->e.path_test == PT_FAILED)
298*4882a593Smuzhiyun RS_SET(smc,RS_PATHTEST) ;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /*EC40a*/
301*4882a593Smuzhiyun if (smc->e.path_test == PT_FAILED &&
302*4882a593Smuzhiyun !smc->mib.fddiSMTBypassPresent) {
303*4882a593Smuzhiyun GO_STATE(EC0_OUT) ;
304*4882a593Smuzhiyun break ;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun /*EC40b*/
307*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT &&
308*4882a593Smuzhiyun !smc->mib.fddiSMTBypassPresent) {
309*4882a593Smuzhiyun GO_STATE(EC0_OUT) ;
310*4882a593Smuzhiyun break ;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun /*EC41*/
313*4882a593Smuzhiyun else if (smc->e.path_test == PT_PASSED) {
314*4882a593Smuzhiyun GO_STATE(EC1_IN) ;
315*4882a593Smuzhiyun break ;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun /*EC47a*/
318*4882a593Smuzhiyun else if (smc->e.path_test == PT_FAILED &&
319*4882a593Smuzhiyun smc->mib.fddiSMTBypassPresent) {
320*4882a593Smuzhiyun GO_STATE(EC7_DEINSERT) ;
321*4882a593Smuzhiyun break ;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun /*EC47b*/
324*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT &&
325*4882a593Smuzhiyun smc->mib.fddiSMTBypassPresent) {
326*4882a593Smuzhiyun GO_STATE(EC7_DEINSERT) ;
327*4882a593Smuzhiyun break ;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun break ;
330*4882a593Smuzhiyun case ACTIONS(EC5_INSERT) :
331*4882a593Smuzhiyun sm_pm_bypass_req(smc,BP_INSERT);
332*4882a593Smuzhiyun start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
333*4882a593Smuzhiyun ACTIONS_DONE() ;
334*4882a593Smuzhiyun break ;
335*4882a593Smuzhiyun case EC5_INSERT :
336*4882a593Smuzhiyun /*EC56*/
337*4882a593Smuzhiyun if (cmd == EC_TIMEOUT_INMAX) {
338*4882a593Smuzhiyun GO_STATE(EC6_CHECK) ;
339*4882a593Smuzhiyun break ;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun /*EC57*/
342*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT) {
343*4882a593Smuzhiyun GO_STATE(EC7_DEINSERT) ;
344*4882a593Smuzhiyun break ;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun break ;
347*4882a593Smuzhiyun case ACTIONS(EC6_CHECK) :
348*4882a593Smuzhiyun /*
349*4882a593Smuzhiyun * in EC6_CHECK, we *POLL* the line state !
350*4882a593Smuzhiyun * check whether both bypass switches have switched.
351*4882a593Smuzhiyun */
352*4882a593Smuzhiyun start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
353*4882a593Smuzhiyun smc->e.ecm_line_state = TRUE ; /* flag to pcm: report Q/HLS */
354*4882a593Smuzhiyun ACTIONS_DONE() ;
355*4882a593Smuzhiyun break ;
356*4882a593Smuzhiyun case EC6_CHECK :
357*4882a593Smuzhiyun ls_a = sm_pm_get_ls(smc,PA) ;
358*4882a593Smuzhiyun ls_b = sm_pm_get_ls(smc,PB) ;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun /*EC61*/
361*4882a593Smuzhiyun if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) &&
362*4882a593Smuzhiyun ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) {
363*4882a593Smuzhiyun smc->e.sb_flag = FALSE ;
364*4882a593Smuzhiyun smc->e.ecm_line_state = FALSE ;
365*4882a593Smuzhiyun GO_STATE(EC1_IN) ;
366*4882a593Smuzhiyun break ;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun /*EC66*/
369*4882a593Smuzhiyun else if (!smc->e.sb_flag &&
370*4882a593Smuzhiyun (((ls_a == PC_ILS) && (ls_b == PC_QLS)) ||
371*4882a593Smuzhiyun ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){
372*4882a593Smuzhiyun smc->e.sb_flag = TRUE ;
373*4882a593Smuzhiyun DB_ECMN(1, "ECM : EC6_CHECK - stuck bypass");
374*4882a593Smuzhiyun AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
375*4882a593Smuzhiyun FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK,
376*4882a593Smuzhiyun smt_get_error_word(smc));
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun /*EC67*/
379*4882a593Smuzhiyun else if (cmd == EC_DISCONNECT) {
380*4882a593Smuzhiyun smc->e.ecm_line_state = FALSE ;
381*4882a593Smuzhiyun GO_STATE(EC7_DEINSERT) ;
382*4882a593Smuzhiyun break ;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun else {
385*4882a593Smuzhiyun /*
386*4882a593Smuzhiyun * restart poll
387*4882a593Smuzhiyun */
388*4882a593Smuzhiyun start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun break ;
391*4882a593Smuzhiyun case ACTIONS(EC7_DEINSERT) :
392*4882a593Smuzhiyun sm_pm_bypass_req(smc,BP_DEINSERT);
393*4882a593Smuzhiyun start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ;
394*4882a593Smuzhiyun ACTIONS_DONE() ;
395*4882a593Smuzhiyun break ;
396*4882a593Smuzhiyun case EC7_DEINSERT:
397*4882a593Smuzhiyun /*EC70*/
398*4882a593Smuzhiyun if (cmd == EC_TIMEOUT_IMAX) {
399*4882a593Smuzhiyun GO_STATE(EC0_OUT) ;
400*4882a593Smuzhiyun break ;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun /*EC75*/
403*4882a593Smuzhiyun else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
404*4882a593Smuzhiyun GO_STATE(EC5_INSERT) ;
405*4882a593Smuzhiyun break ;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun break;
408*4882a593Smuzhiyun default:
409*4882a593Smuzhiyun SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ;
410*4882a593Smuzhiyun break;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun #ifndef CONCENTRATOR
415*4882a593Smuzhiyun /*
416*4882a593Smuzhiyun * trace propagation actions for SAS & DAS
417*4882a593Smuzhiyun */
prop_actions(struct s_smc * smc)418*4882a593Smuzhiyun static void prop_actions(struct s_smc *smc)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun int port_in = 0 ;
421*4882a593Smuzhiyun int port_out = 0 ;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun RS_SET(smc,RS_EVENT) ;
424*4882a593Smuzhiyun switch (smc->s.sas) {
425*4882a593Smuzhiyun case SMT_SAS :
426*4882a593Smuzhiyun port_in = port_out = pcm_get_s_port(smc) ;
427*4882a593Smuzhiyun break ;
428*4882a593Smuzhiyun case SMT_DAS :
429*4882a593Smuzhiyun port_in = cfm_get_mac_input(smc) ; /* PA or PB */
430*4882a593Smuzhiyun port_out = cfm_get_mac_output(smc) ; /* PA or PB */
431*4882a593Smuzhiyun break ;
432*4882a593Smuzhiyun case SMT_NAC :
433*4882a593Smuzhiyun SMT_PANIC(smc,SMT_E0108, SMT_E0108_MSG) ;
434*4882a593Smuzhiyun return ;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun DB_ECM("ECM : prop_actions - trace_prop %lu", smc->e.trace_prop);
438*4882a593Smuzhiyun DB_ECM("ECM : prop_actions - in %d out %d", port_in, port_out);
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
441*4882a593Smuzhiyun /* trace initiatior */
442*4882a593Smuzhiyun DB_ECM("ECM : initiate TRACE on PHY %c", 'A' + port_in - PA);
443*4882a593Smuzhiyun queue_event(smc,EVENT_PCM+port_in,PC_TRACE) ;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PA))) &&
446*4882a593Smuzhiyun port_out != PA) {
447*4882a593Smuzhiyun /* trace propagate upstream */
448*4882a593Smuzhiyun DB_ECM("ECM : propagate TRACE on PHY B");
449*4882a593Smuzhiyun queue_event(smc,EVENT_PCMB,PC_TRACE) ;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PB))) &&
452*4882a593Smuzhiyun port_out != PB) {
453*4882a593Smuzhiyun /* trace propagate upstream */
454*4882a593Smuzhiyun DB_ECM("ECM : propagate TRACE on PHY A");
455*4882a593Smuzhiyun queue_event(smc,EVENT_PCMA,PC_TRACE) ;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun else {
458*4882a593Smuzhiyun /* signal trace termination */
459*4882a593Smuzhiyun DB_ECM("ECM : TRACE terminated");
460*4882a593Smuzhiyun smc->e.path_test = PT_PENDING ;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun smc->e.trace_prop = 0 ;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun #else
465*4882a593Smuzhiyun /*
466*4882a593Smuzhiyun * trace propagation actions for Concentrator
467*4882a593Smuzhiyun */
prop_actions(struct s_smc * smc)468*4882a593Smuzhiyun static void prop_actions(struct s_smc *smc)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun int initiator ;
471*4882a593Smuzhiyun int upstream ;
472*4882a593Smuzhiyun int p ;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun RS_SET(smc,RS_EVENT) ;
475*4882a593Smuzhiyun while (smc->e.trace_prop) {
476*4882a593Smuzhiyun DB_ECM("ECM : prop_actions - trace_prop %d",
477*4882a593Smuzhiyun smc->e.trace_prop);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
480*4882a593Smuzhiyun initiator = ENTITY_MAC ;
481*4882a593Smuzhiyun smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_MAC) ;
482*4882a593Smuzhiyun DB_ECM("ECM: MAC initiates trace");
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun else {
485*4882a593Smuzhiyun for (p = NUMPHYS-1 ; p >= 0 ; p--) {
486*4882a593Smuzhiyun if (smc->e.trace_prop &
487*4882a593Smuzhiyun ENTITY_BIT(ENTITY_PHY(p)))
488*4882a593Smuzhiyun break ;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun initiator = ENTITY_PHY(p) ;
491*4882a593Smuzhiyun smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_PHY(p)) ;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun upstream = cem_get_upstream(smc,initiator) ;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if (upstream == ENTITY_MAC) {
496*4882a593Smuzhiyun /* signal trace termination */
497*4882a593Smuzhiyun DB_ECM("ECM : TRACE terminated");
498*4882a593Smuzhiyun smc->e.path_test = PT_PENDING ;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun else {
501*4882a593Smuzhiyun /* trace propagate upstream */
502*4882a593Smuzhiyun DB_ECM("ECM : propagate TRACE on PHY %d", upstream);
503*4882a593Smuzhiyun queue_event(smc,EVENT_PCM+upstream,PC_TRACE) ;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun #endif
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun /*
511*4882a593Smuzhiyun * SMT timer interface
512*4882a593Smuzhiyun * start ECM timer
513*4882a593Smuzhiyun */
start_ecm_timer(struct s_smc * smc,u_long value,int event)514*4882a593Smuzhiyun static void start_ecm_timer(struct s_smc *smc, u_long value, int event)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event));
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun /*
520*4882a593Smuzhiyun * SMT timer interface
521*4882a593Smuzhiyun * stop ECM timer
522*4882a593Smuzhiyun */
stop_ecm_timer(struct s_smc * smc)523*4882a593Smuzhiyun static void stop_ecm_timer(struct s_smc *smc)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun if (smc->e.ecm_timer.tm_active)
526*4882a593Smuzhiyun smt_timer_stop(smc,&smc->e.ecm_timer) ;
527*4882a593Smuzhiyun }
528