Merge from vendor branch HEIMDAL:
[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  * $DragonFly: src/sys/net/i4b/layer1/isic/i4b_l1fsm.c,v 1.4 2004/09/16 04:36:32 dillon Exp $
32  *
33  *      last edit-date: [Wed Jan 24 09:12:18 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #include "use_isic.h"
38
39 #if NISIC > 0
40
41 #include <sys/param.h>
42 #include <sys/kernel.h>
43 #include <sys/systm.h>
44 #include <sys/socket.h>
45
46 #include <net/if.h>
47
48 #include <net/i4b/include/machine/i4b_debug.h>
49 #include <net/i4b/include/machine/i4b_ioctl.h>
50 #include <net/i4b/include/machine/i4b_trace.h>
51
52 #include "i4b_isic.h"
53
54 #include "../i4b_l1.h"
55 #include "../../include/i4b_global.h"
56 #include "../../include/i4b_mbuf.h"
57
58 #if DO_I4B_DEBUG
59 static char *state_text[N_STATES] = {
60         "F3 Deactivated",
61         "F4 Awaiting Signal",
62         "F5 Identifying Input",
63         "F6 Synchronized",
64         "F7 Activated",
65         "F8 Lost Framing",
66         "Illegal State" 
67 };
68
69 static char *event_text[N_EVENTS] = {
70         "EV_PHAR PH_ACT_REQ",
71         "EV_T3 Timer 3 expired",
72         "EV_INFO0 INFO0 received",
73         "EV_RSY Level Detected",
74         "EV_INFO2 INFO2 received",
75         "EV_INFO48 INFO4 received",
76         "EV_INFO410 INFO4 received",
77         "EV_DR Deactivate Req",
78         "EV_PU Power UP",
79         "EV_DIS Disconnected",
80         "EV_EI Error Ind",
81         "Illegal Event"
82 };
83 #endif
84
85 /* Function prototypes */
86
87 static void timer3_expired (struct l1_softc *sc);
88 static void T3_start (struct l1_softc *sc);
89 static void T3_stop (struct l1_softc *sc);
90 static void F_T3ex (struct l1_softc *sc);
91 static void timer4_expired (struct l1_softc *sc);
92 static void T4_start (struct l1_softc *sc);
93 static void T4_stop (struct l1_softc *sc);
94 static void F_AI8 (struct l1_softc *sc);
95 static void F_AI10 (struct l1_softc *sc);
96 static void F_I01 (struct l1_softc *sc);
97 static void F_I02 (struct l1_softc *sc);
98 static void F_I03 (struct l1_softc *sc);
99 static void F_I2 (struct l1_softc *sc);
100 static void F_ill (struct l1_softc *sc);
101 static void F_NULL (struct l1_softc *sc);
102
103 /*---------------------------------------------------------------------------*
104  *      I.430 Timer T3 expire function
105  *---------------------------------------------------------------------------*/ 
106 static void
107 timer3_expired(struct l1_softc *sc)
108 {
109         if(sc->sc_I430T3)
110         {
111                 NDBGL1(L1_T_ERR, "state = %s", isic_printstate(sc));
112                 sc->sc_I430T3 = 0;
113
114                 /* XXX try some recovery here XXX */
115
116                 isic_recover(sc);
117
118                 sc->sc_init_tries++;    /* increment retry count */
119
120 /*XXX*/         if(sc->sc_init_tries > 4)
121                 {
122                         int s = SPLI4B();
123
124                         sc->sc_init_tries = 0;
125                         
126                         if(sc->sc_obuf2 != NULL)
127                         {
128                                 i4b_Dfreembuf(sc->sc_obuf2);
129                                 sc->sc_obuf2 = NULL;
130                         }
131                         if(sc->sc_obuf != NULL)
132                         {
133                                 i4b_Dfreembuf(sc->sc_obuf);
134                                 sc->sc_obuf = NULL;
135                                 sc->sc_freeflag = 0;
136                                 sc->sc_op = NULL;
137                                 sc->sc_ol = 0;
138                         }
139
140                         splx(s);
141
142                         i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_NOL1ACC, 0, NULL);
143                 }
144                 
145                 isic_next_state(sc, EV_T3);             
146         }
147         else
148         {
149                 NDBGL1(L1_T_ERR, "expired without starting it ....");
150         }
151 }
152
153 /*---------------------------------------------------------------------------*
154  *      I.430 Timer T3 start
155  *---------------------------------------------------------------------------*/ 
156 static void
157 T3_start(struct l1_softc *sc)
158 {
159         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
160         sc->sc_I430T3 = 1;
161         callout_reset(&sc->sc_T3_timeout, 2 * hz,
162                         (TIMEOUT_FUNC_T)timer3_expired, (struct l1_softc *)sc);
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                 callout_stop(&sc->sc_T3_timeout);
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         callout_reset(&sc->sc_T4_timeout, hz,
220                         (TIMEOUT_FUNC_T)timer4_expired, (struct l1_softc *)sc);
221 }
222
223 /*---------------------------------------------------------------------------*
224  *      Timer T4 stop
225  *---------------------------------------------------------------------------*/ 
226 static void
227 T4_stop(struct l1_softc *sc)
228 {
229         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
230
231         if(sc->sc_I430T4)
232         {
233                 sc->sc_I430T4 = 0;
234                 callout_stop(&sc->sc_T4_timeout);
235         }
236 }
237
238 /*---------------------------------------------------------------------------*
239  *      FSM function: received AI8
240  *---------------------------------------------------------------------------*/ 
241 static void
242 F_AI8(struct l1_softc *sc)
243 {
244         T4_stop(sc);
245
246         NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
247
248         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
249                 i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
250
251         T3_stop(sc);
252
253         if(sc->sc_trace & TRACE_I)
254         {
255                 i4b_trace_hdr_t hdr;
256                 char info = INFO4_8;
257                 
258                 hdr.unit = L0ISICUNIT(sc->sc_unit);
259                 hdr.type = TRC_CH_I;
260                 hdr.dir = FROM_NT;
261                 hdr.count = 0;
262                 MICROTIME(hdr.time);
263                 i4b_l1_trace_ind(&hdr, 1, &info);
264         }
265 }
266
267 /*---------------------------------------------------------------------------*
268  *      FSM function: received AI10
269  *---------------------------------------------------------------------------*/ 
270 static void
271 F_AI10(struct l1_softc *sc)
272 {
273         T4_stop(sc);
274         
275         NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
276
277         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
278                 i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
279
280         T3_stop(sc);
281
282         if(sc->sc_trace & TRACE_I)
283         {
284                 i4b_trace_hdr_t hdr;
285                 char info = INFO4_10;
286                 
287                 hdr.unit = L0ISICUNIT(sc->sc_unit);
288                 hdr.type = TRC_CH_I;
289                 hdr.dir = FROM_NT;
290                 hdr.count = 0;
291                 MICROTIME(hdr.time);
292                 i4b_l1_trace_ind(&hdr, 1, &info);
293         }
294 }
295
296 /*---------------------------------------------------------------------------*
297  *      FSM function: received INFO 0 in states F3 .. F5
298  *---------------------------------------------------------------------------*/ 
299 static void
300 F_I01(struct l1_softc *sc)
301 {
302         NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
303
304         if(sc->sc_trace & TRACE_I)
305         {
306                 i4b_trace_hdr_t hdr;
307                 char info = INFO0;
308                 
309                 hdr.unit = L0ISICUNIT(sc->sc_unit);
310                 hdr.type = TRC_CH_I;
311                 hdr.dir = FROM_NT;
312                 hdr.count = 0;
313                 MICROTIME(hdr.time);
314                 i4b_l1_trace_ind(&hdr, 1, &info);
315         }
316 }
317
318 /*---------------------------------------------------------------------------*
319  *      FSM function: received INFO 0 in state F6
320  *---------------------------------------------------------------------------*/ 
321 static void
322 F_I02(struct l1_softc *sc)
323 {
324         NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
325
326         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
327                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
328
329         if(sc->sc_trace & TRACE_I)
330         {
331                 i4b_trace_hdr_t hdr;
332                 char info = INFO0;
333                 
334                 hdr.unit = L0ISICUNIT(sc->sc_unit);
335                 hdr.type = TRC_CH_I;
336                 hdr.dir = FROM_NT;
337                 hdr.count = 0;
338                 MICROTIME(hdr.time);
339                 i4b_l1_trace_ind(&hdr, 1, &info);
340         }
341 }
342
343 /*---------------------------------------------------------------------------*
344  *      FSM function: received INFO 0 in state F7 or F8
345  *---------------------------------------------------------------------------*/ 
346 static void
347 F_I03(struct l1_softc *sc)
348 {
349         NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
350
351         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
352                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
353
354         T4_start(sc);
355         
356         if(sc->sc_trace & TRACE_I)
357         {
358                 i4b_trace_hdr_t hdr;
359                 char info = INFO0;
360                 
361                 hdr.unit = L0ISICUNIT(sc->sc_unit);
362                 hdr.type = TRC_CH_I;
363                 hdr.dir = FROM_NT;
364                 hdr.count = 0;
365                 MICROTIME(hdr.time);
366                 i4b_l1_trace_ind(&hdr, 1, &info);
367         }
368 }
369
370 /*---------------------------------------------------------------------------*
371  *      FSM function: activate request
372  *---------------------------------------------------------------------------*/ 
373 static void
374 F_AR(struct l1_softc *sc)
375 {
376         NDBGL1(L1_F_MSG, "FSM function F_AR executing");
377
378         if(sc->sc_trace & TRACE_I)
379         {
380                 i4b_trace_hdr_t hdr;
381                 char info = INFO1_8;
382                 
383                 hdr.unit = L0ISICUNIT(sc->sc_unit);
384                 hdr.type = TRC_CH_I;
385                 hdr.dir = FROM_TE;
386                 hdr.count = 0;
387                 MICROTIME(hdr.time);
388                 i4b_l1_trace_ind(&hdr, 1, &info);
389         }
390
391         isic_isac_l1_cmd(sc, CMD_AR8);
392
393         T3_start(sc);
394 }
395
396 /*---------------------------------------------------------------------------*
397  *      FSM function: received INFO2
398  *---------------------------------------------------------------------------*/ 
399 static void
400 F_I2(struct l1_softc *sc)
401 {
402         NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
403
404         if(sc->sc_trace & TRACE_I)
405         {
406                 i4b_trace_hdr_t hdr;
407                 char info = INFO2;
408                 
409                 hdr.unit = L0ISICUNIT(sc->sc_unit);
410                 hdr.type = TRC_CH_I;
411                 hdr.dir = FROM_NT;
412                 hdr.count = 0;
413                 MICROTIME(hdr.time);
414                 i4b_l1_trace_ind(&hdr, 1, &info);
415         }               
416
417 }
418
419 /*---------------------------------------------------------------------------*
420  *      illegal state default action
421  *---------------------------------------------------------------------------*/ 
422 static void
423 F_ill(struct l1_softc *sc)
424 {
425         NDBGL1(L1_F_ERR, "FSM function F_ill executing");
426 }
427
428 /*---------------------------------------------------------------------------*
429  *      No action
430  *---------------------------------------------------------------------------*/ 
431 static void
432 F_NULL(struct l1_softc *sc)
433 {
434         NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
435 }
436
437
438 /*---------------------------------------------------------------------------*
439  *      layer 1 state transition table
440  *---------------------------------------------------------------------------*/ 
441 struct isic_state_tab {
442         void (*func) (struct l1_softc *sc);     /* function to execute */
443         int newstate;                           /* next state */
444 } isic_state_tab[N_EVENTS][N_STATES] = {
445
446 /* STATE:       F3                      F4                      F5                      F6                      F7                      F8                      ILLEGAL STATE     */
447 /* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
448 /* 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}},
449 /* 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}},
450 /* 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}},
451 /* 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}},
452 /* 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}},
453 /* 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}},
454 /* 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}},
455 /* 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}},
456 /* 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}},
457 /* 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}},
458 /* 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}},
459 /* 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}}
460 };
461
462 /*---------------------------------------------------------------------------*
463  *      event handler
464  *---------------------------------------------------------------------------*/ 
465 void
466 isic_next_state(struct l1_softc *sc, int event)
467 {
468         int currstate, newstate;
469
470         if(event >= N_EVENTS)
471                 panic("i4b_l1fsm.c: event >= N_EVENTS\n");
472
473         currstate = sc->sc_I430state;
474
475         if(currstate >= N_STATES)
476                 panic("i4b_l1fsm.c: currstate >= N_STATES\n");  
477
478         newstate = isic_state_tab[event][currstate].newstate;
479
480         if(newstate >= N_STATES)
481                 panic("i4b_l1fsm.c: newstate >= N_STATES\n");   
482         
483         NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
484                                            state_text[currstate],
485                                            state_text[newstate]);
486
487         (*isic_state_tab[event][currstate].func)(sc);
488
489         if(newstate == ST_ILL)
490         {
491                 newstate = ST_F3;
492                 NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
493                                         state_text[currstate],
494                                         state_text[newstate],
495                                         event_text[event]);
496         }
497
498         sc->sc_I430state = newstate;
499 }
500
501 #if DO_I4B_DEBUG
502 /*---------------------------------------------------------------------------*
503  *      return pointer to current state description
504  *---------------------------------------------------------------------------*/ 
505 char *
506 isic_printstate(struct l1_softc *sc)
507 {
508         return((char *) state_text[sc->sc_I430state]);
509 }
510 #endif
511         
512 #endif /* NISIC > 0 */
513