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 #include <cyg/infra/cyg_type.h>
80*53ee8cc1Swenshuai.xi #include <cyg/infra/cyg_ass.h>
81*53ee8cc1Swenshuai.xi #include <cyg/infra/diag.h>
82*53ee8cc1Swenshuai.xi #include <cyg/hal/hal_arch.h>
83*53ee8cc1Swenshuai.xi #include <cyg/hal/hal_io.h>
84*53ee8cc1Swenshuai.xi #include <cyg/hal/drv_api.h>
85*53ee8cc1Swenshuai.xi #include <cyg/io/io.h>
86*53ee8cc1Swenshuai.xi #include <cyg/io/devtab.h>
87*53ee8cc1Swenshuai.xi #include <cyg/io/disk.h>
88*53ee8cc1Swenshuai.xi
89*53ee8cc1Swenshuai.xi #include "drvSCSI.h"
90*53ee8cc1Swenshuai.xi #include "drvMassStor.h"
91*53ee8cc1Swenshuai.xi #include "drvUSB.h"
92*53ee8cc1Swenshuai.xi //#include <pkgconf/devs_usb.h>
93*53ee8cc1Swenshuai.xi
94*53ee8cc1Swenshuai.xi extern void RemoveUSBDiskPort(U8 uPort, U8 uLunNum);
95*53ee8cc1Swenshuai.xi //#define USB_DISK_DBG 1
96*53ee8cc1Swenshuai.xi
97*53ee8cc1Swenshuai.xi typedef struct {
98*53ee8cc1Swenshuai.xi int num;
99*53ee8cc1Swenshuai.xi cyg_uint32 size;
100*53ee8cc1Swenshuai.xi int uPort;
101*53ee8cc1Swenshuai.xi int DevId;
102*53ee8cc1Swenshuai.xi } usb_disk_info_t;
103*53ee8cc1Swenshuai.xi
104*53ee8cc1Swenshuai.xi // ----------------------------------------------------------------------------
105*53ee8cc1Swenshuai.xi #ifndef __lint__ //NOTE: lint will complain for the following device tables..
106*53ee8cc1Swenshuai.xi static bool usb_disk_init(struct cyg_devtab_entry *tab);
107*53ee8cc1Swenshuai.xi
108*53ee8cc1Swenshuai.xi static Cyg_ErrNo usb_disk_read(disk_channel *chan,
109*53ee8cc1Swenshuai.xi void *buf,
110*53ee8cc1Swenshuai.xi cyg_uint32 len,
111*53ee8cc1Swenshuai.xi cyg_uint32 block_num);
112*53ee8cc1Swenshuai.xi
113*53ee8cc1Swenshuai.xi static Cyg_ErrNo usb_disk_write(disk_channel *chan,
114*53ee8cc1Swenshuai.xi const void *buf,
115*53ee8cc1Swenshuai.xi cyg_uint32 len,
116*53ee8cc1Swenshuai.xi cyg_uint32 block_num);
117*53ee8cc1Swenshuai.xi
118*53ee8cc1Swenshuai.xi static Cyg_ErrNo usb_disk_get_config(disk_channel *chan,
119*53ee8cc1Swenshuai.xi cyg_uint32 key,
120*53ee8cc1Swenshuai.xi const void *xbuf,
121*53ee8cc1Swenshuai.xi cyg_uint32 *len);
122*53ee8cc1Swenshuai.xi
123*53ee8cc1Swenshuai.xi static Cyg_ErrNo usb_disk_set_config(disk_channel *chan,
124*53ee8cc1Swenshuai.xi cyg_uint32 key,
125*53ee8cc1Swenshuai.xi const void *xbuf,
126*53ee8cc1Swenshuai.xi cyg_uint32 *len);
127*53ee8cc1Swenshuai.xi
128*53ee8cc1Swenshuai.xi static Cyg_ErrNo usb_disk_lookup(struct cyg_devtab_entry **tab,
129*53ee8cc1Swenshuai.xi struct cyg_devtab_entry *sub_tab,
130*53ee8cc1Swenshuai.xi const char *name);
131*53ee8cc1Swenshuai.xi
132*53ee8cc1Swenshuai.xi static struct DISK_FUNS(usb_disk_funs,
133*53ee8cc1Swenshuai.xi &usb_disk_read,
134*53ee8cc1Swenshuai.xi &usb_disk_write,
135*53ee8cc1Swenshuai.xi &usb_disk_get_config,
136*53ee8cc1Swenshuai.xi &usb_disk_set_config
137*53ee8cc1Swenshuai.xi );
138*53ee8cc1Swenshuai.xi
139*53ee8cc1Swenshuai.xi //USB_2
140*53ee8cc1Swenshuai.xi // We define 10 empty block device entries for our USB storage device.
141*53ee8cc1Swenshuai.xi // Initially, these entries can not be used until the USB module connect it.
142*53ee8cc1Swenshuai.xi #if 1
143*53ee8cc1Swenshuai.xi #define USB_DISK_INSTANCE(_number_,_port_,_name_) \
144*53ee8cc1Swenshuai.xi static usb_disk_info_t usb_disk_info##_port_##_number_ = { \
145*53ee8cc1Swenshuai.xi -1, \
146*53ee8cc1Swenshuai.xi 0, \
147*53ee8cc1Swenshuai.xi -1, \
148*53ee8cc1Swenshuai.xi -1 \
149*53ee8cc1Swenshuai.xi }; \
150*53ee8cc1Swenshuai.xi disk_controller usb_disk_controller##_port_##_number_ = { \
151*53ee8cc1Swenshuai.xi priv: NULL, \
152*53ee8cc1Swenshuai.xi init: false, \
153*53ee8cc1Swenshuai.xi busy: false \
154*53ee8cc1Swenshuai.xi }; \
155*53ee8cc1Swenshuai.xi DISK_CHANNEL(usb_disk_channel##_port_##_number_, \
156*53ee8cc1Swenshuai.xi usb_disk_funs, \
157*53ee8cc1Swenshuai.xi usb_disk_info##_port_##_number_, \
158*53ee8cc1Swenshuai.xi usb_disk_controller##_port_##_number_, \
159*53ee8cc1Swenshuai.xi true \
160*53ee8cc1Swenshuai.xi ); \
161*53ee8cc1Swenshuai.xi BLOCK_DEVTAB_ENTRY(usb_disk_io##_port_##_number_, \
162*53ee8cc1Swenshuai.xi _name_, \
163*53ee8cc1Swenshuai.xi 0, \
164*53ee8cc1Swenshuai.xi &cyg_io_disk_devio, \
165*53ee8cc1Swenshuai.xi &usb_disk_init, \
166*53ee8cc1Swenshuai.xi &usb_disk_lookup, \
167*53ee8cc1Swenshuai.xi &usb_disk_channel##_port_##_number_ \
168*53ee8cc1Swenshuai.xi );
169*53ee8cc1Swenshuai.xi #else
170*53ee8cc1Swenshuai.xi #define USB_DISK_INSTANCE(_number_,_port_,_name_) \
171*53ee8cc1Swenshuai.xi static usb_disk_info_t usb_disk_info##_port_##_number_ = { \
172*53ee8cc1Swenshuai.xi num: _number_, \
173*53ee8cc1Swenshuai.xi size: 0, \
174*53ee8cc1Swenshuai.xi uPort: _port_ , \
175*53ee8cc1Swenshuai.xi DevId: -1 \
176*53ee8cc1Swenshuai.xi }; \
177*53ee8cc1Swenshuai.xi disk_controller usb_disk_controller##_port_##_number_ = { \
178*53ee8cc1Swenshuai.xi priv: NULL, \
179*53ee8cc1Swenshuai.xi init: false, \
180*53ee8cc1Swenshuai.xi busy: false \
181*53ee8cc1Swenshuai.xi }; \
182*53ee8cc1Swenshuai.xi DISK_CHANNEL(usb_disk_channel##_port_##_number_, \
183*53ee8cc1Swenshuai.xi usb_disk_funs, \
184*53ee8cc1Swenshuai.xi usb_disk_info##_port_##_number_, \
185*53ee8cc1Swenshuai.xi usb_disk_controller##_port_##_number_, \
186*53ee8cc1Swenshuai.xi true \
187*53ee8cc1Swenshuai.xi ); \
188*53ee8cc1Swenshuai.xi BLOCK_DEVTAB_ENTRY(usb_disk_io##_port_##_number_, \
189*53ee8cc1Swenshuai.xi _name_, \
190*53ee8cc1Swenshuai.xi 0, \
191*53ee8cc1Swenshuai.xi &cyg_io_disk_devio, \
192*53ee8cc1Swenshuai.xi &usb_disk_init, \
193*53ee8cc1Swenshuai.xi &usb_disk_lookup, \
194*53ee8cc1Swenshuai.xi &usb_disk_channel##_port_##_number_ \
195*53ee8cc1Swenshuai.xi );
196*53ee8cc1Swenshuai.xi #endif
197*53ee8cc1Swenshuai.xi
198*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(0, 0, "/dev/sda/");
199*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(1, 0, "/dev/sdb/");
200*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(2, 0, "/dev/sdc/");
201*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(3, 0, "/dev/sdd/");
202*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(4, 0, "/dev/sde/");
203*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(5, 0, "/dev/sdf/");
204*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(6, 0, "/dev/sdg/");
205*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(7, 0, "/dev/sdh/");
206*53ee8cc1Swenshuai.xi
207*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(0, 1, "/dev/sdi/");
208*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(1, 1, "/dev/sdj/");
209*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(2, 1, "/dev/sdk/");
210*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(3, 1, "/dev/sdl/");
211*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(4, 1, "/dev/sdm/");
212*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(5, 1, "/dev/sdn/");
213*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(6, 1, "/dev/sdo/");
214*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(7, 1, "/dev/sdp/");
215*53ee8cc1Swenshuai.xi
216*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(0, 2, "/dev/sdq/");
217*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(1, 2, "/dev/sdr/");
218*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(2, 2, "/dev/sds/");
219*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(3, 2, "/dev/sdt/");
220*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(4, 2, "/dev/sdu/");
221*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(5, 2, "/dev/sdv/");
222*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(6, 2, "/dev/sdw/");
223*53ee8cc1Swenshuai.xi USB_DISK_INSTANCE(7, 2, "/dev/sdx/");
224*53ee8cc1Swenshuai.xi
225*53ee8cc1Swenshuai.xi #ifdef _USB_DISK_DEBUG
dump_data(cyg_uint8 * buf,cyg_uint32 len)226*53ee8cc1Swenshuai.xi void dump_data(cyg_uint8 *buf, cyg_uint32 len)
227*53ee8cc1Swenshuai.xi {
228*53ee8cc1Swenshuai.xi int i, j=0;
229*53ee8cc1Swenshuai.xi
230*53ee8cc1Swenshuai.xi while(j<len)
231*53ee8cc1Swenshuai.xi {
232*53ee8cc1Swenshuai.xi diag_printf("[ ");
233*53ee8cc1Swenshuai.xi for (i=0; i<16; i++)
234*53ee8cc1Swenshuai.xi diag_printf("%x ", buf[j+i]);
235*53ee8cc1Swenshuai.xi diag_printf(" ]\n");
236*53ee8cc1Swenshuai.xi j+=i;
237*53ee8cc1Swenshuai.xi }
238*53ee8cc1Swenshuai.xi
239*53ee8cc1Swenshuai.xi }
240*53ee8cc1Swenshuai.xi #endif
241*53ee8cc1Swenshuai.xi
242*53ee8cc1Swenshuai.xi static bool
usb_disk_init(struct cyg_devtab_entry * tab)243*53ee8cc1Swenshuai.xi usb_disk_init(struct cyg_devtab_entry *tab)
244*53ee8cc1Swenshuai.xi {
245*53ee8cc1Swenshuai.xi disk_channel *chan = (disk_channel *) tab->priv;
246*53ee8cc1Swenshuai.xi cyg_disk_info_t *info = chan->info;
247*53ee8cc1Swenshuai.xi
248*53ee8cc1Swenshuai.xi info->connected = false;
249*53ee8cc1Swenshuai.xi chan->valid = false;
250*53ee8cc1Swenshuai.xi
251*53ee8cc1Swenshuai.xi if (chan->init)
252*53ee8cc1Swenshuai.xi return true;
253*53ee8cc1Swenshuai.xi
254*53ee8cc1Swenshuai.xi
255*53ee8cc1Swenshuai.xi //if (!(chan->callbacks->disk_init)(tab))
256*53ee8cc1Swenshuai.xi // return false;
257*53ee8cc1Swenshuai.xi
258*53ee8cc1Swenshuai.xi // Initially, we declare that we are not connected
259*53ee8cc1Swenshuai.xi info->connected = false;
260*53ee8cc1Swenshuai.xi chan->valid = false;
261*53ee8cc1Swenshuai.xi
262*53ee8cc1Swenshuai.xi return true;
263*53ee8cc1Swenshuai.xi }
264*53ee8cc1Swenshuai.xi
265*53ee8cc1Swenshuai.xi static Cyg_ErrNo
usb_disk_lookup(struct cyg_devtab_entry ** tab,struct cyg_devtab_entry * sub_tab,const char * name)266*53ee8cc1Swenshuai.xi usb_disk_lookup(struct cyg_devtab_entry **tab,
267*53ee8cc1Swenshuai.xi struct cyg_devtab_entry *sub_tab,
268*53ee8cc1Swenshuai.xi const char *name)
269*53ee8cc1Swenshuai.xi {
270*53ee8cc1Swenshuai.xi disk_channel *chan = (disk_channel *) (*tab)->priv;
271*53ee8cc1Swenshuai.xi return (chan->callbacks->disk_lookup(tab, sub_tab, name));
272*53ee8cc1Swenshuai.xi }
273*53ee8cc1Swenshuai.xi
274*53ee8cc1Swenshuai.xi static Cyg_ErrNo
usb_disk_read(disk_channel * chan,void * buf,cyg_uint32 len,cyg_uint32 block_num)275*53ee8cc1Swenshuai.xi usb_disk_read(disk_channel *chan,
276*53ee8cc1Swenshuai.xi void *buf,
277*53ee8cc1Swenshuai.xi cyg_uint32 len,
278*53ee8cc1Swenshuai.xi cyg_uint32 block_num)
279*53ee8cc1Swenshuai.xi {
280*53ee8cc1Swenshuai.xi usb_disk_info_t *usb_info = (usb_disk_info_t *)chan->dev_priv;
281*53ee8cc1Swenshuai.xi
282*53ee8cc1Swenshuai.xi if ((usb_info->uPort == -1) ||
283*53ee8cc1Swenshuai.xi (usb_info->num == -1) ||
284*53ee8cc1Swenshuai.xi (usb_info->DevId == -1) )
285*53ee8cc1Swenshuai.xi {
286*53ee8cc1Swenshuai.xi diag_printf("Err: usb_disk_read: device not exist \n");
287*53ee8cc1Swenshuai.xi return ENODEV;
288*53ee8cc1Swenshuai.xi }
289*53ee8cc1Swenshuai.xi
290*53ee8cc1Swenshuai.xi if (bSCSI_Read_10(usb_info->uPort, usb_info->num, block_num,
291*53ee8cc1Swenshuai.xi len , (cyg_uint8*)buf) )
292*53ee8cc1Swenshuai.xi {
293*53ee8cc1Swenshuai.xi #ifdef _USB_DISK_DEBUG
294*53ee8cc1Swenshuai.xi diag_printf("[%s][%d] ==============================\n", __FUNCTION__, __LINE__);
295*53ee8cc1Swenshuai.xi diag_printf("[%s][%d] %d %d %d %d 0x%08x\n", __FUNCTION__, __LINE__,
296*53ee8cc1Swenshuai.xi usb_info->uPort, usb_info->num, block_num, len , (int)buf);
297*53ee8cc1Swenshuai.xi dump_data(buf, len* 512);
298*53ee8cc1Swenshuai.xi diag_printf("[%s][%d] ==============================\n", __FUNCTION__, __LINE__);
299*53ee8cc1Swenshuai.xi #endif
300*53ee8cc1Swenshuai.xi
301*53ee8cc1Swenshuai.xi return ENOERR;
302*53ee8cc1Swenshuai.xi }
303*53ee8cc1Swenshuai.xi else
304*53ee8cc1Swenshuai.xi
305*53ee8cc1Swenshuai.xi return -EIO;
306*53ee8cc1Swenshuai.xi }
307*53ee8cc1Swenshuai.xi
308*53ee8cc1Swenshuai.xi static Cyg_ErrNo
usb_disk_write(disk_channel * chan,const void * buf,cyg_uint32 len,cyg_uint32 block_num)309*53ee8cc1Swenshuai.xi usb_disk_write(disk_channel *chan,
310*53ee8cc1Swenshuai.xi const void *buf,
311*53ee8cc1Swenshuai.xi cyg_uint32 len,
312*53ee8cc1Swenshuai.xi cyg_uint32 block_num)
313*53ee8cc1Swenshuai.xi {
314*53ee8cc1Swenshuai.xi usb_disk_info_t *usb_info = (usb_disk_info_t *)chan->dev_priv;
315*53ee8cc1Swenshuai.xi
316*53ee8cc1Swenshuai.xi if ((usb_info->uPort == -1) ||
317*53ee8cc1Swenshuai.xi (usb_info->num == -1) ||
318*53ee8cc1Swenshuai.xi (usb_info->DevId == -1) )
319*53ee8cc1Swenshuai.xi {
320*53ee8cc1Swenshuai.xi diag_printf("Err: usb_disk_read: device not exist \n");
321*53ee8cc1Swenshuai.xi return ENODEV;
322*53ee8cc1Swenshuai.xi }
323*53ee8cc1Swenshuai.xi
324*53ee8cc1Swenshuai.xi //kevinhuang, no write temporarily coz current FATFS will contaminate FS on the disk
325*53ee8cc1Swenshuai.xi if (bSCSI_Write_10(usb_info->uPort, usb_info->num, block_num,
326*53ee8cc1Swenshuai.xi len, (cyg_uint8*) buf) )
327*53ee8cc1Swenshuai.xi return ENOERR;
328*53ee8cc1Swenshuai.xi else
329*53ee8cc1Swenshuai.xi return -EIO;
330*53ee8cc1Swenshuai.xi }
331*53ee8cc1Swenshuai.xi
332*53ee8cc1Swenshuai.xi static Cyg_ErrNo
usb_disk_get_config(disk_channel * chan,cyg_uint32 key,const void * xbuf,cyg_uint32 * len)333*53ee8cc1Swenshuai.xi usb_disk_get_config(disk_channel *chan,
334*53ee8cc1Swenshuai.xi cyg_uint32 key,
335*53ee8cc1Swenshuai.xi const void *xbuf,
336*53ee8cc1Swenshuai.xi cyg_uint32 *len)
337*53ee8cc1Swenshuai.xi {
338*53ee8cc1Swenshuai.xi
339*53ee8cc1Swenshuai.xi
340*53ee8cc1Swenshuai.xi return -EINVAL;
341*53ee8cc1Swenshuai.xi }
342*53ee8cc1Swenshuai.xi
343*53ee8cc1Swenshuai.xi static Cyg_ErrNo
usb_disk_set_config(disk_channel * chan,cyg_uint32 key,const void * xbuf,cyg_uint32 * len)344*53ee8cc1Swenshuai.xi usb_disk_set_config(disk_channel *chan,
345*53ee8cc1Swenshuai.xi cyg_uint32 key,
346*53ee8cc1Swenshuai.xi const void *xbuf,
347*53ee8cc1Swenshuai.xi cyg_uint32 *len)
348*53ee8cc1Swenshuai.xi {
349*53ee8cc1Swenshuai.xi Cyg_ErrNo result = ENOERR;
350*53ee8cc1Swenshuai.xi // cyg_mmc_bus_device* disk = (cyg_mmc_bus_device*) chan->dev_priv;
351*53ee8cc1Swenshuai.xi // cyg_disk_info_t *info = chan->info;
352*53ee8cc1Swenshuai.xi
353*53ee8cc1Swenshuai.xi switch(key)
354*53ee8cc1Swenshuai.xi {
355*53ee8cc1Swenshuai.xi case CYG_IO_SET_CONFIG_DISK_MOUNT:
356*53ee8cc1Swenshuai.xi // There will have been a successful lookup(), so there's
357*53ee8cc1Swenshuai.xi // little point in checking the disk again.
358*53ee8cc1Swenshuai.xi // if ((sd_chk_ready()!=_DEVICE_READY)&&
359*53ee8cc1Swenshuai.xi // result=-EINVAL;
360*53ee8cc1Swenshuai.xi //else device is OK
361*53ee8cc1Swenshuai.xi
362*53ee8cc1Swenshuai.xi break;
363*53ee8cc1Swenshuai.xi
364*53ee8cc1Swenshuai.xi case CYG_IO_SET_CONFIG_DISK_UMOUNT:
365*53ee8cc1Swenshuai.xi if (0 == chan->info->mounts)
366*53ee8cc1Swenshuai.xi {
367*53ee8cc1Swenshuai.xi //cyg_mmc_bus* bus = disk->mmc_bus_dev;
368*53ee8cc1Swenshuai.xi
369*53ee8cc1Swenshuai.xi // If this is the last unmount of the card, mark it as
370*53ee8cc1Swenshuai.xi // disconnected. If the user then removes the card and
371*53ee8cc1Swenshuai.xi // plugs in a new one everything works cleanly.
372*53ee8cc1Swenshuai.xi // disk->mmc_connected = false;
373*53ee8cc1Swenshuai.xi // info->connected = false;
374*53ee8cc1Swenshuai.xi //result = (chan->callbacks->disk_disconnected)(chan);
375*53ee8cc1Swenshuai.xi
376*53ee8cc1Swenshuai.xi // * deselect it too if it had been selected * //
377*53ee8cc1Swenshuai.xi // * We don't care about any error really. This device is going away. * //
378*53ee8cc1Swenshuai.xi //mmc_bus_select_card( bus, NULL );
379*53ee8cc1Swenshuai.xi }
380*53ee8cc1Swenshuai.xi break;
381*53ee8cc1Swenshuai.xi }
382*53ee8cc1Swenshuai.xi
383*53ee8cc1Swenshuai.xi return result;
384*53ee8cc1Swenshuai.xi // return -EINVAL;
385*53ee8cc1Swenshuai.xi
386*53ee8cc1Swenshuai.xi }
387*53ee8cc1Swenshuai.xi #endif
388*53ee8cc1Swenshuai.xi
389*53ee8cc1Swenshuai.xi extern struct us_data *Mass_stor_us[];
MDrv_USB_MscLookupHostID(char * str)390*53ee8cc1Swenshuai.xi U8 MDrv_USB_MscLookupHostID(char *str)
391*53ee8cc1Swenshuai.xi {
392*53ee8cc1Swenshuai.xi cyg_devtab_entry_t *t;
393*53ee8cc1Swenshuai.xi disk_channel *chan;
394*53ee8cc1Swenshuai.xi usb_disk_info_t *p_usb_info;
395*53ee8cc1Swenshuai.xi U8 host_id = 0xff;
396*53ee8cc1Swenshuai.xi
397*53ee8cc1Swenshuai.xi for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
398*53ee8cc1Swenshuai.xi {
399*53ee8cc1Swenshuai.xi chan = (disk_channel *) t->priv;
400*53ee8cc1Swenshuai.xi if (chan == NULL)
401*53ee8cc1Swenshuai.xi continue;
402*53ee8cc1Swenshuai.xi p_usb_info = (usb_disk_info_t *) chan->dev_priv;
403*53ee8cc1Swenshuai.xi if (p_usb_info == NULL)
404*53ee8cc1Swenshuai.xi continue;
405*53ee8cc1Swenshuai.xi
406*53ee8cc1Swenshuai.xi if ((p_usb_info->DevId != (-1)) && (strcmp(str, t->name) == 0)) // find the table entry
407*53ee8cc1Swenshuai.xi {
408*53ee8cc1Swenshuai.xi host_id = Mass_stor_us[p_usb_info->uPort]->host_id;
409*53ee8cc1Swenshuai.xi break;
410*53ee8cc1Swenshuai.xi }
411*53ee8cc1Swenshuai.xi }
412*53ee8cc1Swenshuai.xi if (host_id == 0xff)
413*53ee8cc1Swenshuai.xi diag_printf("Not found %s on any USB host port\n", str);
414*53ee8cc1Swenshuai.xi return (host_id);
415*53ee8cc1Swenshuai.xi }
416*53ee8cc1Swenshuai.xi
MDrv_USB_MscLookupProductString(char * str)417*53ee8cc1Swenshuai.xi char *MDrv_USB_MscLookupProductString(char *str)
418*53ee8cc1Swenshuai.xi {
419*53ee8cc1Swenshuai.xi cyg_devtab_entry_t *t;
420*53ee8cc1Swenshuai.xi disk_channel *chan;
421*53ee8cc1Swenshuai.xi usb_disk_info_t *p_usb_info;
422*53ee8cc1Swenshuai.xi char *pstr;
423*53ee8cc1Swenshuai.xi
424*53ee8cc1Swenshuai.xi pstr = NULL;
425*53ee8cc1Swenshuai.xi for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
426*53ee8cc1Swenshuai.xi {
427*53ee8cc1Swenshuai.xi chan = (disk_channel *) t->priv;
428*53ee8cc1Swenshuai.xi if (chan == NULL)
429*53ee8cc1Swenshuai.xi continue;
430*53ee8cc1Swenshuai.xi p_usb_info = (usb_disk_info_t *) chan->dev_priv;
431*53ee8cc1Swenshuai.xi if (p_usb_info == NULL)
432*53ee8cc1Swenshuai.xi continue;
433*53ee8cc1Swenshuai.xi
434*53ee8cc1Swenshuai.xi if ((p_usb_info->DevId != (-1)) && (strcmp(str, t->name) == 0)) // find the table entry
435*53ee8cc1Swenshuai.xi {
436*53ee8cc1Swenshuai.xi pstr = Mass_stor_us[p_usb_info->uPort]->pusb_dev->product;
437*53ee8cc1Swenshuai.xi break;
438*53ee8cc1Swenshuai.xi }
439*53ee8cc1Swenshuai.xi }
440*53ee8cc1Swenshuai.xi if (pstr == NULL)
441*53ee8cc1Swenshuai.xi diag_printf("Product string not found\n");
442*53ee8cc1Swenshuai.xi return (pstr);
443*53ee8cc1Swenshuai.xi }
444*53ee8cc1Swenshuai.xi
ConnectUSBDisk(U8 uPort,U8 uLunNum)445*53ee8cc1Swenshuai.xi BOOL ConnectUSBDisk(U8 uPort, U8 uLunNum)
446*53ee8cc1Swenshuai.xi {
447*53ee8cc1Swenshuai.xi struct LUN_Device *LunDevice = Mass_stor_us[uPort]->Mass_stor_device;
448*53ee8cc1Swenshuai.xi // Cyg_ErrNo err;
449*53ee8cc1Swenshuai.xi cyg_devtab_entry_t *dev_h;
450*53ee8cc1Swenshuai.xi // cyg_io_handle_t io_h;
451*53ee8cc1Swenshuai.xi disk_channel *chan;
452*53ee8cc1Swenshuai.xi usb_disk_info_t *p_usb_info;
453*53ee8cc1Swenshuai.xi cyg_disk_identify_t ident;
454*53ee8cc1Swenshuai.xi cyg_devtab_entry_t *t;
455*53ee8cc1Swenshuai.xi char szUSBDevName[12]={0};
456*53ee8cc1Swenshuai.xi //int ret;
457*53ee8cc1Swenshuai.xi
458*53ee8cc1Swenshuai.xi for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
459*53ee8cc1Swenshuai.xi {
460*53ee8cc1Swenshuai.xi chan = (disk_channel *) t->priv;
461*53ee8cc1Swenshuai.xi if (chan == NULL)
462*53ee8cc1Swenshuai.xi continue;
463*53ee8cc1Swenshuai.xi p_usb_info = (usb_disk_info_t *) chan->dev_priv;
464*53ee8cc1Swenshuai.xi if (p_usb_info == NULL)
465*53ee8cc1Swenshuai.xi continue;
466*53ee8cc1Swenshuai.xi if (p_usb_info->DevId == ((uPort+1)*MAX_USB_STOR_LUNS + uLunNum) )
467*53ee8cc1Swenshuai.xi {
468*53ee8cc1Swenshuai.xi diag_printf("Warning : find one previous device here !!\n");
469*53ee8cc1Swenshuai.xi //call RemoveUSBDiskPort()???
470*53ee8cc1Swenshuai.xi RemoveUSBDiskPort(uPort, uLunNum);
471*53ee8cc1Swenshuai.xi p_usb_info->DevId = -1;
472*53ee8cc1Swenshuai.xi }
473*53ee8cc1Swenshuai.xi }
474*53ee8cc1Swenshuai.xi
475*53ee8cc1Swenshuai.xi for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
476*53ee8cc1Swenshuai.xi {
477*53ee8cc1Swenshuai.xi
478*53ee8cc1Swenshuai.xi chan = (disk_channel *) t->priv;
479*53ee8cc1Swenshuai.xi if (chan == NULL)
480*53ee8cc1Swenshuai.xi continue;
481*53ee8cc1Swenshuai.xi p_usb_info = (usb_disk_info_t *) chan->dev_priv;
482*53ee8cc1Swenshuai.xi if (p_usb_info == NULL)
483*53ee8cc1Swenshuai.xi continue;
484*53ee8cc1Swenshuai.xi
485*53ee8cc1Swenshuai.xi if (p_usb_info->DevId == (-1))
486*53ee8cc1Swenshuai.xi {
487*53ee8cc1Swenshuai.xi p_usb_info->DevId = (uPort+1)*MAX_USB_STOR_LUNS + uLunNum;
488*53ee8cc1Swenshuai.xi break;
489*53ee8cc1Swenshuai.xi }
490*53ee8cc1Swenshuai.xi }
491*53ee8cc1Swenshuai.xi
492*53ee8cc1Swenshuai.xi if (t == &__DEVTAB_END__)
493*53ee8cc1Swenshuai.xi {
494*53ee8cc1Swenshuai.xi diag_printf("Error! Can't find available disk name. Exceed maximum support number!\n");
495*53ee8cc1Swenshuai.xi return FALSE;
496*53ee8cc1Swenshuai.xi }
497*53ee8cc1Swenshuai.xi
498*53ee8cc1Swenshuai.xi chan = (disk_channel *) t->priv;
499*53ee8cc1Swenshuai.xi chan->info->connected = true;
500*53ee8cc1Swenshuai.xi
501*53ee8cc1Swenshuai.xi #if 0
502*53ee8cc1Swenshuai.xi szUSBDevName[7] = t->name[7];
503*53ee8cc1Swenshuai.xi diag_printf("cyg_io_lookup %s ..", szUSBDevName);
504*53ee8cc1Swenshuai.xi
505*53ee8cc1Swenshuai.xi err = cyg_io_lookup(szUSBDevName, &io_h);
506*53ee8cc1Swenshuai.xi if (err != ENOERR)
507*53ee8cc1Swenshuai.xi {
508*53ee8cc1Swenshuai.xi diag_printf(" FALSE !!\n");
509*53ee8cc1Swenshuai.xi return FALSE;
510*53ee8cc1Swenshuai.xi }
511*53ee8cc1Swenshuai.xi diag_printf(" OK\n");
512*53ee8cc1Swenshuai.xi
513*53ee8cc1Swenshuai.xi dev_h = (cyg_devtab_entry_t *) io_h;
514*53ee8cc1Swenshuai.xi #endif
515*53ee8cc1Swenshuai.xi
516*53ee8cc1Swenshuai.xi dev_h = t;
517*53ee8cc1Swenshuai.xi
518*53ee8cc1Swenshuai.xi chan = (disk_channel*) dev_h->priv;
519*53ee8cc1Swenshuai.xi p_usb_info = (usb_disk_info_t *) chan->dev_priv;
520*53ee8cc1Swenshuai.xi p_usb_info->uPort = uPort;
521*53ee8cc1Swenshuai.xi p_usb_info->num = uLunNum;
522*53ee8cc1Swenshuai.xi
523*53ee8cc1Swenshuai.xi ident.serial[0] = '\0';
524*53ee8cc1Swenshuai.xi ident.firmware_rev[0] = '\0';
525*53ee8cc1Swenshuai.xi ident.model_num[0] = '\0';
526*53ee8cc1Swenshuai.xi // ident.lba_sectors_num = usb_info->size / 512;
527*53ee8cc1Swenshuai.xi ident.lba_sectors_num = LunDevice[uLunNum].u32BlockTotalNum;
528*53ee8cc1Swenshuai.xi ident.cylinders_num = 0;
529*53ee8cc1Swenshuai.xi ident.heads_num = 0;
530*53ee8cc1Swenshuai.xi ident.sectors_num = 0;
531*53ee8cc1Swenshuai.xi ident.phys_block_size = LunDevice[uLunNum].u32BlockSize;
532*53ee8cc1Swenshuai.xi ident.max_transfer = LunDevice[uLunNum].u32BlockSize;// 512;
533*53ee8cc1Swenshuai.xi
534*53ee8cc1Swenshuai.xi //diag_printf("Connect USB disk %s\n", szUSBDevName);
535*53ee8cc1Swenshuai.xi diag_printf("Connect USB disk %s\n", dev_h->name);
536*53ee8cc1Swenshuai.xi diag_printf("Port:%d Lun:%d Id:%d\n", p_usb_info->uPort, p_usb_info->num, p_usb_info->DevId);
537*53ee8cc1Swenshuai.xi if (!(chan->callbacks->disk_init)(dev_h))
538*53ee8cc1Swenshuai.xi return FALSE;
539*53ee8cc1Swenshuai.xi
540*53ee8cc1Swenshuai.xi if (ENOERR != (chan->callbacks->disk_connected)(dev_h, &ident))
541*53ee8cc1Swenshuai.xi return FALSE;
542*53ee8cc1Swenshuai.xi
543*53ee8cc1Swenshuai.xi if ( _DrvUSB_CBFun != NULL )
544*53ee8cc1Swenshuai.xi {
545*53ee8cc1Swenshuai.xi if (strlen(dev_h->name) < 12)
546*53ee8cc1Swenshuai.xi strcpy(szUSBDevName, dev_h->name);
547*53ee8cc1Swenshuai.xi _DrvUSB_CBFun(USB_PLUG_IN, USB_EVENT_DEV_TYPE_STOR, szUSBDevName);
548*53ee8cc1Swenshuai.xi }
549*53ee8cc1Swenshuai.xi //Test
550*53ee8cc1Swenshuai.xi //ret = mount("/dev/sda/1", "/", "fatfs");
551*53ee8cc1Swenshuai.xi //diag_printf("mount status : %d \n", ret);
552*53ee8cc1Swenshuai.xi diag_printf("@@ Host ID %x\n", MDrv_USB_MscLookupHostID(szUSBDevName));
553*53ee8cc1Swenshuai.xi
554*53ee8cc1Swenshuai.xi return TRUE;
555*53ee8cc1Swenshuai.xi }
556*53ee8cc1Swenshuai.xi
RemoveUSBDiskPort(U8 uPort,U8 uLunNum)557*53ee8cc1Swenshuai.xi VOID RemoveUSBDiskPort(U8 uPort, U8 uLunNum)
558*53ee8cc1Swenshuai.xi {
559*53ee8cc1Swenshuai.xi // Cyg_ErrNo err;
560*53ee8cc1Swenshuai.xi cyg_devtab_entry_t *dev_h, *t;
561*53ee8cc1Swenshuai.xi // cyg_io_handle_t io_h;
562*53ee8cc1Swenshuai.xi disk_channel *chan;
563*53ee8cc1Swenshuai.xi cyg_disk_info_t *info;
564*53ee8cc1Swenshuai.xi usb_disk_info_t *p_usb_info;
565*53ee8cc1Swenshuai.xi char szUSBDevName[12]={0};
566*53ee8cc1Swenshuai.xi ///struct LUN_Device* LunDevice = Mass_stor_us[uPort]->Mass_stor_device;
567*53ee8cc1Swenshuai.xi
568*53ee8cc1Swenshuai.xi
569*53ee8cc1Swenshuai.xi #if 0
570*53ee8cc1Swenshuai.xi //UTL_snprintf(szUSBDevName, 12, "/dev/sd%c/", 'a' + uLunNum);
571*53ee8cc1Swenshuai.xi szUSBDevName[7]= 'a' + (uPort * MAX_USB_STOR_LUNS) + uLunNum;
572*53ee8cc1Swenshuai.xi
573*53ee8cc1Swenshuai.xi err = cyg_io_lookup(szUSBDevName, &io_h);
574*53ee8cc1Swenshuai.xi if (err != ENOERR)
575*53ee8cc1Swenshuai.xi return;
576*53ee8cc1Swenshuai.xi dev_h = (cyg_devtab_entry_t *) io_h;
577*53ee8cc1Swenshuai.xi #endif
578*53ee8cc1Swenshuai.xi
579*53ee8cc1Swenshuai.xi for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
580*53ee8cc1Swenshuai.xi {
581*53ee8cc1Swenshuai.xi
582*53ee8cc1Swenshuai.xi chan = (disk_channel *) t->priv;
583*53ee8cc1Swenshuai.xi if (chan == NULL)
584*53ee8cc1Swenshuai.xi continue;
585*53ee8cc1Swenshuai.xi p_usb_info = (usb_disk_info_t *) chan->dev_priv;
586*53ee8cc1Swenshuai.xi if (p_usb_info == NULL)
587*53ee8cc1Swenshuai.xi continue;
588*53ee8cc1Swenshuai.xi
589*53ee8cc1Swenshuai.xi if (p_usb_info->DevId == ((uPort+1)*MAX_USB_STOR_LUNS + uLunNum))
590*53ee8cc1Swenshuai.xi {
591*53ee8cc1Swenshuai.xi if ((p_usb_info->uPort != uPort) || (p_usb_info->num != uLunNum))
592*53ee8cc1Swenshuai.xi {
593*53ee8cc1Swenshuai.xi diag_printf("Warning: RemoveUSBDiskPort not match !!\n");
594*53ee8cc1Swenshuai.xi diag_printf("[Port lun]: [%d %d]->[%d %d]\n", uPort,uLunNum,p_usb_info->uPort,p_usb_info->num);
595*53ee8cc1Swenshuai.xi }
596*53ee8cc1Swenshuai.xi diag_printf("RemoveUSBDiskPort:%d %d %d\n",p_usb_info->uPort,p_usb_info->num,p_usb_info->DevId);
597*53ee8cc1Swenshuai.xi break;
598*53ee8cc1Swenshuai.xi }
599*53ee8cc1Swenshuai.xi }
600*53ee8cc1Swenshuai.xi
601*53ee8cc1Swenshuai.xi if (t == &__DEVTAB_END__)
602*53ee8cc1Swenshuai.xi {
603*53ee8cc1Swenshuai.xi diag_printf("RemoveUSBDiskPort: Can't find match Port:%d Lun:%d\n", uPort, uLunNum);
604*53ee8cc1Swenshuai.xi return;
605*53ee8cc1Swenshuai.xi }
606*53ee8cc1Swenshuai.xi
607*53ee8cc1Swenshuai.xi dev_h = t;
608*53ee8cc1Swenshuai.xi chan = (disk_channel *) dev_h->priv;
609*53ee8cc1Swenshuai.xi info = chan->info;
610*53ee8cc1Swenshuai.xi p_usb_info = (usb_disk_info_t *) chan->dev_priv;
611*53ee8cc1Swenshuai.xi p_usb_info->DevId = -1;
612*53ee8cc1Swenshuai.xi p_usb_info->uPort = -1;
613*53ee8cc1Swenshuai.xi p_usb_info->num = -1;
614*53ee8cc1Swenshuai.xi
615*53ee8cc1Swenshuai.xi //diag_printf("Remove USB disk %s\n", szUSBDevName);
616*53ee8cc1Swenshuai.xi diag_printf("Remove USB disk %s\n", dev_h->name);
617*53ee8cc1Swenshuai.xi chan->callbacks->disk_disconnected(chan);
618*53ee8cc1Swenshuai.xi
619*53ee8cc1Swenshuai.xi if ( _DrvUSB_CBFun != NULL )
620*53ee8cc1Swenshuai.xi {
621*53ee8cc1Swenshuai.xi if (strlen(dev_h->name) < 12)
622*53ee8cc1Swenshuai.xi strcpy(szUSBDevName, dev_h->name);
623*53ee8cc1Swenshuai.xi _DrvUSB_CBFun(USB_PLUG_OUT, USB_EVENT_DEV_TYPE_STOR, szUSBDevName);
624*53ee8cc1Swenshuai.xi }
625*53ee8cc1Swenshuai.xi
626*53ee8cc1Swenshuai.xi //info->connected = false;
627*53ee8cc1Swenshuai.xi //chan->valid = false;
628*53ee8cc1Swenshuai.xi }
629*53ee8cc1Swenshuai.xi
630