Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / net / i4b / layer1 / isic / i4b_l1fsm.c
1 /*
2  * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_l1fsm.c - isdn4bsd layer 1 I.430 state machine
28  *      --------------------------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/layer1/isic/i4b_l1fsm.c,v 1.5.2.1 2001/08/10 14:08:38 obrien Exp $
31  *
32  *      last edit-date: [Wed Jan 24 09:12:18 2001]
33  *
34  *---------------------------------------------------------------------------*/
35
36 #include "isic.h"
37
38 #if NISIC > 0
39
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/systm.h>
43 #include <sys/socket.h>
44
45 #include <net/if.h>
46
47 #include <machine/i4b_debug.h>
48 #include <machine/i4b_ioctl.h>
49 #include <machine/i4b_trace.h>
50
51 #include <i4b/layer1/isic/i4b_isic.h>
52
53 #include <i4b/layer1/i4b_l1.h>
54
55 #include <i4b/include/i4b_global.h>
56
57 #include <i4b/include/i4b_mbuf.h>
58
59 #if DO_I4B_DEBUG
60 static char *state_text[N_STATES] = {
61         "F3 Deactivated",
62         "F4 Awaiting Signal",
63         "F5 Identifying Input",
64         "F6 Synchronized",
65         "F7 Activated",
66         "F8 Lost Framing",
67         "Illegal State" 
68 };
69
70 static char *event_text[N_EVENTS] = {
71         "EV_PHAR PH_ACT_REQ",
72         "EV_T3 Timer 3 expired",
73         "EV_INFO0 INFO0 received",
74         "EV_RSY Level Detected",
75         "EV_INFO2 INFO2 received",
76         "EV_INFO48 INFO4 received",
77         "EV_INFO410 INFO4 received",
78         "EV_DR Deactivate Req",
79         "EV_PU Power UP",
80         "EV_DIS Disconnected",
81         "EV_EI Error Ind",
82         "Illegal Event"
83 };
84 #endif
85
86 /* Function prototypes */
87
88 static void timer3_expired (struct l1_softc *sc);
89 static void T3_start (struct l1_softc *sc);
90 static void T3_stop (struct l1_softc *sc);
91 static void F_T3ex (struct l1_softc *sc);
92 static void timer4_expired (struct l1_softc *sc);
93 static void T4_start (struct l1_softc *sc);
94 static void T4_stop (struct l1_softc *sc);
95 static void F_AI8 (struct l1_softc *sc);
96 static void F_AI10 (struct l1_softc *sc);
97 static void F_I01 (struct l1_softc *sc);
98 static void F_I02 (struct l1_softc *sc);
99 static void F_I03 (struct l1_softc *sc);
100 static void F_I2 (struct l1_softc *sc);
101 static void F_ill (struct l1_softc *sc);
102 static void F_NULL (struct l1_softc *sc);
103
104 /*---------------------------------------------------------------------------*
105  *      I.430 Timer T3 expire function
106  *---------------------------------------------------------------------------*/ 
107 static void
108 timer3_expired(struct l1_softc *sc)
109 {
110         if(sc->sc_I430T3)
111         {
112                 NDBGL1(L1_T_ERR, "state = %s", isic_printstate(sc));
113                 sc->sc_I430T3 = 0;
114
115                 /* XXX try some recovery here XXX */
116
117                 isic_recover(sc);
118
119                 sc->sc_init_tries++;    /* increment retry count */
120
121 /*XXX*/         if(sc->sc_init_tries > 4)
122                 {
123                         int s = SPLI4B();
124
125                         sc->sc_init_tries = 0;
126                         
127                         if(sc->sc_obuf2 != NULL)
128                         {
129                                 i4b_Dfreembuf(sc->sc_obuf2);
130                                 sc->sc_obuf2 = NULL;
131                         }
132                         if(sc->sc_obuf != NULL)
133                         {
134                                 i4b_Dfreembuf(sc->sc_obuf);
135                                 sc->sc_obuf = NULL;
136                                 sc->sc_freeflag = 0;
137                                 sc->sc_op = NULL;
138                                 sc->sc_ol = 0;
139                         }
140
141                         splx(s);
142
143                         i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_NOL1ACC, 0, NULL);
144                 }
145                 
146                 isic_next_state(sc, EV_T3);             
147         }
148         else
149         {
150                 NDBGL1(L1_T_ERR, "expired without starting it ....");
151         }
152 }
153
154 /*---------------------------------------------------------------------------*
155  *      I.430 Timer T3 start
156  *---------------------------------------------------------------------------*/ 
157 static void
158 T3_start(struct l1_softc *sc)
159 {
160         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
161         sc->sc_I430T3 = 1;
162         sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, 2*hz);
163 }
164
165 /*---------------------------------------------------------------------------*
166  *      I.430 Timer T3 stop
167  *---------------------------------------------------------------------------*/ 
168 static void
169 T3_stop(struct l1_softc *sc)
170 {
171         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
172
173         sc->sc_init_tries = 0;  /* init connect retry count */
174         
175         if(sc->sc_I430T3)
176         {
177                 sc->sc_I430T3 = 0;
178                 untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, sc->sc_T3_callout);
179         }
180 }
181
182 /*---------------------------------------------------------------------------*
183  *      I.430 Timer T3 expiry
184  *---------------------------------------------------------------------------*/ 
185 static void
186 F_T3ex(struct l1_softc *sc)
187 {
188         NDBGL1(L1_F_MSG, "FSM function F_T3ex executing");
189         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
190                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
191 }
192
193 /*---------------------------------------------------------------------------*
194  *      Timer T4 expire function
195  *---------------------------------------------------------------------------*/ 
196 static void
197 timer4_expired(struct l1_softc *sc)
198 {
199         if(sc->sc_I430T4)
200         {
201                 NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
202                 sc->sc_I430T4 = 0;
203                 i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_PDEACT, 0, NULL);
204         }
205         else
206         {
207                 NDBGL1(L1_T_ERR, "expired without starting it ....");
208         }
209 }
210
211 /*---------------------------------------------------------------------------*
212  *      Timer T4 start
213  *---------------------------------------------------------------------------*/ 
214 static void
215 T4_start(struct l1_softc *sc)
216 {
217         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
218         sc->sc_I430T4 = 1;
219         sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, hz);
220 }
221
222 /*---------------------------------------------------------------------------*
223  *      Timer T4 stop
224  *---------------------------------------------------------------------------*/ 
225 static void
226 T4_stop(struct l1_softc *sc)
227 {
228         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
229
230         if(sc->sc_I430T4)
231         {
232                 sc->sc_I430T4 = 0;
233                 untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, sc->sc_T4_callout);
234         }
235 }
236
237 /*---------------------------------------------------------------------------*
238  *      FSM function: received AI8
239  *---------------------------------------------------------------------------*/ 
240 static void
241 F_AI8(struct l1_softc *sc)
242 {
243         T4_stop(sc);
244
245         NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
246
247         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
248                 i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
249
250         T3_stop(sc);
251
252         if(sc->sc_trace & TRACE_I)
253         {
254                 i4b_trace_hdr_t hdr;
255                 char info = INFO4_8;
256                 
257                 hdr.unit = L0ISICUNIT(sc->sc_unit);
258                 hdr.type = TRC_CH_I;
259                 hdr.dir = FROM_NT;
260                 hdr.count = 0;
261                 MICROTIME(hdr.time);
262                 i4b_l1_trace_ind(&hdr, 1, &info);
263         }
264 }
265
266 /*---------------------------------------------------------------------------*
267  *      FSM function: received AI10
268  *---------------------------------------------------------------------------*/ 
269 static void
270 F_AI10(struct l1_softc *sc)
271 {
272         T4_stop(sc);
273         
274         NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
275
276         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
277                 i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
278
279         T3_stop(sc);
280
281         if(sc->sc_trace & TRACE_I)
282         {
283                 i4b_trace_hdr_t hdr;
284                 char info = INFO4_10;
285                 
286                 hdr.unit = L0ISICUNIT(sc->sc_unit);
287                 hdr.type = TRC_CH_I;
288                 hdr.dir = FROM_NT;
289                 hdr.count = 0;
290                 MICROTIME(hdr.time);
291                 i4b_l1_trace_ind(&hdr, 1, &info);
292         }
293 }
294
295 /*---------------------------------------------------------------------------*
296  *      FSM function: received INFO 0 in states F3 .. F5
297  *---------------------------------------------------------------------------*/ 
298 static void
299 F_I01(struct l1_softc *sc)
300 {
301         NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
302
303         if(sc->sc_trace & TRACE_I)
304         {
305                 i4b_trace_hdr_t hdr;
306                 char info = INFO0;
307                 
308                 hdr.unit = L0ISICUNIT(sc->sc_unit);
309                 hdr.type = TRC_CH_I;
310                 hdr.dir = FROM_NT;
311                 hdr.count = 0;
312                 MICROTIME(hdr.time);
313                 i4b_l1_trace_ind(&hdr, 1, &info);
314         }
315 }
316
317 /*---------------------------------------------------------------------------*
318  *      FSM function: received INFO 0 in state F6
319  *---------------------------------------------------------------------------*/ 
320 static void
321 F_I02(struct l1_softc *sc)
322 {
323         NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
324
325         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
326                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
327
328         if(sc->sc_trace & TRACE_I)
329         {
330                 i4b_trace_hdr_t hdr;
331                 char info = INFO0;
332                 
333                 hdr.unit = L0ISICUNIT(sc->sc_unit);
334                 hdr.type = TRC_CH_I;
335                 hdr.dir = FROM_NT;
336                 hdr.count = 0;
337                 MICROTIME(hdr.time);
338                 i4b_l1_trace_ind(&hdr, 1, &info);
339         }
340 }
341
342 /*---------------------------------------------------------------------------*
343  *      FSM function: received INFO 0 in state F7 or F8
344  *---------------------------------------------------------------------------*/ 
345 static void
346 F_I03(struct l1_softc *sc)
347 {
348         NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
349
350         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
351                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
352
353         T4_start(sc);
354         
355         if(sc->sc_trace & TRACE_I)
356         {
357                 i4b_trace_hdr_t hdr;
358                 char info = INFO0;
359                 
360                 hdr.unit = L0ISICUNIT(sc->sc_unit);
361                 hdr.type = TRC_CH_I;
362                 hdr.dir = FROM_NT;
363                 hdr.count = 0;
364                 MICROTIME(hdr.time);
365                 i4b_l1_trace_ind(&hdr, 1, &info);
366         }
367 }
368
369 /*---------------------------------------------------------------------------*
370  *      FSM function: activate request
371  *---------------------------------------------------------------------------*/ 
372 static void
373 F_AR(struct l1_softc *sc)
374 {
375         NDBGL1(L1_F_MSG, "FSM function F_AR executing");
376
377         if(sc->sc_trace & TRACE_I)
378         {
379                 i4b_trace_hdr_t hdr;
380                 char info = INFO1_8;
381                 
382                 hdr.unit = L0ISICUNIT(sc->sc_unit);
383                 hdr.type = TRC_CH_I;
384                 hdr.dir = FROM_TE;
385                 hdr.count = 0;
386                 MICROTIME(hdr.time);
387                 i4b_l1_trace_ind(&hdr, 1, &info);
388         }
389
390         isic_isac_l1_cmd(sc, CMD_AR8);
391
392         T3_start(sc);
393 }
394
395 /*---------------------------------------------------------------------------*
396  *      FSM function: received INFO2
397  *---------------------------------------------------------------------------*/ 
398 static void
399 F_I2(struct l1_softc *sc)
400 {
401         NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
402
403         if(sc->sc_trace & TRACE_I)
404         {
405                 i4b_trace_hdr_t hdr;
406                 char info = INFO2;
407                 
408                 hdr.unit = L0ISICUNIT(sc->sc_unit);
409                 hdr.type = TRC_CH_I;
410                 hdr.dir = FROM_NT;
411                 hdr.count = 0;
412                 MICROTIME(hdr.time);
413                 i4b_l1_trace_ind(&hdr, 1, &info);
414         }               
415
416 }
417
418 /*---------------------------------------------------------------------------*
419  *      illegal state default action
420  *---------------------------------------------------------------------------*/ 
421 static void
422 F_ill(struct l1_softc *sc)
423 {
424         NDBGL1(L1_F_ERR, "FSM function F_ill executing");
425 }
426
427 /*---------------------------------------------------------------------------*
428  *      No action
429  *---------------------------------------------------------------------------*/ 
430 static void
431 F_NULL(struct l1_softc *sc)
432 {
433         NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
434 }
435
436
437 /*---------------------------------------------------------------------------*
438  *      layer 1 state transition table
439  *---------------------------------------------------------------------------*/ 
440 struct isic_state_tab {
441         void (*func) (struct l1_softc *sc);     /* function to execute */
442         int newstate;                           /* next state */
443 } isic_state_tab[N_EVENTS][N_STATES] = {
444
445 /* STATE:       F3                      F4                      F5                      F6                      F7                      F8                      ILLEGAL STATE     */
446 /* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
447 /* EV_PHAR x*/  {{F_AR,   ST_F4},       {F_NULL, ST_F4},        {F_NULL, ST_F5},        {F_NULL, ST_F6},        {F_ill,  ST_ILL},       {F_NULL, ST_F8},        {F_ill, ST_ILL}},
448 /* EV_T3   x*/  {{F_NULL, ST_F3},       {F_T3ex, ST_F3},        {F_T3ex, ST_F3},        {F_T3ex, ST_F3},        {F_NULL, ST_F7},        {F_NULL, ST_F8},        {F_ill, ST_ILL}},
449 /* EV_INFO0 */  {{F_I01,  ST_F3},       {F_I01,  ST_F4},        {F_I01,  ST_F5},        {F_I02,  ST_F3},        {F_I03,  ST_F3},        {F_I03,  ST_F3},        {F_ill, ST_ILL}},
450 /* EV_RSY  x*/  {{F_NULL, ST_F3},       {F_NULL, ST_F5},        {F_NULL, ST_F5},        {F_NULL, ST_F8},        {F_NULL, ST_F8},        {F_NULL, ST_F8},        {F_ill, ST_ILL}},
451 /* EV_INFO2 */  {{F_I2,   ST_F6},       {F_I2,   ST_F6},        {F_I2,   ST_F6},        {F_I2,   ST_F6},        {F_I2,   ST_F6},        {F_I2,   ST_F6},        {F_ill, ST_ILL}},
452 /* EV_INFO48*/  {{F_AI8,  ST_F7},       {F_AI8,  ST_F7},        {F_AI8,  ST_F7},        {F_AI8,  ST_F7},        {F_NULL, ST_F7},        {F_AI8,  ST_F7},        {F_ill, ST_ILL}},
453 /* EV_INFO41*/  {{F_AI10, ST_F7},       {F_AI10, ST_F7},        {F_AI10, ST_F7},        {F_AI10, ST_F7},        {F_NULL, ST_F7},        {F_AI10, ST_F7},        {F_ill, ST_ILL}},
454 /* EV_DR    */  {{F_NULL, ST_F3},       {F_NULL, ST_F4},        {F_NULL, ST_F5},        {F_NULL, ST_F6},        {F_NULL, ST_F7},        {F_NULL, ST_F8},        {F_ill, ST_ILL}},
455 /* EV_PU    */  {{F_NULL, ST_F3},       {F_NULL, ST_F4},        {F_NULL, ST_F5},        {F_NULL, ST_F6},        {F_NULL, ST_F7},        {F_NULL, ST_F8},        {F_ill, ST_ILL}},
456 /* EV_DIS   */  {{F_ill,  ST_ILL},      {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill, ST_ILL}},
457 /* EV_EI    */  {{F_NULL, ST_F3},       {F_NULL, ST_F3},        {F_NULL, ST_F3},        {F_NULL, ST_F3},        {F_NULL, ST_F3},        {F_NULL, ST_F3},        {F_ill, ST_ILL}},
458 /* EV_ILL   */  {{F_ill,  ST_ILL},      {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill,  ST_ILL},       {F_ill, ST_ILL}}
459 };
460
461 /*---------------------------------------------------------------------------*
462  *      event handler
463  *---------------------------------------------------------------------------*/ 
464 void
465 isic_next_state(struct l1_softc *sc, int event)
466 {
467         int currstate, newstate;
468
469         if(event >= N_EVENTS)
470                 panic("i4b_l1fsm.c: event >= N_EVENTS\n");
471
472         currstate = sc->sc_I430state;
473
474         if(currstate >= N_STATES)
475                 panic("i4b_l1fsm.c: currstate >= N_STATES\n");  
476
477         newstate = isic_state_tab[event][currstate].newstate;
478
479         if(newstate >= N_STATES)
480                 panic("i4b_l1fsm.c: newstate >= N_STATES\n");   
481         
482         NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
483                                            state_text[currstate],
484                                            state_text[newstate]);
485
486         (*isic_state_tab[event][currstate].func)(sc);
487
488         if(newstate == ST_ILL)
489         {
490                 newstate = ST_F3;
491                 NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
492                                         state_text[currstate],
493                                         state_text[newstate],
494                                         event_text[event]);
495         }
496
497         sc->sc_I430state = newstate;
498 }
499
500 #if DO_I4B_DEBUG
501 /*---------------------------------------------------------------------------*
502  *      return pointer to current state description
503  *---------------------------------------------------------------------------*/ 
504 char *
505 isic_printstate(struct l1_softc *sc)
506 {
507         return((char *) state_text[sc->sc_I430state]);
508 }
509 #endif
510         
511 #endif /* NISIC > 0 */
512