]>
git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/isdn/hisax/st5481_b.c
2 * Driver for ST5481 USB ISDN modem
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
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 <linux/bitrev.h>
20 static inline void B_L1L2(struct st5481_bcs
*bcs
, int pr
, void *arg
)
22 struct hisax_if
*ifc
= (struct hisax_if
*) &bcs
->b_if
;
24 ifc
->l1l2(ifc
, pr
, arg
);
28 * Encode and transmit next frame.
30 static void usb_b_out(struct st5481_bcs
*bcs
, int buf_nr
)
32 struct st5481_b_out
*b_out
= &bcs
->b_out
;
33 struct st5481_adapter
*adapter
= bcs
->adapter
;
35 unsigned int packet_size
, offset
;
36 int len
, buf_size
, bytes_sent
;
40 if (test_and_set_bit(buf_nr
, &b_out
->busy
)) {
41 DBG(4, "ep %d urb %d busy", (bcs
->channel
+ 1) * 2, buf_nr
);
44 urb
= b_out
->urb
[buf_nr
];
46 // Adjust isoc buffer size according to flow state
47 if (b_out
->flow_event
& (OUT_DOWN
| OUT_UNDERRUN
)) {
48 buf_size
= NUM_ISO_PACKETS_B
* SIZE_ISO_PACKETS_B_OUT
+ B_FLOW_ADJUST
;
49 packet_size
= SIZE_ISO_PACKETS_B_OUT
+ B_FLOW_ADJUST
;
50 DBG(4, "B%d,adjust flow,add %d bytes", bcs
->channel
+ 1, B_FLOW_ADJUST
);
51 } else if (b_out
->flow_event
& OUT_UP
) {
52 buf_size
= NUM_ISO_PACKETS_B
* SIZE_ISO_PACKETS_B_OUT
- B_FLOW_ADJUST
;
53 packet_size
= SIZE_ISO_PACKETS_B_OUT
- B_FLOW_ADJUST
;
54 DBG(4, "B%d,adjust flow,remove %d bytes", bcs
->channel
+ 1, B_FLOW_ADJUST
);
56 buf_size
= NUM_ISO_PACKETS_B
* SIZE_ISO_PACKETS_B_OUT
;
59 b_out
->flow_event
= 0;
62 while (len
< buf_size
) {
63 if ((skb
= b_out
->tx_skb
)) {
65 DBG(4, "B%d,len=%d", bcs
->channel
+ 1, skb
->len
);
67 if (bcs
->mode
== L1_MODE_TRANS
) {
68 bytes_sent
= buf_size
- len
;
69 if (skb
->len
< bytes_sent
)
70 bytes_sent
= skb
->len
;
71 { /* swap tx bytes to get hearable audio data */
72 register unsigned char *src
= skb
->data
;
73 register unsigned char *dest
= urb
->transfer_buffer
+ len
;
74 register unsigned int count
;
75 for (count
= 0; count
< bytes_sent
; count
++)
76 *dest
++ = bitrev8(*src
++);
80 len
+= isdnhdlc_encode(&b_out
->hdlc_state
,
81 skb
->data
, skb
->len
, &bytes_sent
,
82 urb
->transfer_buffer
+ len
, buf_size
-len
);
85 skb_pull(skb
, bytes_sent
);
90 B_L1L2(bcs
, PH_DATA
| CONFIRM
, (void *)(unsigned long) skb
->truesize
);
91 dev_kfree_skb_any(skb
);
93 /* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
94 /* st5481B_sched_event(bcs, B_XMTBUFREADY); */
98 if (bcs
->mode
== L1_MODE_TRANS
) {
99 memset(urb
->transfer_buffer
+ len
, 0xff, buf_size
-len
);
103 len
+= isdnhdlc_encode(&b_out
->hdlc_state
,
104 NULL
, 0, &bytes_sent
,
105 urb
->transfer_buffer
+ len
, buf_size
-len
);
111 for (i
= 0, offset
= 0; offset
< len
; i
++) {
112 urb
->iso_frame_desc
[i
].offset
= offset
;
113 urb
->iso_frame_desc
[i
].length
= packet_size
;
114 offset
+= packet_size
;
115 packet_size
= SIZE_ISO_PACKETS_B_OUT
;
117 urb
->transfer_buffer_length
= len
;
118 urb
->number_of_packets
= i
;
119 urb
->dev
= adapter
->usb_dev
;
121 DBG_ISO_PACKET(0x200, urb
);
123 SUBMIT_URB(urb
, GFP_NOIO
);
127 * Start transferring (flags or data) on the B channel, since
128 * FIFO counters has been set to a non-zero value.
130 static void st5481B_start_xfer(void *context
)
132 struct st5481_bcs
*bcs
= context
;
134 DBG(4, "B%d", bcs
->channel
+ 1);
136 // Start transmitting (flags or data) on B channel
143 * If the adapter has only 2 LEDs, the green
144 * LED will blink with a rate depending
145 * on the number of channels opened.
147 static void led_blink(struct st5481_adapter
*adapter
)
149 u_char leds
= adapter
->leds
;
151 // 50 frames/sec for each channel
152 if (++adapter
->led_counter
% 50) {
156 if (adapter
->led_counter
% 100) {
162 st5481_usb_device_ctrl_msg(adapter
, GPIO_OUT
, leds
, NULL
, NULL
);
165 static void usb_b_out_complete(struct urb
*urb
)
167 struct st5481_bcs
*bcs
= urb
->context
;
168 struct st5481_b_out
*b_out
= &bcs
->b_out
;
169 struct st5481_adapter
*adapter
= bcs
->adapter
;
172 buf_nr
= get_buf_nr(b_out
->urb
, urb
);
173 test_and_clear_bit(buf_nr
, &b_out
->busy
);
175 if (unlikely(urb
->status
< 0)) {
176 switch (urb
->status
) {
180 DBG(4, "urb killed status %d", urb
->status
);
183 WARNING("urb status %d", urb
->status
);
184 if (b_out
->busy
== 0) {
185 st5481_usb_pipe_reset(adapter
, (bcs
->channel
+ 1) * 2 | USB_DIR_OUT
, NULL
, NULL
);
191 usb_b_out(bcs
, buf_nr
);
193 if (adapter
->number_of_leds
== 2)
198 * Start or stop the transfer on the B channel.
200 static void st5481B_mode(struct st5481_bcs
*bcs
, int mode
)
202 struct st5481_b_out
*b_out
= &bcs
->b_out
;
203 struct st5481_adapter
*adapter
= bcs
->adapter
;
205 DBG(4, "B%d,mode=%d", bcs
->channel
+ 1, mode
);
207 if (bcs
->mode
== mode
)
212 // Cancel all USB transfers on this B channel
213 usb_unlink_urb(b_out
->urb
[0]);
214 usb_unlink_urb(b_out
->urb
[1]);
217 st5481_in_mode(&bcs
->b_in
, mode
);
218 if (bcs
->mode
!= L1_MODE_NULL
) {
219 // Open the B channel
220 if (bcs
->mode
!= L1_MODE_TRANS
) {
221 u32 features
= HDLC_BITREVERSE
;
222 if (bcs
->mode
== L1_MODE_HDLC_56K
)
223 features
|= HDLC_56KBIT
;
224 isdnhdlc_out_init(&b_out
->hdlc_state
, features
);
226 st5481_usb_pipe_reset(adapter
, (bcs
->channel
+ 1) * 2, NULL
, NULL
);
228 // Enable B channel interrupts
229 st5481_usb_device_ctrl_msg(adapter
, FFMSK_B1
+ (bcs
->channel
* 2),
230 OUT_UP
+ OUT_DOWN
+ OUT_UNDERRUN
, NULL
, NULL
);
232 // Enable B channel FIFOs
233 st5481_usb_device_ctrl_msg(adapter
, OUT_B1_COUNTER
+(bcs
->channel
* 2), 32, st5481B_start_xfer
, bcs
);
234 if (adapter
->number_of_leds
== 4) {
235 if (bcs
->channel
== 0) {
236 adapter
->leds
|= B1_LED
;
238 adapter
->leds
|= B2_LED
;
242 // Disble B channel interrupts
243 st5481_usb_device_ctrl_msg(adapter
, FFMSK_B1
+(bcs
->channel
* 2), 0, NULL
, NULL
);
245 // Disable B channel FIFOs
246 st5481_usb_device_ctrl_msg(adapter
, OUT_B1_COUNTER
+(bcs
->channel
* 2), 0, NULL
, NULL
);
248 if (adapter
->number_of_leds
== 4) {
249 if (bcs
->channel
== 0) {
250 adapter
->leds
&= ~B1_LED
;
252 adapter
->leds
&= ~B2_LED
;
255 st5481_usb_device_ctrl_msg(adapter
, GPIO_OUT
, adapter
->leds
, NULL
, NULL
);
258 dev_kfree_skb_any(b_out
->tx_skb
);
259 b_out
->tx_skb
= NULL
;
265 static int st5481_setup_b_out(struct st5481_bcs
*bcs
)
267 struct usb_device
*dev
= bcs
->adapter
->usb_dev
;
268 struct usb_interface
*intf
;
269 struct usb_host_interface
*altsetting
= NULL
;
270 struct usb_host_endpoint
*endpoint
;
271 struct st5481_b_out
*b_out
= &bcs
->b_out
;
275 intf
= usb_ifnum_to_if(dev
, 0);
277 altsetting
= usb_altnum_to_altsetting(intf
, 3);
281 // Allocate URBs and buffers for the B channel out
282 endpoint
= &altsetting
->endpoint
[EP_B1_OUT
- 1 + bcs
->channel
* 2];
284 DBG(4, "endpoint address=%02x,packet size=%d",
285 endpoint
->desc
.bEndpointAddress
, le16_to_cpu(endpoint
->desc
.wMaxPacketSize
));
287 // Allocate memory for 8000bytes/sec + extra bytes if underrun
288 return st5481_setup_isocpipes(b_out
->urb
, dev
,
289 usb_sndisocpipe(dev
, endpoint
->desc
.bEndpointAddress
),
290 NUM_ISO_PACKETS_B
, SIZE_ISO_PACKETS_B_OUT
,
291 NUM_ISO_PACKETS_B
* SIZE_ISO_PACKETS_B_OUT
+ B_FLOW_ADJUST
,
292 usb_b_out_complete
, bcs
);
295 static void st5481_release_b_out(struct st5481_bcs
*bcs
)
297 struct st5481_b_out
*b_out
= &bcs
->b_out
;
301 st5481_release_isocpipes(b_out
->urb
);
304 int st5481_setup_b(struct st5481_bcs
*bcs
)
310 retval
= st5481_setup_b_out(bcs
);
313 bcs
->b_in
.bufsize
= HSCX_BUFMAX
;
314 bcs
->b_in
.num_packets
= NUM_ISO_PACKETS_B
;
315 bcs
->b_in
.packet_size
= SIZE_ISO_PACKETS_B_IN
;
316 bcs
->b_in
.ep
= (bcs
->channel
? EP_B2_IN
: EP_B1_IN
) | USB_DIR_IN
;
317 bcs
->b_in
.counter
= bcs
->channel
? IN_B2_COUNTER
: IN_B1_COUNTER
;
318 bcs
->b_in
.adapter
= bcs
->adapter
;
319 bcs
->b_in
.hisax_if
= &bcs
->b_if
.ifc
;
320 retval
= st5481_setup_in(&bcs
->b_in
);
328 st5481_release_b_out(bcs
);
334 * Release buffers and URBs for the B channels
336 void st5481_release_b(struct st5481_bcs
*bcs
)
340 st5481_release_in(&bcs
->b_in
);
341 st5481_release_b_out(bcs
);
345 * st5481_b_l2l1 is the entry point for upper layer routines that want to
346 * transmit on the B channel. PH_DATA | REQUEST is a normal packet that
347 * we either start transmitting (if idle) or queue (if busy).
348 * PH_PULL | REQUEST can be called to request a callback message
349 * (PH_PULL | CONFIRM)
350 * once the link is idle. After a "pull" callback, the upper layer
351 * routines can use PH_PULL | INDICATION to send data.
353 void st5481_b_l2l1(struct hisax_if
*ifc
, int pr
, void *arg
)
355 struct st5481_bcs
*bcs
= ifc
->priv
;
356 struct sk_buff
*skb
= arg
;
362 case PH_DATA
| REQUEST
:
363 BUG_ON(bcs
->b_out
.tx_skb
);
364 bcs
->b_out
.tx_skb
= skb
;
366 case PH_ACTIVATE
| REQUEST
:
368 DBG(4, "B%d,PH_ACTIVATE_REQUEST %ld", bcs
->channel
+ 1, mode
);
369 st5481B_mode(bcs
, mode
);
370 B_L1L2(bcs
, PH_ACTIVATE
| INDICATION
, NULL
);
372 case PH_DEACTIVATE
| REQUEST
:
373 DBG(4, "B%d,PH_DEACTIVATE_REQUEST", bcs
->channel
+ 1);
374 st5481B_mode(bcs
, L1_MODE_NULL
);
375 B_L1L2(bcs
, PH_DEACTIVATE
| INDICATION
, NULL
);
378 WARNING("pr %#x\n", pr
);