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