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