Remove spl*() calls from net/i4b, replacing them with critical sections.
[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.5 2005/06/03 16:50:05 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 #include <sys/thread2.h>
46
47 #include <net/if.h>
48
49 #include <net/i4b/include/machine/i4b_debug.h>
50 #include <net/i4b/include/machine/i4b_ioctl.h>
51 #include <net/i4b/include/machine/i4b_trace.h>
52
53 #include "i4b_isic.h"
54
55 #include "../i4b_l1.h"
56 #include "../../include/i4b_global.h"
57 #include "../../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                         crit_enter();
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                         crit_exit();
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         callout_reset(&sc->sc_T3_timeout, 2 * hz,
163                         (TIMEOUT_FUNC_T)timer3_expired, (struct l1_softc *)sc);
164 }
165
166 /*---------------------------------------------------------------------------*
167  *      I.430 Timer T3 stop
168  *---------------------------------------------------------------------------*/ 
169 static void
170 T3_stop(struct l1_softc *sc)
171 {
172         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
173
174         sc->sc_init_tries = 0;  /* init connect retry count */
175         
176         if(sc->sc_I430T3)
177         {
178                 sc->sc_I430T3 = 0;
179                 callout_stop(&sc->sc_T3_timeout);
180         }
181 }
182
183 /*---------------------------------------------------------------------------*
184  *      I.430 Timer T3 expiry
185  *---------------------------------------------------------------------------*/ 
186 static void
187 F_T3ex(struct l1_softc *sc)
188 {
189         NDBGL1(L1_F_MSG, "FSM function F_T3ex executing");
190         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
191                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
192 }
193
194 /*---------------------------------------------------------------------------*
195  *      Timer T4 expire function
196  *---------------------------------------------------------------------------*/ 
197 static void
198 timer4_expired(struct l1_softc *sc)
199 {
200         if(sc->sc_I430T4)
201         {
202                 NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
203                 sc->sc_I430T4 = 0;
204                 i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_PDEACT, 0, NULL);
205         }
206         else
207         {
208                 NDBGL1(L1_T_ERR, "expired without starting it ....");
209         }
210 }
211
212 /*---------------------------------------------------------------------------*
213  *      Timer T4 start
214  *---------------------------------------------------------------------------*/ 
215 static void
216 T4_start(struct l1_softc *sc)
217 {
218         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
219         sc->sc_I430T4 = 1;
220         callout_reset(&sc->sc_T4_timeout, hz,
221                         (TIMEOUT_FUNC_T)timer4_expired, (struct l1_softc *)sc);
222 }
223
224 /*---------------------------------------------------------------------------*
225  *      Timer T4 stop
226  *---------------------------------------------------------------------------*/ 
227 static void
228 T4_stop(struct l1_softc *sc)
229 {
230         NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
231
232         if(sc->sc_I430T4)
233         {
234                 sc->sc_I430T4 = 0;
235                 callout_stop(&sc->sc_T4_timeout);
236         }
237 }
238
239 /*---------------------------------------------------------------------------*
240  *      FSM function: received AI8
241  *---------------------------------------------------------------------------*/ 
242 static void
243 F_AI8(struct l1_softc *sc)
244 {
245         T4_stop(sc);
246
247         NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
248
249         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
250                 i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
251
252         T3_stop(sc);
253
254         if(sc->sc_trace & TRACE_I)
255         {
256                 i4b_trace_hdr_t hdr;
257                 char info = INFO4_8;
258                 
259                 hdr.unit = L0ISICUNIT(sc->sc_unit);
260                 hdr.type = TRC_CH_I;
261                 hdr.dir = FROM_NT;
262                 hdr.count = 0;
263                 MICROTIME(hdr.time);
264                 i4b_l1_trace_ind(&hdr, 1, &info);
265         }
266 }
267
268 /*---------------------------------------------------------------------------*
269  *      FSM function: received AI10
270  *---------------------------------------------------------------------------*/ 
271 static void
272 F_AI10(struct l1_softc *sc)
273 {
274         T4_stop(sc);
275         
276         NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
277
278         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
279                 i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
280
281         T3_stop(sc);
282
283         if(sc->sc_trace & TRACE_I)
284         {
285                 i4b_trace_hdr_t hdr;
286                 char info = INFO4_10;
287                 
288                 hdr.unit = L0ISICUNIT(sc->sc_unit);
289                 hdr.type = TRC_CH_I;
290                 hdr.dir = FROM_NT;
291                 hdr.count = 0;
292                 MICROTIME(hdr.time);
293                 i4b_l1_trace_ind(&hdr, 1, &info);
294         }
295 }
296
297 /*---------------------------------------------------------------------------*
298  *      FSM function: received INFO 0 in states F3 .. F5
299  *---------------------------------------------------------------------------*/ 
300 static void
301 F_I01(struct l1_softc *sc)
302 {
303         NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
304
305         if(sc->sc_trace & TRACE_I)
306         {
307                 i4b_trace_hdr_t hdr;
308                 char info = INFO0;
309                 
310                 hdr.unit = L0ISICUNIT(sc->sc_unit);
311                 hdr.type = TRC_CH_I;
312                 hdr.dir = FROM_NT;
313                 hdr.count = 0;
314                 MICROTIME(hdr.time);
315                 i4b_l1_trace_ind(&hdr, 1, &info);
316         }
317 }
318
319 /*---------------------------------------------------------------------------*
320  *      FSM function: received INFO 0 in state F6
321  *---------------------------------------------------------------------------*/ 
322 static void
323 F_I02(struct l1_softc *sc)
324 {
325         NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
326
327         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
328                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
329
330         if(sc->sc_trace & TRACE_I)
331         {
332                 i4b_trace_hdr_t hdr;
333                 char info = INFO0;
334                 
335                 hdr.unit = L0ISICUNIT(sc->sc_unit);
336                 hdr.type = TRC_CH_I;
337                 hdr.dir = FROM_NT;
338                 hdr.count = 0;
339                 MICROTIME(hdr.time);
340                 i4b_l1_trace_ind(&hdr, 1, &info);
341         }
342 }
343
344 /*---------------------------------------------------------------------------*
345  *      FSM function: received INFO 0 in state F7 or F8
346  *---------------------------------------------------------------------------*/ 
347 static void
348 F_I03(struct l1_softc *sc)
349 {
350         NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
351
352         if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
353                 i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
354
355         T4_start(sc);
356         
357         if(sc->sc_trace & TRACE_I)
358         {
359                 i4b_trace_hdr_t hdr;
360                 char info = INFO0;
361                 
362                 hdr.unit = L0ISICUNIT(sc->sc_unit);
363                 hdr.type = TRC_CH_I;
364                 hdr.dir = FROM_NT;
365                 hdr.count = 0;
366                 MICROTIME(hdr.time);
367                 i4b_l1_trace_ind(&hdr, 1, &info);
368         }
369 }
370
371 /*---------------------------------------------------------------------------*
372  *      FSM function: activate request
373  *---------------------------------------------------------------------------*/ 
374 static void
375 F_AR(struct l1_softc *sc)
376 {
377         NDBGL1(L1_F_MSG, "FSM function F_AR executing");
378
379         if(sc->sc_trace & TRACE_I)
380         {
381                 i4b_trace_hdr_t hdr;
382                 char info = INFO1_8;
383                 
384                 hdr.unit = L0ISICUNIT(sc->sc_unit);
385                 hdr.type = TRC_CH_I;
386                 hdr.dir = FROM_TE;
387                 hdr.count = 0;
388                 MICROTIME(hdr.time);
389                 i4b_l1_trace_ind(&hdr, 1, &info);
390         }
391
392         isic_isac_l1_cmd(sc, CMD_AR8);
393
394         T3_start(sc);
395 }
396
397 /*---------------------------------------------------------------------------*
398  *      FSM function: received INFO2
399  *---------------------------------------------------------------------------*/ 
400 static void
401 F_I2(struct l1_softc *sc)
402 {
403         NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
404
405         if(sc->sc_trace & TRACE_I)
406         {
407                 i4b_trace_hdr_t hdr;
408                 char info = INFO2;
409                 
410                 hdr.unit = L0ISICUNIT(sc->sc_unit);
411                 hdr.type = TRC_CH_I;
412                 hdr.dir = FROM_NT;
413                 hdr.count = 0;
414                 MICROTIME(hdr.time);
415                 i4b_l1_trace_ind(&hdr, 1, &info);
416         }               
417
418 }
419
420 /*---------------------------------------------------------------------------*
421  *      illegal state default action
422  *---------------------------------------------------------------------------*/ 
423 static void
424 F_ill(struct l1_softc *sc)
425 {
426         NDBGL1(L1_F_ERR, "FSM function F_ill executing");
427 }
428
429 /*---------------------------------------------------------------------------*
430  *      No action
431  *---------------------------------------------------------------------------*/ 
432 static void
433 F_NULL(struct l1_softc *sc)
434 {
435         NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
436 }
437
438
439 /*---------------------------------------------------------------------------*
440  *      layer 1 state transition table
441  *---------------------------------------------------------------------------*/ 
442 struct isic_state_tab {
443         void (*func) (struct l1_softc *sc);     /* function to execute */
444         int newstate;                           /* next state */
445 } isic_state_tab[N_EVENTS][N_STATES] = {
446
447 /* STATE:       F3                      F4                      F5                      F6                      F7                      F8                      ILLEGAL STATE     */
448 /* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
449 /* 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}},
450 /* 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}},
451 /* 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}},
452 /* 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}},
453 /* 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}},
454 /* 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}},
455 /* 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}},
456 /* 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}},
457 /* 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}},
458 /* 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}},
459 /* 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}},
460 /* 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}}
461 };
462
463 /*---------------------------------------------------------------------------*
464  *      event handler
465  *---------------------------------------------------------------------------*/ 
466 void
467 isic_next_state(struct l1_softc *sc, int event)
468 {
469         int currstate, newstate;
470
471         if(event >= N_EVENTS)
472                 panic("i4b_l1fsm.c: event >= N_EVENTS\n");
473
474         currstate = sc->sc_I430state;
475
476         if(currstate >= N_STATES)
477                 panic("i4b_l1fsm.c: currstate >= N_STATES\n");  
478
479         newstate = isic_state_tab[event][currstate].newstate;
480
481         if(newstate >= N_STATES)
482                 panic("i4b_l1fsm.c: newstate >= N_STATES\n");   
483         
484         NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
485                                            state_text[currstate],
486                                            state_text[newstate]);
487
488         (*isic_state_tab[event][currstate].func)(sc);
489
490         if(newstate == ST_ILL)
491         {
492                 newstate = ST_F3;
493                 NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
494                                         state_text[currstate],
495                                         state_text[newstate],
496                                         event_text[event]);
497         }
498
499         sc->sc_I430state = newstate;
500 }
501
502 #if DO_I4B_DEBUG
503 /*---------------------------------------------------------------------------*
504  *      return pointer to current state description
505  *---------------------------------------------------------------------------*/ 
506 char *
507 isic_printstate(struct l1_softc *sc)
508 {
509         return((char *) state_text[sc->sc_I430state]);
510 }
511 #endif
512         
513 #endif /* NISIC > 0 */
514