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