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