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