Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh...
[pandora-kernel.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  *      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      struct urb *urb
77     );
78
79
80 static
81 void
82 s_nsBulkInUsbIoCompleteRead(
83      struct urb *urb
84     );
85
86
87 static
88 void
89 s_nsBulkOutIoCompleteWrite(
90      struct urb *urb
91     );
92
93
94 static
95 void
96 s_nsControlInUsbIoCompleteRead(
97      struct urb *urb
98     );
99
100 static
101 void
102 s_nsControlInUsbIoCompleteWrite(
103      struct urb *urb
104     );
105
106 /*---------------------  Export Variables  --------------------------*/
107
108 /*---------------------  Export Functions  --------------------------*/
109
110
111
112 NTSTATUS
113 PIPEnsControlOutAsyn(
114      PSDevice     pDevice,
115      BYTE         byRequest,
116      WORD         wValue,
117      WORD         wIndex,
118      WORD         wLength,
119      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                             (void *) 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      PSDevice     pDevice,
166      BYTE         byRequest,
167      WORD         wValue,
168      WORD         wIndex,
169      WORD         wLength,
170      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      PSDevice     pDevice,
228      BYTE         byRequest,
229      WORD         wValue,
230      WORD         wIndex,
231      WORD         wLength,
232        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      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      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      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                          (void *) 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                          (void *) 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                 (void *) 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      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     } else {
488             pDevice->ulIntInBytesRead += (unsigned long) urb->actual_length;
489             pDevice->ulIntInContCRCError = 0;
490             pDevice->bEventAvailable = TRUE;
491             INTnsProcessData(pDevice);
492     }
493
494     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus);
495
496
497     if (pDevice->fKillEventPollingThread != TRUE) {
498    #if 0               //reserve int URB submit
499         ntStatus = usb_submit_urb(urb, GFP_ATOMIC);
500         if (ntStatus != 0) {
501             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Re-Submit int URB failed %d\n", ntStatus);
502     }
503    #else                                                                                     //replace int URB submit by bulk transfer
504     #ifdef Safe_Close
505        usb_fill_bulk_urb(pDevice->pInterruptURB,
506                       pDevice->usb,
507                       usb_rcvbulkpipe(pDevice->usb, 1),
508                      (void *) pDevice->intBuf.pDataBuf,
509                      MAX_INTERRUPT_SIZE,
510                      s_nsInterruptUsbIoCompleteRead,
511                      pDevice);
512
513         ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
514         if (ntStatus != 0) {
515             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
516            }
517
518     #else
519         tasklet_schedule(&pDevice->EventWorkItem);
520     #endif
521 #endif
522     }
523     //
524     // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
525     // routine (IofCompleteRequest) will stop working on the irp.
526     //
527     return ;
528 }
529
530 /*
531  * Description:
532  *      Allocates an usb BulkIn  irp and calls USBD.
533  *
534  * Parameters:
535  *  In:
536  *      pDevice     - Pointer to the adapter
537  *  Out:
538  *      none
539  *
540  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
541  *
542  */
543 NTSTATUS
544 PIPEnsBulkInUsbRead(
545      PSDevice pDevice,
546      PRCB     pRCB
547     )
548 {
549     NTSTATUS            ntStatus= 0;
550     struct urb          *pUrb;
551
552
553     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
554
555     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
556         return STATUS_FAILURE;
557
558     pDevice->ulBulkInPosted++;
559
560
561         pUrb = pRCB->pUrb;
562     //
563     // Now that we have created the urb, we will send a
564     // request to the USB device object.
565     //
566     if (pRCB->skb == NULL) {
567         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
568         return ntStatus;
569     }
570
571         usb_fill_bulk_urb(pUrb,
572                 pDevice->usb,
573                 usb_rcvbulkpipe(pDevice->usb, 2),
574                 (void *) (pRCB->skb->data),
575                 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
576                 s_nsBulkInUsbIoCompleteRead,
577                 pRCB);
578
579         ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC);
580         if (ntStatus != 0) {
581                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
582                 return STATUS_FAILURE ;
583         }
584     pRCB->Ref = 1;
585     pRCB->bBoolInUse= TRUE;
586
587     return ntStatus;
588 }
589
590
591
592
593 /*
594  * Description:
595  *      Complete function of usb BulkIn irp.
596  *
597  * Parameters:
598  *  In:
599  *      pDevice     - Pointer to the adapter
600  *
601  *  Out:
602  *      none
603  *
604  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
605  *
606  */
607 static
608 void
609 s_nsBulkInUsbIoCompleteRead(
610      struct urb *urb
611     )
612
613 {
614     PRCB    pRCB = (PRCB)urb->context;
615     PSDevice pDevice = (PSDevice)pRCB->pDevice;
616     unsigned long   bytesRead;
617     BOOL    bIndicateReceive = FALSE;
618     BOOL    bReAllocSkb = FALSE;
619     NTSTATUS    status;
620
621
622
623     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
624     status = urb->status;
625     bytesRead = urb->actual_length;
626
627     if (status) {
628         pDevice->ulBulkInError++;
629         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
630
631         #ifdef Calcu_LinkQual
632            pDevice->scStatistic.RxFcsErrCnt ++;
633         #endif
634 //todo...xxxxxx
635 //        if (status == USBD_STATUS_CRC) {
636 //            pDevice->ulBulkInContCRCError++;
637 //        }
638 //        if (status == STATUS_DEVICE_NOT_CONNECTED )
639 //        {
640 //            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
641 //        }
642     } else {
643         bIndicateReceive = TRUE;
644         pDevice->ulBulkInContCRCError = 0;
645         pDevice->ulBulkInBytesRead += bytesRead;
646
647         #ifdef Calcu_LinkQual
648            pDevice->scStatistic.RxOkCnt ++;
649         #endif
650     }
651
652
653     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status);
654
655     if (bIndicateReceive) {
656         spin_lock(&pDevice->lock);
657         if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == TRUE)
658             bReAllocSkb = TRUE;
659         spin_unlock(&pDevice->lock);
660     }
661     pRCB->Ref--;
662     if (pRCB->Ref == 0)
663     {
664         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
665         spin_lock(&pDevice->lock);
666         RXvFreeRCB(pRCB, bReAllocSkb);
667         spin_unlock(&pDevice->lock);
668     }
669
670
671     return;
672 }
673
674 /*
675  * Description:
676  *      Allocates an usb BulkOut  irp and calls USBD.
677  *
678  * Parameters:
679  *  In:
680  *      pDevice     - Pointer to the adapter
681  *  Out:
682  *      none
683  *
684  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
685  *
686  */
687 NDIS_STATUS
688 PIPEnsSendBulkOut(
689       PSDevice pDevice,
690       PUSB_SEND_CONTEXT pContext
691     )
692 {
693     NTSTATUS            status;
694     struct urb          *pUrb;
695
696
697
698     pDevice->bPWBitOn = FALSE;
699
700 /*
701     if (pDevice->pPendingBulkOutContext != NULL) {
702         pDevice->NumContextsQueued++;
703         EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
704         status = STATUS_PENDING;
705         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
706         return status;
707     }
708 */
709
710     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
711
712     if(MP_IS_READY(pDevice) && MP_TEST_FLAG(pDevice, fMP_POST_WRITES)) {
713
714         pUrb = pContext->pUrb;
715         pDevice->ulBulkOutPosted++;
716 //        pDevice->pPendingBulkOutContext = pContext;
717         usb_fill_bulk_urb(
718                     pUrb,
719                         pDevice->usb,
720                     usb_sndbulkpipe(pDevice->usb, 3),
721                     (void *) &(pContext->Data[0]),
722                         pContext->uBufLen,
723                         s_nsBulkOutIoCompleteWrite,
724                         pContext);
725
726         status = usb_submit_urb(pUrb, GFP_ATOMIC);
727         if (status != 0)
728         {
729                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
730                 return STATUS_FAILURE;
731         }
732         return STATUS_PENDING;
733     }
734     else {
735         pContext->bBoolInUse = FALSE;
736         return STATUS_RESOURCES;
737     }
738 }
739
740 /*
741  * Description: s_nsBulkOutIoCompleteWrite
742  *     1a) Indicate to the protocol the status of the write.
743  *     1b) Return ownership of the packet to the protocol.
744  *
745  *     2)  If any more packets are queue for sending, send another packet
746  *         to USBD.
747  *         If the attempt to send the packet to the driver fails,
748  *         return ownership of the packet to the protocol and
749  *         try another packet (until one succeeds).
750  *
751  * Parameters:
752  *  In:
753  *      pdoUsbDevObj  - pointer to the USB device object which
754  *                      completed the irp
755  *      pIrp          - the irp which was completed by the
756  *                      device object
757  *      pContext      - the context given to IoSetCompletionRoutine
758  *                      before calling IoCallDriver on the irp
759  *                      The pContext is a pointer to the USB device object.
760  *  Out:
761  *      none
762  *
763  * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
764  *               (IofCompleteRequest) to stop working on the irp.
765  *
766  */
767 static
768 void
769 s_nsBulkOutIoCompleteWrite(
770      struct urb *urb
771     )
772 {
773     PSDevice            pDevice;
774     NTSTATUS            status;
775     CONTEXT_TYPE        ContextType;
776     unsigned long               ulBufLen;
777     PUSB_SEND_CONTEXT   pContext;
778
779
780     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
781     //
782     // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
783     //
784     pContext = (PUSB_SEND_CONTEXT) urb->context;
785     ASSERT( NULL != pContext );
786
787     pDevice = pContext->pDevice;
788     ContextType = pContext->Type;
789     ulBufLen = pContext->uBufLen;
790
791     if (!netif_device_present(pDevice->dev))
792             return;
793
794    //
795     // Perform various IRP, URB, and buffer 'sanity checks'
796     //
797
798     status = urb->status;
799     //we should have failed, succeeded, or cancelled, but NOT be pending
800     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status);
801
802     if(status == STATUS_SUCCESS) {
803         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
804         pDevice->ulBulkOutBytesWrite += ulBufLen;
805         pDevice->ulBulkOutContCRCError = 0;
806         //2007-0115-06<Add>by MikeLiu
807            #ifdef TxInSleep
808              pDevice->nTxDataTimeCout = 0;
809            #endif
810
811     } else {
812         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
813         pDevice->ulBulkOutError++;
814     }
815
816 //    pDevice->ulCheckForHangCount = 0;
817 //    pDevice->pPendingBulkOutContext = NULL;
818
819     if ( CONTEXT_DATA_PACKET == ContextType ) {
820         // Indicate to the protocol the status of the sent packet and return
821         // ownership of the packet.
822             if (pContext->pPacket != NULL) {
823                 dev_kfree_skb_irq(pContext->pPacket);
824                 pContext->pPacket = NULL;
825             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx  %d bytes\n",(int)ulBufLen);
826             }
827
828         pDevice->dev->trans_start = jiffies;
829
830
831         if (status == STATUS_SUCCESS) {
832             pDevice->packetsSent++;
833         }
834         else {
835             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
836             pDevice->packetsSentDropped++;
837         }
838
839     }
840     if (pDevice->bLinkPass == TRUE) {
841         if (netif_queue_stopped(pDevice->dev))
842             netif_wake_queue(pDevice->dev);
843     }
844     pContext->bBoolInUse = FALSE;
845
846     return;
847 }