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