1 /*
2 * Copyright (c) 1997, 2000 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 * $Id: isic_l1fsm.c,v 1.14 2011/07/17 20:54:51 joerg Exp $
31 *
32 * last edit-date: [Fri Jan 5 11:36:11 2001]
33 *
34 *---------------------------------------------------------------------------*/
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: isic_l1fsm.c,v 1.14 2011/07/17 20:54:51 joerg Exp $");
38
39 #include <sys/param.h>
40 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
41 #include <sys/ioccom.h>
42 #else
43 #include <sys/ioctl.h>
44 #endif
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
47 #include <sys/mbuf.h>
48
49 #ifdef __FreeBSD__
50 #include <machine/clock.h>
51 #include <i386/isa/isa_device.h>
52 #else
53 #ifndef __bsdi__
54 #include <sys/bus.h>
55 #endif
56 #include <sys/device.h>
57 #endif
58
59 #include <sys/socket.h>
60 #include <net/if.h>
61
62 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
63 #include <sys/callout.h>
64 #endif
65
66 #ifdef __FreeBSD__
67 #include <machine/i4b_debug.h>
68 #include <machine/i4b_ioctl.h>
69 #else
70 #include <netisdn/i4b_debug.h>
71 #include <netisdn/i4b_ioctl.h>
72 #endif
73
74 #include <netisdn/i4b_global.h>
75 #include <netisdn/i4b_trace.h>
76 #include <netisdn/i4b_l2.h>
77 #include <netisdn/i4b_l1l2.h>
78 #include <netisdn/i4b_mbuf.h>
79
80 #include <dev/ic/isic_l1.h>
81 #include <dev/ic/isac.h>
82 #include <dev/ic/hscx.h>
83
84 #include "nisac.h"
85 #include "nisacsx.h"
86
87 #if DO_I4B_DEBUG
88 static const char *state_text[N_STATES] = {
89 "F3 Deactivated",
90 "F4 Awaiting Signal",
91 "F5 Identifying Input",
92 "F6 Synchronized",
93 "F7 Activated",
94 "F8 Lost Framing",
95 "Illegal State"
96 };
97
98 static const char *event_text[N_EVENTS] = {
99 "EV_PHAR PH_ACT_REQ",
100 "EV_T3 Timer 3 expired",
101 "EV_INFO0 INFO0 received",
102 "EV_RSY Level Detected",
103 "EV_INFO2 INFO2 received",
104 "EV_INFO48 INFO4 received",
105 "EV_INFO410 INFO4 received",
106 "EV_DR Deactivate Req",
107 "EV_PU Power UP",
108 "EV_DIS Disconnected",
109 "EV_EI Error Ind",
110 "Illegal Event"
111 };
112 #endif
113
114 /* Function prototypes */
115
116 static void timer3_expired (struct isic_softc *sc);
117 static void T3_start (struct isic_softc *sc);
118 static void T3_stop (struct isic_softc *sc);
119 static void F_T3ex (struct isic_softc *sc);
120 static void timer4_expired (struct isic_softc *sc);
121 static void T4_start (struct isic_softc *sc);
122 static void T4_stop (struct isic_softc *sc);
123 static void F_AI8 (struct isic_softc *sc);
124 static void F_AI10 (struct isic_softc *sc);
125 static void F_I01 (struct isic_softc *sc);
126 static void F_I02 (struct isic_softc *sc);
127 static void F_I03 (struct isic_softc *sc);
128 static void F_I2 (struct isic_softc *sc);
129 static void F_ill (struct isic_softc *sc);
130 static void F_NULL (struct isic_softc *sc);
131
132 /*---------------------------------------------------------------------------*
133 * I.430 Timer T3 expire function
134 *---------------------------------------------------------------------------*/
135 static void
timer3_expired(struct isic_softc * sc)136 timer3_expired(struct isic_softc *sc)
137 {
138 if(sc->sc_I430T3)
139 {
140 NDBGL1(L1_T_ERR, "state = %s", isic_printstate(sc));
141 sc->sc_I430T3 = 0;
142
143 /* XXX try some recovery here XXX */
144 switch(sc->sc_cardtyp) {
145 #if NNISACSX > 0
146 case CARD_TYPEP_AVMA1PCIV2:
147 isic_isacsx_recover(sc);
148 break;
149 #endif /* NNISACSX > 0 */
150 default:
151 #if NNISAC > 0
152 isic_recover(sc);
153 #endif /* NNISAC > 0 */
154 break;
155 }
156
157 sc->sc_init_tries++; /* increment retry count */
158
159 /*XXX*/ if(sc->sc_init_tries > 4)
160 {
161 int s = splnet();
162
163 sc->sc_init_tries = 0;
164
165 if(sc->sc_obuf2 != NULL)
166 {
167 i4b_Dfreembuf(sc->sc_obuf2);
168 sc->sc_obuf2 = NULL;
169 }
170 if(sc->sc_obuf != NULL)
171 {
172 i4b_Dfreembuf(sc->sc_obuf);
173 sc->sc_obuf = NULL;
174 sc->sc_freeflag = 0;
175 sc->sc_op = NULL;
176 sc->sc_ol = 0;
177 }
178
179 splx(s);
180
181 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_NOL1ACC, 0);
182 }
183
184 isic_next_state(sc, EV_T3);
185 }
186 else
187 {
188 NDBGL1(L1_T_ERR, "expired without starting it ....");
189 }
190 }
191
192 /*---------------------------------------------------------------------------*
193 * I.430 Timer T3 start
194 *---------------------------------------------------------------------------*/
195 static void
T3_start(struct isic_softc * sc)196 T3_start(struct isic_softc *sc)
197 {
198 NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
199 sc->sc_I430T3 = 1;
200
201 START_TIMER(sc->sc_T3_callout, timer3_expired, sc, 2*hz);
202 }
203
204 /*---------------------------------------------------------------------------*
205 * I.430 Timer T3 stop
206 *---------------------------------------------------------------------------*/
207 static void
T3_stop(struct isic_softc * sc)208 T3_stop(struct isic_softc *sc)
209 {
210 NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
211
212 sc->sc_init_tries = 0; /* init connect retry count */
213
214 if(sc->sc_I430T3)
215 {
216 sc->sc_I430T3 = 0;
217 STOP_TIMER(sc->sc_T3_callout, timer3_expired, sc);
218 }
219 }
220
221 /*---------------------------------------------------------------------------*
222 * I.430 Timer T3 expiry
223 *---------------------------------------------------------------------------*/
224 static void
F_T3ex(struct isic_softc * sc)225 F_T3ex(struct isic_softc *sc)
226 {
227 NDBGL1(L1_F_MSG, "FSM function F_T3ex executing");
228 if(((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)
229 isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 0);
230 }
231
232 /*---------------------------------------------------------------------------*
233 * Timer T4 expire function
234 *---------------------------------------------------------------------------*/
235 static void
timer4_expired(struct isic_softc * sc)236 timer4_expired(struct isic_softc *sc)
237 {
238 if(sc->sc_I430T4)
239 {
240 NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
241 sc->sc_I430T4 = 0;
242 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_PDEACT, 0);
243 }
244 else
245 {
246 NDBGL1(L1_T_ERR, "expired without starting it ....");
247 }
248 }
249
250 /*---------------------------------------------------------------------------*
251 * Timer T4 start
252 *---------------------------------------------------------------------------*/
253 static void
T4_start(struct isic_softc * sc)254 T4_start(struct isic_softc *sc)
255 {
256 NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
257 sc->sc_I430T4 = 1;
258
259 START_TIMER(sc->sc_T4_callout, timer4_expired, sc, hz);
260 }
261
262 /*---------------------------------------------------------------------------*
263 * Timer T4 stop
264 *---------------------------------------------------------------------------*/
265 static void
T4_stop(struct isic_softc * sc)266 T4_stop(struct isic_softc *sc)
267 {
268 NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
269
270 if(sc->sc_I430T4)
271 {
272 sc->sc_I430T4 = 0;
273 STOP_TIMER(sc->sc_T4_callout, timer4_expired, sc);
274 }
275 }
276
277 /*---------------------------------------------------------------------------*
278 * FSM function: received AI8
279 *---------------------------------------------------------------------------*/
280 static void
F_AI8(struct isic_softc * sc)281 F_AI8(struct isic_softc *sc)
282 {
283 T4_stop(sc);
284
285 NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
286
287 if(((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)
288 isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 1);
289
290 T3_stop(sc);
291
292 if(sc->sc_trace & TRACE_I)
293 {
294 i4b_trace_hdr hdr;
295 char info = INFO4_8;
296
297 hdr.type = TRC_CH_I;
298 hdr.dir = FROM_NT;
299 hdr.count = 0;
300 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
301 }
302 }
303
304 /*---------------------------------------------------------------------------*
305 * FSM function: received AI10
306 *---------------------------------------------------------------------------*/
307 static void
F_AI10(struct isic_softc * sc)308 F_AI10(struct isic_softc *sc)
309 {
310 T4_stop(sc);
311
312 NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
313
314 if(((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)
315 isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 1);
316
317 T3_stop(sc);
318
319 if(sc->sc_trace & TRACE_I)
320 {
321 i4b_trace_hdr hdr;
322 char info = INFO4_10;
323
324 hdr.type = TRC_CH_I;
325 hdr.dir = FROM_NT;
326 hdr.count = 0;
327 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
328 }
329 }
330
331 /*---------------------------------------------------------------------------*
332 * FSM function: received INFO 0 in states F3 .. F5
333 *---------------------------------------------------------------------------*/
334 static void
F_I01(struct isic_softc * sc)335 F_I01(struct isic_softc *sc)
336 {
337 NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
338
339 if(sc->sc_trace & TRACE_I)
340 {
341 i4b_trace_hdr hdr;
342 char info = INFO0;
343
344 hdr.type = TRC_CH_I;
345 hdr.dir = FROM_NT;
346 hdr.count = 0;
347 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
348 }
349 }
350
351 /*---------------------------------------------------------------------------*
352 * FSM function: received INFO 0 in state F6
353 *---------------------------------------------------------------------------*/
354 static void
F_I02(struct isic_softc * sc)355 F_I02(struct isic_softc *sc)
356 {
357 NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
358
359 if(((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)
360 isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 0);
361
362 if(sc->sc_trace & TRACE_I)
363 {
364 i4b_trace_hdr hdr;
365 char info = INFO0;
366
367 hdr.type = TRC_CH_I;
368 hdr.dir = FROM_NT;
369 hdr.count = 0;
370 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
371 }
372 }
373
374 /*---------------------------------------------------------------------------*
375 * FSM function: received INFO 0 in state F7 or F8
376 *---------------------------------------------------------------------------*/
377 static void
F_I03(struct isic_softc * sc)378 F_I03(struct isic_softc *sc)
379 {
380 NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
381
382 if(((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)
383 isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 0);
384
385 T4_start(sc);
386
387 if(sc->sc_trace & TRACE_I)
388 {
389 i4b_trace_hdr hdr;
390 char info = INFO0;
391
392 hdr.type = TRC_CH_I;
393 hdr.dir = FROM_NT;
394 hdr.count = 0;
395 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
396 }
397 }
398
399 /*---------------------------------------------------------------------------*
400 * FSM function: activate request
401 *---------------------------------------------------------------------------*/
402 static void
F_AR(struct isic_softc * sc)403 F_AR(struct isic_softc *sc)
404 {
405 NDBGL1(L1_F_MSG, "FSM function F_AR executing");
406
407 if(sc->sc_trace & TRACE_I)
408 {
409 i4b_trace_hdr hdr;
410 char info = INFO1_8;
411
412 hdr.type = TRC_CH_I;
413 hdr.dir = FROM_TE;
414 hdr.count = 0;
415 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
416 }
417
418 switch(sc->sc_cardtyp) {
419 #if NNISACSX > 0
420 case CARD_TYPEP_AVMA1PCIV2:
421 isic_isacsx_l1_cmd(sc, CMD_AR8);
422 break;
423 #endif /* NNISACSX > 0 */
424 default:
425 #if NNISAC > 0
426 isic_isac_l1_cmd(sc, CMD_AR8);
427 #endif /* NNISAC > 0 */
428 break;
429 }
430
431 T3_start(sc);
432 }
433
434 /*---------------------------------------------------------------------------*
435 * FSM function: received INFO2
436 *---------------------------------------------------------------------------*/
437 static void
F_I2(struct isic_softc * sc)438 F_I2(struct isic_softc *sc)
439 {
440 NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
441
442 if(sc->sc_trace & TRACE_I)
443 {
444 i4b_trace_hdr hdr;
445 char info = INFO2;
446
447 hdr.type = TRC_CH_I;
448 hdr.dir = FROM_NT;
449 hdr.count = 0;
450 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
451 }
452 }
453
454 /*---------------------------------------------------------------------------*
455 * illegal state default action
456 *---------------------------------------------------------------------------*/
457 static void
F_ill(struct isic_softc * sc)458 F_ill(struct isic_softc *sc)
459 {
460 NDBGL1(L1_F_ERR, "FSM function F_ill executing");
461 }
462
463 /*---------------------------------------------------------------------------*
464 * No action
465 *---------------------------------------------------------------------------*/
466 static void
F_NULL(struct isic_softc * sc)467 F_NULL(struct isic_softc *sc)
468 {
469 NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
470 }
471
472
473 /*---------------------------------------------------------------------------*
474 * layer 1 state transition table
475 *---------------------------------------------------------------------------*/
476 struct isic_state_tab {
477 void (*func) (struct isic_softc *sc); /* function to execute */
478 int newstate; /* next state */
479 } isic_state_tab[N_EVENTS][N_STATES] = {
480
481 /* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
482 /* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
483 /* 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}},
484 /* 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}},
485 /* 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}},
486 /* 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}},
487 /* 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}},
488 /* 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}},
489 /* 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}},
490 /* 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}},
491 /* 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}},
492 /* 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}},
493 /* 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}},
494 /* 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}}
495 };
496
497 /*---------------------------------------------------------------------------*
498 * event handler
499 *---------------------------------------------------------------------------*/
500 void
isic_next_state(struct isic_softc * sc,int event)501 isic_next_state(struct isic_softc *sc, int event)
502 {
503 int currstate, newstate;
504
505 if(event >= N_EVENTS)
506 panic("i4b_l1fsm.c: event >= N_EVENTS");
507
508 currstate = sc->sc_I430state;
509
510 if(currstate >= N_STATES)
511 panic("i4b_l1fsm.c: currstate >= N_STATES");
512
513 newstate = isic_state_tab[event][currstate].newstate;
514
515 if(newstate >= N_STATES)
516 panic("i4b_l1fsm.c: newstate >= N_STATES");
517
518 NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
519 state_text[currstate],
520 state_text[newstate]);
521
522 (*isic_state_tab[event][currstate].func)(sc);
523
524 if(newstate == ST_ILL)
525 {
526 newstate = ST_F3;
527 NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
528 state_text[currstate],
529 state_text[newstate],
530 event_text[event]);
531 }
532
533 sc->sc_I430state = newstate;
534 }
535
536 #if DO_I4B_DEBUG
537 /*---------------------------------------------------------------------------*
538 * return pointer to current state description
539 *---------------------------------------------------------------------------*/
540 const char *
isic_printstate(struct isic_softc * sc)541 isic_printstate(struct isic_softc *sc)
542 {
543 return(state_text[sc->sc_I430state]);
544 }
545 #endif
546