xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/newhost/drvMassStor.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 
79*53ee8cc1Swenshuai.xi //=============================================================================
80*53ee8cc1Swenshuai.xi //================include file======================//
81*53ee8cc1Swenshuai.xi //#include <MsCommon.h> // NUSED
82*53ee8cc1Swenshuai.xi #include "include/drvConfig.h"
83*53ee8cc1Swenshuai.xi //#include "include/drvErrno.h" // NUSED
84*53ee8cc1Swenshuai.xi //#include "include/drvUSBHost.h" // NUSED
85*53ee8cc1Swenshuai.xi #include "drvBulktran.h"
86*53ee8cc1Swenshuai.xi #include "include/drvBitops.h"
87*53ee8cc1Swenshuai.xi //#include "include/drvCPE_AMBA.h" // NUSED
88*53ee8cc1Swenshuai.xi //#include "drvUsbHostConfig.h" // NUSED
89*53ee8cc1Swenshuai.xi #include "drvUsbd.h"
90*53ee8cc1Swenshuai.xi //==================================================//
91*53ee8cc1Swenshuai.xi 
92*53ee8cc1Swenshuai.xi //==================Definition======================//
93*53ee8cc1Swenshuai.xi static int ms_usb_msc_probe(struct usb_interface *iface, const struct usb_device_id *id);
94*53ee8cc1Swenshuai.xi static void ms_usb_msc_disconnect(struct usb_interface *iface);
95*53ee8cc1Swenshuai.xi extern void RemoveUSBDiskPort(U8 uPort, U8 uLunNum);
96*53ee8cc1Swenshuai.xi 
97*53ee8cc1Swenshuai.xi #define GET_INTERFACE_INFO(cl,sc,pr) \
98*53ee8cc1Swenshuai.xi         USB_DEVICE_ID_MATCH_INT_INFO,0,0,0,0,0,0,0, (cl), (sc), (pr),0
99*53ee8cc1Swenshuai.xi //==================================================//
100*53ee8cc1Swenshuai.xi 
101*53ee8cc1Swenshuai.xi static struct usb_device_id MSC_usb_ids [] =
102*53ee8cc1Swenshuai.xi {
103*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_RBC_SC, MS_CB_PR) },
104*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_ATAPI_SC,MS_CB_PR) },
105*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_QIC_SC, MS_CB_PR) },
106*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_UFI_SC, MS_CB_PR) },
107*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SFF_SC,MS_CB_PR) },
108*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SCSI_SC,MS_CB_PR) },
109*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_RBC_SC, MS_CBI_PR) },
110*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_ATAPI_SC, MS_CBI_PR) },
111*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_QIC_SC, MS_CBI_PR) },
112*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_UFI_SC, MS_CBI_PR) },
113*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SFF_SC, MS_CBI_PR) },
114*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SCSI_SC, MS_CBI_PR) },
115*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_RBC_SC, MS_BULK_PR) },
116*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_ATAPI_SC, MS_BULK_PR) },
117*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_QIC_SC, MS_BULK_PR) },
118*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_UFI_SC, MS_BULK_PR) },
119*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SFF_SC, MS_BULK_PR) },
120*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SCSI_SC, MS_BULK_PR) },
121*53ee8cc1Swenshuai.xi     {GET_INTERFACE_INFO (USB_CLASS_STORAGE, 0xFF, MS_CB_PR) },
122*53ee8cc1Swenshuai.xi     {0,0,0,0,0,0,0,0,0,0,0,0}
123*53ee8cc1Swenshuai.xi };
124*53ee8cc1Swenshuai.xi 
125*53ee8cc1Swenshuai.xi static struct stUnusual_dev MS_USB_unusual_dev_list[] =
126*53ee8cc1Swenshuai.xi {
127*53ee8cc1Swenshuai.xi     { 0,0, MS_RBC_SC, MS_CB_PR,0,0 },
128*53ee8cc1Swenshuai.xi     { 0,0, MS_ATAPI_SC, MS_CB_PR,0,0 },
129*53ee8cc1Swenshuai.xi     { 0,0, MS_QIC_SC, MS_CB_PR,0,0 },
130*53ee8cc1Swenshuai.xi     { 0,0, MS_UFI_SC, MS_CB_PR,0,0 },
131*53ee8cc1Swenshuai.xi     { 0,0, MS_SFF_SC, MS_CB_PR,0,0 },
132*53ee8cc1Swenshuai.xi     { 0,0, MS_SCSI_SC, MS_CB_PR,0,0 },
133*53ee8cc1Swenshuai.xi     { 0,0, MS_RBC_SC, MS_CBI_PR,0,0 },
134*53ee8cc1Swenshuai.xi     { 0,0, MS_ATAPI_SC, MS_CBI_PR,0,0 },
135*53ee8cc1Swenshuai.xi     { 0,0, MS_QIC_SC, MS_CBI_PR,0,0 },
136*53ee8cc1Swenshuai.xi     { 0,0, MS_UFI_SC, MS_CBI_PR,0,0 },
137*53ee8cc1Swenshuai.xi     { 0,0, MS_SFF_SC, MS_CBI_PR,0,0 },
138*53ee8cc1Swenshuai.xi     { 0,0, MS_SCSI_SC, MS_CBI_PR,0,0 },
139*53ee8cc1Swenshuai.xi     { 0,0, MS_RBC_SC, MS_BULK_PR,0,0 },
140*53ee8cc1Swenshuai.xi     { 0,0, MS_ATAPI_SC, MS_BULK_PR,0,0 },
141*53ee8cc1Swenshuai.xi     { 0,0, MS_QIC_SC, MS_BULK_PR,0,0 },
142*53ee8cc1Swenshuai.xi     { 0,0, MS_UFI_SC, MS_BULK_PR,0,0 },
143*53ee8cc1Swenshuai.xi     { 0,0, MS_SFF_SC, MS_BULK_PR,0,0 },
144*53ee8cc1Swenshuai.xi     { 0,0, MS_SCSI_SC, MS_BULK_PR,0,0 },
145*53ee8cc1Swenshuai.xi     { 0,0, 0xFF, MS_CB_PR,0,0 },
146*53ee8cc1Swenshuai.xi     { 0,0,0,0,0,0 }
147*53ee8cc1Swenshuai.xi };
148*53ee8cc1Swenshuai.xi 
149*53ee8cc1Swenshuai.xi struct usb_driver usb_storage_driver =
150*53ee8cc1Swenshuai.xi {
151*53ee8cc1Swenshuai.xi     "usb-storage",
152*53ee8cc1Swenshuai.xi     ms_usb_msc_probe,
153*53ee8cc1Swenshuai.xi     ms_usb_msc_disconnect,
154*53ee8cc1Swenshuai.xi     MSC_usb_ids
155*53ee8cc1Swenshuai.xi };
156*53ee8cc1Swenshuai.xi 
ms_usb_inquiry_data(struct ms_usdata * ms_us)157*53ee8cc1Swenshuai.xi static void ms_usb_inquiry_data(struct ms_usdata *ms_us)
158*53ee8cc1Swenshuai.xi {
159*53ee8cc1Swenshuai.xi     U32 data_len=36;
160*53ee8cc1Swenshuai.xi     int len,len1,len2;
161*53ee8cc1Swenshuai.xi     unsigned char data_ptr[36] = {0x00, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00};
162*53ee8cc1Swenshuai.xi 
163*53ee8cc1Swenshuai.xi     if (ms_test_bit(MS_IDX_DISCONNECTING, &ms_us->flags))
164*53ee8cc1Swenshuai.xi     {
165*53ee8cc1Swenshuai.xi         ms_usbhost_msg("No command allowed during disconnection\n");
166*53ee8cc1Swenshuai.xi         ms_us->srb.result = DID_BAD_TARGET << 16;
167*53ee8cc1Swenshuai.xi     }
168*53ee8cc1Swenshuai.xi     else if (ms_us->srb.sc_data_direction == SCSI_DATA_UNKNOWN)
169*53ee8cc1Swenshuai.xi     {
170*53ee8cc1Swenshuai.xi         ms_usbhost_msg("UNKNOWN data direction\n");
171*53ee8cc1Swenshuai.xi         ms_us->srb.result = DID_ERROR << 16;
172*53ee8cc1Swenshuai.xi     }
173*53ee8cc1Swenshuai.xi     else if ((ms_us->srb.cmnd[0] == INQUIRY) && (ms_us->flags & MS_FIX_INQUIRY))
174*53ee8cc1Swenshuai.xi     {
175*53ee8cc1Swenshuai.xi         ms_usbhost_msg("Faking INQUIRY command\n");
176*53ee8cc1Swenshuai.xi         if(ms_us->srb.req_buf_len > data_len)
177*53ee8cc1Swenshuai.xi             len=data_len;
178*53ee8cc1Swenshuai.xi         else
179*53ee8cc1Swenshuai.xi             len=ms_us->srb.req_buf_len;
180*53ee8cc1Swenshuai.xi 
181*53ee8cc1Swenshuai.xi         if(data_len >= 36)
182*53ee8cc1Swenshuai.xi         {
183*53ee8cc1Swenshuai.xi             if(data_ptr[0]&0x20)
184*53ee8cc1Swenshuai.xi                 memset(data_ptr+8,0,28);
185*53ee8cc1Swenshuai.xi             else
186*53ee8cc1Swenshuai.xi             {
187*53ee8cc1Swenshuai.xi                 if(strlen(ms_us->unusual_dev->vendorName) > 8)
188*53ee8cc1Swenshuai.xi                     len1 = 8;
189*53ee8cc1Swenshuai.xi                 else
190*53ee8cc1Swenshuai.xi                     len1 = strlen(ms_us->unusual_dev->vendorName);
191*53ee8cc1Swenshuai.xi                 memcpy(data_ptr+8, ms_us->unusual_dev->vendorName,len1);
192*53ee8cc1Swenshuai.xi 
193*53ee8cc1Swenshuai.xi                 if(strlen(ms_us->unusual_dev->productName) > 16)
194*53ee8cc1Swenshuai.xi                     len2 = 16;
195*53ee8cc1Swenshuai.xi                 else
196*53ee8cc1Swenshuai.xi                     len2 = strlen(ms_us->unusual_dev->productName);
197*53ee8cc1Swenshuai.xi                 memcpy(data_ptr+16, ms_us->unusual_dev->productName,len2);
198*53ee8cc1Swenshuai.xi 
199*53ee8cc1Swenshuai.xi                 data_ptr[32] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
200*53ee8cc1Swenshuai.xi                 data_ptr[33] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
201*53ee8cc1Swenshuai.xi                 data_ptr[34] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
202*53ee8cc1Swenshuai.xi                 data_ptr[35] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice) & 0x0F);
203*53ee8cc1Swenshuai.xi             }
204*53ee8cc1Swenshuai.xi 
205*53ee8cc1Swenshuai.xi             memset(ms_us->srb.req_buf, 0, ms_us->srb.req_buf_len);
206*53ee8cc1Swenshuai.xi             memcpy(ms_us->srb.req_buf, data_ptr, len);
207*53ee8cc1Swenshuai.xi         }
208*53ee8cc1Swenshuai.xi 
209*53ee8cc1Swenshuai.xi         ms_us->srb.result = MS_STAT_GOOD;
210*53ee8cc1Swenshuai.xi     }
211*53ee8cc1Swenshuai.xi     else
212*53ee8cc1Swenshuai.xi         ms_us->proto_handler(&ms_us->srb, ms_us);
213*53ee8cc1Swenshuai.xi }
214*53ee8cc1Swenshuai.xi 
ms_usb_msc_control_thread(void * __us)215*53ee8cc1Swenshuai.xi int ms_usb_msc_control_thread(void * __us)
216*53ee8cc1Swenshuai.xi {
217*53ee8cc1Swenshuai.xi     struct ms_usdata *ms_us = (struct ms_usdata *)__us;
218*53ee8cc1Swenshuai.xi 
219*53ee8cc1Swenshuai.xi     ms_usbhost_debug("*** thread awakened.\n");
220*53ee8cc1Swenshuai.xi     //if (ms_us->usb_state == ABORTING_STATE)
221*53ee8cc1Swenshuai.xi     //{
222*53ee8cc1Swenshuai.xi     //    ms_us->srb.result = DID_ABORT << 16;
223*53ee8cc1Swenshuai.xi     //    goto Stop_transfer;
224*53ee8cc1Swenshuai.xi     //}
225*53ee8cc1Swenshuai.xi     //ms_us->usb_state = RUNNING_STATE;
226*53ee8cc1Swenshuai.xi     //osapi_down(&(ms_us->dev_semaphore));
227*53ee8cc1Swenshuai.xi     osapi_mutex_lock(ms_us->dev_mutex);
228*53ee8cc1Swenshuai.xi     ms_usb_inquiry_data(ms_us);
229*53ee8cc1Swenshuai.xi     //osapi_up(&(ms_us->dev_semaphore));    //unlock the device pointers
230*53ee8cc1Swenshuai.xi     osapi_mutex_unlock(ms_us->dev_mutex);
231*53ee8cc1Swenshuai.xi 
232*53ee8cc1Swenshuai.xi     /* lock access to the state */
233*53ee8cc1Swenshuai.xi     /* indicate that the command is done */
234*53ee8cc1Swenshuai.xi     if (ms_us->srb.result != DID_ABORT << 16)
235*53ee8cc1Swenshuai.xi     {
236*53ee8cc1Swenshuai.xi         ms_usbhost_debug("SCSI cmd done, result=0x%x\n", ms_us->srb.result);
237*53ee8cc1Swenshuai.xi         if(ms_us->srb.scsi_done != NULL)
238*53ee8cc1Swenshuai.xi             ms_us->srb.scsi_done(&ms_us->srb);
239*53ee8cc1Swenshuai.xi     }
240*53ee8cc1Swenshuai.xi     else
241*53ee8cc1Swenshuai.xi     {
242*53ee8cc1Swenshuai.xi //Stop_transfer:
243*53ee8cc1Swenshuai.xi         ms_usbhost_msg("SCSI command aborted\n");
244*53ee8cc1Swenshuai.xi     }
245*53ee8cc1Swenshuai.xi     //if (ms_us->usb_state == ABORTING_STATE)
246*53ee8cc1Swenshuai.xi     //    complete(&(ms_us->notify));
247*53ee8cc1Swenshuai.xi     //ms_us->usb_state = IDLE_STATE;
248*53ee8cc1Swenshuai.xi     //complete(&(ms_us->notify));
249*53ee8cc1Swenshuai.xi 
250*53ee8cc1Swenshuai.xi     return 0;
251*53ee8cc1Swenshuai.xi }
252*53ee8cc1Swenshuai.xi 
ms_usb_associate_dev(struct ms_usdata * ms_us,struct usb_interface * ms_intf)253*53ee8cc1Swenshuai.xi static int ms_usb_associate_dev(struct ms_usdata *ms_us, struct usb_interface *ms_intf)
254*53ee8cc1Swenshuai.xi {
255*53ee8cc1Swenshuai.xi     ms_us->pusb_dev = interface_to_usbdev(ms_intf);
256*53ee8cc1Swenshuai.xi     ms_us->pusb_intf = ms_intf;
257*53ee8cc1Swenshuai.xi     ms_us->ifnum = ms_intf->altsetting->desc.bInterfaceNumber;
258*53ee8cc1Swenshuai.xi 
259*53ee8cc1Swenshuai.xi     ms_usb_set_intfdata(ms_intf, ms_us);
260*53ee8cc1Swenshuai.xi     ms_usb_get_dev(ms_us->pusb_dev);
261*53ee8cc1Swenshuai.xi     ms_us->cr = (struct usb_ctrlrequest*) ms_usb_buffer_alloc(ms_us->pusb_dev, sizeof(*ms_us->cr), GFP_KERNEL, &ms_us->cr_dma);
262*53ee8cc1Swenshuai.xi     ms_us->iobuf = (unsigned char*) ms_usb_buffer_alloc(ms_us->pusb_dev, MS_IOBUF_SIZE, GFP_KERNEL, &ms_us->iobuf_dma);
263*53ee8cc1Swenshuai.xi     if((!ms_us->cr) || (!ms_us->iobuf))
264*53ee8cc1Swenshuai.xi     {
265*53ee8cc1Swenshuai.xi         ms_usbhost_msg("[ms_usb_associate_dev] Allocating failed\n");
266*53ee8cc1Swenshuai.xi         return -ENOMEM;
267*53ee8cc1Swenshuai.xi     }
268*53ee8cc1Swenshuai.xi     return 0;
269*53ee8cc1Swenshuai.xi }
270*53ee8cc1Swenshuai.xi 
ms_usb_set_subclass(struct ms_usdata * ms_us,struct stUnusual_dev * unusual_dev,struct usb_interface_descriptor * idesc)271*53ee8cc1Swenshuai.xi static void ms_usb_set_subclass(struct ms_usdata *ms_us,struct stUnusual_dev *unusual_dev, struct usb_interface_descriptor *idesc)
272*53ee8cc1Swenshuai.xi {
273*53ee8cc1Swenshuai.xi     if (unusual_dev->vendorName)
274*53ee8cc1Swenshuai.xi         ms_usbhost_msg("[ms_usb_get_device_info] Vendor: %s\n", unusual_dev->vendorName);
275*53ee8cc1Swenshuai.xi 
276*53ee8cc1Swenshuai.xi     if(unusual_dev->useProtocol == MS_DEVICE_SC)
277*53ee8cc1Swenshuai.xi         ms_us->subclass = idesc->bInterfaceSubClass;
278*53ee8cc1Swenshuai.xi     else
279*53ee8cc1Swenshuai.xi         ms_us->subclass = unusual_dev->useProtocol;
280*53ee8cc1Swenshuai.xi 
281*53ee8cc1Swenshuai.xi     if (strlen(ms_us->vendor) == 0)
282*53ee8cc1Swenshuai.xi     {
283*53ee8cc1Swenshuai.xi         if (unusual_dev->vendorName)
284*53ee8cc1Swenshuai.xi         {
285*53ee8cc1Swenshuai.xi             strncpy(ms_us->vendor, unusual_dev->vendorName, sizeof(ms_us->vendor)-1);
286*53ee8cc1Swenshuai.xi             ms_us->vendor[sizeof(ms_us->vendor)-1] = '\0';
287*53ee8cc1Swenshuai.xi         }
288*53ee8cc1Swenshuai.xi         else
289*53ee8cc1Swenshuai.xi             strncpy(ms_us->vendor, "Unknown", sizeof(ms_us->vendor));
290*53ee8cc1Swenshuai.xi     }
291*53ee8cc1Swenshuai.xi }
292*53ee8cc1Swenshuai.xi 
ms_usb_set_protocol(struct ms_usdata * ms_us,struct stUnusual_dev * unusual_dev,struct usb_interface_descriptor * idesc)293*53ee8cc1Swenshuai.xi static void ms_usb_set_protocol(struct ms_usdata *ms_us,struct stUnusual_dev *unusual_dev, struct usb_interface_descriptor *idesc)
294*53ee8cc1Swenshuai.xi {
295*53ee8cc1Swenshuai.xi     if (unusual_dev->productName)
296*53ee8cc1Swenshuai.xi         ms_usbhost_msg("[ms_usb_get_device_info] Product: %s\n", unusual_dev->productName);
297*53ee8cc1Swenshuai.xi 
298*53ee8cc1Swenshuai.xi     if(unusual_dev->useTransport == MS_DEVICE_PR)
299*53ee8cc1Swenshuai.xi         ms_us->protocol = idesc->bInterfaceProtocol;
300*53ee8cc1Swenshuai.xi     else
301*53ee8cc1Swenshuai.xi         ms_us->protocol = unusual_dev->useTransport;
302*53ee8cc1Swenshuai.xi 
303*53ee8cc1Swenshuai.xi     if (strlen(ms_us->product) == 0)
304*53ee8cc1Swenshuai.xi     {
305*53ee8cc1Swenshuai.xi         if (unusual_dev->productName)
306*53ee8cc1Swenshuai.xi         {
307*53ee8cc1Swenshuai.xi             strncpy(ms_us->product, unusual_dev->productName, sizeof(ms_us->product)-1);
308*53ee8cc1Swenshuai.xi             ms_us->product[sizeof(ms_us->product)-1] = '\0';
309*53ee8cc1Swenshuai.xi         }
310*53ee8cc1Swenshuai.xi         else
311*53ee8cc1Swenshuai.xi             strncpy(ms_us->product, "Unknown", sizeof(ms_us->product));
312*53ee8cc1Swenshuai.xi     }
313*53ee8cc1Swenshuai.xi }
314*53ee8cc1Swenshuai.xi 
ms_usb_get_device_info(struct ms_usdata * ms_us,int idx)315*53ee8cc1Swenshuai.xi static void ms_usb_get_device_info(struct ms_usdata *ms_us, int idx)
316*53ee8cc1Swenshuai.xi {
317*53ee8cc1Swenshuai.xi     struct usb_interface_descriptor *idesc =
318*53ee8cc1Swenshuai.xi         &ms_us->pusb_intf->altsetting[ms_us->pusb_intf->act_altsetting].desc;
319*53ee8cc1Swenshuai.xi     struct stUnusual_dev *unusual_dev = &MS_USB_unusual_dev_list[idx];
320*53ee8cc1Swenshuai.xi 
321*53ee8cc1Swenshuai.xi     ms_us->unusual_dev = unusual_dev;
322*53ee8cc1Swenshuai.xi     ms_us->flags = unusual_dev->flags;
323*53ee8cc1Swenshuai.xi     ms_usb_set_subclass(ms_us,unusual_dev,idesc);
324*53ee8cc1Swenshuai.xi     ms_usb_set_protocol(ms_us,unusual_dev,idesc);
325*53ee8cc1Swenshuai.xi }
326*53ee8cc1Swenshuai.xi 
ms_usb_get_transport(struct ms_usdata * ms_us)327*53ee8cc1Swenshuai.xi static int ms_usb_get_transport(struct ms_usdata *ms_us)
328*53ee8cc1Swenshuai.xi {
329*53ee8cc1Swenshuai.xi     switch (ms_us->protocol)
330*53ee8cc1Swenshuai.xi     {
331*53ee8cc1Swenshuai.xi         case MS_CB_PR:
332*53ee8cc1Swenshuai.xi             ms_usbhost_msg("CB Protocol\n");
333*53ee8cc1Swenshuai.xi             ms_us->transport = ms_usb_CB_transport;
334*53ee8cc1Swenshuai.xi             ms_us->transport_reset = ms_usb_CB_reset;
335*53ee8cc1Swenshuai.xi             ms_us->max_lun = 0; //FIXME, Find some way to get real Max. LUN
336*53ee8cc1Swenshuai.xi             break;
337*53ee8cc1Swenshuai.xi         case MS_BULK_PR:
338*53ee8cc1Swenshuai.xi             ms_usbhost_debug("BULK Protocol\n");
339*53ee8cc1Swenshuai.xi             ms_us->transport = ms_usb_bulk_transport;
340*53ee8cc1Swenshuai.xi             ms_us->transport_reset = ms_usb_bulk_reset;
341*53ee8cc1Swenshuai.xi             break;
342*53ee8cc1Swenshuai.xi         case MS_CBI_PR:
343*53ee8cc1Swenshuai.xi             ms_usbhost_msg("Not support CBI Protocol..\n");
344*53ee8cc1Swenshuai.xi         default:
345*53ee8cc1Swenshuai.xi             return -EIO;
346*53ee8cc1Swenshuai.xi     }
347*53ee8cc1Swenshuai.xi     if (ms_us->flags & MS_SINGLE_LUN)
348*53ee8cc1Swenshuai.xi         ms_us->max_lun = 0;
349*53ee8cc1Swenshuai.xi     return 0;
350*53ee8cc1Swenshuai.xi }
351*53ee8cc1Swenshuai.xi 
ms_usb_get_protocol(struct ms_usdata * ms_us)352*53ee8cc1Swenshuai.xi static int ms_usb_get_protocol(struct ms_usdata *ms_us)
353*53ee8cc1Swenshuai.xi {
354*53ee8cc1Swenshuai.xi     switch (ms_us->subclass)
355*53ee8cc1Swenshuai.xi     {
356*53ee8cc1Swenshuai.xi         case MS_RBC_SC:
357*53ee8cc1Swenshuai.xi             ms_usbhost_msg("RBC Subclass\n");
358*53ee8cc1Swenshuai.xi             ms_us->proto_handler = ms_usb_transparent_scsi_command;
359*53ee8cc1Swenshuai.xi             break;
360*53ee8cc1Swenshuai.xi         case MS_SFF_SC:
361*53ee8cc1Swenshuai.xi         case MS_SCSI_SC:
362*53ee8cc1Swenshuai.xi         case 0xFF:	// For Sony DC P8 (P series) and Sony DV
363*53ee8cc1Swenshuai.xi             ms_usbhost_debug("Transparent SCSI\n");
364*53ee8cc1Swenshuai.xi             ms_us->proto_handler = ms_usb_transparent_scsi_command;
365*53ee8cc1Swenshuai.xi             break;
366*53ee8cc1Swenshuai.xi         case MS_ATAPI_SC:
367*53ee8cc1Swenshuai.xi             ms_usbhost_msg("ATAPI Subclass\n");
368*53ee8cc1Swenshuai.xi             ms_us->proto_handler = ms_usb_transparent_scsi_command;
369*53ee8cc1Swenshuai.xi             ms_us->max_lun = 0;
370*53ee8cc1Swenshuai.xi             break;
371*53ee8cc1Swenshuai.xi #if SupportOtherDevice
372*53ee8cc1Swenshuai.xi         case MS_QIC_SC:
373*53ee8cc1Swenshuai.xi             ms_usbhost_msg("QIC-157 Subclass\n");
374*53ee8cc1Swenshuai.xi             ms_us->proto_handler = ms_usb_qic157_command;
375*53ee8cc1Swenshuai.xi             ms_us->max_lun = 0;
376*53ee8cc1Swenshuai.xi             break;
377*53ee8cc1Swenshuai.xi         case MS_UFI_SC:
378*53ee8cc1Swenshuai.xi             ms_usbhost_msg("UFI Subclass\n");
379*53ee8cc1Swenshuai.xi             ms_us->proto_handler = ms_usb_ufi_command;
380*53ee8cc1Swenshuai.xi             break;
381*53ee8cc1Swenshuai.xi #endif
382*53ee8cc1Swenshuai.xi         default:
383*53ee8cc1Swenshuai.xi             return -EIO;
384*53ee8cc1Swenshuai.xi     }
385*53ee8cc1Swenshuai.xi     return 0;
386*53ee8cc1Swenshuai.xi }
387*53ee8cc1Swenshuai.xi 
ms_usb_set_pipe(struct ms_usdata * ms_us,struct usb_endpoint_descriptor * ep_in,struct usb_endpoint_descriptor * ep_out,struct usb_endpoint_descriptor * ep_int)388*53ee8cc1Swenshuai.xi static void ms_usb_set_pipe(struct ms_usdata *ms_us,
389*53ee8cc1Swenshuai.xi     struct usb_endpoint_descriptor *ep_in,
390*53ee8cc1Swenshuai.xi     struct usb_endpoint_descriptor *ep_out,
391*53ee8cc1Swenshuai.xi     struct usb_endpoint_descriptor *ep_int)
392*53ee8cc1Swenshuai.xi {
393*53ee8cc1Swenshuai.xi     ms_us->ctrl_send_pipe = usb_sndctrlpipe(ms_us->pusb_dev, 0);
394*53ee8cc1Swenshuai.xi     ms_us->ctrl_recv_pipe = usb_rcvctrlpipe(ms_us->pusb_dev, 0);
395*53ee8cc1Swenshuai.xi     ms_us->bulk_send_pipe = usb_sndbulkpipe(ms_us->pusb_dev, ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
396*53ee8cc1Swenshuai.xi     ms_us->bulk_recv_pipe = usb_rcvbulkpipe(ms_us->pusb_dev, ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
397*53ee8cc1Swenshuai.xi     if (ep_int)
398*53ee8cc1Swenshuai.xi     {
399*53ee8cc1Swenshuai.xi         ms_us->int_recv_pipe = usb_rcvbulkpipe(ms_us->pusb_dev,
400*53ee8cc1Swenshuai.xi         ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
401*53ee8cc1Swenshuai.xi         ms_us->bInterval_ep = ep_int->bInterval;
402*53ee8cc1Swenshuai.xi     }
403*53ee8cc1Swenshuai.xi }
404*53ee8cc1Swenshuai.xi 
ms_usb_get_pipes(struct ms_usdata * ms_us)405*53ee8cc1Swenshuai.xi static int ms_usb_get_pipes(struct ms_usdata *ms_us)
406*53ee8cc1Swenshuai.xi {
407*53ee8cc1Swenshuai.xi     int tmp;
408*53ee8cc1Swenshuai.xi 
409*53ee8cc1Swenshuai.xi     struct usb_host_interface *altsetting =&ms_us->pusb_intf->altsetting[ms_us->pusb_intf->act_altsetting];
410*53ee8cc1Swenshuai.xi     struct usb_endpoint_descriptor *ep_tmp;
411*53ee8cc1Swenshuai.xi     struct usb_endpoint_descriptor *ep_in = NULL;
412*53ee8cc1Swenshuai.xi     struct usb_endpoint_descriptor *ep_out = NULL;
413*53ee8cc1Swenshuai.xi     struct usb_endpoint_descriptor *ep_int = NULL;
414*53ee8cc1Swenshuai.xi 
415*53ee8cc1Swenshuai.xi     for (tmp = 0; tmp < altsetting->desc.bNumEndpoints; tmp++)
416*53ee8cc1Swenshuai.xi     {
417*53ee8cc1Swenshuai.xi         ep_tmp=&altsetting->endpoint[tmp].desc;
418*53ee8cc1Swenshuai.xi         if ((ep_tmp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
419*53ee8cc1Swenshuai.xi         {
420*53ee8cc1Swenshuai.xi             if (ep_tmp->bEndpointAddress & USB_DIR_IN)
421*53ee8cc1Swenshuai.xi                 ep_in = ep_tmp;
422*53ee8cc1Swenshuai.xi             else
423*53ee8cc1Swenshuai.xi                 ep_out = ep_tmp;
424*53ee8cc1Swenshuai.xi         }
425*53ee8cc1Swenshuai.xi         else if ((ep_tmp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
426*53ee8cc1Swenshuai.xi             ep_int = ep_tmp;
427*53ee8cc1Swenshuai.xi     }
428*53ee8cc1Swenshuai.xi     if (!ep_in || !ep_out || (ms_us->protocol == MS_CBI_PR && !ep_int))
429*53ee8cc1Swenshuai.xi     {
430*53ee8cc1Swenshuai.xi         ms_usbhost_msg("EP sanity check failed! Rejecting dev.\n");
431*53ee8cc1Swenshuai.xi         return -EIO;
432*53ee8cc1Swenshuai.xi     }
433*53ee8cc1Swenshuai.xi 
434*53ee8cc1Swenshuai.xi     ms_usb_set_pipe(ms_us,ep_in,ep_out,ep_tmp);
435*53ee8cc1Swenshuai.xi 
436*53ee8cc1Swenshuai.xi     return 0;
437*53ee8cc1Swenshuai.xi }
438*53ee8cc1Swenshuai.xi 
ms_usb_acquire_resources(struct ms_usdata * ms_us)439*53ee8cc1Swenshuai.xi static int ms_usb_acquire_resources(struct ms_usdata *ms_us)
440*53ee8cc1Swenshuai.xi {
441*53ee8cc1Swenshuai.xi     int regval;
442*53ee8cc1Swenshuai.xi 
443*53ee8cc1Swenshuai.xi     ms_us->current_urb = ms_usb_alloc_urb(GFP_KERNEL);
444*53ee8cc1Swenshuai.xi     //ms_us->data_urb = ms_usb_alloc_urb(GFP_KERNEL);
445*53ee8cc1Swenshuai.xi     //ms_us->status_urb = ms_usb_alloc_urb(GFP_KERNEL);
446*53ee8cc1Swenshuai.xi     if((!ms_us->current_urb)/* || (!ms_us->data_urb) || (!ms_us->status_urb)*/)
447*53ee8cc1Swenshuai.xi     {
448*53ee8cc1Swenshuai.xi         ms_usbhost_err("USB Request Block allocates failed\n");
449*53ee8cc1Swenshuai.xi         return -ENOMEM;
450*53ee8cc1Swenshuai.xi     }
451*53ee8cc1Swenshuai.xi     //osapi_down(&ms_us->dev_semaphore);
452*53ee8cc1Swenshuai.xi     osapi_mutex_lock(ms_us->dev_mutex);
453*53ee8cc1Swenshuai.xi     if (ms_us->protocol == MS_BULK_PR)
454*53ee8cc1Swenshuai.xi     {
455*53ee8cc1Swenshuai.xi         regval = ms_usb_control_msg(ms_us, ms_us->ctrl_recv_pipe, BULK_GET_MAX_LUN,
456*53ee8cc1Swenshuai.xi                     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
457*53ee8cc1Swenshuai.xi                     0, ms_us->ifnum, ms_us->iobuf, 1, HZ*5);
458*53ee8cc1Swenshuai.xi 
459*53ee8cc1Swenshuai.xi         ms_usbhost_debug("GetMaxLUN command regval is %d, data is %d\n", regval, ms_us->iobuf[0]);
460*53ee8cc1Swenshuai.xi 
461*53ee8cc1Swenshuai.xi         if (regval == 1)
462*53ee8cc1Swenshuai.xi             ms_us->max_lun = ms_us->iobuf[0];
463*53ee8cc1Swenshuai.xi         else
464*53ee8cc1Swenshuai.xi             ms_us->max_lun = 0;
465*53ee8cc1Swenshuai.xi     }
466*53ee8cc1Swenshuai.xi 
467*53ee8cc1Swenshuai.xi     ms_us->msc_device=(struct LUN_Device*)kmalloc(sizeof(struct LUN_Device)*(ms_us->max_lun+1), GFP_KERNEL);
468*53ee8cc1Swenshuai.xi     memset(ms_us->msc_device,0 , sizeof(struct LUN_Device)*(ms_us->max_lun+1));
469*53ee8cc1Swenshuai.xi     if (ms_us->unusual_dev->initFunction)
470*53ee8cc1Swenshuai.xi         ms_us->unusual_dev->initFunction(ms_us);
471*53ee8cc1Swenshuai.xi 
472*53ee8cc1Swenshuai.xi     //osapi_up(&ms_us->dev_semaphore);
473*53ee8cc1Swenshuai.xi     osapi_mutex_unlock(ms_us->dev_mutex);
474*53ee8cc1Swenshuai.xi     //ms_us->usb_state = IDLE_STATE;
475*53ee8cc1Swenshuai.xi 
476*53ee8cc1Swenshuai.xi     return 0;
477*53ee8cc1Swenshuai.xi }
478*53ee8cc1Swenshuai.xi 
ms_usb_unregister_dev(struct ms_usdata * ms_us)479*53ee8cc1Swenshuai.xi static void ms_usb_unregister_dev(struct ms_usdata *ms_us)
480*53ee8cc1Swenshuai.xi {
481*53ee8cc1Swenshuai.xi     MS_U8 u8Lun;
482*53ee8cc1Swenshuai.xi 
483*53ee8cc1Swenshuai.xi     //osapi_down(&ms_us->dev_semaphore);
484*53ee8cc1Swenshuai.xi     osapi_mutex_lock(ms_us->dev_mutex);
485*53ee8cc1Swenshuai.xi     if (ms_us->cr)
486*53ee8cc1Swenshuai.xi     {
487*53ee8cc1Swenshuai.xi         ms_usb_buffer_free(ms_us->pusb_dev, sizeof(*ms_us->cr), ms_us->cr, ms_us->cr_dma);
488*53ee8cc1Swenshuai.xi         ms_us->cr = NULL;
489*53ee8cc1Swenshuai.xi     }
490*53ee8cc1Swenshuai.xi     if (ms_us->iobuf)
491*53ee8cc1Swenshuai.xi     {
492*53ee8cc1Swenshuai.xi         ms_usb_buffer_free(ms_us->pusb_dev, MS_IOBUF_SIZE, ms_us->iobuf, ms_us->iobuf_dma);
493*53ee8cc1Swenshuai.xi         ms_us->iobuf = NULL;
494*53ee8cc1Swenshuai.xi     }
495*53ee8cc1Swenshuai.xi     ms_usb_set_intfdata(ms_us->pusb_intf, NULL);
496*53ee8cc1Swenshuai.xi     ms_usb_put_dev(ms_us->pusb_dev);
497*53ee8cc1Swenshuai.xi     ms_us->pusb_dev = NULL;
498*53ee8cc1Swenshuai.xi     ms_us->pusb_intf = NULL;
499*53ee8cc1Swenshuai.xi     //osapi_up(&ms_us->dev_semaphore); // if ms_us to be protected, unlock later
500*53ee8cc1Swenshuai.xi 
501*53ee8cc1Swenshuai.xi     if (ms_us->extra_destructor)
502*53ee8cc1Swenshuai.xi     {
503*53ee8cc1Swenshuai.xi         ms_usbhost_msg("--> Call extra_destructor()\n");
504*53ee8cc1Swenshuai.xi         ms_us->extra_destructor(ms_us->extra);
505*53ee8cc1Swenshuai.xi     }
506*53ee8cc1Swenshuai.xi     if (ms_us->extra)
507*53ee8cc1Swenshuai.xi         kfree(ms_us->extra);
508*53ee8cc1Swenshuai.xi     if (ms_us->current_urb)
509*53ee8cc1Swenshuai.xi         ms_usb_free_urb(ms_us->current_urb);
510*53ee8cc1Swenshuai.xi     //if (ms_us->data_urb)
511*53ee8cc1Swenshuai.xi     //    ms_usb_free_urb(ms_us->data_urb);
512*53ee8cc1Swenshuai.xi     //if (ms_us->status_urb)
513*53ee8cc1Swenshuai.xi     //    ms_usb_free_urb(ms_us->status_urb);
514*53ee8cc1Swenshuai.xi 
515*53ee8cc1Swenshuai.xi     for (u8Lun=0; u8Lun<=ms_us->max_lun; u8Lun++)
516*53ee8cc1Swenshuai.xi         if (ms_us->msc_device[u8Lun].bFSInit)
517*53ee8cc1Swenshuai.xi             RemoveUSBDiskPort(ms_us->ustor_id, u8Lun);
518*53ee8cc1Swenshuai.xi     Mass_stor_us[ms_us->ustor_id] = NULL;
519*53ee8cc1Swenshuai.xi 
520*53ee8cc1Swenshuai.xi     if (ms_us->msc_device)
521*53ee8cc1Swenshuai.xi         kfree(ms_us->msc_device);
522*53ee8cc1Swenshuai.xi 
523*53ee8cc1Swenshuai.xi     osapi_mutex_unlock(ms_us->dev_mutex);
524*53ee8cc1Swenshuai.xi     osapi_mutex_delete(ms_us->dev_mutex);
525*53ee8cc1Swenshuai.xi     kfree(ms_us);
526*53ee8cc1Swenshuai.xi }
527*53ee8cc1Swenshuai.xi 
ms_usb_msc_probe(struct usb_interface * ms_intf,const struct usb_device_id * id)528*53ee8cc1Swenshuai.xi static int ms_usb_msc_probe(struct usb_interface *ms_intf, const struct usb_device_id *id)
529*53ee8cc1Swenshuai.xi {
530*53ee8cc1Swenshuai.xi     struct ms_usdata *ms_us;
531*53ee8cc1Swenshuai.xi     const int idx = id - MSC_usb_ids;
532*53ee8cc1Swenshuai.xi     int regval,tmp,i;
533*53ee8cc1Swenshuai.xi     struct usb_device *pudev;
534*53ee8cc1Swenshuai.xi     unsigned char startId;
535*53ee8cc1Swenshuai.xi 
536*53ee8cc1Swenshuai.xi     ms_usbhost_debug("USB MSC device detected\n");
537*53ee8cc1Swenshuai.xi     ms_usbhost_debug("act_altsetting = %d, idx = %d\n", ms_intf->act_altsetting, idx);
538*53ee8cc1Swenshuai.xi     ms_us = (struct ms_usdata *) kmalloc(sizeof(*ms_us), GFP_KERNEL);
539*53ee8cc1Swenshuai.xi     if (!ms_us)
540*53ee8cc1Swenshuai.xi     {
541*53ee8cc1Swenshuai.xi         ms_usbhost_msg("Out of memory %d\n", ms_us);
542*53ee8cc1Swenshuai.xi         return -ENOMEM;
543*53ee8cc1Swenshuai.xi     }
544*53ee8cc1Swenshuai.xi 
545*53ee8cc1Swenshuai.xi     memset(ms_us, 0, sizeof(struct ms_usdata));
546*53ee8cc1Swenshuai.xi     //osapi_init_MUTEX(&(ms_us->dev_semaphore));
547*53ee8cc1Swenshuai.xi     osapi_mutex_init(ms_us->dev_mutex, "US_MUTEX");
548*53ee8cc1Swenshuai.xi     //osapi_init_MUTEX_LOCKED(&(ms_us->sema));
549*53ee8cc1Swenshuai.xi     //init_completion(&(ms_us->notify));
550*53ee8cc1Swenshuai.xi 
551*53ee8cc1Swenshuai.xi     regval = ms_usb_associate_dev(ms_us, ms_intf);
552*53ee8cc1Swenshuai.xi     if (regval)
553*53ee8cc1Swenshuai.xi     {
554*53ee8cc1Swenshuai.xi         ms_usb_unregister_dev(ms_us);
555*53ee8cc1Swenshuai.xi         return regval;
556*53ee8cc1Swenshuai.xi     }
557*53ee8cc1Swenshuai.xi 
558*53ee8cc1Swenshuai.xi     ms_usb_get_device_info(ms_us, idx);
559*53ee8cc1Swenshuai.xi     if (strlen(ms_us->serial) == 0)
560*53ee8cc1Swenshuai.xi         strncpy(ms_us->serial, "None", sizeof(ms_us->serial));
561*53ee8cc1Swenshuai.xi 
562*53ee8cc1Swenshuai.xi     regval = ms_usb_get_transport(ms_us);
563*53ee8cc1Swenshuai.xi     if (regval)
564*53ee8cc1Swenshuai.xi     {
565*53ee8cc1Swenshuai.xi         ms_usb_unregister_dev(ms_us);
566*53ee8cc1Swenshuai.xi         return regval;
567*53ee8cc1Swenshuai.xi     }
568*53ee8cc1Swenshuai.xi     regval = ms_usb_get_protocol(ms_us);
569*53ee8cc1Swenshuai.xi     if (regval)
570*53ee8cc1Swenshuai.xi     {
571*53ee8cc1Swenshuai.xi         ms_usb_unregister_dev(ms_us);
572*53ee8cc1Swenshuai.xi         return regval;
573*53ee8cc1Swenshuai.xi     }
574*53ee8cc1Swenshuai.xi     regval = ms_usb_get_pipes(ms_us);
575*53ee8cc1Swenshuai.xi     if (regval)
576*53ee8cc1Swenshuai.xi     {
577*53ee8cc1Swenshuai.xi         ms_usb_unregister_dev(ms_us);
578*53ee8cc1Swenshuai.xi         return regval;
579*53ee8cc1Swenshuai.xi     }
580*53ee8cc1Swenshuai.xi     regval = ms_usb_acquire_resources(ms_us);
581*53ee8cc1Swenshuai.xi     if (regval)
582*53ee8cc1Swenshuai.xi     {
583*53ee8cc1Swenshuai.xi         ms_usb_unregister_dev(ms_us);
584*53ee8cc1Swenshuai.xi         return regval;
585*53ee8cc1Swenshuai.xi     }
586*53ee8cc1Swenshuai.xi 
587*53ee8cc1Swenshuai.xi     pudev = interface_to_usbdev(ms_intf);
588*53ee8cc1Swenshuai.xi 
589*53ee8cc1Swenshuai.xi     startId = (MAX_USTOR* (((struct usb_hcd *)pudev->bus->hcpriv)->host_id));
590*53ee8cc1Swenshuai.xi     USB_ASSERT(startId < NUM_OF_ROOT_HUB*MAX_USTOR, "startId >= NUM_OF_ROOT_HUB*MAX_USTOR\n");
591*53ee8cc1Swenshuai.xi 
592*53ee8cc1Swenshuai.xi     tmp = (-1);
593*53ee8cc1Swenshuai.xi     for (i=startId; i<startId+MAX_USTOR; i++)
594*53ee8cc1Swenshuai.xi     {
595*53ee8cc1Swenshuai.xi         if (Mass_stor_us[i] == NULL)
596*53ee8cc1Swenshuai.xi             tmp = i; // the result sequence 7,6,5...
597*53ee8cc1Swenshuai.xi     }
598*53ee8cc1Swenshuai.xi 
599*53ee8cc1Swenshuai.xi     //ERROR: Exceed the max support number of usb storage device !!
600*53ee8cc1Swenshuai.xi     if (tmp != (-1))
601*53ee8cc1Swenshuai.xi     {
602*53ee8cc1Swenshuai.xi         Mass_stor_us[tmp] = ms_us;
603*53ee8cc1Swenshuai.xi         ms_us->ustor_id = (unsigned char)tmp;
604*53ee8cc1Swenshuai.xi     }
605*53ee8cc1Swenshuai.xi     else
606*53ee8cc1Swenshuai.xi     {
607*53ee8cc1Swenshuai.xi         ms_usbhost_err("MSC: exceed the max number of support devices!!!\n");
608*53ee8cc1Swenshuai.xi         ms_usb_unregister_dev(ms_us);
609*53ee8cc1Swenshuai.xi         return -ENOBUFS;
610*53ee8cc1Swenshuai.xi     }
611*53ee8cc1Swenshuai.xi 
612*53ee8cc1Swenshuai.xi     ms_us->host_id = ((struct usb_hcd *)pudev->bus->hcpriv)->host_id;
613*53ee8cc1Swenshuai.xi     for(tmp = 0; tmp<=ms_us->max_lun; tmp++)
614*53ee8cc1Swenshuai.xi         ms_us->msc_device[tmp].bDeviceReady = FALSE;
615*53ee8cc1Swenshuai.xi 
616*53ee8cc1Swenshuai.xi     ms_usbhost_msg("find USB MSC device at device number %d\n", ms_us->pusb_dev->u32DevNum);
617*53ee8cc1Swenshuai.xi 
618*53ee8cc1Swenshuai.xi     return 0;
619*53ee8cc1Swenshuai.xi }
620*53ee8cc1Swenshuai.xi 
ms_usb_msc_disconnect(struct usb_interface * ms_intf)621*53ee8cc1Swenshuai.xi static void ms_usb_msc_disconnect(struct usb_interface *ms_intf)
622*53ee8cc1Swenshuai.xi {
623*53ee8cc1Swenshuai.xi     struct ms_usdata *ms_us = (struct ms_usdata*) ms_usb_get_intfdata(ms_intf);
624*53ee8cc1Swenshuai.xi 
625*53ee8cc1Swenshuai.xi     ms_usbhost_msg("MSC disconnect id: %d, us->flag %x \n", ms_us->ustor_id, ms_us->flags);
626*53ee8cc1Swenshuai.xi     ms_set_bit(MS_IDX_DISCONNECTING, &ms_us->flags, unsigned long);
627*53ee8cc1Swenshuai.xi     if (ms_test_and_clear_bit(MS_IDX_URB_ACTIVE, &ms_us->flags))
628*53ee8cc1Swenshuai.xi     {
629*53ee8cc1Swenshuai.xi         ms_usbhost_err("[MSCDIS]--> cancel USB request block\n");
630*53ee8cc1Swenshuai.xi         ms_usb_unlink_urb(ms_us->current_urb);
631*53ee8cc1Swenshuai.xi     }
632*53ee8cc1Swenshuai.xi     ms_usb_unregister_dev(ms_us);
633*53ee8cc1Swenshuai.xi }
634*53ee8cc1Swenshuai.xi 
ms_ioctl_issue_ctrl(struct ms_usdata * ms_us,void * pData)635*53ee8cc1Swenshuai.xi int ms_ioctl_issue_ctrl(struct ms_usdata *ms_us, void *pData)
636*53ee8cc1Swenshuai.xi {
637*53ee8cc1Swenshuai.xi     struct usb_ioctl_ctrl_xfer *pCtrlData = (struct usb_ioctl_ctrl_xfer*)pData;
638*53ee8cc1Swenshuai.xi     int retval = -1;
639*53ee8cc1Swenshuai.xi 
640*53ee8cc1Swenshuai.xi     ms_usbhost_msg("[USB] control urb: bRequestType=%02x "
641*53ee8cc1Swenshuai.xi             "bRequest=%02x wValue=%04x "
642*53ee8cc1Swenshuai.xi             "wIndex=%04x wLength=%04x\n",
643*53ee8cc1Swenshuai.xi             pCtrlData->bRequestType,
644*53ee8cc1Swenshuai.xi             pCtrlData->bRequest,
645*53ee8cc1Swenshuai.xi             pCtrlData->wValue,
646*53ee8cc1Swenshuai.xi             pCtrlData->wIndex,
647*53ee8cc1Swenshuai.xi             pCtrlData->wLength);
648*53ee8cc1Swenshuai.xi 
649*53ee8cc1Swenshuai.xi     if((pCtrlData->wLength > 0) && ((pCtrlData->bRequestType & USB_DIR_IN) == 0)) /* OUT transfer */
650*53ee8cc1Swenshuai.xi         memcpy(ms_us->iobuf, pCtrlData->pDataBuf, pCtrlData->wLength);
651*53ee8cc1Swenshuai.xi 
652*53ee8cc1Swenshuai.xi     retval = ms_usb_control_msg(ms_us, ms_us->ctrl_recv_pipe,
653*53ee8cc1Swenshuai.xi               pCtrlData->bRequest,
654*53ee8cc1Swenshuai.xi               pCtrlData->bRequestType,
655*53ee8cc1Swenshuai.xi               pCtrlData->wValue,
656*53ee8cc1Swenshuai.xi               pCtrlData->wIndex,
657*53ee8cc1Swenshuai.xi               ms_us->iobuf,
658*53ee8cc1Swenshuai.xi               pCtrlData->wLength,
659*53ee8cc1Swenshuai.xi               (pCtrlData->timeout*HZ)/1000);
660*53ee8cc1Swenshuai.xi 
661*53ee8cc1Swenshuai.xi     ms_usbhost_msg("[USB] ctrl ioctl reault: %d\n", retval);
662*53ee8cc1Swenshuai.xi 
663*53ee8cc1Swenshuai.xi     if(retval < 0)
664*53ee8cc1Swenshuai.xi     {
665*53ee8cc1Swenshuai.xi         goto done;
666*53ee8cc1Swenshuai.xi     }
667*53ee8cc1Swenshuai.xi 
668*53ee8cc1Swenshuai.xi     if((pCtrlData->wLength > 0) && (pCtrlData->bRequestType & USB_DIR_IN)) /* IN transfer */
669*53ee8cc1Swenshuai.xi         memcpy(pCtrlData->pDataBuf, ms_us->iobuf, pCtrlData->wLength);
670*53ee8cc1Swenshuai.xi 
671*53ee8cc1Swenshuai.xi done:
672*53ee8cc1Swenshuai.xi     return retval;
673*53ee8cc1Swenshuai.xi }
674*53ee8cc1Swenshuai.xi 
ms_ioctl_issue_bulk(struct ms_usdata * ms_us,void * pData)675*53ee8cc1Swenshuai.xi int ms_ioctl_issue_bulk(struct ms_usdata *ms_us, void *pData)
676*53ee8cc1Swenshuai.xi {
677*53ee8cc1Swenshuai.xi     struct usb_ioctl_bulk_xfer *pBulkData = (struct usb_ioctl_bulk_xfer*)pData;
678*53ee8cc1Swenshuai.xi     int retval = -1;
679*53ee8cc1Swenshuai.xi     U32 act_len = 0;
680*53ee8cc1Swenshuai.xi     U32 pipe;
681*53ee8cc1Swenshuai.xi 
682*53ee8cc1Swenshuai.xi     ms_usbhost_msg("[USB] bulk urb: dir=%02x "
683*53ee8cc1Swenshuai.xi             "len=%02x timeout=%04x\n",
684*53ee8cc1Swenshuai.xi             pBulkData->dir,
685*53ee8cc1Swenshuai.xi             pBulkData->len);
686*53ee8cc1Swenshuai.xi 
687*53ee8cc1Swenshuai.xi     pipe = (pBulkData->dir == USB_IOCTL_BULK_OUT) ? ms_us->bulk_send_pipe : ms_us->bulk_recv_pipe;
688*53ee8cc1Swenshuai.xi 
689*53ee8cc1Swenshuai.xi     retval = ms_usb_bulk_transfer_buf(ms_us, pipe, pBulkData->pDataBuf, pBulkData->len, &act_len);
690*53ee8cc1Swenshuai.xi 
691*53ee8cc1Swenshuai.xi     if(retval == 0)
692*53ee8cc1Swenshuai.xi     {
693*53ee8cc1Swenshuai.xi         retval = act_len;
694*53ee8cc1Swenshuai.xi     }
695*53ee8cc1Swenshuai.xi 
696*53ee8cc1Swenshuai.xi     return retval;
697*53ee8cc1Swenshuai.xi }
698*53ee8cc1Swenshuai.xi 
699*53ee8cc1Swenshuai.xi #define DECLARE_VID_PID(VID, PID) (((U32)VID & 0xFFFF) << 16 | ((U32)PID & 0xFFFF))
700*53ee8cc1Swenshuai.xi #define QUIRK_TABLE_TERMINATOR DECLARE_VID_PID(0x0000, 0x0000)
701*53ee8cc1Swenshuai.xi #define QUIRK_NULL_FLAG	0x00000000UL
702*53ee8cc1Swenshuai.xi 
703*53ee8cc1Swenshuai.xi struct quirk {
704*53ee8cc1Swenshuai.xi     U32 vid_pid;
705*53ee8cc1Swenshuai.xi     U32 flag;
706*53ee8cc1Swenshuai.xi };
707*53ee8cc1Swenshuai.xi 
708*53ee8cc1Swenshuai.xi #define QUIRK_NUMMAX  20
709*53ee8cc1Swenshuai.xi 
710*53ee8cc1Swenshuai.xi struct quirk quirk_list[QUIRK_NUMMAX];
711*53ee8cc1Swenshuai.xi int quirk_num;
712*53ee8cc1Swenshuai.xi 
quirk_list_init(void)713*53ee8cc1Swenshuai.xi void quirk_list_init(void)
714*53ee8cc1Swenshuai.xi {
715*53ee8cc1Swenshuai.xi     int i;
716*53ee8cc1Swenshuai.xi 
717*53ee8cc1Swenshuai.xi     diag_printf("[USB] quirk list init, support max %d\n", QUIRK_NUMMAX);
718*53ee8cc1Swenshuai.xi     quirk_num = 0;
719*53ee8cc1Swenshuai.xi 
720*53ee8cc1Swenshuai.xi     for(i = 0;i < QUIRK_NUMMAX; i++)
721*53ee8cc1Swenshuai.xi     {
722*53ee8cc1Swenshuai.xi         quirk_list[i].vid_pid = QUIRK_TABLE_TERMINATOR;
723*53ee8cc1Swenshuai.xi         quirk_list[i].flag = QUIRK_NULL_FLAG;
724*53ee8cc1Swenshuai.xi     }
725*53ee8cc1Swenshuai.xi }
726*53ee8cc1Swenshuai.xi 
quirk_list_add(U32 vid_pid,U32 flag)727*53ee8cc1Swenshuai.xi int quirk_list_add(U32 vid_pid, U32 flag)
728*53ee8cc1Swenshuai.xi {
729*53ee8cc1Swenshuai.xi     int retval = -1;
730*53ee8cc1Swenshuai.xi 
731*53ee8cc1Swenshuai.xi     if(quirk_num < QUIRK_NUMMAX)
732*53ee8cc1Swenshuai.xi     {
733*53ee8cc1Swenshuai.xi         quirk_list[quirk_num].vid_pid = vid_pid;
734*53ee8cc1Swenshuai.xi         quirk_list[quirk_num].flag = flag;
735*53ee8cc1Swenshuai.xi 
736*53ee8cc1Swenshuai.xi         diag_printf("[USB] quirk(%d) add vid/pid 0x%x flag 0x%x\n", quirk_num, vid_pid, flag);
737*53ee8cc1Swenshuai.xi         quirk_num++;
738*53ee8cc1Swenshuai.xi         retval = 0;
739*53ee8cc1Swenshuai.xi     }
740*53ee8cc1Swenshuai.xi     else
741*53ee8cc1Swenshuai.xi     {
742*53ee8cc1Swenshuai.xi         diag_printf("[USB] quirk num overrun, max(%d)\n", QUIRK_NUMMAX);
743*53ee8cc1Swenshuai.xi         retval = -1;
744*53ee8cc1Swenshuai.xi     }
745*53ee8cc1Swenshuai.xi     return retval;
746*53ee8cc1Swenshuai.xi }
747*53ee8cc1Swenshuai.xi 
quirk_list_add_3g(U32 vid_pid)748*53ee8cc1Swenshuai.xi int quirk_list_add_3g(U32 vid_pid)
749*53ee8cc1Swenshuai.xi {
750*53ee8cc1Swenshuai.xi     return quirk_list_add(vid_pid, QUIRK_IGNORE_TUR | QUIRK_IGNORE_CD_ROM | QUIRK_IGNORE_RD_CAP | QUIRK_IGNORE_MOD_SENSE);
751*53ee8cc1Swenshuai.xi }
752*53ee8cc1Swenshuai.xi 
quirk_bypass_stage(struct ms_usdata * ms_us,U32 stage_flag)753*53ee8cc1Swenshuai.xi bool quirk_bypass_stage(struct ms_usdata *ms_us, U32 stage_flag)
754*53ee8cc1Swenshuai.xi {
755*53ee8cc1Swenshuai.xi     U32 vid_pid = DECLARE_VID_PID(ms_us->pusb_dev->descriptor.idVendor,  ms_us->pusb_dev->descriptor.idProduct);
756*53ee8cc1Swenshuai.xi     int iter;
757*53ee8cc1Swenshuai.xi 
758*53ee8cc1Swenshuai.xi     iter = 0;
759*53ee8cc1Swenshuai.xi 
760*53ee8cc1Swenshuai.xi     while(iter < QUIRK_NUMMAX && quirk_list[iter].vid_pid != QUIRK_TABLE_TERMINATOR)
761*53ee8cc1Swenshuai.xi     {
762*53ee8cc1Swenshuai.xi         if((vid_pid == quirk_list[iter].vid_pid) && (quirk_list[iter].flag & stage_flag))
763*53ee8cc1Swenshuai.xi         {
764*53ee8cc1Swenshuai.xi             diag_printf("[USB] quirk bypass stage(0x%x) (VID_PID=0x%x)\n", stage_flag, vid_pid);
765*53ee8cc1Swenshuai.xi             return true;
766*53ee8cc1Swenshuai.xi         }
767*53ee8cc1Swenshuai.xi         iter++;
768*53ee8cc1Swenshuai.xi     }
769*53ee8cc1Swenshuai.xi     return false;
770*53ee8cc1Swenshuai.xi }
771