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