Merge branch 'ixp4xx' of git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux-2.6
[linux/fpc-iii.git] / drivers / staging / vt6656 / usbpipe.c
blob65e91a332a66fb69e66b5f4c7991f9c34b87de21
1 /*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
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.
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.
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.
20 * File: usbpipe.c
22 * Purpose: Handle USB control endpoint
24 * Author: Warren Hsu
26 * Date: Mar. 29, 2005
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
35 * Revision History:
36 * 04-05-2004 Jerry Chen: Initial release
37 * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte
41 #include "int.h"
42 #include "rxtx.h"
43 #include "dpc.h"
44 #include "control.h"
45 #include "desc.h"
46 #include "device.h"
48 /*--------------------- Static Definitions -------------------------*/
49 //endpoint def
50 //endpoint 0: control
51 //endpoint 1: interrupt
52 //endpoint 2: read bulk
53 //endpoint 3: write bulk
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;
62 #define USB_CTL_WAIT 500 //ms
64 #ifndef URB_ASYNC_UNLINK
65 #define URB_ASYNC_UNLINK 0
66 #endif
68 /*--------------------- Static Classes ----------------------------*/
70 /*--------------------- Static Variables --------------------------*/
72 /*--------------------- Static Functions --------------------------*/
73 static
74 VOID
75 s_nsInterruptUsbIoCompleteRead(
76 IN struct urb *urb
80 static
81 VOID
82 s_nsBulkInUsbIoCompleteRead(
83 IN struct urb *urb
87 static
88 VOID
89 s_nsBulkOutIoCompleteWrite(
90 IN struct urb *urb
94 static
95 VOID
96 s_nsControlInUsbIoCompleteRead(
97 IN struct urb *urb
100 static
101 VOID
102 s_nsControlInUsbIoCompleteWrite(
103 IN struct urb *urb
106 /*--------------------- Export Variables --------------------------*/
108 /*--------------------- Export Functions --------------------------*/
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
122 NTSTATUS ntStatus;
125 if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
126 return STATUS_FAILURE;
129 if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES)) {
130 return STATUS_FAILURE;
133 if (in_interrupt()) {
134 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest);
135 return STATUS_FAILURE;
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,
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);
156 return ntStatus;
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
173 NTSTATUS ntStatus = 0;
174 int ii;
177 if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
178 return STATUS_FAILURE;
180 if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES)) {
181 return STATUS_FAILURE;
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);
196 if ((ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC)) != 0) {
197 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus);
198 return STATUS_FAILURE;
200 else {
201 MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
203 spin_unlock_irq(&pDevice->lock);
204 for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
205 if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES))
206 mdelay(1);
207 else
208 break;
209 if (ii >= USB_CTL_WAIT) {
210 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission timeout \n");
211 spin_lock_irq(&pDevice->lock);
212 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
213 return STATUS_FAILURE;
216 spin_lock_irq(&pDevice->lock);
218 return STATUS_SUCCESS;
224 NTSTATUS
225 PIPEnsControlIn(
226 IN PSDevice pDevice,
227 IN BYTE byRequest,
228 IN WORD wValue,
229 IN WORD wIndex,
230 IN WORD wLength,
231 IN OUT PBYTE pbyBuffer
234 NTSTATUS ntStatus = 0;
235 int ii;
237 if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
238 return STATUS_FAILURE;
240 if (MP_TEST_FLAG(pDevice, fMP_CONTROL_READS)) {
241 return STATUS_FAILURE;
243 pDevice->sUsbCtlRequest.bRequestType = 0xC0;
244 pDevice->sUsbCtlRequest.bRequest = byRequest;
245 pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
246 pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
247 pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
248 pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
249 pDevice->pControlURB->actual_length = 0;
250 usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
251 usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
252 pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice);
254 if ((ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC)) != 0) {
255 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus);
256 }else {
257 MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
260 spin_unlock_irq(&pDevice->lock);
261 for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
262 if (MP_TEST_FLAG(pDevice, fMP_CONTROL_READS))
263 mdelay(1);
264 else {
265 break;
267 if (ii >= USB_CTL_WAIT) {
268 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control rcv request submission timeout \n");
269 spin_lock_irq(&pDevice->lock);
270 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
271 return STATUS_FAILURE;
274 spin_lock_irq(&pDevice->lock);
276 return ntStatus;
279 static
280 VOID
281 s_nsControlInUsbIoCompleteWrite(
282 IN struct urb *urb
285 PSDevice pDevice;
287 pDevice = urb->context;
288 switch (urb->status) {
289 case 0:
290 break;
291 case -EINPROGRESS:
292 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status);
293 break;
294 case -ENOENT:
295 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status);
296 break;
297 default:
298 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status);
301 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
307 * Description:
308 * Complete function of usb Control callback
310 * Parameters:
311 * In:
312 * pDevice - Pointer to the adapter
314 * Out:
315 * none
317 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
320 static
321 VOID
322 s_nsControlInUsbIoCompleteRead(
323 IN struct urb *urb
326 PSDevice pDevice;
328 pDevice = urb->context;
329 switch (urb->status) {
330 case 0:
331 break;
332 case -EINPROGRESS:
333 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status);
334 break;
335 case -ENOENT:
336 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status);
337 break;
338 default:
339 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status);
342 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
349 * Description:
350 * Allocates an usb interrupt in irp and calls USBD.
352 * Parameters:
353 * In:
354 * pDevice - Pointer to the adapter
355 * Out:
356 * none
358 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
361 NTSTATUS
362 PIPEnsInterruptRead(
363 IN PSDevice pDevice
366 NTSTATUS ntStatus = STATUS_FAILURE;
369 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
371 if(pDevice->intBuf.bInUse == TRUE){
372 return (STATUS_FAILURE);
374 pDevice->intBuf.bInUse = TRUE;
375 // pDevice->bEventAvailable = FALSE;
376 pDevice->ulIntInPosted++;
379 // Now that we have created the urb, we will send a
380 // request to the USB device object.
382 #if 0 //reserve int URB submit
383 usb_fill_int_urb(pDevice->pInterruptURB,
384 pDevice->usb,
385 usb_rcvintpipe(pDevice->usb, 1),
386 (PVOID) pDevice->intBuf.pDataBuf,
387 MAX_INTERRUPT_SIZE,
388 s_nsInterruptUsbIoCompleteRead,
389 pDevice,
390 pDevice->int_interval
392 #else //replace int URB submit by bulk transfer
393 #ifndef Safe_Close
394 usb_fill_int_urb(pDevice->pInterruptURB,
395 pDevice->usb,
396 usb_rcvintpipe(pDevice->usb, 1),
397 (PVOID) pDevice->intBuf.pDataBuf,
398 MAX_INTERRUPT_SIZE,
399 s_nsInterruptUsbIoCompleteRead,
400 pDevice,
401 pDevice->int_interval
403 #else
405 pDevice->pInterruptURB->interval = pDevice->int_interval;
407 usb_fill_bulk_urb(pDevice->pInterruptURB,
408 pDevice->usb,
409 usb_rcvbulkpipe(pDevice->usb, 1),
410 (PVOID) pDevice->intBuf.pDataBuf,
411 MAX_INTERRUPT_SIZE,
412 s_nsInterruptUsbIoCompleteRead,
413 pDevice);
414 #endif
415 #endif
417 if ((ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC)) != 0) {
418 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
421 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
422 return ntStatus;
427 * Description:
428 * Complete function of usb interrupt in irp.
430 * Parameters:
431 * In:
432 * pDevice - Pointer to the adapter
434 * Out:
435 * none
437 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
440 static
441 VOID
442 s_nsInterruptUsbIoCompleteRead(
443 IN struct urb *urb
447 PSDevice pDevice;
448 NTSTATUS ntStatus;
451 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n");
453 // The context given to IoSetCompletionRoutine is the receive buffer object
455 pDevice = (PSDevice)urb->context;
458 // We have a number of cases:
459 // 1) The USB read timed out and we received no data.
460 // 2) The USB read timed out and we received some data.
461 // 3) The USB read was successful and fully filled our irp buffer.
462 // 4) The irp was cancelled.
463 // 5) Some other failure from the USB device object.
465 ntStatus = urb->status;
467 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus);
469 // if we were not successful, we need to free the int buffer for future use right here
470 // otherwise interrupt data handler will free int buffer after it handle it.
471 if (( ntStatus != STATUS_SUCCESS )) {
472 pDevice->ulBulkInError++;
473 pDevice->intBuf.bInUse = FALSE;
475 // if (ntStatus == USBD_STATUS_CRC) {
476 // pDevice->ulIntInContCRCError++;
477 // }
479 // if (ntStatus == STATUS_NOT_CONNECTED )
480 // {
481 pDevice->fKillEventPollingThread = TRUE;
482 // }
483 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus );
485 else {
486 pDevice->ulIntInBytesRead += (ULONG)urb->actual_length;
487 pDevice->ulIntInContCRCError = 0;
488 pDevice->bEventAvailable = TRUE;
489 INTnsProcessData(pDevice);
492 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus);
495 if (pDevice->fKillEventPollingThread != TRUE) {
496 #if 0 //reserve int URB submit
497 if ((ntStatus = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
498 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Re-Submit int URB failed %d\n", ntStatus);
500 #else //replace int URB submit by bulk transfer
501 #ifdef Safe_Close
502 usb_fill_bulk_urb(pDevice->pInterruptURB,
503 pDevice->usb,
504 usb_rcvbulkpipe(pDevice->usb, 1),
505 (PVOID) pDevice->intBuf.pDataBuf,
506 MAX_INTERRUPT_SIZE,
507 s_nsInterruptUsbIoCompleteRead,
508 pDevice);
510 if ((ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC)) != 0) {
511 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
514 #else
515 tasklet_schedule(&pDevice->EventWorkItem);
516 #endif
517 #endif
520 // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
521 // routine (IofCompleteRequest) will stop working on the irp.
523 return ;
527 * Description:
528 * Allocates an usb BulkIn irp and calls USBD.
530 * Parameters:
531 * In:
532 * pDevice - Pointer to the adapter
533 * Out:
534 * none
536 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
539 NTSTATUS
540 PIPEnsBulkInUsbRead(
541 IN PSDevice pDevice,
542 IN PRCB pRCB
545 NTSTATUS ntStatus= 0;
546 struct urb *pUrb;
549 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
551 if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
552 return STATUS_FAILURE;
554 pDevice->ulBulkInPosted++;
557 pUrb = pRCB->pUrb;
559 // Now that we have created the urb, we will send a
560 // request to the USB device object.
562 if (pRCB->skb == NULL) {
563 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
564 return ntStatus;
567 usb_fill_bulk_urb(pUrb,
568 pDevice->usb,
569 usb_rcvbulkpipe(pDevice->usb, 2),
570 (PVOID) (pRCB->skb->data),
571 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
572 s_nsBulkInUsbIoCompleteRead,
573 pRCB);
575 if((ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC)) != 0){
576 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
577 return STATUS_FAILURE ;
579 pRCB->Ref = 1;
580 pRCB->bBoolInUse= TRUE;
582 return ntStatus;
589 * Description:
590 * Complete function of usb BulkIn irp.
592 * Parameters:
593 * In:
594 * pDevice - Pointer to the adapter
596 * Out:
597 * none
599 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
602 static
603 VOID
604 s_nsBulkInUsbIoCompleteRead(
605 IN struct urb *urb
609 PRCB pRCB = (PRCB)urb->context;
610 PSDevice pDevice = (PSDevice)pRCB->pDevice;
611 ULONG bytesRead;
612 BOOL bIndicateReceive = FALSE;
613 BOOL bReAllocSkb = FALSE;
614 NTSTATUS status;
618 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
619 status = urb->status;
620 bytesRead = urb->actual_length;
622 if (status) {
623 pDevice->ulBulkInError++;
624 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
626 #ifdef Calcu_LinkQual
627 pDevice->scStatistic.RxFcsErrCnt ++;
628 #endif
629 //todo...xxxxxx
630 // if (status == USBD_STATUS_CRC) {
631 // pDevice->ulBulkInContCRCError++;
632 // }
633 // if (status == STATUS_DEVICE_NOT_CONNECTED )
634 // {
635 // MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
636 // }
637 } else {
638 bIndicateReceive = TRUE;
639 pDevice->ulBulkInContCRCError = 0;
640 pDevice->ulBulkInBytesRead += bytesRead;
642 #ifdef Calcu_LinkQual
643 pDevice->scStatistic.RxOkCnt ++;
644 #endif
648 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status);
650 if (bIndicateReceive) {
651 spin_lock(&pDevice->lock);
652 if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == TRUE)
653 bReAllocSkb = TRUE;
654 spin_unlock(&pDevice->lock);
656 pRCB->Ref--;
657 if (pRCB->Ref == 0)
659 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
660 spin_lock(&pDevice->lock);
661 RXvFreeRCB(pRCB, bReAllocSkb);
662 spin_unlock(&pDevice->lock);
666 return;
670 * Description:
671 * Allocates an usb BulkOut irp and calls USBD.
673 * Parameters:
674 * In:
675 * pDevice - Pointer to the adapter
676 * Out:
677 * none
679 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
682 NDIS_STATUS
683 PIPEnsSendBulkOut(
684 IN PSDevice pDevice,
685 IN PUSB_SEND_CONTEXT pContext
688 NTSTATUS status;
689 struct urb *pUrb;
693 pDevice->bPWBitOn = FALSE;
696 if (pDevice->pPendingBulkOutContext != NULL) {
697 pDevice->NumContextsQueued++;
698 EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
699 status = STATUS_PENDING;
700 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
701 return status;
705 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
707 if(MP_IS_READY(pDevice) && MP_TEST_FLAG(pDevice, fMP_POST_WRITES)) {
709 pUrb = pContext->pUrb;
710 pDevice->ulBulkOutPosted++;
711 // pDevice->pPendingBulkOutContext = pContext;
712 usb_fill_bulk_urb(
713 pUrb,
714 pDevice->usb,
715 usb_sndbulkpipe(pDevice->usb, 3),
716 (PVOID) &(pContext->Data[0]),
717 pContext->uBufLen,
718 s_nsBulkOutIoCompleteWrite,
719 pContext);
721 if((status = usb_submit_urb(pUrb, GFP_ATOMIC))!=0)
723 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
724 return STATUS_FAILURE;
726 return STATUS_PENDING;
728 else {
729 pContext->bBoolInUse = FALSE;
730 return STATUS_RESOURCES;
735 * Description: s_nsBulkOutIoCompleteWrite
736 * 1a) Indicate to the protocol the status of the write.
737 * 1b) Return ownership of the packet to the protocol.
739 * 2) If any more packets are queue for sending, send another packet
740 * to USBD.
741 * If the attempt to send the packet to the driver fails,
742 * return ownership of the packet to the protocol and
743 * try another packet (until one succeeds).
745 * Parameters:
746 * In:
747 * pdoUsbDevObj - pointer to the USB device object which
748 * completed the irp
749 * pIrp - the irp which was completed by the
750 * device object
751 * pContext - the context given to IoSetCompletionRoutine
752 * before calling IoCallDriver on the irp
753 * The pContext is a pointer to the USB device object.
754 * Out:
755 * none
757 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
758 * (IofCompleteRequest) to stop working on the irp.
761 static
762 VOID
763 s_nsBulkOutIoCompleteWrite(
764 IN struct urb *urb
767 PSDevice pDevice;
768 NTSTATUS status;
769 CONTEXT_TYPE ContextType;
770 ULONG ulBufLen;
771 PUSB_SEND_CONTEXT pContext;
774 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
776 // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
778 pContext = (PUSB_SEND_CONTEXT) urb->context;
779 ASSERT( NULL != pContext );
781 pDevice = pContext->pDevice;
782 ContextType = pContext->Type;
783 ulBufLen = pContext->uBufLen;
785 if (!netif_device_present(pDevice->dev))
786 return;
789 // Perform various IRP, URB, and buffer 'sanity checks'
792 status = urb->status;
793 //we should have failed, succeeded, or cancelled, but NOT be pending
794 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status);
796 if(status == STATUS_SUCCESS) {
797 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
798 pDevice->ulBulkOutBytesWrite += ulBufLen;
799 pDevice->ulBulkOutContCRCError = 0;
800 //2007-0115-06<Add>by MikeLiu
801 #ifdef TxInSleep
802 pDevice->nTxDataTimeCout = 0;
803 #endif
805 } else {
806 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
807 pDevice->ulBulkOutError++;
810 // pDevice->ulCheckForHangCount = 0;
811 // pDevice->pPendingBulkOutContext = NULL;
813 if ( CONTEXT_DATA_PACKET == ContextType ) {
814 // Indicate to the protocol the status of the sent packet and return
815 // ownership of the packet.
816 if (pContext->pPacket != NULL) {
817 dev_kfree_skb_irq(pContext->pPacket);
818 pContext->pPacket = NULL;
819 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx %d bytes\n",(int)ulBufLen);
822 pDevice->dev->trans_start = jiffies;
825 if (status == STATUS_SUCCESS) {
826 pDevice->packetsSent++;
828 else {
829 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
830 pDevice->packetsSentDropped++;
834 if (pDevice->bLinkPass == TRUE) {
835 if (netif_queue_stopped(pDevice->dev))
836 netif_wake_queue(pDevice->dev);
838 pContext->bBoolInUse = FALSE;
840 return;