blob: 39e8e49cfd2de8ee0ae293eda4409a5b707f006e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Driver for ST5481 USB ISDN modem
3 *
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.
10 *
11 */
12
13#include <linux/init.h>
14#include <linux/usb.h>
15#include <linux/slab.h>
16#include <linux/netdevice.h>
17#include "st5481.h"
18
19static void ph_connect(struct st5481_adapter *adapter);
20static void ph_disconnect(struct st5481_adapter *adapter);
21
22static struct Fsm l1fsm;
23
24static char *strL1State[] =
25{
26 "ST_L1_F3",
27 "ST_L1_F4",
28 "ST_L1_F6",
29 "ST_L1_F7",
30 "ST_L1_F8",
31};
32
33static char *strL1Event[] =
34{
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",
54};
55
56static inline void D_L1L2(struct st5481_adapter *adapter, int pr, void *arg)
57{
58 struct hisax_if *ifc = (struct hisax_if *) &adapter->hisax_d_if;
59
60 ifc->l1l2(ifc, pr, arg);
61}
62
63static void
64l1_go_f3(struct FsmInst *fi, int event, void *arg)
65{
66 struct st5481_adapter *adapter = fi->userdata;
67
68 if (fi->state == ST_L1_F7)
69 ph_disconnect(adapter);
70
71 FsmChangeState(fi, ST_L1_F3);
72 D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
73}
74
75static void
76l1_go_f6(struct FsmInst *fi, int event, void *arg)
77{
78 struct st5481_adapter *adapter = fi->userdata;
79
80 if (fi->state == ST_L1_F7)
81 ph_disconnect(adapter);
82
83 FsmChangeState(fi, ST_L1_F6);
84}
85
86static void
87l1_go_f7(struct FsmInst *fi, int event, void *arg)
88{
89 struct st5481_adapter *adapter = fi->userdata;
90
91 FsmDelTimer(&adapter->timer, 0);
92 ph_connect(adapter);
93 FsmChangeState(fi, ST_L1_F7);
94 D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);
95}
96
97static void
98l1_go_f8(struct FsmInst *fi, int event, void *arg)
99{
100 struct st5481_adapter *adapter = fi->userdata;
101
102 if (fi->state == ST_L1_F7)
103 ph_disconnect(adapter);
104
105 FsmChangeState(fi, ST_L1_F8);
106}
107
108static void
109l1_timer3(struct FsmInst *fi, int event, void *arg)
110{
111 struct st5481_adapter *adapter = fi->userdata;
112
113 st5481_ph_command(adapter, ST5481_CMD_DR);
114 FsmChangeState(fi, ST_L1_F3);
115 D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);
116}
117
118static void
119l1_ignore(struct FsmInst *fi, int event, void *arg)
120{
121}
122
123static void
124l1_activate(struct FsmInst *fi, int event, void *arg)
125{
126 struct st5481_adapter *adapter = fi->userdata;
127
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);
133}
134
135static struct FsmNode L1FnList[] __initdata =
136{
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},
142
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},
148
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},
155
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},
161
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},
168};
169
170static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
171{
172 va_list args;
173 char buf[256];
174
175 va_start(args, fmt);
Alexey Dobriyan0b2dd132006-12-08 02:39:34 -0800176 vsnprintf(buf, sizeof(buf), fmt, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 DBG(8, "%s", buf);
178 va_end(args);
179}
180
181/* ======================================================================
182 * D-Channel out
183 */
184
185/*
186 D OUT state machine:
187 ====================
188
189 Transmit short frame (< 16 bytes of encoded data):
190
191 L1 FRAME D_OUT_STATE USB D CHANNEL
192 -------- ----------- --- ---------
193
194 FIXME
195
196 -> [xx..xx] SHORT_INIT -> [7Exx..xxC1C27EFF]
197 SHORT_WAIT_DEN <> OUT_D_COUNTER=16
198
199 END_OF_SHORT <- DEN_EVENT -> 7Exx
200 xxxx
201 xxxx
202 xxxx
203 xxxx
204 xxxx
205 C1C1
206 7EFF
207 WAIT_FOR_RESET_IDLE <- D_UNDERRUN <- (8ms)
208 IDLE <> Reset pipe
209
210
211
212 Transmit long frame (>= 16 bytes of encoded data):
213
214 L1 FRAME D_OUT_STATE USB D CHANNEL
215 -------- ----------- --- ---------
216
217 -> [xx...xx] IDLE
218 WAIT_FOR_STOP <> OUT_D_COUNTER=0
219 WAIT_FOR_RESET <> Reset pipe
220 STOP
221 INIT_LONG_FRAME -> [7Exx..xx]
222 WAIT_DEN <> OUT_D_COUNTER=16
223 OUT_NORMAL <- DEN_EVENT -> 7Exx
224 END_OF_FRAME_BUSY -> [xxxx] xxxx
225 END_OF_FRAME_NOT_BUSY -> [xxxx] xxxx
226 -> [xxxx] xxxx
227 -> [C1C2] xxxx
228 -> [7EFF] xxxx
229 xxxx
230 xxxx
231 ....
232 xxxx
233 C1C2
234 7EFF
235 <- D_UNDERRUN <- (> 8ms)
236 WAIT_FOR_STOP <> OUT_D_COUNTER=0
237 WAIT_FOR_RESET <> Reset pipe
238 STOP
239
240*/
241
242static struct Fsm dout_fsm;
243
244static char *strDoutState[] =
245{
246 "ST_DOUT_NONE",
247
248 "ST_DOUT_SHORT_INIT",
249 "ST_DOUT_SHORT_WAIT_DEN",
250
251 "ST_DOUT_LONG_INIT",
252 "ST_DOUT_LONG_WAIT_DEN",
253 "ST_DOUT_NORMAL",
254
255 "ST_DOUT_WAIT_FOR_UNDERRUN",
256 "ST_DOUT_WAIT_FOR_NOT_BUSY",
257 "ST_DOUT_WAIT_FOR_STOP",
258 "ST_DOUT_WAIT_FOR_RESET",
259};
260
261static char *strDoutEvent[] =
262{
263 "EV_DOUT_START_XMIT",
264 "EV_DOUT_COMPLETE",
265 "EV_DOUT_DEN",
266 "EV_DOUT_RESETED",
267 "EV_DOUT_STOPPED",
268 "EV_DOUT_COLL",
269 "EV_DOUT_UNDERRUN",
270};
271
272static void dout_debug(struct FsmInst *fi, char *fmt, ...)
273{
274 va_list args;
275 char buf[256];
276
277 va_start(args, fmt);
Alexey Dobriyan0b2dd132006-12-08 02:39:34 -0800278 vsnprintf(buf, sizeof(buf), fmt, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 DBG(0x2, "%s", buf);
280 va_end(args);
281}
282
283static void dout_stop_event(void *context)
284{
285 struct st5481_adapter *adapter = context;
286
287 FsmEvent(&adapter->d_out.fsm, EV_DOUT_STOPPED, NULL);
288}
289
290/*
291 * Start the transfer of a D channel frame.
292 */
293static void usb_d_out(struct st5481_adapter *adapter, int buf_nr)
294{
295 struct st5481_d_out *d_out = &adapter->d_out;
296 struct urb *urb;
297 unsigned int num_packets, packet_offset;
298 int len, buf_size, bytes_sent;
299 struct sk_buff *skb;
300 struct usb_iso_packet_descriptor *desc;
301
302 if (d_out->fsm.state != ST_DOUT_NORMAL)
303 return;
304
305 if (test_and_set_bit(buf_nr, &d_out->busy)) {
306 DBG(2, "ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
307 return;
308 }
309 urb = d_out->urb[buf_nr];
310
311 skb = d_out->tx_skb;
312
313 buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT;
314
315 if (skb) {
316 len = isdnhdlc_encode(&d_out->hdlc_state,
317 skb->data, skb->len, &bytes_sent,
318 urb->transfer_buffer, buf_size);
319 skb_pull(skb,bytes_sent);
320 } else {
321 // Send flags or idle
322 len = isdnhdlc_encode(&d_out->hdlc_state,
323 NULL, 0, &bytes_sent,
324 urb->transfer_buffer, buf_size);
325 }
326
327 if (len < buf_size) {
328 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN);
329 }
330 if (skb && !skb->len) {
331 d_out->tx_skb = NULL;
332 D_L1L2(adapter, PH_DATA | CONFIRM, NULL);
333 dev_kfree_skb_any(skb);
334 }
335
336 // Prepare the URB
337 urb->transfer_buffer_length = len;
338 num_packets = 0;
339 packet_offset = 0;
340 while (packet_offset < len) {
341 desc = &urb->iso_frame_desc[num_packets];
342 desc->offset = packet_offset;
343 desc->length = SIZE_ISO_PACKETS_D_OUT;
344 if (len - packet_offset < desc->length)
345 desc->length = len - packet_offset;
346 num_packets++;
347 packet_offset += desc->length;
348 }
349 urb->number_of_packets = num_packets;
350
351 // Prepare the URB
352 urb->dev = adapter->usb_dev;
353 // Need to transmit the next buffer 2ms after the DEN_EVENT
354 urb->transfer_flags = 0;
355 urb->start_frame = usb_get_current_frame_number(adapter->usb_dev)+2;
356
357 DBG_ISO_PACKET(0x20,urb);
358
359 if (usb_submit_urb(urb, GFP_KERNEL) < 0) {
360 // There is another URB queued up
361 urb->transfer_flags = URB_ISO_ASAP;
362 SUBMIT_URB(urb, GFP_KERNEL);
363 }
364}
365
366static void fifo_reseted(void *context)
367{
368 struct st5481_adapter *adapter = context;
369
370 FsmEvent(&adapter->d_out.fsm, EV_DOUT_RESETED, NULL);
371}
372
David Howells7d12e782006-10-05 14:55:46 +0100373static void usb_d_out_complete(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
375 struct st5481_adapter *adapter = urb->context;
376 struct st5481_d_out *d_out = &adapter->d_out;
Alan Cox17a45062006-10-03 01:13:55 -0700377 long buf_nr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 DBG(2, "");
380
381 buf_nr = get_buf_nr(d_out->urb, urb);
382 test_and_clear_bit(buf_nr, &d_out->busy);
383
384 if (unlikely(urb->status < 0)) {
Karsten Keil61ffcaf2005-09-17 23:52:42 +0200385 switch (urb->status) {
386 case -ENOENT:
387 case -ESHUTDOWN:
388 case -ECONNRESET:
389 DBG(1,"urb killed status %d", urb->status);
390 break;
391 default:
Arjan van de Venb6c63932008-07-25 01:45:52 -0700392 WARNING("urb status %d",urb->status);
Karsten Keil61ffcaf2005-09-17 23:52:42 +0200393 if (d_out->busy == 0) {
394 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
395 }
396 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 }
Karsten Keil61ffcaf2005-09-17 23:52:42 +0200398 return; // Give up
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 }
400
401 FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr);
402}
403
404/* ====================================================================== */
405
406static void dout_start_xmit(struct FsmInst *fsm, int event, void *arg)
407{
408 // FIXME unify?
409 struct st5481_adapter *adapter = fsm->userdata;
410 struct st5481_d_out *d_out = &adapter->d_out;
411 struct urb *urb;
412 int len, bytes_sent;
413 struct sk_buff *skb;
414 int buf_nr = 0;
415
416 skb = d_out->tx_skb;
417
418 DBG(2,"len=%d",skb->len);
419
Karsten Keilc38fc3b2009-07-08 20:31:42 +0200420 isdnhdlc_out_init(&d_out->hdlc_state, HDLC_DCHANNEL | HDLC_BITREVERSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
422 if (test_and_set_bit(buf_nr, &d_out->busy)) {
Arjan van de Venb6c63932008-07-25 01:45:52 -0700423 WARNING("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 return;
425 }
426 urb = d_out->urb[buf_nr];
427
428 DBG_SKB(0x10, skb);
429 len = isdnhdlc_encode(&d_out->hdlc_state,
430 skb->data, skb->len, &bytes_sent,
431 urb->transfer_buffer, 16);
432 skb_pull(skb, bytes_sent);
433
434 if(len < 16)
435 FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_INIT);
436 else
437 FsmChangeState(&d_out->fsm, ST_DOUT_LONG_INIT);
438
439 if (skb->len == 0) {
440 d_out->tx_skb = NULL;
441 D_L1L2(adapter, PH_DATA | CONFIRM, NULL);
442 dev_kfree_skb_any(skb);
443 }
444
445// Prepare the URB
446 urb->transfer_buffer_length = len;
447
448 urb->iso_frame_desc[0].offset = 0;
449 urb->iso_frame_desc[0].length = len;
450 urb->number_of_packets = 1;
451
452 // Prepare the URB
453 urb->dev = adapter->usb_dev;
454 urb->transfer_flags = URB_ISO_ASAP;
455
456 DBG_ISO_PACKET(0x20,urb);
457 SUBMIT_URB(urb, GFP_KERNEL);
458}
459
460static void dout_short_fifo(struct FsmInst *fsm, int event, void *arg)
461{
462 struct st5481_adapter *adapter = fsm->userdata;
463 struct st5481_d_out *d_out = &adapter->d_out;
464
465 FsmChangeState(&d_out->fsm, ST_DOUT_SHORT_WAIT_DEN);
466 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL);
467}
468
469static void dout_end_short_frame(struct FsmInst *fsm, int event, void *arg)
470{
471 struct st5481_adapter *adapter = fsm->userdata;
472 struct st5481_d_out *d_out = &adapter->d_out;
473
474 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_UNDERRUN);
475}
476
477static void dout_long_enable_fifo(struct FsmInst *fsm, int event, void *arg)
478{
479 struct st5481_adapter *adapter = fsm->userdata;
480 struct st5481_d_out *d_out = &adapter->d_out;
481
482 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 16, NULL, NULL);
483 FsmChangeState(&d_out->fsm, ST_DOUT_LONG_WAIT_DEN);
484}
485
486static void dout_long_den(struct FsmInst *fsm, int event, void *arg)
487{
488 struct st5481_adapter *adapter = fsm->userdata;
489 struct st5481_d_out *d_out = &adapter->d_out;
490
491 FsmChangeState(&d_out->fsm, ST_DOUT_NORMAL);
492 usb_d_out(adapter, 0);
493 usb_d_out(adapter, 1);
494}
495
496static void dout_reset(struct FsmInst *fsm, int event, void *arg)
497{
498 struct st5481_adapter *adapter = fsm->userdata;
499 struct st5481_d_out *d_out = &adapter->d_out;
500
501 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_RESET);
502 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
503}
504
505static void dout_stop(struct FsmInst *fsm, int event, void *arg)
506{
507 struct st5481_adapter *adapter = fsm->userdata;
508 struct st5481_d_out *d_out = &adapter->d_out;
509
510 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_STOP);
511 st5481_usb_device_ctrl_msg(adapter, OUT_D_COUNTER, 0, dout_stop_event, adapter);
512}
513
514static void dout_underrun(struct FsmInst *fsm, int event, void *arg)
515{
516 struct st5481_adapter *adapter = fsm->userdata;
517 struct st5481_d_out *d_out = &adapter->d_out;
518
519 if (test_bit(0, &d_out->busy) || test_bit(1, &d_out->busy)) {
520 FsmChangeState(&d_out->fsm, ST_DOUT_WAIT_FOR_NOT_BUSY);
521 } else {
522 dout_stop(fsm, event, arg);
523 }
524}
525
526static void dout_check_busy(struct FsmInst *fsm, int event, void *arg)
527{
528 struct st5481_adapter *adapter = fsm->userdata;
529 struct st5481_d_out *d_out = &adapter->d_out;
530
531 if (!test_bit(0, &d_out->busy) && !test_bit(1, &d_out->busy))
532 dout_stop(fsm, event, arg);
533}
534
535static void dout_reseted(struct FsmInst *fsm, int event, void *arg)
536{
537 struct st5481_adapter *adapter = fsm->userdata;
538 struct st5481_d_out *d_out = &adapter->d_out;
539
540 FsmChangeState(&d_out->fsm, ST_DOUT_NONE);
541 // FIXME locking
542 if (d_out->tx_skb)
543 FsmEvent(&d_out->fsm, EV_DOUT_START_XMIT, NULL);
544}
545
546static void dout_complete(struct FsmInst *fsm, int event, void *arg)
547{
548 struct st5481_adapter *adapter = fsm->userdata;
Alan Cox17a45062006-10-03 01:13:55 -0700549 long buf_nr = (long) arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
551 usb_d_out(adapter, buf_nr);
552}
553
554static void dout_ignore(struct FsmInst *fsm, int event, void *arg)
555{
556}
557
558static struct FsmNode DoutFnList[] __initdata =
559{
560 {ST_DOUT_NONE, EV_DOUT_START_XMIT, dout_start_xmit},
561
562 {ST_DOUT_SHORT_INIT, EV_DOUT_COMPLETE, dout_short_fifo},
563
564 {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_DEN, dout_end_short_frame},
565 {ST_DOUT_SHORT_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun},
566
567 {ST_DOUT_LONG_INIT, EV_DOUT_COMPLETE, dout_long_enable_fifo},
568
569 {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_DEN, dout_long_den},
570 {ST_DOUT_LONG_WAIT_DEN, EV_DOUT_UNDERRUN, dout_underrun},
571
572 {ST_DOUT_NORMAL, EV_DOUT_UNDERRUN, dout_underrun},
573 {ST_DOUT_NORMAL, EV_DOUT_COMPLETE, dout_complete},
574
575 {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_UNDERRUN, dout_underrun},
576 {ST_DOUT_WAIT_FOR_UNDERRUN, EV_DOUT_COMPLETE, dout_ignore},
577
578 {ST_DOUT_WAIT_FOR_NOT_BUSY, EV_DOUT_COMPLETE, dout_check_busy},
579
580 {ST_DOUT_WAIT_FOR_STOP, EV_DOUT_STOPPED, dout_reset},
581
582 {ST_DOUT_WAIT_FOR_RESET, EV_DOUT_RESETED, dout_reseted},
583};
584
585void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
586{
587 struct st5481_adapter *adapter = hisax_d_if->priv;
588 struct sk_buff *skb = arg;
589
590 switch (pr) {
591 case PH_ACTIVATE | REQUEST:
592 FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL);
593 break;
594 case PH_DEACTIVATE | REQUEST:
595 FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL);
596 break;
597 case PH_DATA | REQUEST:
598 DBG(2, "PH_DATA REQUEST len %d", skb->len);
Eric Sesterhenn6dd44a72006-03-26 18:19:26 +0200599 BUG_ON(adapter->d_out.tx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 adapter->d_out.tx_skb = skb;
601 FsmEvent(&adapter->d_out.fsm, EV_DOUT_START_XMIT, NULL);
602 break;
603 default:
Arjan van de Venb6c63932008-07-25 01:45:52 -0700604 WARNING("pr %#x\n", pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 break;
606 }
607}
608
609/* ======================================================================
610 */
611
612/*
613 * Start receiving on the D channel since entered state F7.
614 */
615static void ph_connect(struct st5481_adapter *adapter)
616{
617 struct st5481_d_out *d_out = &adapter->d_out;
618 struct st5481_in *d_in = &adapter->d_in;
619
620 DBG(8,"");
621
622 FsmChangeState(&d_out->fsm, ST_DOUT_NONE);
623
624 // st5481_usb_device_ctrl_msg(adapter, FFMSK_D, OUT_UNDERRUN, NULL, NULL);
625 st5481_usb_device_ctrl_msg(adapter, FFMSK_D, 0xfc, NULL, NULL);
626 st5481_in_mode(d_in, L1_MODE_HDLC);
627
628#ifdef LOOPBACK
629 // Turn loopback on (data sent on B and D looped back)
630 st5481_usb_device_ctrl_msg(cs, LBB, 0x04, NULL, NULL);
631#endif
632
633 st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, NULL, NULL);
634
635 // Turn on the green LED to tell that we are in state F7
636 adapter->leds |= GREEN_LED;
637 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL);
638}
639
640/*
641 * Stop receiving on the D channel since not in state F7.
642 */
643static void ph_disconnect(struct st5481_adapter *adapter)
644{
645 DBG(8,"");
646
647 st5481_in_mode(&adapter->d_in, L1_MODE_NULL);
648
649 // Turn off the green LED to tell that we left state F7
650 adapter->leds &= ~GREEN_LED;
651 st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, adapter->leds, NULL, NULL);
652}
653
654static int st5481_setup_d_out(struct st5481_adapter *adapter)
655{
656 struct usb_device *dev = adapter->usb_dev;
657 struct usb_interface *intf;
658 struct usb_host_interface *altsetting = NULL;
659 struct usb_host_endpoint *endpoint;
660 struct st5481_d_out *d_out = &adapter->d_out;
661
662 DBG(2,"");
663
664 intf = usb_ifnum_to_if(dev, 0);
665 if (intf)
666 altsetting = usb_altnum_to_altsetting(intf, 3);
667 if (!altsetting)
668 return -ENXIO;
669
670 // Allocate URBs and buffers for the D channel out
671 endpoint = &altsetting->endpoint[EP_D_OUT-1];
672
673 DBG(2,"endpoint address=%02x,packet size=%d",
674 endpoint->desc.bEndpointAddress, le16_to_cpu(endpoint->desc.wMaxPacketSize));
675
676 return st5481_setup_isocpipes(d_out->urb, dev,
677 usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress),
678 NUM_ISO_PACKETS_D, SIZE_ISO_PACKETS_D_OUT,
679 NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT,
680 usb_d_out_complete, adapter);
681}
682
683static void st5481_release_d_out(struct st5481_adapter *adapter)
684{
685 struct st5481_d_out *d_out = &adapter->d_out;
686
687 DBG(2,"");
688
689 st5481_release_isocpipes(d_out->urb);
690}
691
692int st5481_setup_d(struct st5481_adapter *adapter)
693{
694 int retval;
695
696 DBG(2,"");
697
698 retval = st5481_setup_d_out(adapter);
699 if (retval)
700 goto err;
701 adapter->d_in.bufsize = MAX_DFRAME_LEN_L1;
702 adapter->d_in.num_packets = NUM_ISO_PACKETS_D;
703 adapter->d_in.packet_size = SIZE_ISO_PACKETS_D_IN;
704 adapter->d_in.ep = EP_D_IN | USB_DIR_IN;
705 adapter->d_in.counter = IN_D_COUNTER;
706 adapter->d_in.adapter = adapter;
707 adapter->d_in.hisax_if = &adapter->hisax_d_if.ifc;
708 retval = st5481_setup_in(&adapter->d_in);
709 if (retval)
710 goto err_d_out;
711
712 adapter->l1m.fsm = &l1fsm;
713 adapter->l1m.state = ST_L1_F3;
Karsten Keil61ffcaf2005-09-17 23:52:42 +0200714 adapter->l1m.debug = st5481_debug & 0x100;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 adapter->l1m.userdata = adapter;
716 adapter->l1m.printdebug = l1m_debug;
717 FsmInitTimer(&adapter->l1m, &adapter->timer);
718
719 adapter->d_out.fsm.fsm = &dout_fsm;
720 adapter->d_out.fsm.state = ST_DOUT_NONE;
Karsten Keil61ffcaf2005-09-17 23:52:42 +0200721 adapter->d_out.fsm.debug = st5481_debug & 0x100;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 adapter->d_out.fsm.userdata = adapter;
723 adapter->d_out.fsm.printdebug = dout_debug;
724
725 return 0;
726
727 err_d_out:
728 st5481_release_d_out(adapter);
729 err:
730 return retval;
731}
732
733void st5481_release_d(struct st5481_adapter *adapter)
734{
735 DBG(2,"");
736
737 st5481_release_in(&adapter->d_in);
738 st5481_release_d_out(adapter);
739}
740
741/* ======================================================================
742 * init / exit
743 */
744
745int __init st5481_d_init(void)
746{
747 int retval;
748
749 l1fsm.state_count = L1_STATE_COUNT;
750 l1fsm.event_count = L1_EVENT_COUNT;
751 l1fsm.strEvent = strL1Event;
752 l1fsm.strState = strL1State;
753 retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
754 if (retval)
755 goto err;
756
757 dout_fsm.state_count = DOUT_STATE_COUNT;
758 dout_fsm.event_count = DOUT_EVENT_COUNT;
759 dout_fsm.strEvent = strDoutEvent;
760 dout_fsm.strState = strDoutState;
761 retval = FsmNew(&dout_fsm, DoutFnList, ARRAY_SIZE(DoutFnList));
762 if (retval)
763 goto err_l1;
764
765 return 0;
766
767 err_l1:
768 FsmFree(&l1fsm);
769 err:
770 return retval;
771}
772
773// can't be __exit
774void st5481_d_exit(void)
775{
776 FsmFree(&l1fsm);
777 FsmFree(&dout_fsm);
778}