staging: vt6656: rename PIPEnsControlOut/CONTROLnsRequestOut to vnt_control_out
[cascardo/linux.git] / drivers / staging / vt6656 / usbpipe.c
1 /*
2  * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  *
20  * File: usbpipe.c
21  *
22  * Purpose: Handle USB control endpoint
23  *
24  * Author: Warren Hsu
25  *
26  * Date: Mar. 29, 2005
27  *
28  * Functions:
29  *      vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
30  *      CONTROLnsRequestIn - Read variable length bytes from MEM/BB/MAC/EEPROM
31  *      ControlvWriteByte - Write one byte to MEM/BB/MAC/EEPROM
32  *      ControlvReadByte - Read one byte from MEM/BB/MAC/EEPROM
33  *      ControlvMaskByte - Read one byte from MEM/BB/MAC/EEPROM and clear/set some bits in the same address
34  *
35  * Revision History:
36  *      04-05-2004 Jerry Chen:  Initial release
37  *      11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte
38  *
39  */
40
41 #include "int.h"
42 #include "rxtx.h"
43 #include "dpc.h"
44 #include "control.h"
45 #include "desc.h"
46 #include "device.h"
47
48 //endpoint def
49 //endpoint 0: control
50 //endpoint 1: interrupt
51 //endpoint 2: read bulk
52 //endpoint 3: write bulk
53
54 #define USB_CTL_WAIT   500 //ms
55
56 #ifndef URB_ASYNC_UNLINK
57 #define URB_ASYNC_UNLINK    0
58 #endif
59
60 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb);
61 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb);
62 static void s_nsBulkOutIoCompleteWrite(struct urb *urb);
63
64 int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
65                 u16 index, u16 length, u8 *buffer)
66 {
67         int status = 0;
68
69         if (priv->Flags & fMP_DISCONNECTED)
70                 return STATUS_FAILURE;
71
72         mutex_lock(&priv->usb_lock);
73
74         status = usb_control_msg(priv->usb,
75                 usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
76                         index, buffer, length, USB_CTL_WAIT);
77
78         mutex_unlock(&priv->usb_lock);
79
80         if (status < (int)length)
81                 return STATUS_FAILURE;
82
83         return STATUS_SUCCESS;
84 }
85
86 int PIPEnsControlIn(struct vnt_private *priv, u8 request, u16 value,
87                 u16 index, u16 length, u8 *buffer)
88 {
89         int status;
90
91         if (priv->Flags & fMP_DISCONNECTED)
92                 return STATUS_FAILURE;
93
94         mutex_lock(&priv->usb_lock);
95
96         status = usb_control_msg(priv->usb,
97                 usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
98                         index, buffer, length, USB_CTL_WAIT);
99
100         mutex_unlock(&priv->usb_lock);
101
102         if (status < (int)length)
103                 return STATUS_FAILURE;
104
105         return STATUS_SUCCESS;
106 }
107
108 /*
109  * Description:
110  *      Allocates an usb interrupt in irp and calls USBD.
111  *
112  * Parameters:
113  *  In:
114  *      pDevice     - Pointer to the adapter
115  *  Out:
116  *      none
117  *
118  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
119  *
120  */
121
122 int PIPEnsInterruptRead(struct vnt_private *priv)
123 {
124         int status = STATUS_FAILURE;
125
126         if (priv->int_buf.in_use == true)
127                 return STATUS_FAILURE;
128
129         priv->int_buf.in_use = true;
130
131         usb_fill_int_urb(priv->pInterruptURB,
132                 priv->usb,
133                 usb_rcvintpipe(priv->usb, 1),
134                 priv->int_buf.data_buf,
135                 MAX_INTERRUPT_SIZE,
136                 s_nsInterruptUsbIoCompleteRead,
137                 priv,
138                 priv->int_interval);
139
140         status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
141         if (status) {
142                 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
143                 priv->int_buf.in_use = false;
144         }
145
146         return status;
147 }
148
149 /*
150  * Description:
151  *      Complete function of usb interrupt in irp.
152  *
153  * Parameters:
154  *  In:
155  *      pDevice     - Pointer to the adapter
156  *
157  *  Out:
158  *      none
159  *
160  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
161  *
162  */
163
164 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
165 {
166         struct vnt_private *priv = urb->context;
167         int status;
168
169         switch (urb->status) {
170         case 0:
171         case -ETIMEDOUT:
172                 break;
173         case -ECONNRESET:
174         case -ENOENT:
175         case -ESHUTDOWN:
176                 priv->int_buf.in_use = false;
177                 return;
178         default:
179                 break;
180         }
181
182         status = urb->status;
183
184         if (status != STATUS_SUCCESS) {
185                 priv->int_buf.in_use = false;
186
187                 dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
188         } else {
189                 INTnsProcessData(priv);
190         }
191
192         status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
193         if (status) {
194                 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
195         } else {
196                 priv->int_buf.in_use = true;
197         }
198
199         return;
200 }
201
202 /*
203  * Description:
204  *      Allocates an usb BulkIn  irp and calls USBD.
205  *
206  * Parameters:
207  *  In:
208  *      pDevice     - Pointer to the adapter
209  *  Out:
210  *      none
211  *
212  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
213  *
214  */
215
216 int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
217 {
218         int status = 0;
219         struct urb *urb;
220
221         if (priv->Flags & fMP_DISCONNECTED)
222                 return STATUS_FAILURE;
223
224         urb = rcb->pUrb;
225         if (rcb->skb == NULL) {
226                 dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
227                 return status;
228         }
229
230         usb_fill_bulk_urb(urb,
231                 priv->usb,
232                 usb_rcvbulkpipe(priv->usb, 2),
233                 (void *) (rcb->skb->data),
234                 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
235                 s_nsBulkInUsbIoCompleteRead,
236                 rcb);
237
238         status = usb_submit_urb(urb, GFP_ATOMIC);
239         if (status != 0) {
240                 dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", status);
241                 return STATUS_FAILURE ;
242         }
243
244         rcb->Ref = 1;
245         rcb->bBoolInUse = true;
246
247         return status;
248 }
249
250 /*
251  * Description:
252  *      Complete function of usb BulkIn irp.
253  *
254  * Parameters:
255  *  In:
256  *      pDevice     - Pointer to the adapter
257  *
258  *  Out:
259  *      none
260  *
261  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
262  *
263  */
264
265 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
266 {
267         struct vnt_rcb *rcb = urb->context;
268         struct vnt_private *priv = rcb->pDevice;
269         unsigned long flags;
270         int re_alloc_skb = false;
271
272         switch (urb->status) {
273         case 0:
274                 break;
275         case -ECONNRESET:
276         case -ENOENT:
277         case -ESHUTDOWN:
278                 return;
279         case -ETIMEDOUT:
280         default:
281                 dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
282                 break;
283         }
284
285         if (urb->actual_length) {
286                 spin_lock_irqsave(&priv->lock, flags);
287
288                 if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
289                         re_alloc_skb = true;
290
291                 spin_unlock_irqrestore(&priv->lock, flags);
292         }
293
294         rcb->Ref--;
295         if (rcb->Ref == 0) {
296                 dev_dbg(&priv->usb->dev,
297                                 "RxvFreeNormal %d\n", priv->NumRecvFreeList);
298
299                 spin_lock_irqsave(&priv->lock, flags);
300
301                 RXvFreeRCB(rcb, re_alloc_skb);
302
303                 spin_unlock_irqrestore(&priv->lock, flags);
304         }
305
306         return;
307 }
308
309 /*
310  * Description:
311  *      Allocates an usb BulkOut  irp and calls USBD.
312  *
313  * Parameters:
314  *  In:
315  *      pDevice     - Pointer to the adapter
316  *  Out:
317  *      none
318  *
319  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
320  *
321  */
322
323 int PIPEnsSendBulkOut(struct vnt_private *priv,
324                                 struct vnt_usb_send_context *context)
325 {
326         int status;
327         struct urb *urb;
328
329         priv->bPWBitOn = false;
330
331         if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
332                 context->in_use = false;
333                 return STATUS_RESOURCES;
334         }
335
336         urb = context->urb;
337
338         usb_fill_bulk_urb(urb,
339                         priv->usb,
340                         usb_sndbulkpipe(priv->usb, 3),
341                         context->data,
342                         context->buf_len,
343                         s_nsBulkOutIoCompleteWrite,
344                         context);
345
346         status = usb_submit_urb(urb, GFP_ATOMIC);
347         if (status != 0) {
348                 dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
349
350                 context->in_use = false;
351                 return STATUS_FAILURE;
352         }
353
354         return STATUS_PENDING;
355 }
356
357 /*
358  * Description: s_nsBulkOutIoCompleteWrite
359  *     1a) Indicate to the protocol the status of the write.
360  *     1b) Return ownership of the packet to the protocol.
361  *
362  *     2)  If any more packets are queue for sending, send another packet
363  *         to USBD.
364  *         If the attempt to send the packet to the driver fails,
365  *         return ownership of the packet to the protocol and
366  *         try another packet (until one succeeds).
367  *
368  * Parameters:
369  *  In:
370  *      pdoUsbDevObj  - pointer to the USB device object which
371  *                      completed the irp
372  *      pIrp          - the irp which was completed by the
373  *                      device object
374  *      pContext      - the context given to IoSetCompletionRoutine
375  *                      before calling IoCallDriver on the irp
376  *                      The pContext is a pointer to the USB device object.
377  *  Out:
378  *      none
379  *
380  * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
381  *               (IofCompleteRequest) to stop working on the irp.
382  *
383  */
384
385 static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
386 {
387         struct vnt_usb_send_context *context = urb->context;
388         struct vnt_private *priv = context->priv;
389         u8 context_type = context->type;
390
391         switch (urb->status) {
392         case 0:
393                 dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
394                 break;
395         case -ECONNRESET:
396         case -ENOENT:
397         case -ESHUTDOWN:
398                 context->in_use = false;
399                 return;
400         case -ETIMEDOUT:
401         default:
402                 dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
403                 break;
404         }
405
406         if (!netif_device_present(priv->dev))
407                 return;
408
409         if (CONTEXT_DATA_PACKET == context_type) {
410                 if (context->skb != NULL) {
411                         dev_kfree_skb_irq(context->skb);
412                         context->skb = NULL;
413                         dev_dbg(&priv->usb->dev,
414                                         "tx  %d bytes\n", context->buf_len);
415                 }
416
417                 priv->dev->trans_start = jiffies;
418         }
419
420         if (priv->bLinkPass == true) {
421                 if (netif_queue_stopped(priv->dev))
422                         netif_wake_queue(priv->dev);
423         }
424
425         context->in_use = false;
426
427         return;
428 }