cd1da33cff7adb8733a4993728d5e243cb78b2c2
[safe/jmp/linux-2.6] / 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  *      CONTROLnsRequestOut - 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 /*---------------------  Static Definitions -------------------------*/
49 //endpoint def
50 //endpoint 0: control
51 //endpoint 1: interrupt
52 //endpoint 2: read bulk
53 //endpoint 3: write bulk
54
55 //RequestType:
56 //#define REQUEST_OUT       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) // 0x40
57 //#define REQUEST_IN        (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE )  //0xc0
58 //static int          msglevel                =MSG_LEVEL_DEBUG;
59 static int          msglevel                =MSG_LEVEL_INFO;
60
61
62 #define USB_CTL_WAIT   500 //ms
63
64 #ifndef URB_ASYNC_UNLINK
65 #define URB_ASYNC_UNLINK    0
66 #endif
67
68 /*---------------------  Static Classes  ----------------------------*/
69
70 /*---------------------  Static Variables  --------------------------*/
71
72 /*---------------------  Static Functions  --------------------------*/
73 static
74 VOID
75 s_nsInterruptUsbIoCompleteRead(
76     IN struct urb *urb
77     );
78
79
80 static
81 VOID
82 s_nsBulkInUsbIoCompleteRead(
83     IN struct urb *urb
84     );
85
86
87 static
88 VOID
89 s_nsBulkOutIoCompleteWrite(
90     IN struct urb *urb
91     );
92
93
94 static
95 VOID
96 s_nsControlInUsbIoCompleteRead(
97     IN struct urb *urb
98     );
99
100 static
101 VOID
102 s_nsControlInUsbIoCompleteWrite(
103     IN struct urb *urb
104     );
105
106 /*---------------------  Export Variables  --------------------------*/
107
108 /*---------------------  Export Functions  --------------------------*/
109
110
111
112 NTSTATUS
113 PIPEnsControlOutAsyn(
114     IN PSDevice     pDevice,
115     IN BYTE         byRequest,
116     IN WORD         wValue,
117     IN WORD         wIndex,
118     IN WORD         wLength,
119     IN PBYTE        pbyBuffer
120     )
121 {
122     NTSTATUS                ntStatus;
123
124
125     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
126         return STATUS_FAILURE;
127
128
129     if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES)) {
130         return STATUS_FAILURE;
131     }
132
133     if (in_interrupt()) {
134         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest);
135         return STATUS_FAILURE;
136     }
137
138     ntStatus = usb_control_msg(
139                             pDevice->usb,
140                             usb_sndctrlpipe(pDevice->usb , 0),
141                             byRequest,
142                             0x40, // RequestType
143                             wValue,
144                             wIndex,
145                             (PVOID) pbyBuffer,
146                             wLength,
147                             HZ
148                           );
149     if (ntStatus >= 0) {
150         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus);
151         ntStatus = 0;
152     } else {
153         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus);
154     }
155
156     return ntStatus;
157 }
158
159
160
161
162
163 NTSTATUS
164 PIPEnsControlOut(
165     IN PSDevice     pDevice,
166     IN BYTE         byRequest,
167     IN WORD         wValue,
168     IN WORD         wIndex,
169     IN WORD         wLength,
170     IN PBYTE        pbyBuffer
171     )
172 {
173     NTSTATUS            ntStatus = 0;
174     int ii;
175
176
177     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
178         return STATUS_FAILURE;
179
180     if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES)) {
181         return STATUS_FAILURE;
182     }
183
184         pDevice->sUsbCtlRequest.bRequestType = 0x40;
185         pDevice->sUsbCtlRequest.bRequest = byRequest;
186         pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
187         pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
188         pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
189         pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
190     pDevice->pControlURB->actual_length = 0;
191     // Notice, pbyBuffer limited point to variable buffer, can't be constant.
192         usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
193                          usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
194                          pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice);
195
196         ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
197         if (ntStatus != 0) {
198                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus);
199                 return STATUS_FAILURE;
200         }
201         else {
202             MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
203         }
204         spin_unlock_irq(&pDevice->lock);
205     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
206         if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES))
207             mdelay(1);
208         else
209             break;
210         if (ii >= USB_CTL_WAIT) {
211             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission timeout \n");
212             spin_lock_irq(&pDevice->lock);
213             MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
214             return STATUS_FAILURE;
215         }
216     }
217         spin_lock_irq(&pDevice->lock);
218
219     return STATUS_SUCCESS;
220 }
221
222
223
224
225 NTSTATUS
226 PIPEnsControlIn(
227     IN PSDevice     pDevice,
228     IN BYTE         byRequest,
229     IN WORD         wValue,
230     IN WORD         wIndex,
231     IN WORD         wLength,
232     IN OUT  PBYTE   pbyBuffer
233     )
234 {
235     NTSTATUS            ntStatus = 0;
236     int ii;
237
238     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
239         return STATUS_FAILURE;
240
241     if (MP_TEST_FLAG(pDevice, fMP_CONTROL_READS)) {
242         return STATUS_FAILURE;
243     }
244         pDevice->sUsbCtlRequest.bRequestType = 0xC0;
245         pDevice->sUsbCtlRequest.bRequest = byRequest;
246         pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
247         pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
248         pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
249         pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
250     pDevice->pControlURB->actual_length = 0;
251         usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
252                          usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
253                          pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice);
254
255         ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
256         if (ntStatus != 0) {
257                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus);
258         }else {
259                 MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
260     }
261
262         spin_unlock_irq(&pDevice->lock);
263     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
264         if (MP_TEST_FLAG(pDevice, fMP_CONTROL_READS))
265             mdelay(1);
266         else {
267             break;
268         }
269         if (ii >= USB_CTL_WAIT) {
270             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control rcv request submission timeout \n");
271             spin_lock_irq(&pDevice->lock);
272             MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
273             return STATUS_FAILURE;
274         }
275     }
276         spin_lock_irq(&pDevice->lock);
277
278     return ntStatus;
279 }
280
281 static
282 VOID
283 s_nsControlInUsbIoCompleteWrite(
284     IN struct urb *urb
285     )
286 {
287     PSDevice        pDevice;
288
289         pDevice = urb->context;
290         switch (urb->status) {
291         case 0:
292                 break;
293         case -EINPROGRESS:
294                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status);
295                 break;
296         case -ENOENT:
297                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status);
298                 break;
299         default:
300                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status);
301         }
302
303     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
304 }
305
306
307
308 /*
309  * Description:
310  *      Complete function of usb Control callback
311  *
312  * Parameters:
313  *  In:
314  *      pDevice     - Pointer to the adapter
315  *
316  *  Out:
317  *      none
318  *
319  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
320  *
321  */
322 static
323 VOID
324 s_nsControlInUsbIoCompleteRead(
325     IN struct urb *urb
326     )
327 {
328     PSDevice        pDevice;
329
330         pDevice = urb->context;
331         switch (urb->status) {
332         case 0:
333                 break;
334         case -EINPROGRESS:
335                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status);
336                 break;
337         case -ENOENT:
338                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status);
339                 break;
340         default:
341                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status);
342         }
343
344     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
345 }
346
347
348
349
350 /*
351  * Description:
352  *      Allocates an usb interrupt in irp and calls USBD.
353  *
354  * Parameters:
355  *  In:
356  *      pDevice     - Pointer to the adapter
357  *  Out:
358  *      none
359  *
360  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
361  *
362  */
363 NTSTATUS
364 PIPEnsInterruptRead(
365     IN PSDevice pDevice
366     )
367 {
368     NTSTATUS            ntStatus = STATUS_FAILURE;
369
370
371     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
372
373     if(pDevice->intBuf.bInUse == TRUE){
374         return (STATUS_FAILURE);
375     }
376     pDevice->intBuf.bInUse = TRUE;
377 //    pDevice->bEventAvailable = FALSE;
378     pDevice->ulIntInPosted++;
379
380     //
381     // Now that we have created the urb, we will send a
382     // request to the USB device object.
383     //
384 #if 0            //reserve int URB submit
385         usb_fill_int_urb(pDevice->pInterruptURB,
386                          pDevice->usb,
387                          usb_rcvintpipe(pDevice->usb, 1),
388                          (PVOID) pDevice->intBuf.pDataBuf,
389                          MAX_INTERRUPT_SIZE,
390                          s_nsInterruptUsbIoCompleteRead,
391                          pDevice,
392                          pDevice->int_interval
393                          );
394 #else            //replace int URB submit by bulk transfer
395 #ifndef Safe_Close
396         usb_fill_int_urb(pDevice->pInterruptURB,
397                          pDevice->usb,
398                          usb_rcvintpipe(pDevice->usb, 1),
399                          (PVOID) pDevice->intBuf.pDataBuf,
400                          MAX_INTERRUPT_SIZE,
401                          s_nsInterruptUsbIoCompleteRead,
402                          pDevice,
403                          pDevice->int_interval
404                          );
405 #else
406
407     pDevice->pInterruptURB->interval = pDevice->int_interval;
408
409 usb_fill_bulk_urb(pDevice->pInterruptURB,
410                 pDevice->usb,
411                 usb_rcvbulkpipe(pDevice->usb, 1),
412                 (PVOID) pDevice->intBuf.pDataBuf,
413                 MAX_INTERRUPT_SIZE,
414                 s_nsInterruptUsbIoCompleteRead,
415                 pDevice);
416 #endif
417 #endif
418
419         ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
420         if (ntStatus != 0) {
421             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
422     }
423
424     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
425     return ntStatus;
426 }
427
428
429 /*
430  * Description:
431  *      Complete function of usb interrupt in irp.
432  *
433  * Parameters:
434  *  In:
435  *      pDevice     - Pointer to the adapter
436  *
437  *  Out:
438  *      none
439  *
440  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
441  *
442  */
443 static
444 VOID
445 s_nsInterruptUsbIoCompleteRead(
446     IN struct urb *urb
447     )
448
449 {
450     PSDevice        pDevice;
451     NTSTATUS        ntStatus;
452
453
454     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n");
455     //
456     // The context given to IoSetCompletionRoutine is the receive buffer object
457     //
458     pDevice = (PSDevice)urb->context;
459
460     //
461     // We have a number of cases:
462     //      1) The USB read timed out and we received no data.
463     //      2) The USB read timed out and we received some data.
464     //      3) The USB read was successful and fully filled our irp buffer.
465     //      4) The irp was cancelled.
466     //      5) Some other failure from the USB device object.
467     //
468     ntStatus = urb->status;
469
470     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus);
471
472     // if we were not successful, we need to free the int buffer for future use right here
473     // otherwise interrupt data handler will free int buffer after it handle it.
474     if (( ntStatus != STATUS_SUCCESS )) {
475         pDevice->ulBulkInError++;
476         pDevice->intBuf.bInUse = FALSE;
477
478 //        if (ntStatus == USBD_STATUS_CRC) {
479 //            pDevice->ulIntInContCRCError++;
480 //        }
481
482 //        if (ntStatus == STATUS_NOT_CONNECTED )
483 //        {
484             pDevice->fKillEventPollingThread = TRUE;
485 //        }
486         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus );
487     }
488     else {
489         pDevice->ulIntInBytesRead += (ULONG)urb->actual_length;
490         pDevice->ulIntInContCRCError = 0;
491         pDevice->bEventAvailable = TRUE;
492         INTnsProcessData(pDevice);
493     }
494
495     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus);
496
497
498     if (pDevice->fKillEventPollingThread != TRUE) {
499    #if 0               //reserve int URB submit
500         ntStatus = usb_submit_urb(urb, GFP_ATOMIC);
501         if (ntStatus != 0) {
502             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Re-Submit int URB failed %d\n", ntStatus);
503     }
504    #else                                                                                     //replace int URB submit by bulk transfer
505     #ifdef Safe_Close
506        usb_fill_bulk_urb(pDevice->pInterruptURB,
507                       pDevice->usb,
508                       usb_rcvbulkpipe(pDevice->usb, 1),
509                      (PVOID) pDevice->intBuf.pDataBuf,
510                      MAX_INTERRUPT_SIZE,
511                      s_nsInterruptUsbIoCompleteRead,
512                      pDevice);
513
514         ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
515         if (ntStatus != 0) {
516             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
517            }
518
519     #else
520         tasklet_schedule(&pDevice->EventWorkItem);
521     #endif
522 #endif
523     }
524     //
525     // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
526     // routine (IofCompleteRequest) will stop working on the irp.
527     //
528     return ;
529 }
530
531 /*
532  * Description:
533  *      Allocates an usb BulkIn  irp and calls USBD.
534  *
535  * Parameters:
536  *  In:
537  *      pDevice     - Pointer to the adapter
538  *  Out:
539  *      none
540  *
541  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
542  *
543  */
544 NTSTATUS
545 PIPEnsBulkInUsbRead(
546     IN PSDevice pDevice,
547     IN PRCB     pRCB
548     )
549 {
550     NTSTATUS            ntStatus= 0;
551     struct urb          *pUrb;
552
553
554     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
555
556     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
557         return STATUS_FAILURE;
558
559     pDevice->ulBulkInPosted++;
560
561
562         pUrb = pRCB->pUrb;
563     //
564     // Now that we have created the urb, we will send a
565     // request to the USB device object.
566     //
567     if (pRCB->skb == NULL) {
568         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
569         return ntStatus;
570     }
571
572         usb_fill_bulk_urb(pUrb,
573                 pDevice->usb,
574                 usb_rcvbulkpipe(pDevice->usb, 2),
575                 (PVOID) (pRCB->skb->data),
576                 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
577                 s_nsBulkInUsbIoCompleteRead,
578                 pRCB);
579
580         ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC);
581         if (ntStatus != 0) {
582                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
583                 return STATUS_FAILURE ;
584         }
585     pRCB->Ref = 1;
586     pRCB->bBoolInUse= TRUE;
587
588     return ntStatus;
589 }
590
591
592
593
594 /*
595  * Description:
596  *      Complete function of usb BulkIn irp.
597  *
598  * Parameters:
599  *  In:
600  *      pDevice     - Pointer to the adapter
601  *
602  *  Out:
603  *      none
604  *
605  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
606  *
607  */
608 static
609 VOID
610 s_nsBulkInUsbIoCompleteRead(
611     IN struct urb *urb
612     )
613
614 {
615     PRCB    pRCB = (PRCB)urb->context;
616     PSDevice pDevice = (PSDevice)pRCB->pDevice;
617     ULONG   bytesRead;
618     BOOL    bIndicateReceive = FALSE;
619     BOOL    bReAllocSkb = FALSE;
620     NTSTATUS    status;
621
622
623
624     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
625     status = urb->status;
626     bytesRead = urb->actual_length;
627
628     if (status) {
629         pDevice->ulBulkInError++;
630         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
631
632         #ifdef Calcu_LinkQual
633            pDevice->scStatistic.RxFcsErrCnt ++;
634         #endif
635 //todo...xxxxxx
636 //        if (status == USBD_STATUS_CRC) {
637 //            pDevice->ulBulkInContCRCError++;
638 //        }
639 //        if (status == STATUS_DEVICE_NOT_CONNECTED )
640 //        {
641 //            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
642 //        }
643     } else {
644         bIndicateReceive = TRUE;
645         pDevice->ulBulkInContCRCError = 0;
646         pDevice->ulBulkInBytesRead += bytesRead;
647
648         #ifdef Calcu_LinkQual
649            pDevice->scStatistic.RxOkCnt ++;
650         #endif
651     }
652
653
654     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status);
655
656     if (bIndicateReceive) {
657         spin_lock(&pDevice->lock);
658         if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == TRUE)
659             bReAllocSkb = TRUE;
660         spin_unlock(&pDevice->lock);
661     }
662     pRCB->Ref--;
663     if (pRCB->Ref == 0)
664     {
665         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
666         spin_lock(&pDevice->lock);
667         RXvFreeRCB(pRCB, bReAllocSkb);
668         spin_unlock(&pDevice->lock);
669     }
670
671
672     return;
673 }
674
675 /*
676  * Description:
677  *      Allocates an usb BulkOut  irp and calls USBD.
678  *
679  * Parameters:
680  *  In:
681  *      pDevice     - Pointer to the adapter
682  *  Out:
683  *      none
684  *
685  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
686  *
687  */
688 NDIS_STATUS
689 PIPEnsSendBulkOut(
690     IN  PSDevice pDevice,
691     IN  PUSB_SEND_CONTEXT pContext
692     )
693 {
694     NTSTATUS            status;
695     struct urb          *pUrb;
696
697
698
699     pDevice->bPWBitOn = FALSE;
700
701 /*
702     if (pDevice->pPendingBulkOutContext != NULL) {
703         pDevice->NumContextsQueued++;
704         EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
705         status = STATUS_PENDING;
706         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
707         return status;
708     }
709 */
710
711     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
712
713     if(MP_IS_READY(pDevice) && MP_TEST_FLAG(pDevice, fMP_POST_WRITES)) {
714
715         pUrb = pContext->pUrb;
716         pDevice->ulBulkOutPosted++;
717 //        pDevice->pPendingBulkOutContext = pContext;
718         usb_fill_bulk_urb(
719                     pUrb,
720                         pDevice->usb,
721                         usb_sndbulkpipe(pDevice->usb, 3),
722                         (PVOID) &(pContext->Data[0]),
723                         pContext->uBufLen,
724                         s_nsBulkOutIoCompleteWrite,
725                         pContext);
726
727         status = usb_submit_urb(pUrb, GFP_ATOMIC);
728         if (status != 0)
729         {
730                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
731                 return STATUS_FAILURE;
732         }
733         return STATUS_PENDING;
734     }
735     else {
736         pContext->bBoolInUse = FALSE;
737         return STATUS_RESOURCES;
738     }
739 }
740
741 /*
742  * Description: s_nsBulkOutIoCompleteWrite
743  *     1a) Indicate to the protocol the status of the write.
744  *     1b) Return ownership of the packet to the protocol.
745  *
746  *     2)  If any more packets are queue for sending, send another packet
747  *         to USBD.
748  *         If the attempt to send the packet to the driver fails,
749  *         return ownership of the packet to the protocol and
750  *         try another packet (until one succeeds).
751  *
752  * Parameters:
753  *  In:
754  *      pdoUsbDevObj  - pointer to the USB device object which
755  *                      completed the irp
756  *      pIrp          - the irp which was completed by the
757  *                      device object
758  *      pContext      - the context given to IoSetCompletionRoutine
759  *                      before calling IoCallDriver on the irp
760  *                      The pContext is a pointer to the USB device object.
761  *  Out:
762  *      none
763  *
764  * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
765  *               (IofCompleteRequest) to stop working on the irp.
766  *
767  */
768 static
769 VOID
770 s_nsBulkOutIoCompleteWrite(
771     IN struct urb *urb
772     )
773 {
774     PSDevice            pDevice;
775     NTSTATUS            status;
776     CONTEXT_TYPE        ContextType;
777     ULONG               ulBufLen;
778     PUSB_SEND_CONTEXT   pContext;
779
780
781     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
782     //
783     // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
784     //
785     pContext = (PUSB_SEND_CONTEXT) urb->context;
786     ASSERT( NULL != pContext );
787
788     pDevice = pContext->pDevice;
789     ContextType = pContext->Type;
790     ulBufLen = pContext->uBufLen;
791
792     if (!netif_device_present(pDevice->dev))
793             return;
794
795    //
796     // Perform various IRP, URB, and buffer 'sanity checks'
797     //
798
799     status = urb->status;
800     //we should have failed, succeeded, or cancelled, but NOT be pending
801     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status);
802
803     if(status == STATUS_SUCCESS) {
804         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
805         pDevice->ulBulkOutBytesWrite += ulBufLen;
806         pDevice->ulBulkOutContCRCError = 0;
807         //2007-0115-06<Add>by MikeLiu
808            #ifdef TxInSleep
809              pDevice->nTxDataTimeCout = 0;
810            #endif
811
812     } else {
813         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
814         pDevice->ulBulkOutError++;
815     }
816
817 //    pDevice->ulCheckForHangCount = 0;
818 //    pDevice->pPendingBulkOutContext = NULL;
819
820     if ( CONTEXT_DATA_PACKET == ContextType ) {
821         // Indicate to the protocol the status of the sent packet and return
822         // ownership of the packet.
823             if (pContext->pPacket != NULL) {
824                 dev_kfree_skb_irq(pContext->pPacket);
825                 pContext->pPacket = NULL;
826             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx  %d bytes\n",(int)ulBufLen);
827             }
828
829         pDevice->dev->trans_start = jiffies;
830
831
832         if (status == STATUS_SUCCESS) {
833             pDevice->packetsSent++;
834         }
835         else {
836             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
837             pDevice->packetsSentDropped++;
838         }
839
840     }
841     if (pDevice->bLinkPass == TRUE) {
842         if (netif_queue_stopped(pDevice->dev))
843             netif_wake_queue(pDevice->dev);
844     }
845     pContext->bBoolInUse = FALSE;
846
847     return;
848 }