xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/newhost/drvBulktran.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
1*53ee8cc1Swenshuai.xi //<MStar Software>
2*53ee8cc1Swenshuai.xi //******************************************************************************
3*53ee8cc1Swenshuai.xi // MStar Software
4*53ee8cc1Swenshuai.xi // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5*53ee8cc1Swenshuai.xi // All software, firmware and related documentation herein ("MStar Software") are
6*53ee8cc1Swenshuai.xi // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7*53ee8cc1Swenshuai.xi // law, including, but not limited to, copyright law and international treaties.
8*53ee8cc1Swenshuai.xi // Any use, modification, reproduction, retransmission, or republication of all
9*53ee8cc1Swenshuai.xi // or part of MStar Software is expressly prohibited, unless prior written
10*53ee8cc1Swenshuai.xi // permission has been granted by MStar.
11*53ee8cc1Swenshuai.xi //
12*53ee8cc1Swenshuai.xi // By accessing, browsing and/or using MStar Software, you acknowledge that you
13*53ee8cc1Swenshuai.xi // have read, understood, and agree, to be bound by below terms ("Terms") and to
14*53ee8cc1Swenshuai.xi // comply with all applicable laws and regulations:
15*53ee8cc1Swenshuai.xi //
16*53ee8cc1Swenshuai.xi // 1. MStar shall retain any and all right, ownership and interest to MStar
17*53ee8cc1Swenshuai.xi //    Software and any modification/derivatives thereof.
18*53ee8cc1Swenshuai.xi //    No right, ownership, or interest to MStar Software and any
19*53ee8cc1Swenshuai.xi //    modification/derivatives thereof is transferred to you under Terms.
20*53ee8cc1Swenshuai.xi //
21*53ee8cc1Swenshuai.xi // 2. You understand that MStar Software might include, incorporate or be
22*53ee8cc1Swenshuai.xi //    supplied together with third party`s software and the use of MStar
23*53ee8cc1Swenshuai.xi //    Software may require additional licenses from third parties.
24*53ee8cc1Swenshuai.xi //    Therefore, you hereby agree it is your sole responsibility to separately
25*53ee8cc1Swenshuai.xi //    obtain any and all third party right and license necessary for your use of
26*53ee8cc1Swenshuai.xi //    such third party`s software.
27*53ee8cc1Swenshuai.xi //
28*53ee8cc1Swenshuai.xi // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29*53ee8cc1Swenshuai.xi //    MStar`s confidential information and you agree to keep MStar`s
30*53ee8cc1Swenshuai.xi //    confidential information in strictest confidence and not disclose to any
31*53ee8cc1Swenshuai.xi //    third party.
32*53ee8cc1Swenshuai.xi //
33*53ee8cc1Swenshuai.xi // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34*53ee8cc1Swenshuai.xi //    kind. Any warranties are hereby expressly disclaimed by MStar, including
35*53ee8cc1Swenshuai.xi //    without limitation, any warranties of merchantability, non-infringement of
36*53ee8cc1Swenshuai.xi //    intellectual property rights, fitness for a particular purpose, error free
37*53ee8cc1Swenshuai.xi //    and in conformity with any international standard.  You agree to waive any
38*53ee8cc1Swenshuai.xi //    claim against MStar for any loss, damage, cost or expense that you may
39*53ee8cc1Swenshuai.xi //    incur related to your use of MStar Software.
40*53ee8cc1Swenshuai.xi //    In no event shall MStar be liable for any direct, indirect, incidental or
41*53ee8cc1Swenshuai.xi //    consequential damages, including without limitation, lost of profit or
42*53ee8cc1Swenshuai.xi //    revenues, lost or damage of data, and unauthorized system use.
43*53ee8cc1Swenshuai.xi //    You agree that this Section 4 shall still apply without being affected
44*53ee8cc1Swenshuai.xi //    even if MStar Software has been modified by MStar in accordance with your
45*53ee8cc1Swenshuai.xi //    request or instruction for your use, except otherwise agreed by both
46*53ee8cc1Swenshuai.xi //    parties in writing.
47*53ee8cc1Swenshuai.xi //
48*53ee8cc1Swenshuai.xi // 5. If requested, MStar may from time to time provide technical supports or
49*53ee8cc1Swenshuai.xi //    services in relation with MStar Software to you for your use of
50*53ee8cc1Swenshuai.xi //    MStar Software in conjunction with your or your customer`s product
51*53ee8cc1Swenshuai.xi //    ("Services").
52*53ee8cc1Swenshuai.xi //    You understand and agree that, except otherwise agreed by both parties in
53*53ee8cc1Swenshuai.xi //    writing, Services are provided on an "AS IS" basis and the warranty
54*53ee8cc1Swenshuai.xi //    disclaimer set forth in Section 4 above shall apply.
55*53ee8cc1Swenshuai.xi //
56*53ee8cc1Swenshuai.xi // 6. Nothing contained herein shall be construed as by implication, estoppels
57*53ee8cc1Swenshuai.xi //    or otherwise:
58*53ee8cc1Swenshuai.xi //    (a) conferring any license or right to use MStar name, trademark, service
59*53ee8cc1Swenshuai.xi //        mark, symbol or any other identification;
60*53ee8cc1Swenshuai.xi //    (b) obligating MStar or any of its affiliates to furnish any person,
61*53ee8cc1Swenshuai.xi //        including without limitation, you and your customers, any assistance
62*53ee8cc1Swenshuai.xi //        of any kind whatsoever, or any information; or
63*53ee8cc1Swenshuai.xi //    (c) conferring any license or right under any intellectual property right.
64*53ee8cc1Swenshuai.xi //
65*53ee8cc1Swenshuai.xi // 7. These terms shall be governed by and construed in accordance with the laws
66*53ee8cc1Swenshuai.xi //    of Taiwan, R.O.C., excluding its conflict of law rules.
67*53ee8cc1Swenshuai.xi //    Any and all dispute arising out hereof or related hereto shall be finally
68*53ee8cc1Swenshuai.xi //    settled by arbitration referred to the Chinese Arbitration Association,
69*53ee8cc1Swenshuai.xi //    Taipei in accordance with the ROC Arbitration Law and the Arbitration
70*53ee8cc1Swenshuai.xi //    Rules of the Association by three (3) arbitrators appointed in accordance
71*53ee8cc1Swenshuai.xi //    with the said Rules.
72*53ee8cc1Swenshuai.xi //    The place of arbitration shall be in Taipei, Taiwan and the language shall
73*53ee8cc1Swenshuai.xi //    be English.
74*53ee8cc1Swenshuai.xi //    The arbitration award shall be final and binding to both parties.
75*53ee8cc1Swenshuai.xi //
76*53ee8cc1Swenshuai.xi //******************************************************************************
77*53ee8cc1Swenshuai.xi //<MStar Software>
78*53ee8cc1Swenshuai.xi //#define MSTAR_USB_DEBUG_MSG
79*53ee8cc1Swenshuai.xi 
80*53ee8cc1Swenshuai.xi //=============include file=================//
81*53ee8cc1Swenshuai.xi //#include <MsCommon.h> // NUSED
82*53ee8cc1Swenshuai.xi //#include <cyg/hal/hal_if.h> // NUSED
83*53ee8cc1Swenshuai.xi 
84*53ee8cc1Swenshuai.xi //#include "include/drvKernel.h" // NUSED
85*53ee8cc1Swenshuai.xi #include "include/drvConfig.h"
86*53ee8cc1Swenshuai.xi #include "drvBulktran.h"
87*53ee8cc1Swenshuai.xi //#include "drvMassStor.h" // NUSED
88*53ee8cc1Swenshuai.xi //#include "drvUsbHostConfig.h" // NUSED
89*53ee8cc1Swenshuai.xi 
90*53ee8cc1Swenshuai.xi #include "include/drvErrno.h"
91*53ee8cc1Swenshuai.xi //#include "include/drvTimer.h" // NUSED
92*53ee8cc1Swenshuai.xi #include "include/drvBitops.h"
93*53ee8cc1Swenshuai.xi //#include "drvUsbd.h" // NUSED
94*53ee8cc1Swenshuai.xi //#include "drvEHCI.h" // NUSED
95*53ee8cc1Swenshuai.xi #include "drvUSBHwCtl.h"
96*53ee8cc1Swenshuai.xi /* applying drvUsbHostConfig.h (inside drvUSBHwCtl.h) */
97*53ee8cc1Swenshuai.xi 
98*53ee8cc1Swenshuai.xi //========================================//
99*53ee8cc1Swenshuai.xi //=============Definition=================//
100*53ee8cc1Swenshuai.xi #define BLK_COMPLETE    1
101*53ee8cc1Swenshuai.xi #define PTP_COMPLETE    2
102*53ee8cc1Swenshuai.xi #define BLK_ASYNC       4
103*53ee8cc1Swenshuai.xi #define ILLEGAL_REQUEST         0x05
104*53ee8cc1Swenshuai.xi 
105*53ee8cc1Swenshuai.xi unsigned char invalid_CDB[18] =
106*53ee8cc1Swenshuai.xi { 0x70, 0, ILLEGAL_REQUEST,0,0,0,0,0x0a,0, 0, 0, 0, 0x24, 0, 0, 0, 0, 0};
107*53ee8cc1Swenshuai.xi //========================================//
108*53ee8cc1Swenshuai.xi 
109*53ee8cc1Swenshuai.xi 
ms_usb_find_data_location(stCmd_scsi * request_block)110*53ee8cc1Swenshuai.xi static void *ms_usb_find_data_location(stCmd_scsi *request_block)
111*53ee8cc1Swenshuai.xi {
112*53ee8cc1Swenshuai.xi     return (void *) request_block->req_buf;
113*53ee8cc1Swenshuai.xi }
114*53ee8cc1Swenshuai.xi 
ms_usb_invoke_and_inquiry(stCmd_scsi * request_block,struct ms_usdata * ms_us)115*53ee8cc1Swenshuai.xi static void ms_usb_invoke_and_inquiry(stCmd_scsi *request_block, struct ms_usdata *ms_us)
116*53ee8cc1Swenshuai.xi {
117*53ee8cc1Swenshuai.xi     unsigned char *data_ptr;
118*53ee8cc1Swenshuai.xi 
119*53ee8cc1Swenshuai.xi     ms_usb_invoke_transport(request_block, ms_us);
120*53ee8cc1Swenshuai.xi     if (request_block->result == MS_STAT_GOOD)
121*53ee8cc1Swenshuai.xi     {
122*53ee8cc1Swenshuai.xi         if (request_block->cmnd[0] != INQUIRY)
123*53ee8cc1Swenshuai.xi             return;
124*53ee8cc1Swenshuai.xi 
125*53ee8cc1Swenshuai.xi         if (request_block->req_buf_len < 3)
126*53ee8cc1Swenshuai.xi             return;
127*53ee8cc1Swenshuai.xi 
128*53ee8cc1Swenshuai.xi         data_ptr = (unsigned char*) ms_usb_find_data_location(request_block);
129*53ee8cc1Swenshuai.xi 
130*53ee8cc1Swenshuai.xi         if ((data_ptr[2] & 7) == 2)
131*53ee8cc1Swenshuai.xi             return;
132*53ee8cc1Swenshuai.xi 
133*53ee8cc1Swenshuai.xi         ms_usbhost_debug("Fixing INQUIRY data (SCSI rev--2) = %d\n", data_ptr[2] & 7);
134*53ee8cc1Swenshuai.xi 
135*53ee8cc1Swenshuai.xi         data_ptr[2] = (data_ptr[2] & ~7) | 2;
136*53ee8cc1Swenshuai.xi     }
137*53ee8cc1Swenshuai.xi }
138*53ee8cc1Swenshuai.xi 
139*53ee8cc1Swenshuai.xi #if SupportOtherDevice
ms_usb_qic157_command(stCmd_scsi * request_block,struct ms_usdata * ms_us)140*53ee8cc1Swenshuai.xi void ms_usb_qic157_command(stCmd_scsi *request_block, struct ms_usdata *ms_us)
141*53ee8cc1Swenshuai.xi {
142*53ee8cc1Swenshuai.xi     for (; request_block->cmd_len<12; request_block->cmd_len++)
143*53ee8cc1Swenshuai.xi         request_block->cmnd[request_block->cmd_len] = 0;
144*53ee8cc1Swenshuai.xi 
145*53ee8cc1Swenshuai.xi     request_block->cmd_len = 12;
146*53ee8cc1Swenshuai.xi     ms_usb_invoke_and_inquiry(request_block, ms_us);
147*53ee8cc1Swenshuai.xi }
148*53ee8cc1Swenshuai.xi 
ms_usb_ufi_command(stCmd_scsi * request_block,struct ms_usdata * ms_us)149*53ee8cc1Swenshuai.xi void ms_usb_ufi_command(stCmd_scsi *request_block, struct ms_usdata *ms_us)
150*53ee8cc1Swenshuai.xi {
151*53ee8cc1Swenshuai.xi     for (; request_block->cmd_len<12; request_block->cmd_len++)
152*53ee8cc1Swenshuai.xi         request_block->cmnd[request_block->cmd_len] = 0;
153*53ee8cc1Swenshuai.xi 
154*53ee8cc1Swenshuai.xi     request_block->cmd_len = 12;
155*53ee8cc1Swenshuai.xi 
156*53ee8cc1Swenshuai.xi     switch (request_block->cmnd[0])
157*53ee8cc1Swenshuai.xi     {
158*53ee8cc1Swenshuai.xi         case INQUIRY:
159*53ee8cc1Swenshuai.xi             request_block->cmnd[4] = 36;
160*53ee8cc1Swenshuai.xi             break;
161*53ee8cc1Swenshuai.xi 
162*53ee8cc1Swenshuai.xi         //case MODE_SENSE_10:
163*53ee8cc1Swenshuai.xi         case MODE_SENSE:
164*53ee8cc1Swenshuai.xi             request_block->cmnd[7] = 0;
165*53ee8cc1Swenshuai.xi             request_block->cmnd[8] = 8;
166*53ee8cc1Swenshuai.xi             break;
167*53ee8cc1Swenshuai.xi 
168*53ee8cc1Swenshuai.xi         case REQUEST_SENSE:
169*53ee8cc1Swenshuai.xi             request_block->cmnd[4] = 18;
170*53ee8cc1Swenshuai.xi             break;
171*53ee8cc1Swenshuai.xi     } /* end switch on cmnd[0] */
172*53ee8cc1Swenshuai.xi 
173*53ee8cc1Swenshuai.xi     ms_usb_invoke_and_inquiry(request_block, ms_us);
174*53ee8cc1Swenshuai.xi }
175*53ee8cc1Swenshuai.xi #endif
176*53ee8cc1Swenshuai.xi 
ms_usb_transparent_scsi_command(stCmd_scsi * request_block,struct ms_usdata * ms_us)177*53ee8cc1Swenshuai.xi void ms_usb_transparent_scsi_command(stCmd_scsi *request_block, struct ms_usdata *ms_us)
178*53ee8cc1Swenshuai.xi {
179*53ee8cc1Swenshuai.xi     unsigned char *dp;
180*53ee8cc1Swenshuai.xi     U32 capacity;
181*53ee8cc1Swenshuai.xi 
182*53ee8cc1Swenshuai.xi     ms_usb_invoke_and_inquiry(request_block, ms_us);
183*53ee8cc1Swenshuai.xi     if (request_block->result == MS_STAT_GOOD)
184*53ee8cc1Swenshuai.xi     {
185*53ee8cc1Swenshuai.xi         if (ms_us->flags & MS_FIX_CAPACITY)
186*53ee8cc1Swenshuai.xi         {
187*53ee8cc1Swenshuai.xi             if (request_block->cmnd[0] != READ_CAPACITY)
188*53ee8cc1Swenshuai.xi                 return;
189*53ee8cc1Swenshuai.xi 
190*53ee8cc1Swenshuai.xi             dp = (unsigned char*) ms_usb_find_data_location(request_block);
191*53ee8cc1Swenshuai.xi 
192*53ee8cc1Swenshuai.xi             capacity = (dp[0]<<24) + (dp[1]<<16) + (dp[2]<<8) + (dp[3]);
193*53ee8cc1Swenshuai.xi             ms_usbhost_msg("US: Fixing capacity (from %ld to %ld)\n", capacity+1, capacity);
194*53ee8cc1Swenshuai.xi             capacity--;
195*53ee8cc1Swenshuai.xi             dp[0] = (capacity >> 24);
196*53ee8cc1Swenshuai.xi             dp[1] = (capacity >> 16);
197*53ee8cc1Swenshuai.xi             dp[2] = (capacity >> 8);
198*53ee8cc1Swenshuai.xi             dp[3] = (capacity);
199*53ee8cc1Swenshuai.xi         }
200*53ee8cc1Swenshuai.xi     }
201*53ee8cc1Swenshuai.xi }
202*53ee8cc1Swenshuai.xi 
ms_usb_set_dma_buf(struct urb * request_block)203*53ee8cc1Swenshuai.xi void ms_usb_set_dma_buf(struct urb *request_block)
204*53ee8cc1Swenshuai.xi {
205*53ee8cc1Swenshuai.xi     if (request_block->SetDMABuf != NULL)
206*53ee8cc1Swenshuai.xi     {
207*53ee8cc1Swenshuai.xi         Usb_FreeNonCachedMemory(request_block->SetDMABuf);
208*53ee8cc1Swenshuai.xi         request_block->SetDMABuf = NULL;
209*53ee8cc1Swenshuai.xi     }
210*53ee8cc1Swenshuai.xi }
211*53ee8cc1Swenshuai.xi 
ms_usb_set_tx_dma_buf(struct urb * request_block)212*53ee8cc1Swenshuai.xi void ms_usb_set_tx_dma_buf(struct urb *request_block)
213*53ee8cc1Swenshuai.xi {
214*53ee8cc1Swenshuai.xi #ifdef DEBUG_PERFORMANCE
215*53ee8cc1Swenshuai.xi     int max_packet_size=512;
216*53ee8cc1Swenshuai.xi #endif
217*53ee8cc1Swenshuai.xi     if (request_block->TxDMABuf != NULL)
218*53ee8cc1Swenshuai.xi     {
219*53ee8cc1Swenshuai.xi         if (usb_pipein(request_block->u32Pipe))
220*53ee8cc1Swenshuai.xi         {
221*53ee8cc1Swenshuai.xi #ifdef DEBUG_PERFORMANCE
222*53ee8cc1Swenshuai.xi             if (request_block->u32TransferBufferLength >= max_packet_size)
223*53ee8cc1Swenshuai.xi                 ms_usbhost_msg("Blocking Completion (len: 0x%lx)\n", request_block->u32TransferBufferLength);
224*53ee8cc1Swenshuai.xi #endif
225*53ee8cc1Swenshuai.xi #ifdef MIPS_TOOLCHAIN_482_ISSUE
226*53ee8cc1Swenshuai.xi             MsOS_Dcache_Invalidate((U32) request_block->TxDMABuf, request_block->u32TransferBufferLength);
227*53ee8cc1Swenshuai.xi #endif
228*53ee8cc1Swenshuai.xi             memcpy(request_block->pTransferBuffer, request_block->TxDMABuf, request_block->u32TransferBufferLength);
229*53ee8cc1Swenshuai.xi         }
230*53ee8cc1Swenshuai.xi         Usb_FreeNonCachedMemory(request_block->TxDMABuf);
231*53ee8cc1Swenshuai.xi         request_block->TxDMABuf = NULL;
232*53ee8cc1Swenshuai.xi     }
233*53ee8cc1Swenshuai.xi }
234*53ee8cc1Swenshuai.xi 
ms_usb_blocking_completion(struct urb * request_block,struct stPtRegs * registers)235*53ee8cc1Swenshuai.xi static void ms_usb_blocking_completion(struct urb *request_block, struct stPtRegs *registers)
236*53ee8cc1Swenshuai.xi {
237*53ee8cc1Swenshuai.xi     struct stCompletion *request_block_done = (struct stCompletion *)request_block->pContext;
238*53ee8cc1Swenshuai.xi     //BOOL    err;
239*53ee8cc1Swenshuai.xi 
240*53ee8cc1Swenshuai.xi     /* move to ms_usb_hcd_giveback_urb() to support 3rd party driver */
241*53ee8cc1Swenshuai.xi     //ms_usb_set_dma_buf(request_block);
242*53ee8cc1Swenshuai.xi     //ms_usb_set_tx_dma_buf(request_block);
243*53ee8cc1Swenshuai.xi     complete(request_block_done);
244*53ee8cc1Swenshuai.xi     /*err = */MsOS_SetEvent(request_block->WaitFlag_storage, BLK_COMPLETE);
245*53ee8cc1Swenshuai.xi }
246*53ee8cc1Swenshuai.xi 
247*53ee8cc1Swenshuai.xi #ifndef URB_TIMEOUT_BY_WAIT_EVENT
ms_usb_timeout_handler(U32 tmp)248*53ee8cc1Swenshuai.xi static void ms_usb_timeout_handler(U32 tmp)
249*53ee8cc1Swenshuai.xi {
250*53ee8cc1Swenshuai.xi     struct timer_list *ptr_timer = (struct timer_list *) tmp;
251*53ee8cc1Swenshuai.xi     struct ms_usdata *ptr = (struct ms_usdata *) ptr_timer->data_ex;
252*53ee8cc1Swenshuai.xi 
253*53ee8cc1Swenshuai.xi     struct usb_hcd    *host_controller_device = (struct usb_hcd*) ptr->current_urb->dev->bus->hcpriv;
254*53ee8cc1Swenshuai.xi 
255*53ee8cc1Swenshuai.xi     if ( ptr_timer->tmout_step > 0 )
256*53ee8cc1Swenshuai.xi         ptr_timer->tmout_value -= ptr_timer->tmout_step;
257*53ee8cc1Swenshuai.xi     else
258*53ee8cc1Swenshuai.xi         ptr_timer->tmout_value = 0;
259*53ee8cc1Swenshuai.xi 
260*53ee8cc1Swenshuai.xi     if ( ms_RoothubPortConnected(host_controller_device) &&
261*53ee8cc1Swenshuai.xi             (ptr_timer->tmout_value > 0) )
262*53ee8cc1Swenshuai.xi         ms_update_timer(ptr_timer, ptr_timer->tmout_value, ptr_timer->tmout_step);
263*53ee8cc1Swenshuai.xi     else
264*53ee8cc1Swenshuai.xi     {
265*53ee8cc1Swenshuai.xi         int retv;
266*53ee8cc1Swenshuai.xi         /* remove (20150422) */
267*53ee8cc1Swenshuai.xi         //struct stCompletion *request_block_done = (struct stCompletion *)ptr->current_urb->pContext;
268*53ee8cc1Swenshuai.xi 
269*53ee8cc1Swenshuai.xi         ms_usbhost_err("Timeout handler .. Warning!! Cancel urb @ qh %p\n",ptr->current_urb->hcpriv);
270*53ee8cc1Swenshuai.xi         ms_usbhost_err("LOG: dev%d ep%d%s[%d] qtd --> status %d, len=%d\n",
271*53ee8cc1Swenshuai.xi             usb_pipedevice (ptr->current_urb->u32Pipe),
272*53ee8cc1Swenshuai.xi             usb_pipeendpoint (ptr->current_urb->u32Pipe),
273*53ee8cc1Swenshuai.xi             usb_pipein (ptr->current_urb->u32Pipe) ? "in" : "out",usb_pipetype (ptr->current_urb->u32Pipe), ptr->current_urb->s32Status, ptr->current_urb->u32TransferBufferLength);
274*53ee8cc1Swenshuai.xi         ms_usbhost_msg("unlink USB request block ongoing...\n");
275*53ee8cc1Swenshuai.xi         //enhanced_host_controller_interface->uDontSendIAA = 0; // force IAA command
276*53ee8cc1Swenshuai.xi         retv = ms_usb_unlink_urb(ptr->current_urb);
277*53ee8cc1Swenshuai.xi         ms_usbhost_err("unlink URB return(%d)\n", retv);
278*53ee8cc1Swenshuai.xi 
279*53ee8cc1Swenshuai.xi         ptr->current_urb->s32Status = -ETIMEDOUT;
280*53ee8cc1Swenshuai.xi 
281*53ee8cc1Swenshuai.xi         /* remove (20150422) */
282*53ee8cc1Swenshuai.xi         /*  to relieve wait event if necessary (20140702) */
283*53ee8cc1Swenshuai.xi         //if (request_block_done->done == 0);
284*53ee8cc1Swenshuai.xi         //    MsOS_SetEvent(ptr->current_urb->WaitFlag_storage, BLK_COMPLETE);
285*53ee8cc1Swenshuai.xi     }
286*53ee8cc1Swenshuai.xi }
287*53ee8cc1Swenshuai.xi 
ms_usb_wait_for_completion(struct stCompletion * cpt,S32 flag)288*53ee8cc1Swenshuai.xi static void ms_usb_wait_for_completion(struct stCompletion *cpt, S32 flag)
289*53ee8cc1Swenshuai.xi {
290*53ee8cc1Swenshuai.xi     BOOL    error;
291*53ee8cc1Swenshuai.xi     U32 u32Pattern;
292*53ee8cc1Swenshuai.xi 
293*53ee8cc1Swenshuai.xi     error = MsOS_WaitEvent(flag, BLK_COMPLETE, &u32Pattern, E_OR_CLEAR, MSOS_WAIT_FOREVER);
294*53ee8cc1Swenshuai.xi 
295*53ee8cc1Swenshuai.xi     if (cpt->done != 1)
296*53ee8cc1Swenshuai.xi         ms_usbhost_err("Completion fail %08lX %ld, error %d\n", u32Pattern, cpt->done, error);
297*53ee8cc1Swenshuai.xi }
298*53ee8cc1Swenshuai.xi #else
299*53ee8cc1Swenshuai.xi #define TIMEOUT_STEP 500 //ms
ms_usb_wait_for_completion_timeout(struct stCompletion * cpt,S32 flag,struct ms_usdata * ptr,U32 wait_ms)300*53ee8cc1Swenshuai.xi static void ms_usb_wait_for_completion_timeout(struct stCompletion *cpt, S32 flag, struct ms_usdata *ptr, U32 wait_ms)
301*53ee8cc1Swenshuai.xi {
302*53ee8cc1Swenshuai.xi     BOOL    error = 0;
303*53ee8cc1Swenshuai.xi     BOOL    disconn = 0;
304*53ee8cc1Swenshuai.xi     U32 u32Pattern;
305*53ee8cc1Swenshuai.xi     U32 wait_remain = wait_ms;
306*53ee8cc1Swenshuai.xi     struct urb *urb = ptr->current_urb;
307*53ee8cc1Swenshuai.xi     struct usb_hcd *hcd = urb->dev->bus->hcpriv;
308*53ee8cc1Swenshuai.xi 
309*53ee8cc1Swenshuai.xi     while(wait_remain > 0)
310*53ee8cc1Swenshuai.xi     {
311*53ee8cc1Swenshuai.xi         if((urb->dev->parent != NULL) && (urb->dev->parent->parent == NULL) // device on roothub
312*53ee8cc1Swenshuai.xi             && (ms_RoothubPortConnectChg(hcd) || !ms_RoothubPortConnected(hcd))) // CSC or disconnect happen on ehci port
313*53ee8cc1Swenshuai.xi         {
314*53ee8cc1Swenshuai.xi             error = 0;
315*53ee8cc1Swenshuai.xi             disconn = 1;
316*53ee8cc1Swenshuai.xi             diag_printf("[USB][BULK] stop wait CMP, wait_remain %d csc [%d] connect [%d]\n",
317*53ee8cc1Swenshuai.xi                 wait_remain, ms_RoothubPortConnectChg(hcd), ms_RoothubPortConnected(hcd));
318*53ee8cc1Swenshuai.xi             break;
319*53ee8cc1Swenshuai.xi         }
320*53ee8cc1Swenshuai.xi 
321*53ee8cc1Swenshuai.xi         if(wait_remain >= TIMEOUT_STEP)
322*53ee8cc1Swenshuai.xi         {
323*53ee8cc1Swenshuai.xi              //diag_printf("[USB] wait_remain %d csc [%d] connect [%d]\n",
324*53ee8cc1Swenshuai.xi              //    wait_remain, ms_RoothubPortConnectChg(hcd), ms_RoothubPortConnected(hcd));
325*53ee8cc1Swenshuai.xi              error = MsOS_WaitEvent(flag, BLK_COMPLETE, &u32Pattern, E_OR_CLEAR, TIMEOUT_STEP);
326*53ee8cc1Swenshuai.xi              wait_remain -= TIMEOUT_STEP;
327*53ee8cc1Swenshuai.xi         }
328*53ee8cc1Swenshuai.xi         else
329*53ee8cc1Swenshuai.xi         {
330*53ee8cc1Swenshuai.xi              error = MsOS_WaitEvent(flag, BLK_COMPLETE, &u32Pattern, E_OR_CLEAR, wait_remain);
331*53ee8cc1Swenshuai.xi              wait_remain = 0;
332*53ee8cc1Swenshuai.xi         }
333*53ee8cc1Swenshuai.xi 
334*53ee8cc1Swenshuai.xi         if(error)
335*53ee8cc1Swenshuai.xi             break;
336*53ee8cc1Swenshuai.xi     }
337*53ee8cc1Swenshuai.xi 
338*53ee8cc1Swenshuai.xi     if (!error) // time out
339*53ee8cc1Swenshuai.xi     {
340*53ee8cc1Swenshuai.xi         int retv;
341*53ee8cc1Swenshuai.xi 
342*53ee8cc1Swenshuai.xi 	diag_printf("[timeout] kill urb (qh:%p)!\n",
343*53ee8cc1Swenshuai.xi 		ptr->current_urb->hcpriv);
344*53ee8cc1Swenshuai.xi         retv = ms_hcd_unlink_urb(ptr->current_urb, -ENOENT);
345*53ee8cc1Swenshuai.xi 	//diag_printf("[timeout] unlink current urb (qh:%p)!\n",
346*53ee8cc1Swenshuai.xi 	//	ptr->current_urb->hcpriv);
347*53ee8cc1Swenshuai.xi         //retv = ms_usb_unlink_urb(ptr->current_urb);
348*53ee8cc1Swenshuai.xi 	/* if there is done bit completed, it is really done although timeout event */
349*53ee8cc1Swenshuai.xi 	if (cpt->done == 1) {
350*53ee8cc1Swenshuai.xi 		ptr->current_urb->s32Status = 0;
351*53ee8cc1Swenshuai.xi 		return;
352*53ee8cc1Swenshuai.xi 	}
353*53ee8cc1Swenshuai.xi         ms_usbhost_err("<%s> unlink USB request block done (%d)...\n", __FUNCTION__, retv);
354*53ee8cc1Swenshuai.xi 
355*53ee8cc1Swenshuai.xi         ptr->current_urb->s32Status = disconn ? -ENODEV : -ETIMEDOUT;
356*53ee8cc1Swenshuai.xi     }
357*53ee8cc1Swenshuai.xi     if (cpt->done != 1)
358*53ee8cc1Swenshuai.xi         ms_usbhost_err("Completion fail %08lX %ld, error %d\n", u32Pattern, cpt->done, error);
359*53ee8cc1Swenshuai.xi }
360*53ee8cc1Swenshuai.xi #endif
361*53ee8cc1Swenshuai.xi 
ms_usb_msg_common(struct ms_usdata * ptr,int time_out)362*53ee8cc1Swenshuai.xi static int ms_usb_msg_common(struct ms_usdata *ptr, int time_out)
363*53ee8cc1Swenshuai.xi {
364*53ee8cc1Swenshuai.xi     struct stCompletion request_block_done;
365*53ee8cc1Swenshuai.xi #ifndef URB_TIMEOUT_BY_WAIT_EVENT
366*53ee8cc1Swenshuai.xi     struct timer_list to_timer;
367*53ee8cc1Swenshuai.xi #endif
368*53ee8cc1Swenshuai.xi     int status;
369*53ee8cc1Swenshuai.xi     S32 flag;
370*53ee8cc1Swenshuai.xi 
371*53ee8cc1Swenshuai.xi     if (ptr->flags & NO_SUBMIT)
372*53ee8cc1Swenshuai.xi         return -EIO;
373*53ee8cc1Swenshuai.xi 
374*53ee8cc1Swenshuai.xi     init_completion(&request_block_done);
375*53ee8cc1Swenshuai.xi 
376*53ee8cc1Swenshuai.xi     /*Get urb status*/
377*53ee8cc1Swenshuai.xi     ptr->current_urb->pContext = &request_block_done;
378*53ee8cc1Swenshuai.xi     ptr->current_urb->u32ActualLength = 0;
379*53ee8cc1Swenshuai.xi     //ptr->current_urb->s32Status = 0; // dummy
380*53ee8cc1Swenshuai.xi     //ptr->current_urb->u32TransferFlags = MS_FLAG_URB_ASYNC_UNLINK | MS_FLAG_URB_NO_SETUP_DMA_MAP;
381*53ee8cc1Swenshuai.xi     ptr->current_urb->u32TransferFlags = MS_FLAG_URB_NO_SETUP_DMA_MAP;
382*53ee8cc1Swenshuai.xi 
383*53ee8cc1Swenshuai.xi     if (ptr->current_urb->pTransferBuffer == ptr->iobuf)
384*53ee8cc1Swenshuai.xi         ptr->current_urb->u32TransferFlags |= MS_FLAG_URB_NO_TRANSFER_DMA_MAP;
385*53ee8cc1Swenshuai.xi     ptr->current_urb->tTransferDma = ptr->iobuf_dma;
386*53ee8cc1Swenshuai.xi     ptr->current_urb->tSetupDma = ptr->cr_dma;
387*53ee8cc1Swenshuai.xi 
388*53ee8cc1Swenshuai.xi     //Add patch by Jonas
389*53ee8cc1Swenshuai.xi     {
390*53ee8cc1Swenshuai.xi     struct usb_hcd *hcd = ptr->pusb_dev->bus->hcpriv;
391*53ee8cc1Swenshuai.xi     flag = hcd->USBWaitFlg;
392*53ee8cc1Swenshuai.xi     }
393*53ee8cc1Swenshuai.xi 
394*53ee8cc1Swenshuai.xi     ptr->current_urb->WaitFlag_storage = flag;
395*53ee8cc1Swenshuai.xi     MsOS_ClearEvent(flag, BLK_COMPLETE); // 20160328 clear flag before waiting
396*53ee8cc1Swenshuai.xi 
397*53ee8cc1Swenshuai.xi     status = ms_usb_submit_urb(ptr->current_urb, GFP_NOIO);
398*53ee8cc1Swenshuai.xi     if (status)
399*53ee8cc1Swenshuai.xi         return status;
400*53ee8cc1Swenshuai.xi 
401*53ee8cc1Swenshuai.xi     ms_set_bit(MS_IDX_URB_ACTIVE, &ptr->flags, U32);
402*53ee8cc1Swenshuai.xi     if (ptr->flags & NO_SUBMIT)
403*53ee8cc1Swenshuai.xi     {
404*53ee8cc1Swenshuai.xi         if (ms_test_and_clear_bit(MS_IDX_URB_ACTIVE, &ptr->flags))
405*53ee8cc1Swenshuai.xi         {
406*53ee8cc1Swenshuai.xi             ms_usbhost_err("NO_SUBMIT --> Cancel USB request block\n");
407*53ee8cc1Swenshuai.xi             ms_usb_unlink_urb(ptr->current_urb);
408*53ee8cc1Swenshuai.xi         }
409*53ee8cc1Swenshuai.xi     }
410*53ee8cc1Swenshuai.xi #ifndef URB_TIMEOUT_BY_WAIT_EVENT
411*53ee8cc1Swenshuai.xi     if (time_out > 0)
412*53ee8cc1Swenshuai.xi     {
413*53ee8cc1Swenshuai.xi         ms_init_timer(&to_timer);
414*53ee8cc1Swenshuai.xi         to_timer.tmout_value = time_out;
415*53ee8cc1Swenshuai.xi         to_timer.tmout_step = 2000;
416*53ee8cc1Swenshuai.xi         to_timer.function = ms_usb_timeout_handler;
417*53ee8cc1Swenshuai.xi         to_timer.data = (U32) &to_timer;
418*53ee8cc1Swenshuai.xi         to_timer.data_ex = (U32) ptr;
419*53ee8cc1Swenshuai.xi         ms_add_timer(&to_timer);
420*53ee8cc1Swenshuai.xi     }
421*53ee8cc1Swenshuai.xi     ms_usb_wait_for_completion(&request_block_done, flag);
422*53ee8cc1Swenshuai.xi #else
423*53ee8cc1Swenshuai.xi     ms_usb_wait_for_completion_timeout(&request_block_done, flag, ptr, ms_jiffies_to_msecs(time_out));
424*53ee8cc1Swenshuai.xi #endif
425*53ee8cc1Swenshuai.xi     ms_clear_bit(MS_IDX_URB_ACTIVE, &ptr->flags, U32);
426*53ee8cc1Swenshuai.xi #ifndef URB_TIMEOUT_BY_WAIT_EVENT
427*53ee8cc1Swenshuai.xi     if (time_out > 0)
428*53ee8cc1Swenshuai.xi         ms_del_timer_sync(&to_timer);
429*53ee8cc1Swenshuai.xi #endif
430*53ee8cc1Swenshuai.xi 
431*53ee8cc1Swenshuai.xi     /* ETIMEOUT process already done, else just return */
432*53ee8cc1Swenshuai.xi     //if (ptr->current_urb->s32Status < 0 && ptr->current_urb->s32Status != -ETIMEDOUT)
433*53ee8cc1Swenshuai.xi     //{
434*53ee8cc1Swenshuai.xi     //    struct usb_hcd    *hcd = (struct usb_hcd*) ptr->current_urb->dev->bus->hcpriv;
435*53ee8cc1Swenshuai.xi     //
436*53ee8cc1Swenshuai.xi     //    /* kill error return urb */
437*53ee8cc1Swenshuai.xi     //    ms_unlink1(hcd, ptr->current_urb);
438*53ee8cc1Swenshuai.xi     //    diag_printf("[UM] msg_common urb status %d\n", ptr->current_urb->s32Status);
439*53ee8cc1Swenshuai.xi     //}
440*53ee8cc1Swenshuai.xi     return ptr->current_urb->s32Status;
441*53ee8cc1Swenshuai.xi }
442*53ee8cc1Swenshuai.xi 
ms_usb_control_msg(struct ms_usdata * ptr,U32 pipe,unsigned char req,unsigned char rt,U16 val,U16 idx,void * data,U16 len,int time_out)443*53ee8cc1Swenshuai.xi int ms_usb_control_msg(struct ms_usdata *ptr, U32 pipe,
444*53ee8cc1Swenshuai.xi             unsigned char req, unsigned char rt, U16 val, U16 idx, void *data, U16 len, int time_out)
445*53ee8cc1Swenshuai.xi {
446*53ee8cc1Swenshuai.xi     int state;
447*53ee8cc1Swenshuai.xi 
448*53ee8cc1Swenshuai.xi     ms_usbhost_debug("<ms_usb_control_msg>: req=%02x rt=%02x val=%04x idx=%02x len=%u\n",
449*53ee8cc1Swenshuai.xi             req, rt, val, idx, len);
450*53ee8cc1Swenshuai.xi 
451*53ee8cc1Swenshuai.xi     ptr->cr->bRequestType = rt;
452*53ee8cc1Swenshuai.xi     ptr->cr->bRequest = req;
453*53ee8cc1Swenshuai.xi     ptr->cr->wValue = val;
454*53ee8cc1Swenshuai.xi     ptr->cr->wIndex = idx;
455*53ee8cc1Swenshuai.xi     ptr->cr->wLength = len;
456*53ee8cc1Swenshuai.xi 
457*53ee8cc1Swenshuai.xi     ms_usb_stuff_control_urb(ptr->current_urb, ptr->pusb_dev, pipe,
458*53ee8cc1Swenshuai.xi             (unsigned char*) ptr->cr, data, len, ms_usb_blocking_completion, NULL);
459*53ee8cc1Swenshuai.xi 
460*53ee8cc1Swenshuai.xi     state = ms_usb_msg_common(ptr, time_out);
461*53ee8cc1Swenshuai.xi     if (!state)
462*53ee8cc1Swenshuai.xi         state = ptr->current_urb->u32ActualLength;
463*53ee8cc1Swenshuai.xi 
464*53ee8cc1Swenshuai.xi     return state;
465*53ee8cc1Swenshuai.xi }
466*53ee8cc1Swenshuai.xi 
ms_usb_msc_clear_halt(struct ms_usdata * ptr,U32 pipe)467*53ee8cc1Swenshuai.xi int ms_usb_msc_clear_halt(struct ms_usdata *ptr, U32 pipe)
468*53ee8cc1Swenshuai.xi {
469*53ee8cc1Swenshuai.xi     int regval,ep;
470*53ee8cc1Swenshuai.xi 
471*53ee8cc1Swenshuai.xi     ep = usb_pipeendpoint(pipe);
472*53ee8cc1Swenshuai.xi     if (usb_pipein (pipe))
473*53ee8cc1Swenshuai.xi         ep |= USB_DIR_IN;
474*53ee8cc1Swenshuai.xi 
475*53ee8cc1Swenshuai.xi     regval = ms_usb_control_msg(ptr, ptr->ctrl_send_pipe,
476*53ee8cc1Swenshuai.xi         USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, ep, NULL, 0, 3*HZ);
477*53ee8cc1Swenshuai.xi     //usb_endpoint_running(ptr->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
478*53ee8cc1Swenshuai.xi     usb_settoggle(ptr->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
479*53ee8cc1Swenshuai.xi     ms_usbhost_msg("<ms_usb_msc_clear_halt> regval = %d\n", regval);
480*53ee8cc1Swenshuai.xi     return regval;
481*53ee8cc1Swenshuai.xi }
482*53ee8cc1Swenshuai.xi 
ms_usb_interpret_uRequest_Block_result(struct ms_usdata * ptr,U32 pipe,U32 len,int regval,U32 partial)483*53ee8cc1Swenshuai.xi static int ms_usb_interpret_uRequest_Block_result(struct ms_usdata *ptr, U32 pipe,
484*53ee8cc1Swenshuai.xi         U32 len, int regval, U32 partial)
485*53ee8cc1Swenshuai.xi {
486*53ee8cc1Swenshuai.xi     ms_usbhost_debug("regval=%d, transferred=%u/%u\n", regval, partial, len);
487*53ee8cc1Swenshuai.xi 
488*53ee8cc1Swenshuai.xi     switch (regval)
489*53ee8cc1Swenshuai.xi     {
490*53ee8cc1Swenshuai.xi         case 0:
491*53ee8cc1Swenshuai.xi             if (partial != len)
492*53ee8cc1Swenshuai.xi             {
493*53ee8cc1Swenshuai.xi                 ms_usbhost_debug("--> short transfer\n");
494*53ee8cc1Swenshuai.xi                 return XFER_SHORT;
495*53ee8cc1Swenshuai.xi             }
496*53ee8cc1Swenshuai.xi 
497*53ee8cc1Swenshuai.xi             ms_usbhost_debug("--> transfer complete\n");
498*53ee8cc1Swenshuai.xi             return XFER_GOOD;
499*53ee8cc1Swenshuai.xi         case -EPIPE:
500*53ee8cc1Swenshuai.xi             if (usb_pipecontrol(pipe))
501*53ee8cc1Swenshuai.xi             {
502*53ee8cc1Swenshuai.xi                 ms_usbhost_msg("--> stall on control pipe\n");
503*53ee8cc1Swenshuai.xi                 return XFER_STALLED;
504*53ee8cc1Swenshuai.xi             }
505*53ee8cc1Swenshuai.xi             ms_usbhost_debug("clearing endpoint halt for pipe 0x%x\n", pipe);
506*53ee8cc1Swenshuai.xi             if (ms_usb_msc_clear_halt(ptr, pipe) < 0)
507*53ee8cc1Swenshuai.xi                 return XFER_ERROR;
508*53ee8cc1Swenshuai.xi             return XFER_STALLED;
509*53ee8cc1Swenshuai.xi         case -ETIMEDOUT:
510*53ee8cc1Swenshuai.xi             ms_usbhost_err("--> timeout or NAK\n");
511*53ee8cc1Swenshuai.xi             return XFER_ERROR;
512*53ee8cc1Swenshuai.xi #ifdef ENABLE_DISCONNECT_FAST_RESPONSE
513*53ee8cc1Swenshuai.xi         case -ENODEV:
514*53ee8cc1Swenshuai.xi             ms_usbhost_err("<urb_result> no dev\n");
515*53ee8cc1Swenshuai.xi             return XFER_NO_DEV;
516*53ee8cc1Swenshuai.xi #endif
517*53ee8cc1Swenshuai.xi         case -MS_ERR_OVERFLOW:
518*53ee8cc1Swenshuai.xi             ms_usbhost_msg("--> babble\n");
519*53ee8cc1Swenshuai.xi             return XFER_LONG;
520*53ee8cc1Swenshuai.xi         case -ECONNRESET:
521*53ee8cc1Swenshuai.xi             ms_usbhost_msg("--> transfer cancelled\n");
522*53ee8cc1Swenshuai.xi             return XFER_ERROR;
523*53ee8cc1Swenshuai.xi         case -MS_ERR_REMOTEIO:
524*53ee8cc1Swenshuai.xi             ms_usbhost_msg("--> short read transfer\n");
525*53ee8cc1Swenshuai.xi             return XFER_SHORT;
526*53ee8cc1Swenshuai.xi         case -EIO:
527*53ee8cc1Swenshuai.xi             ms_usbhost_msg("--> abort or disconnect in progress\n");
528*53ee8cc1Swenshuai.xi             return XFER_ERROR;
529*53ee8cc1Swenshuai.xi         default:
530*53ee8cc1Swenshuai.xi             ms_usbhost_err("--> unknown error (%d)\n", regval);
531*53ee8cc1Swenshuai.xi             return XFER_ERROR;
532*53ee8cc1Swenshuai.xi     }
533*53ee8cc1Swenshuai.xi }
534*53ee8cc1Swenshuai.xi 
ms_usb_bulk_transfer_buf(struct ms_usdata * ptr,U32 pipe,void * buf,U32 len,U32 * act_len)535*53ee8cc1Swenshuai.xi int ms_usb_bulk_transfer_buf(struct ms_usdata *ptr, U32 pipe, void *buf, U32 len, U32 *act_len)
536*53ee8cc1Swenshuai.xi {
537*53ee8cc1Swenshuai.xi     int regval,time_out=10000;
538*53ee8cc1Swenshuai.xi 
539*53ee8cc1Swenshuai.xi     ms_usbhost_debug("<ms_usb_bulk_transfer_buf>: transfer %u bytes, buf=%p\n", len, buf);
540*53ee8cc1Swenshuai.xi     ms_usb_stuff_bulk_urb(ptr->current_urb, ptr->pusb_dev, pipe, buf, len,
541*53ee8cc1Swenshuai.xi             ms_usb_blocking_completion, NULL);
542*53ee8cc1Swenshuai.xi     regval = ms_usb_msg_common(ptr, time_out);
543*53ee8cc1Swenshuai.xi     if (act_len)
544*53ee8cc1Swenshuai.xi         *act_len = ptr->current_urb->u32ActualLength;
545*53ee8cc1Swenshuai.xi 
546*53ee8cc1Swenshuai.xi     return ms_usb_interpret_uRequest_Block_result(ptr, pipe, len, regval,
547*53ee8cc1Swenshuai.xi             ptr->current_urb->u32ActualLength);
548*53ee8cc1Swenshuai.xi }
549*53ee8cc1Swenshuai.xi 
ms_usb_bulk_transfer(struct ms_usdata * ptr,U32 pipe,void * buf,U32 trans_left,int * residual)550*53ee8cc1Swenshuai.xi static int ms_usb_bulk_transfer(struct ms_usdata* ptr, U32 pipe,
551*53ee8cc1Swenshuai.xi         void *buf, U32 trans_left, int *residual)
552*53ee8cc1Swenshuai.xi {
553*53ee8cc1Swenshuai.xi     int regval = -EIO;
554*53ee8cc1Swenshuai.xi     U32 partial;
555*53ee8cc1Swenshuai.xi 
556*53ee8cc1Swenshuai.xi     regval = ms_usb_bulk_transfer_buf(ptr, pipe, buf, trans_left, &partial);
557*53ee8cc1Swenshuai.xi     trans_left -= partial;
558*53ee8cc1Swenshuai.xi 
559*53ee8cc1Swenshuai.xi     if (residual)
560*53ee8cc1Swenshuai.xi         *residual = trans_left;
561*53ee8cc1Swenshuai.xi     return regval;
562*53ee8cc1Swenshuai.xi }
563*53ee8cc1Swenshuai.xi 
ms_us_port_reset(struct ms_usdata * pUsdata)564*53ee8cc1Swenshuai.xi static int ms_us_port_reset(struct ms_usdata *pUsdata)
565*53ee8cc1Swenshuai.xi {
566*53ee8cc1Swenshuai.xi 	int rval = 1;
567*53ee8cc1Swenshuai.xi 
568*53ee8cc1Swenshuai.xi 	if (pUsdata->pusb_dev->eState == USB_STATE_NOTATTACHED)
569*53ee8cc1Swenshuai.xi 		rval = -ENODEV;
570*53ee8cc1Swenshuai.xi 	if (pUsdata->pusb_dev->eState == USB_STATE_SUSPENDED)
571*53ee8cc1Swenshuai.xi 		rval = -EHOSTUNREACH;
572*53ee8cc1Swenshuai.xi 
573*53ee8cc1Swenshuai.xi 	if (rval < 0)
574*53ee8cc1Swenshuai.xi 	{
575*53ee8cc1Swenshuai.xi 		ms_usbhost_err("unable to lock device for reset: %d\n", rval);
576*53ee8cc1Swenshuai.xi 	}
577*53ee8cc1Swenshuai.xi 	else {
578*53ee8cc1Swenshuai.xi 		if (ms_test_bit(MS_IDX_DISCONNECTING, &pUsdata->flags)) {
579*53ee8cc1Swenshuai.xi 			rval = -EIO;
580*53ee8cc1Swenshuai.xi 			ms_usbhost_err("No reset during disconnect\n");
581*53ee8cc1Swenshuai.xi 		} else {
582*53ee8cc1Swenshuai.xi 			rval = ms_usb_reset_device(pUsdata->pusb_dev);
583*53ee8cc1Swenshuai.xi 			if (rval)
584*53ee8cc1Swenshuai.xi 			    ms_usbhost_err("usb_reset_device returns %d\n",	rval);
585*53ee8cc1Swenshuai.xi 		}
586*53ee8cc1Swenshuai.xi 	}
587*53ee8cc1Swenshuai.xi 	return rval;
588*53ee8cc1Swenshuai.xi }
589*53ee8cc1Swenshuai.xi 
ms_usb_invoke_transport(stCmd_scsi * scsi_request_block,struct ms_usdata * pUsdata)590*53ee8cc1Swenshuai.xi void ms_usb_invoke_transport(stCmd_scsi *scsi_request_block, struct ms_usdata *pUsdata)
591*53ee8cc1Swenshuai.xi {
592*53ee8cc1Swenshuai.xi     int auto_sense_activate,regval,temp_result;
593*53ee8cc1Swenshuai.xi 
594*53ee8cc1Swenshuai.xi     scsi_request_block->resid = 0;
595*53ee8cc1Swenshuai.xi     regval = pUsdata->transport(scsi_request_block, pUsdata);
596*53ee8cc1Swenshuai.xi 
597*53ee8cc1Swenshuai.xi     //if (pUsdata->usb_state == ABORTING_STATE) // get abort command from higer layer
598*53ee8cc1Swenshuai.xi     //{
599*53ee8cc1Swenshuai.xi     //    ms_usbhost_msg("--> command aborted\n");
600*53ee8cc1Swenshuai.xi     //    scsi_request_block->result = DID_ABORT << 16;
601*53ee8cc1Swenshuai.xi     //    goto Erros_Process;
602*53ee8cc1Swenshuai.xi     //}
603*53ee8cc1Swenshuai.xi 
604*53ee8cc1Swenshuai.xi #ifdef ENABLE_DISCONNECT_FAST_RESPONSE
605*53ee8cc1Swenshuai.xi     if (regval == TRANSPORT_NO_DEVICE) // break if no device
606*53ee8cc1Swenshuai.xi     {
607*53ee8cc1Swenshuai.xi         ms_usbhost_msg("[USB][BULK] device removed\n");
608*53ee8cc1Swenshuai.xi         scsi_request_block->result = DID_NO_CONNECT << 16;
609*53ee8cc1Swenshuai.xi         return;
610*53ee8cc1Swenshuai.xi     }
611*53ee8cc1Swenshuai.xi #endif
612*53ee8cc1Swenshuai.xi 
613*53ee8cc1Swenshuai.xi     if (regval == TRANSPORT_ERROR)
614*53ee8cc1Swenshuai.xi     {
615*53ee8cc1Swenshuai.xi         ms_usbhost_msg("--> transport error, resetting\n");
616*53ee8cc1Swenshuai.xi         scsi_request_block->result = DID_ERROR << 16;
617*53ee8cc1Swenshuai.xi         goto Erros_Process;
618*53ee8cc1Swenshuai.xi     }
619*53ee8cc1Swenshuai.xi 
620*53ee8cc1Swenshuai.xi     if (regval == TRANSPORT_NO_SENSE)
621*53ee8cc1Swenshuai.xi     {
622*53ee8cc1Swenshuai.xi         ms_usbhost_err("--> transport no sense\n");
623*53ee8cc1Swenshuai.xi         scsi_request_block->result = MS_STAT_CHECK_CONDITION;
624*53ee8cc1Swenshuai.xi         return;
625*53ee8cc1Swenshuai.xi     }
626*53ee8cc1Swenshuai.xi 
627*53ee8cc1Swenshuai.xi     auto_sense_activate = 0;
628*53ee8cc1Swenshuai.xi     if (pUsdata->protocol == MS_CB_PR)
629*53ee8cc1Swenshuai.xi     {
630*53ee8cc1Swenshuai.xi         ms_usbhost_msg("--> CB transport device requiring auto-sense\n");
631*53ee8cc1Swenshuai.xi         auto_sense_activate = 1;
632*53ee8cc1Swenshuai.xi         if (pUsdata->subclass == MS_UFI_SC &&
633*53ee8cc1Swenshuai.xi             ((scsi_request_block->cmnd[0] == REQUEST_SENSE) || (scsi_request_block->cmnd[0] == INQUIRY)))
634*53ee8cc1Swenshuai.xi         {
635*53ee8cc1Swenshuai.xi             ms_usbhost_msg("** no auto-sense for a special command\n");
636*53ee8cc1Swenshuai.xi             auto_sense_activate = 0;
637*53ee8cc1Swenshuai.xi         }
638*53ee8cc1Swenshuai.xi     }
639*53ee8cc1Swenshuai.xi 
640*53ee8cc1Swenshuai.xi     if (regval == TRANSPORT_FAILED)
641*53ee8cc1Swenshuai.xi     {
642*53ee8cc1Swenshuai.xi         ms_usbhost_debug("--> transport command fail\n");
643*53ee8cc1Swenshuai.xi         auto_sense_activate = 1;
644*53ee8cc1Swenshuai.xi     }
645*53ee8cc1Swenshuai.xi 
646*53ee8cc1Swenshuai.xi     if ((scsi_request_block->resid > 0) && !((scsi_request_block->cmnd[0] == REQUEST_SENSE) ||
647*53ee8cc1Swenshuai.xi         (scsi_request_block->cmnd[0] == INQUIRY) || (scsi_request_block->cmnd[0] == MODE_SENSE)))
648*53ee8cc1Swenshuai.xi     {
649*53ee8cc1Swenshuai.xi         ms_usbhost_debug("--> unexpectedly short transfer\n");
650*53ee8cc1Swenshuai.xi         // to see kernel 2.6.28.9, not need to activate auto sense
651*53ee8cc1Swenshuai.xi         //auto_sense_activate = 1;
652*53ee8cc1Swenshuai.xi     }
653*53ee8cc1Swenshuai.xi 
654*53ee8cc1Swenshuai.xi     if (auto_sense_activate)
655*53ee8cc1Swenshuai.xi     {
656*53ee8cc1Swenshuai.xi         struct scMsc_cmd srb_need_auto_sense;
657*53ee8cc1Swenshuai.xi 
658*53ee8cc1Swenshuai.xi         //backup scsi request block and issue request sense
659*53ee8cc1Swenshuai.xi         memcpy(&srb_need_auto_sense, &pUsdata->srb, sizeof(srb_need_auto_sense));
660*53ee8cc1Swenshuai.xi         scsi_request_block->cmnd[0] = REQUEST_SENSE;
661*53ee8cc1Swenshuai.xi         scsi_request_block->cmnd[1] = srb_need_auto_sense.cmnd[1] & 0xE0;
662*53ee8cc1Swenshuai.xi         scsi_request_block->cmnd[4] = 18;
663*53ee8cc1Swenshuai.xi         scsi_request_block->cmd_len = 12;
664*53ee8cc1Swenshuai.xi         scsi_request_block->sc_data_direction = SCSI_DATA_READ;
665*53ee8cc1Swenshuai.xi         scsi_request_block->req_buf = scsi_request_block->sense_buffer;
666*53ee8cc1Swenshuai.xi         scsi_request_block->req_buf_len = 18;
667*53ee8cc1Swenshuai.xi         scsi_request_block->serial_number ^= 0x80000000;
668*53ee8cc1Swenshuai.xi 
669*53ee8cc1Swenshuai.xi         temp_result = pUsdata->transport(&pUsdata->srb, pUsdata);
670*53ee8cc1Swenshuai.xi 
671*53ee8cc1Swenshuai.xi         // restore previous scsi request block
672*53ee8cc1Swenshuai.xi         memcpy(&pUsdata->srb, &srb_need_auto_sense, sizeof(srb_need_auto_sense));
673*53ee8cc1Swenshuai.xi 
674*53ee8cc1Swenshuai.xi         //if (pUsdata->usb_state == ABORTING_STATE)
675*53ee8cc1Swenshuai.xi         //{
676*53ee8cc1Swenshuai.xi         //    ms_usbhost_msg("--> auto-sense aborted\n");
677*53ee8cc1Swenshuai.xi         //    scsi_request_block->result = DID_ABORT << 16;
678*53ee8cc1Swenshuai.xi         //    goto Erros_Process;
679*53ee8cc1Swenshuai.xi         //}
680*53ee8cc1Swenshuai.xi #ifdef ENABLE_DISCONNECT_FAST_RESPONSE
681*53ee8cc1Swenshuai.xi         if (regval == TRANSPORT_NO_DEVICE) // break if no device
682*53ee8cc1Swenshuai.xi         {
683*53ee8cc1Swenshuai.xi             ms_usbhost_msg("[USB][BULK] auto-sense device removed\n");
684*53ee8cc1Swenshuai.xi             scsi_request_block->result = DID_NO_CONNECT << 16;
685*53ee8cc1Swenshuai.xi             return;
686*53ee8cc1Swenshuai.xi         }
687*53ee8cc1Swenshuai.xi #endif
688*53ee8cc1Swenshuai.xi         if (temp_result != TRANSPORT_GOOD)
689*53ee8cc1Swenshuai.xi         {
690*53ee8cc1Swenshuai.xi             ms_usbhost_msg("--> auto-sense fail\n");
691*53ee8cc1Swenshuai.xi             scsi_request_block->result = DID_ERROR << 16;
692*53ee8cc1Swenshuai.xi             if (!(pUsdata->flags & MS_SCM_MULT_TARG))
693*53ee8cc1Swenshuai.xi             {
694*53ee8cc1Swenshuai.xi                 goto Erros_Process;
695*53ee8cc1Swenshuai.xi             }
696*53ee8cc1Swenshuai.xi             return;
697*53ee8cc1Swenshuai.xi         }
698*53ee8cc1Swenshuai.xi         ms_usbhost_debug("--> Result from auto-sense is %d\n", temp_result);
699*53ee8cc1Swenshuai.xi         ms_usbhost_debug("--> code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
700*53ee8cc1Swenshuai.xi                 scsi_request_block->sense_buffer[0], scsi_request_block->sense_buffer[2] & 0xf,
701*53ee8cc1Swenshuai.xi                 scsi_request_block->sense_buffer[12], scsi_request_block->sense_buffer[13]);
702*53ee8cc1Swenshuai.xi 
703*53ee8cc1Swenshuai.xi         scsi_request_block->result = MS_STAT_CHECK_CONDITION;
704*53ee8cc1Swenshuai.xi         if ((scsi_request_block->sense_buffer[2] & 0xf) == 0x0)
705*53ee8cc1Swenshuai.xi             scsi_request_block->result = MS_STAT_GOOD;
706*53ee8cc1Swenshuai.xi     }
707*53ee8cc1Swenshuai.xi     else
708*53ee8cc1Swenshuai.xi         scsi_request_block->result = MS_STAT_GOOD;
709*53ee8cc1Swenshuai.xi 
710*53ee8cc1Swenshuai.xi     if (regval == TRANSPORT_FAILED)
711*53ee8cc1Swenshuai.xi         scsi_request_block->result = MS_STAT_CHECK_CONDITION;
712*53ee8cc1Swenshuai.xi     if ((pUsdata->protocol == MS_CB_PR) && (regval == TRANSPORT_GOOD) && ((scsi_request_block->sense_buffer[2] & 0xf) == 0x0))
713*53ee8cc1Swenshuai.xi         scsi_request_block->sense_buffer[0] = 0x0;
714*53ee8cc1Swenshuai.xi     return;
715*53ee8cc1Swenshuai.xi 
716*53ee8cc1Swenshuai.xi Erros_Process:
717*53ee8cc1Swenshuai.xi 
718*53ee8cc1Swenshuai.xi     ms_set_bit(MS_IDX_RESETTING, &pUsdata->flags, U32);
719*53ee8cc1Swenshuai.xi     ms_clear_bit(MS_IDX_ABORTING, &pUsdata->flags, U32);
720*53ee8cc1Swenshuai.xi     osapi_mutex_unlock(pUsdata->dev_mutex);
721*53ee8cc1Swenshuai.xi     regval = ms_us_port_reset(pUsdata);
722*53ee8cc1Swenshuai.xi     osapi_mutex_lock(pUsdata->dev_mutex);
723*53ee8cc1Swenshuai.xi #ifdef ENABLE_DISCONNECT_FAST_RESPONSE
724*53ee8cc1Swenshuai.xi     if (regval == -ENODEV)
725*53ee8cc1Swenshuai.xi         scsi_request_block->result = DID_NO_CONNECT << 16;
726*53ee8cc1Swenshuai.xi     else
727*53ee8cc1Swenshuai.xi #endif
728*53ee8cc1Swenshuai.xi     if (regval < 0)
729*53ee8cc1Swenshuai.xi         pUsdata->transport_reset(pUsdata);
730*53ee8cc1Swenshuai.xi     ms_clear_bit(MS_IDX_RESETTING, &pUsdata->flags, U32);
731*53ee8cc1Swenshuai.xi }
732*53ee8cc1Swenshuai.xi 
ms_usb_stor_data_transfer(stCmd_scsi * request_block,struct ms_usdata * ptr,U32 trans_len)733*53ee8cc1Swenshuai.xi static int ms_usb_stor_data_transfer(stCmd_scsi *request_block, struct ms_usdata *ptr, U32 trans_len)
734*53ee8cc1Swenshuai.xi {
735*53ee8cc1Swenshuai.xi     U32 pipe;
736*53ee8cc1Swenshuai.xi 
737*53ee8cc1Swenshuai.xi     if(request_block->sc_data_direction == SCSI_DATA_READ)
738*53ee8cc1Swenshuai.xi         pipe = ptr->bulk_recv_pipe;
739*53ee8cc1Swenshuai.xi     else
740*53ee8cc1Swenshuai.xi         pipe = ptr->bulk_send_pipe;
741*53ee8cc1Swenshuai.xi 
742*53ee8cc1Swenshuai.xi     return ms_usb_bulk_transfer(ptr, pipe, request_block->req_buf, trans_len,
743*53ee8cc1Swenshuai.xi                 &request_block->resid);
744*53ee8cc1Swenshuai.xi }
745*53ee8cc1Swenshuai.xi 
ms_usb_CB_transport(stCmd_scsi * request_block,struct ms_usdata * ptr)746*53ee8cc1Swenshuai.xi int ms_usb_CB_transport(stCmd_scsi *request_block, struct ms_usdata *ptr)
747*53ee8cc1Swenshuai.xi {
748*53ee8cc1Swenshuai.xi     U32 trans_len = request_block->req_buf_len;
749*53ee8cc1Swenshuai.xi     int regval,result,timeout=10000;
750*53ee8cc1Swenshuai.xi 
751*53ee8cc1Swenshuai.xi     ptr->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
752*53ee8cc1Swenshuai.xi     ptr->cr->bRequest = MS_CBI_ADSC;
753*53ee8cc1Swenshuai.xi     ptr->cr->wValue = 0;
754*53ee8cc1Swenshuai.xi     ptr->cr->wIndex = ptr->ifnum;
755*53ee8cc1Swenshuai.xi     ptr->cr->wLength = request_block->cmd_len;
756*53ee8cc1Swenshuai.xi 
757*53ee8cc1Swenshuai.xi     ms_usb_stuff_control_urb(ptr->current_urb, ptr->pusb_dev, ptr->ctrl_send_pipe,
758*53ee8cc1Swenshuai.xi             (unsigned char*) ptr->cr, request_block->cmnd, request_block->cmd_len,
759*53ee8cc1Swenshuai.xi             ms_usb_blocking_completion, NULL);
760*53ee8cc1Swenshuai.xi     result = ms_usb_msg_common(ptr, timeout);
761*53ee8cc1Swenshuai.xi 
762*53ee8cc1Swenshuai.xi     regval = ms_usb_interpret_uRequest_Block_result(ptr, ptr->ctrl_send_pipe,
763*53ee8cc1Swenshuai.xi                 request_block->cmd_len, result, ptr->current_urb->u32ActualLength);
764*53ee8cc1Swenshuai.xi 
765*53ee8cc1Swenshuai.xi     if (regval == XFER_STALLED)
766*53ee8cc1Swenshuai.xi     {
767*53ee8cc1Swenshuai.xi         ms_usbhost_msg("CB xfer stalled\n");
768*53ee8cc1Swenshuai.xi         return TRANSPORT_FAILED;
769*53ee8cc1Swenshuai.xi     }
770*53ee8cc1Swenshuai.xi     if (regval != XFER_GOOD)
771*53ee8cc1Swenshuai.xi     {
772*53ee8cc1Swenshuai.xi         ms_usbhost_msg("CB xfer error\n");
773*53ee8cc1Swenshuai.xi         return TRANSPORT_ERROR;
774*53ee8cc1Swenshuai.xi     }
775*53ee8cc1Swenshuai.xi     if (trans_len)
776*53ee8cc1Swenshuai.xi     {
777*53ee8cc1Swenshuai.xi         regval = ms_usb_stor_data_transfer(request_block,ptr,trans_len);
778*53ee8cc1Swenshuai.xi         ms_usbhost_msg("CB data stage regval is 0x%x\n", regval);
779*53ee8cc1Swenshuai.xi         if (regval > XFER_STALLED)
780*53ee8cc1Swenshuai.xi             return TRANSPORT_ERROR;
781*53ee8cc1Swenshuai.xi     }
782*53ee8cc1Swenshuai.xi 
783*53ee8cc1Swenshuai.xi     return TRANSPORT_GOOD;
784*53ee8cc1Swenshuai.xi }
785*53ee8cc1Swenshuai.xi 
ms_usb_tranCB(struct stBulk_cb * bulk_cb,stCmd_scsi * request_block,struct ms_usdata * ptr,U32 trans_len)786*53ee8cc1Swenshuai.xi static int ms_usb_tranCB(struct stBulk_cb *bulk_cb, stCmd_scsi *request_block, struct ms_usdata *ptr, U32 trans_len)
787*53ee8cc1Swenshuai.xi {
788*53ee8cc1Swenshuai.xi     bulk_cb->Inscription = BULK_CB_SIGN;
789*53ee8cc1Swenshuai.xi     bulk_cb->DataLength = trans_len;
790*53ee8cc1Swenshuai.xi     if(request_block->sc_data_direction == SCSI_DATA_READ)
791*53ee8cc1Swenshuai.xi         bulk_cb->Flag = 1 << 7;
792*53ee8cc1Swenshuai.xi     else
793*53ee8cc1Swenshuai.xi         bulk_cb->Flag = 0;
794*53ee8cc1Swenshuai.xi     bulk_cb->Label = request_block->serial_number;
795*53ee8cc1Swenshuai.xi     bulk_cb->Lun = request_block->lun;
796*53ee8cc1Swenshuai.xi     bulk_cb->Len = request_block->cmd_len;
797*53ee8cc1Swenshuai.xi 
798*53ee8cc1Swenshuai.xi     memset(bulk_cb->CDB, 0, sizeof(bulk_cb->CDB));
799*53ee8cc1Swenshuai.xi     memcpy(bulk_cb->CDB, request_block->cmnd, bulk_cb->Len);
800*53ee8cc1Swenshuai.xi 
801*53ee8cc1Swenshuai.xi     return ms_usb_bulk_transfer_buf(ptr, ptr->bulk_send_pipe, bulk_cb, BULK_CB_WRAP_LEN, NULL);
802*53ee8cc1Swenshuai.xi }
803*53ee8cc1Swenshuai.xi 
ms_usb_tranCS(struct stBulk_cs * bulk_cs,struct ms_usdata * ptr)804*53ee8cc1Swenshuai.xi static int ms_usb_tranCS(struct stBulk_cs *bulk_cs, struct ms_usdata *ptr)
805*53ee8cc1Swenshuai.xi {
806*53ee8cc1Swenshuai.xi     int regval;
807*53ee8cc1Swenshuai.xi     U32 len_csw;
808*53ee8cc1Swenshuai.xi 
809*53ee8cc1Swenshuai.xi     ms_usbhost_debug("Trying to get CSW...\n");
810*53ee8cc1Swenshuai.xi     regval = ms_usb_bulk_transfer_buf(ptr, ptr->bulk_recv_pipe, bulk_cs, BULK_CS_WRAP_LEN, &len_csw);
811*53ee8cc1Swenshuai.xi     if (regval == XFER_SHORT && len_csw == 0) // patch from Linux 3.1.10
812*53ee8cc1Swenshuai.xi     {
813*53ee8cc1Swenshuai.xi         ms_usbhost_warn("Since 0 packet received, retrying to get CSW again...\n");
814*53ee8cc1Swenshuai.xi         regval = ms_usb_bulk_transfer_buf(ptr, ptr->bulk_recv_pipe, bulk_cs, BULK_CS_WRAP_LEN, NULL);
815*53ee8cc1Swenshuai.xi     }
816*53ee8cc1Swenshuai.xi     if (regval == XFER_STALLED)
817*53ee8cc1Swenshuai.xi     {
818*53ee8cc1Swenshuai.xi         ms_usbhost_warn("Trying to get CSW again...\n");
819*53ee8cc1Swenshuai.xi         regval = ms_usb_bulk_transfer_buf(ptr, ptr->bulk_recv_pipe, bulk_cs, BULK_CS_WRAP_LEN, NULL);
820*53ee8cc1Swenshuai.xi     }
821*53ee8cc1Swenshuai.xi     return regval;
822*53ee8cc1Swenshuai.xi }
823*53ee8cc1Swenshuai.xi 
ms_usb_bulk_transport(stCmd_scsi * request_block,struct ms_usdata * ptr)824*53ee8cc1Swenshuai.xi int ms_usb_bulk_transport(stCmd_scsi *request_block, struct ms_usdata *ptr)
825*53ee8cc1Swenshuai.xi {
826*53ee8cc1Swenshuai.xi     unsigned char *tmp_iobuf=0;
827*53ee8cc1Swenshuai.xi     struct stBulk_cb *bulk_cb = (struct stBulk_cb *)(ptr->iobuf - tmp_iobuf);
828*53ee8cc1Swenshuai.xi     struct stBulk_cs *bulk_cs = (struct stBulk_cs *)(ptr->iobuf - tmp_iobuf);
829*53ee8cc1Swenshuai.xi     U32 trans_len = request_block->req_buf_len;
830*53ee8cc1Swenshuai.xi     int regval,fake_sense = 0;
831*53ee8cc1Swenshuai.xi 
832*53ee8cc1Swenshuai.xi     regval = ms_usb_tranCB(bulk_cb,request_block,ptr,trans_len);
833*53ee8cc1Swenshuai.xi     if (regval != XFER_GOOD)
834*53ee8cc1Swenshuai.xi #ifdef ENABLE_DISCONNECT_FAST_RESPONSE
835*53ee8cc1Swenshuai.xi         return (regval == XFER_NO_DEV) ? TRANSPORT_NO_DEVICE : TRANSPORT_ERROR;
836*53ee8cc1Swenshuai.xi #else
837*53ee8cc1Swenshuai.xi         return TRANSPORT_ERROR;
838*53ee8cc1Swenshuai.xi #endif
839*53ee8cc1Swenshuai.xi 
840*53ee8cc1Swenshuai.xi     if (trans_len)
841*53ee8cc1Swenshuai.xi     {
842*53ee8cc1Swenshuai.xi         regval = ms_usb_stor_data_transfer(request_block,ptr,trans_len);
843*53ee8cc1Swenshuai.xi #ifdef ENABLE_DISCONNECT_FAST_RESPONSE
844*53ee8cc1Swenshuai.xi         if (regval == XFER_NO_DEV)
845*53ee8cc1Swenshuai.xi             return TRANSPORT_NO_DEVICE;
846*53ee8cc1Swenshuai.xi #endif
847*53ee8cc1Swenshuai.xi         if (regval == XFER_ERROR)
848*53ee8cc1Swenshuai.xi             return TRANSPORT_ERROR;
849*53ee8cc1Swenshuai.xi         if (regval == XFER_LONG)
850*53ee8cc1Swenshuai.xi             fake_sense = 1;
851*53ee8cc1Swenshuai.xi     }
852*53ee8cc1Swenshuai.xi 
853*53ee8cc1Swenshuai.xi     regval = ms_usb_tranCS(bulk_cs,ptr);
854*53ee8cc1Swenshuai.xi 
855*53ee8cc1Swenshuai.xi     /* check CSW stage result */
856*53ee8cc1Swenshuai.xi #ifdef ENABLE_DISCONNECT_FAST_RESPONSE
857*53ee8cc1Swenshuai.xi     if (regval == XFER_NO_DEV)
858*53ee8cc1Swenshuai.xi     {
859*53ee8cc1Swenshuai.xi         ms_usbhost_msg("device not found..\n");
860*53ee8cc1Swenshuai.xi         return TRANSPORT_NO_DEVICE;
861*53ee8cc1Swenshuai.xi     }
862*53ee8cc1Swenshuai.xi #endif
863*53ee8cc1Swenshuai.xi     if (regval != XFER_GOOD)
864*53ee8cc1Swenshuai.xi     {
865*53ee8cc1Swenshuai.xi         ms_usbhost_msg("transport error..\n");
866*53ee8cc1Swenshuai.xi         return TRANSPORT_ERROR;
867*53ee8cc1Swenshuai.xi     }
868*53ee8cc1Swenshuai.xi 
869*53ee8cc1Swenshuai.xi     ms_usbhost_debug("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
870*53ee8cc1Swenshuai.xi             bulk_cs->Inscription, bulk_cs->Label, bulk_cs->Remains, bulk_cs->Class);
871*53ee8cc1Swenshuai.xi     if ((bulk_cs->Inscription != BULK_CS_SIGN && bulk_cs->Inscription != BULK_CS_OLYMPUS_SIGN) ||
872*53ee8cc1Swenshuai.xi             bulk_cs->Label != request_block->serial_number || bulk_cs->Class > BULK_STAT_PHASE)
873*53ee8cc1Swenshuai.xi     {
874*53ee8cc1Swenshuai.xi         ms_usbhost_msg("Bulk logical error\n");
875*53ee8cc1Swenshuai.xi         return TRANSPORT_ERROR;
876*53ee8cc1Swenshuai.xi     }
877*53ee8cc1Swenshuai.xi     if(bulk_cs->Class == BULK_STAT_OK)
878*53ee8cc1Swenshuai.xi     {
879*53ee8cc1Swenshuai.xi         if (fake_sense)
880*53ee8cc1Swenshuai.xi         {
881*53ee8cc1Swenshuai.xi             memcpy(request_block->sense_buffer, invalid_CDB, sizeof(invalid_CDB));
882*53ee8cc1Swenshuai.xi             return TRANSPORT_NO_SENSE;
883*53ee8cc1Swenshuai.xi         }
884*53ee8cc1Swenshuai.xi         return TRANSPORT_GOOD;
885*53ee8cc1Swenshuai.xi     }
886*53ee8cc1Swenshuai.xi     else if(bulk_cs->Class == BULK_STAT_FAIL)
887*53ee8cc1Swenshuai.xi     {
888*53ee8cc1Swenshuai.xi         if (request_block->cmnd[0])
889*53ee8cc1Swenshuai.xi             ms_usbhost_err("CSW Bulk transfer fail, command %x\n", request_block->cmnd[0]);
890*53ee8cc1Swenshuai.xi         return TRANSPORT_FAILED;
891*53ee8cc1Swenshuai.xi     }
892*53ee8cc1Swenshuai.xi     else if(bulk_cs->Class == BULK_STAT_PHASE)
893*53ee8cc1Swenshuai.xi     {
894*53ee8cc1Swenshuai.xi         ms_usbhost_msg("Bulk transfer phase\n");
895*53ee8cc1Swenshuai.xi         return TRANSPORT_ERROR;
896*53ee8cc1Swenshuai.xi     }
897*53ee8cc1Swenshuai.xi     ms_usbhost_msg("Bulk transfer error\n");
898*53ee8cc1Swenshuai.xi     return TRANSPORT_ERROR;
899*53ee8cc1Swenshuai.xi }
900*53ee8cc1Swenshuai.xi 
ms_usb_reset_common(struct ms_usdata * ptr,unsigned char req,unsigned char rt,U16 val,U16 idx,void * data,U16 len)901*53ee8cc1Swenshuai.xi static int ms_usb_reset_common(struct ms_usdata *ptr, unsigned char req, unsigned char rt,
902*53ee8cc1Swenshuai.xi         U16 val, U16 idx, void *data, U16 len)
903*53ee8cc1Swenshuai.xi {
904*53ee8cc1Swenshuai.xi     int regval,regval1,regval2;
905*53ee8cc1Swenshuai.xi 
906*53ee8cc1Swenshuai.xi     if (ms_test_bit(MS_IDX_DISCONNECTING, &ptr->flags)) // patch from Linux 2.6.28
907*53ee8cc1Swenshuai.xi     {
908*53ee8cc1Swenshuai.xi         ms_usbhost_err("US disconnected no reset\n");
909*53ee8cc1Swenshuai.xi         return FAILED;
910*53ee8cc1Swenshuai.xi     }
911*53ee8cc1Swenshuai.xi 
912*53ee8cc1Swenshuai.xi     regval = ms_usb_control_msg(ptr, ptr->ctrl_send_pipe, req, rt, val, idx, data, len, HZ*20);
913*53ee8cc1Swenshuai.xi     if (regval < 0)
914*53ee8cc1Swenshuai.xi     {
915*53ee8cc1Swenshuai.xi         ms_usbhost_msg("ms_usb_reset_common failed: %d\n", regval);
916*53ee8cc1Swenshuai.xi         return FAILED;
917*53ee8cc1Swenshuai.xi     }
918*53ee8cc1Swenshuai.xi 
919*53ee8cc1Swenshuai.xi     //osapi_up(&ptr->dev_semaphore); // patch from Linux 2.6.28
920*53ee8cc1Swenshuai.xi     set_current_state(TASK_UNINTERRUPTIBLE);
921*53ee8cc1Swenshuai.xi     osapi_schedule_timeout(HZ*6);
922*53ee8cc1Swenshuai.xi     set_current_state(TASK_RUNNING);
923*53ee8cc1Swenshuai.xi     //osapi_down(&ptr->dev_semaphore);
924*53ee8cc1Swenshuai.xi 
925*53ee8cc1Swenshuai.xi     if (ms_test_bit(MS_IDX_DISCONNECTING, &ptr->flags))
926*53ee8cc1Swenshuai.xi     {
927*53ee8cc1Swenshuai.xi         ms_usbhost_err("US DISCONNECTING\n");
928*53ee8cc1Swenshuai.xi         return FAILED;
929*53ee8cc1Swenshuai.xi     }
930*53ee8cc1Swenshuai.xi 
931*53ee8cc1Swenshuai.xi     regval1 = ms_usb_msc_clear_halt(ptr, ptr->bulk_recv_pipe);
932*53ee8cc1Swenshuai.xi     regval2 = ms_usb_msc_clear_halt(ptr, ptr->bulk_send_pipe);
933*53ee8cc1Swenshuai.xi     if (regval1 < 0 || regval2 < 0)
934*53ee8cc1Swenshuai.xi     {
935*53ee8cc1Swenshuai.xi         ms_usbhost_msg("clear reset failed\n");
936*53ee8cc1Swenshuai.xi         return FAILED;
937*53ee8cc1Swenshuai.xi     }
938*53ee8cc1Swenshuai.xi     ms_usbhost_msg("reset command done\n");
939*53ee8cc1Swenshuai.xi     return SUCCESS;
940*53ee8cc1Swenshuai.xi }
941*53ee8cc1Swenshuai.xi 
ms_usb_CB_reset(struct ms_usdata * ptr)942*53ee8cc1Swenshuai.xi int ms_usb_CB_reset(struct ms_usdata *ptr)
943*53ee8cc1Swenshuai.xi {
944*53ee8cc1Swenshuai.xi     int CMD_SIZE=12;
945*53ee8cc1Swenshuai.xi 
946*53ee8cc1Swenshuai.xi     ms_usbhost_msg("Call..<ms_usb_CB_reset>\n");
947*53ee8cc1Swenshuai.xi     memset(ptr->iobuf, 0xFF, CMD_SIZE);
948*53ee8cc1Swenshuai.xi 
949*53ee8cc1Swenshuai.xi     ptr->iobuf[0] = 0x1d;//SEND_DIAGNOSTIC;
950*53ee8cc1Swenshuai.xi     ptr->iobuf[1] = 4;
951*53ee8cc1Swenshuai.xi 
952*53ee8cc1Swenshuai.xi     return ms_usb_reset_common(ptr, MS_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
953*53ee8cc1Swenshuai.xi                 0, ptr->ifnum, ptr->iobuf, CMD_SIZE);
954*53ee8cc1Swenshuai.xi }
955*53ee8cc1Swenshuai.xi 
ms_usb_bulk_reset(struct ms_usdata * ptr)956*53ee8cc1Swenshuai.xi int ms_usb_bulk_reset(struct ms_usdata *ptr)
957*53ee8cc1Swenshuai.xi {
958*53ee8cc1Swenshuai.xi     ms_usbhost_msg("Call..<ms_usb_bulk_reset>\n");
959*53ee8cc1Swenshuai.xi 
960*53ee8cc1Swenshuai.xi     return ms_usb_reset_common(ptr, BULK_RESET_REQUEST, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
961*53ee8cc1Swenshuai.xi                 0, ptr->ifnum, NULL, 0);
962*53ee8cc1Swenshuai.xi }
963