GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / isdn / hisax / st5481_d.c
blob6187c93900ec505d721d6e33d5b5fa7cdcdb628f
1 /*
2 * Driver for ST5481 USB ISDN modem
4 * Author Frode Isaksen
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
13 #include <linux/init.h>
14 #include <linux/gfp.h>
15 #include <linux/usb.h>
16 #include <linux/netdevice.h>
17 #include "st5481.h"
19 static void ph_connect(struct st5481_adapter *adapter);
20 static void ph_disconnect(struct st5481_adapter *adapter);
22 static struct Fsm l1fsm;
24 static char *strL1State[] =
26 "ST_L1_F3",
27 "ST_L1_F4",
28 "ST_L1_F6",
29 "ST_L1_F7",
30 "ST_L1_F8",
33 static char *strL1Event[] =
35 "EV_IND_DP",
36 "EV_IND_1",
37 "EV_IND_2",
38 "EV_IND_3",
39 "EV_IND_RSY",
40 "EV_IND_5",
41 "EV_IND_6",
42 "EV_IND_7",
43 "EV_IND_AP",
44 "EV_IND_9",
45 "EV_IND_10",
46 "EV_IND_11",
47 "EV_IND_AI8",
48 "EV_IND_AI10",
49 "EV_IND_AIL",
50 "EV_IND_DI",
51 "EV_PH_ACTIVATE_REQ",
52 "EV_PH_DEACTIVATE_REQ",
53 "EV_TIMER3",
56 static inline void D_L1L2(struct st5481_adapter *adapter, int pr, void *arg)
58 struct hisax_if *ifc = (struct hisax_if *) &adapter->hisax_d_if;
60 ifc->l1l2(ifc, pr, arg);
63 static void
64 l1_go_f3(struct FsmInst *fi, int event, void *arg)
66 struct st5481_adapter *adapter = fi->userdata;
68 if (fi->state == ST_L1_F7)
69 ph_disconnect(adapter);
71 FsmChangeState(fi, ST_L1_F3);
72 D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
75 static void
76 l1_go_f6(struct FsmInst *fi, int event, void *arg)
78 struct st5481_adapter *adapter = fi->userdata;
80 if (fi->state == ST_L1_F7)
81 ph_disconnect(adapter);
83 FsmChangeState(fi, ST_L1_F6);
86 static void
87 l1_go_f7(struct FsmInst *fi, int event, void *arg)
89 struct st5481_adapter *adapter = fi->userdata;
91 FsmDelTimer(&adapter->timer, 0);
92 ph_connect(adapter);
93 FsmChangeState(fi, ST_L1_F7);
94 D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);
97 static void
98 l1_go_f8(struct FsmInst *fi, int event, void *arg)
100 struct st5481_adapter *adapter = fi->userdata;
102 if (fi->state == ST_L1_F7)
103 ph_disconnect(adapter);
105 FsmChangeState(fi, ST_L1_F8);
108 static void
109 l1_timer3(struct FsmInst *fi, int event, void *arg)
111 struct st5481_adapter *adapter = fi->userdata;
113 st5481_ph_command(adapter, ST5481_CMD_DR);
114 FsmChangeState(fi, ST_L1_F3);
115 D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
118 static void
119 l1_ignore(struct FsmInst *fi, int event, void *arg)
123 static void
124 l1_activate(struct FsmInst *fi, int event, void *arg)
126 struct st5481_adapter *adapter = fi->userdata;
128 st5481_ph_command(adapter, ST5481_CMD_DR);
129 st5481_ph_command(adapter, ST5481_CMD_PUP);
130 FsmRestartTimer(&adapter->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
131 st5481_ph_command(adapter, ST5481_CMD_AR8);
132 FsmChangeState(fi, ST_L1_F4);
135 static struct FsmNode L1FnList[] __initdata =
137 {ST_L1_F3, EV_IND_DP, l1_ignore},
138 {ST_L1_F3, EV_IND_AP, l1_go_f6},
139 {ST_L1_F3, EV_IND_AI8, l1_go_f7},
140 {ST_L1_F3, EV_IND_AI10, l1_go_f7},
141 {ST_L1_F3, EV_PH_ACTIVATE_REQ, l1_activate},
143 {ST_L1_F4, EV_TIMER3, l1_timer3},
144 {ST_L1_F4, EV_IND_DP, l1_go_f3},
145 {ST_L1_F4, EV_IND_AP, l1_go_f6},
146 {ST_L1_F4, EV_IND_AI8, l1_go_f7},
147 {ST_L1_F4, EV_IND_AI10, l1_go_f7},
149 {ST_L1_F6, EV_TIMER3, l1_timer3},
150 {ST_L1_F6, EV_IND_DP, l1_go_f3},
151 {ST_L1_F6, EV_IND_AP, l1_ignore},
152 {ST_L1_F6, EV_IND_AI8, l1_go_f7},
153 {ST_L1_F6, EV_IND_AI10, l1_go_f7},
154 {ST_L1_F7, EV_IND_RSY, l1_go_f8},
156 {ST_L1_F7, EV_IND_DP, l1_go_f3},
157 {ST_L1_F7, EV_IND_AP, l1_go_f6},
158 {ST_L1_F7, EV_IND_AI8, l1_ignore},
159 {ST_L1_F7, EV_IND_AI10, l1_ignore},
160 {ST_L1_F7, EV_IND_RSY, l1_go_f8},
162 {ST_L1_F8, EV_TIMER3, l1_timer3},
163 {ST_L1_F8, EV_IND_DP, l1_go_f3},
164 {ST_L1_F8, EV_IND_AP, l1_go_f6},
165 {ST_L1_F8, EV_IND_AI8, l1_go_f8},
166 {ST_L1_F8, EV_IND_AI10, l1_go_f8},
167 {ST_L1_F8, EV_IND_RSY, l1_ignore},
170 static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
172 va_list args;
173 char buf[256];
175 va_start(args, fmt);
176 vsnprintf(buf, sizeof(buf), fmt, args);
177 DBG(8, "%s", buf);
178 va_end(args);
181 /* ======================================================================
182 * D-Channel out
186 static struct Fsm dout_fsm;
188 static char *strDoutState[] =
190 "ST_DOUT_NONE",
192 "ST_DOUT_SHORT_INIT",
193 "ST_DOUT_SHORT_WAIT_DEN",
195 "ST_DOUT_LONG_INIT",
196 "ST_DOUT_LONG_WAIT_DEN",
197 "ST_DOUT_NORMAL",
199 "ST_DOUT_WAIT_FOR_UNDERRUN",
200 "ST_DOUT_WAIT_FOR_NOT_BUSY",
201 "ST_DOUT_WAIT_FOR_STOP",
202 "ST_DOUT_WAIT_FOR_RESET",
205 static char *strDoutEvent[] =
207 "EV_DOUT_START_XMIT",
208 "EV_DOUT_COMPLETE",
209 "EV_DOUT_DEN",
210 "EV_DOUT_RESETED",
211 "EV_DOUT_STOPPED",
212 "EV_DOUT_COLL",
213 "EV_DOUT_UNDERRUN",
216 static void dout_debug(struct FsmInst *fi, char *fmt, ...)
218 va_list args;
219 char buf[256];
221 va_start(args, fmt);
222 vsnprintf(buf, sizeof(buf), fmt, args);
223 DBG(0x2, "%s", buf);
224 va_end(args);
227 static void dout_stop_event(void *context)
229 struct st5481_adapter *adapter = context;
231 FsmEvent(&adapter->d_out.fsm, EV_DOUT_STOPPED, NULL);
235 * Start the transfer of a D channel frame.
237 static void usb_d_out(struct st5481_adapter *adapter, int buf_nr)
239 struct st5481_d_out *d_out = &adapter->d_out;
240 struct urb *urb;
241 unsigned int num_packets, packet_offset;
242 int len, buf_size, bytes_sent;
243 struct sk_buff *skb;
244 struct usb_iso_packet_descriptor *desc;
246 if (d_out->fsm.state != ST_DOUT_NORMAL)
247 return;
249 if (test_and_set_bit(buf_nr, &d_out->busy)) {
250 DBG(2, "ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
251 return;
253 urb = d_out->urb[buf_nr];
255 skb = d_out->tx_skb;
257 buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT;
259 if (skb) {
260 len = isdnhdlc_encode(&d_out->hdlc_state,
261 skb->data, skb->len, &bytes_sent,
262 urb->transfer_buffer, buf_size);
263 skb_pull(skb,bytes_sent);
264 } else {
265 // Send flags or idle
266 len = isdnhdlc_encode(&d_out->hdlc_state,
267 NULL, 0, &bytes_sent,
268 urb->transfer_buffer, buf_size);
271 if (len < buf_size) {
272 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN);
274 if (skb && !skb->len) {
275 d_out->tx_skb = NULL;
276 D_L1L2(adapter, PH_DATA | CONFIRM, NULL);
277 dev_kfree_skb_any(skb);
280 // Prepare the URB
281 urb->transfer_buffer_length = len;
282 num_packets = 0;
283 packet_offset = 0;
284 while (packet_offset < len) {
285 desc = &urb->iso_frame_desc[num_packets];
286 desc->offset = packet_offset;
287 desc->length = SIZE_ISO_PACKETS_D_OUT;
288 if (len - packet_offset < desc->length)
289 desc->length = len - packet_offset;
290 num_packets++;
291 packet_offset += desc->length;
293 urb->number_of_packets = num_packets;
295 // Prepare the URB
296 urb->dev = adapter->usb_dev;
297 // Need to transmit the next buffer 2ms after the DEN_EVENT
298 urb->transfer_flags = 0;
299 urb->start_frame = usb_get_current_frame_number(adapter->usb_dev)+2;
301 DBG_ISO_PACKET(0x20,urb);
303 if (usb_submit_urb(urb, GFP_KERNEL) < 0) {
304 // There is another URB queued up
305 urb->transfer_flags = URB_ISO_ASAP;
306 SUBMIT_URB(urb, GFP_KERNEL);
310 static void fifo_reseted(void *context)
312 struct st5481_adapter *adapter = context;
314 FsmEvent(&adapter->d_out.fsm, EV_DOUT_RESETED, NULL);
317 static void usb_d_out_complete(struct urb *urb)
319 struct st5481_adapter *adapter = urb->context;
320 struct st5481_d_out *d_out = &adapter->d_out;
321 long buf_nr;
323 DBG(2, "");
325 buf_nr = get_buf_nr(d_out->urb, urb);
326 test_and_clear_bit(buf_nr, &d_out->busy);
328 if (unlikely(urb->status < 0)) {
329 switch (urb->status) {
330 case -ENOENT:
331 case -ESHUTDOWN:
332 case -ECONNRESET:
333 DBG(1,"urb killed status %d", urb->status);
334 break;
335 default:
336 WARNING("urb status %d",urb->status);
337 if (d_out->busy == 0) {
338 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
340 break;
342 return; // Give up
345 FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr);
348 /* ====================================================================== */
350 static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg)
352 struct st5481_adapter *adapter = fsm->userdata;
353 struct st5481_d_out *d_out = &adapter->d_out;
354 struct urb *urb;
355 int len, bytes_sent;
356 struct sk_buff *skb;
357 int buf_nr = 0;
359 skb = d_out->tx_skb;
361 DBG(2,"len=%d",skb->len);
363 isdnhdlc_out_init(&d_out->hdlc_state, HDLC_DCHANNEL | HDLC_BITREVERSE);
365 if (test_and_set_bit(buf_nr, &d_out->busy)) {
366 WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
367 return;
369 urb = d_out->urb[buf_nr];
371 DBG_SKB(0x10, skb);
372 len = isdnhdlc_encode(&d_out->hdlc_state,
373 skb->data, skb->len, &bytes_sent,
374 urb->transfer_buffer, 16);
375 skb_pull(skb, bytes_sent);
377 if(len < 16)
378 FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_INIT);
379 else
380 FsmChangeState(&d_out->fsm, ST_DOUT_LONG_INIT);
382 if (skb->len == 0) {
383 d_out->tx_skb = NULL;
384 D_L1L2(adapter, PH_DATA | CONFIRM, NULL);
385 dev_kfree_skb_any(skb);
388 // Prepare the URB
389 urb->transfer_buffer_length = len;
391 urb->iso_frame_desc[0].offset = 0;
392 urb->iso_frame_desc[0].length = len;
393 urb->number_of_packets = 1;
395 // Prepare the URB
396 urb->dev = adapter->usb_dev;
397 urb->transfer_flags = URB_ISO_ASAP;
399 DBG_ISO_PACKET(0x20,urb);
400 SUBMIT_URB(urb, GFP_KERNEL);
403 static void dout_short_fifo(struct FsmInst *fsm, int event, void *arg)
405 struct st5481_adapter *adapter = fsm->userdata;
406 struct st5481_d_out *d_out = &adapter->d_out;
408 FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_WAIT_DEN);
409 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL);
412 static void dout_end_short_frame(struct FsmInst *fsm, int event, void *arg)
414 struct st5481_adapter *adapter = fsm->userdata;
415 struct st5481_d_out *d_out = &adapter->d_out;
417 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN);
420 static void dout_long_enable_fifo(struct FsmInst *fsm, int event, void *arg)
422 struct st5481_adapter *adapter = fsm->userdata;
423 struct st5481_d_out *d_out = &adapter->d_out;
425 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL);
426 FsmChangeState(&d_out->fsm, ST_DOUT_LONG_WAIT_DEN);
429 static void dout_long_den(struct FsmInst *fsm, int event, void *arg)
431 struct st5481_adapter *adapter = fsm->userdata;
432 struct st5481_d_out *d_out = &adapter->d_out;
434 FsmChangeState(&d_out->fsm, ST_DOUT_NORMAL);
435 usb_d_out(adapter, 0);
436 usb_d_out(adapter, 1);
439 static void dout_reset(struct FsmInst *fsm, int event, void *arg)
441 struct st5481_adapter *adapter = fsm->userdata;
442 struct st5481_d_out *d_out = &adapter->d_out;
444 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_RESET);
445 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
448 static void dout_stop(struct FsmInst *fsm, int event, void *arg)
450 struct st5481_adapter *adapter = fsm->userdata;
451 struct st5481_d_out *d_out = &adapter->d_out;
453 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_STOP);
454 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 0, dout_stop_event, adapter);
457 static void dout_underrun(struct FsmInst *fsm, int event, void *arg)
459 struct st5481_adapter *adapter = fsm->userdata;
460 struct st5481_d_out *d_out = &adapter->d_out;
462 if (test_bit(0, &d_out->busy) || test_bit(1, &d_out->busy)) {
463 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_NOT_BUSY);
464 } else {
465 dout_stop(fsm, event, arg);
469 static void dout_check_busy(struct FsmInst *fsm, int event, void *arg)
471 struct st5481_adapter *adapter = fsm->userdata;
472 struct st5481_d_out *d_out = &adapter->d_out;
474 if (!test_bit(0, &d_out->busy) && !test_bit(1, &d_out->busy))
475 dout_stop(fsm, event, arg);
478 static void dout_reseted(struct FsmInst *fsm, int event, void *arg)
480 struct st5481_adapter *adapter = fsm->userdata;
481 struct st5481_d_out *d_out = &adapter->d_out;
483 FsmChangeState(&d_out->fsm, ST_DOUT_NONE);
484 if (d_out->tx_skb)
485 FsmEvent(&d_out->fsm, EV_DOUT_START_XMIT, NULL);
488 static void dout_complete(struct FsmInst *fsm, int event, void *arg)
490 struct st5481_adapter *adapter = fsm->userdata;
491 long buf_nr = (long) arg;
493 usb_d_out(adapter, buf_nr);
496 static void dout_ignore(struct FsmInst *fsm, int event, void *arg)
500 static struct FsmNode DoutFnList[] __initdata =
502 {ST_DOUT_NONE, EV_DOUT_START_XMIT, dout_start_xmit},
504 {ST_DOUT_SHORT_INIT, EV_DOUT_COMPLETE, dout_short_fifo},
506 {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_DEN, dout_end_short_frame},
507 {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun},
509 {ST_DOUT_LONG_INIT, EV_DOUT_COMPLETE, dout_long_enable_fifo},
511 {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_DEN, dout_long_den},
512 {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun},
514 {ST_DOUT_NORMAL, EV_DOUT_UNDERRUN, dout_underrun},
515 {ST_DOUT_NORMAL, EV_DOUT_COMPLETE, dout_complete},
517 {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_UNDERRUN, dout_underrun},
518 {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_COMPLETE, dout_ignore},
520 {ST_DOUT_WAIT_FOR_NOT_BUSY, EV_DOUT_COMPLETE, dout_check_busy},
522 {ST_DOUT_WAIT_FOR_STOP, EV_DOUT_STOPPED, dout_reset},
524 {ST_DOUT_WAIT_FOR_RESET, EV_DOUT_RESETED, dout_reseted},
527 void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
529 struct st5481_adapter *adapter = hisax_d_if->priv;
530 struct sk_buff *skb = arg;
532 switch (pr) {
533 case PH_ACTIVATE | REQUEST:
534 FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL);
535 break;
536 case PH_DEACTIVATE | REQUEST:
537 FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL);
538 break;
539 case PH_DATA | REQUEST:
540 DBG(2, "PH_DATA REQUEST len %d", skb->len);
541 BUG_ON(adapter->d_out.tx_skb);
542 adapter->d_out.tx_skb = skb;
543 FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL);
544 break;
545 default:
546 WARNING("pr %#x\n", pr);
547 break;
551 /* ======================================================================
555 * Start receiving on the D channel since entered state F7.
557 static void ph_connect(struct st5481_adapter *adapter)
559 struct st5481_d_out *d_out = &adapter->d_out;
560 struct st5481_in *d_in = &adapter->d_in;
562 DBG(8,"");
564 FsmChangeState(&d_out->fsm, ST_DOUT_NONE);
566 // st5481_usb_device_ctrl_msg(adapter, FFMSK_D, OUT_UNDERRUN, NULL, NULL);
567 st5481_usb_device_ctrl_msg(adapter, FFMSK_D, 0xfc, NULL, NULL);
568 st5481_in_mode(d_in, L1_MODE_HDLC);
570 #ifdef LOOPBACK
571 // Turn loopback on (data sent on B and D looped back)
572 st5481_usb_device_ctrl_msg(cs, LBB, 0x04, NULL, NULL);
573 #endif
575 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, NULL, NULL);
577 // Turn on the green LED to tell that we are in state F7
578 adapter->leds |= GREEN_LED;
579 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL);
583 * Stop receiving on the D channel since not in state F7.
585 static void ph_disconnect(struct st5481_adapter *adapter)
587 DBG(8,"");
589 st5481_in_mode(&adapter->d_in, L1_MODE_NULL);
591 // Turn off the green LED to tell that we left state F7
592 adapter->leds &= ~GREEN_LED;
593 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL);
596 static int st5481_setup_d_out(struct st5481_adapter *adapter)
598 struct usb_device *dev = adapter->usb_dev;
599 struct usb_interface *intf;
600 struct usb_host_interface *altsetting = NULL;
601 struct usb_host_endpoint *endpoint;
602 struct st5481_d_out *d_out = &adapter->d_out;
604 DBG(2,"");
606 intf = usb_ifnum_to_if(dev, 0);
607 if (intf)
608 altsetting = usb_altnum_to_altsetting(intf, 3);
609 if (!altsetting)
610 return -ENXIO;
612 // Allocate URBs and buffers for the D channel out
613 endpoint = &altsetting->endpoint[EP_D_OUT-1];
615 DBG(2,"endpoint address=%02x,packet size=%d",
616 endpoint->desc.bEndpointAddress, le16_to_cpu(endpoint->desc.wMaxPacketSize));
618 return st5481_setup_isocpipes(d_out->urb, dev,
619 usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress),
620 NUM_ISO_PACKETS_D, SIZE_ISO_PACKETS_D_OUT,
621 NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT,
622 usb_d_out_complete, adapter);
625 static void st5481_release_d_out(struct st5481_adapter *adapter)
627 struct st5481_d_out *d_out = &adapter->d_out;
629 DBG(2,"");
631 st5481_release_isocpipes(d_out->urb);
634 int st5481_setup_d(struct st5481_adapter *adapter)
636 int retval;
638 DBG(2,"");
640 retval = st5481_setup_d_out(adapter);
641 if (retval)
642 goto err;
643 adapter->d_in.bufsize = MAX_DFRAME_LEN_L1;
644 adapter->d_in.num_packets = NUM_ISO_PACKETS_D;
645 adapter->d_in.packet_size = SIZE_ISO_PACKETS_D_IN;
646 adapter->d_in.ep = EP_D_IN | USB_DIR_IN;
647 adapter->d_in.counter = IN_D_COUNTER;
648 adapter->d_in.adapter = adapter;
649 adapter->d_in.hisax_if = &adapter->hisax_d_if.ifc;
650 retval = st5481_setup_in(&adapter->d_in);
651 if (retval)
652 goto err_d_out;
654 adapter->l1m.fsm = &l1fsm;
655 adapter->l1m.state = ST_L1_F3;
656 adapter->l1m.debug = st5481_debug & 0x100;
657 adapter->l1m.userdata = adapter;
658 adapter->l1m.printdebug = l1m_debug;
659 FsmInitTimer(&adapter->l1m, &adapter->timer);
661 adapter->d_out.fsm.fsm = &dout_fsm;
662 adapter->d_out.fsm.state = ST_DOUT_NONE;
663 adapter->d_out.fsm.debug = st5481_debug & 0x100;
664 adapter->d_out.fsm.userdata = adapter;
665 adapter->d_out.fsm.printdebug = dout_debug;
667 return 0;
669 err_d_out:
670 st5481_release_d_out(adapter);
671 err:
672 return retval;
675 void st5481_release_d(struct st5481_adapter *adapter)
677 DBG(2,"");
679 st5481_release_in(&adapter->d_in);
680 st5481_release_d_out(adapter);
683 /* ======================================================================
684 * init / exit
687 int __init st5481_d_init(void)
689 int retval;
691 l1fsm.state_count = L1_STATE_COUNT;
692 l1fsm.event_count = L1_EVENT_COUNT;
693 l1fsm.strEvent = strL1Event;
694 l1fsm.strState = strL1State;
695 retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
696 if (retval)
697 goto err;
699 dout_fsm.state_count = DOUT_STATE_COUNT;
700 dout_fsm.event_count = DOUT_EVENT_COUNT;
701 dout_fsm.strEvent = strDoutEvent;
702 dout_fsm.strState = strDoutState;
703 retval = FsmNew(&dout_fsm, DoutFnList, ARRAY_SIZE(DoutFnList));
704 if (retval)
705 goto err_l1;
707 return 0;
709 err_l1:
710 FsmFree(&l1fsm);
711 err:
712 return retval;
715 // can't be __exit
716 void st5481_d_exit(void)
718 FsmFree(&l1fsm);
719 FsmFree(&dout_fsm);