1 /*
2 ********************************************************************************************************************
3 * usb host driver
4 *
5 * (c) Copyright 2007-2010, javen.China
6 * All Rights Reserved
7 *
8 * File Name : mscTransport_i.c
9 *
10 * Author : javen
11 *
12 * Version : 2.0
13 *
14 * Date : 2010.7.12
15 *
16 * Description :
17 * USB Mass Storage Class传输容错辅助处理部分。
18 *
19 * 这部分主要是为了解决USB光驱中光盘突然弹出时,USB容错时间过长。其原因是Lun中media已经不存在,但是lun本身还在,
20 * 虽不可读/写数据,但是可以操作Lun。因此现在增加了在读写操作超时后,先去test_unit_ready,判断Lun的状态后,
21 * 再决定下一步的操作。
22 *
23 * History :
24 *
25 ********************************************************************************************************************
26 */
27 #include "usb_os_platform.h"
28 #include "error.h"
29 #include "usb_host_common.h"
30 #include "urb.h"
31 #include "usb_gen_hub.h"
32 #include "usb_msc_i.h"
33 #include "mscTransport.h"
34 #include "Scsi2.h"
35
36 /*
37 *******************************************************************************
38 * mscTransportRequestSense
39 *
40 * Description:
41 *
42 *
43 * Parameters:
44 *
45 *
46 * Return value:
47 *
48 *
49 * note:
50 *
51 *
52 *******************************************************************************
53 */
mscTransportRequestSense(__mscLun_t * mscLun,void * buffer,unsigned int buffer_len)54 static int mscTransportRequestSense(__mscLun_t *mscLun, void *buffer, unsigned int buffer_len)
55 {
56 __ScsiCmnd_t ScsiCmnd;
57 unsigned char CB[MAX_CDB];
58 unsigned int ret = 0;
59
60 if (mscLun == NULL || buffer == NULL)
61 {
62 // printf("ERR: ScsiInquery: input error, mscLun = %x, buffer = %x\n", (unsigned int)mscLun, (unsigned int)buffer);
63 return USB_STATUS_BAD_ARGUMENTS;
64 }
65
66 if (buffer_len == 0)
67 {
68 printf("ERR: ScsiInquery: input error, buffer_len == %d\n", buffer_len);
69 return USB_STATUS_BUFFER_TOO_SMALL;
70 }
71
72 memset((void *)&ScsiCmnd, 0, sizeof(__ScsiCmnd_t));
73 memset(CB, 0, MAX_CDB);
74 /* create command block */
75 CB[0] = SCSI_REQUEST_SENSE; /* scsi command */
76 CB[1] = ((mscLun->LunNo & 0x7) << 5); /* lun */
77 CB[4] = buffer_len; /* Allocation Length */
78 /* initialize transport command */
79 ScsiCmnd.cmnd.data_direction = DATA_FROM_DEVICE;
80 ScsiCmnd.cmnd.Timeout = SCSI_COMMAND_TIMEOUT;
81 ScsiCmnd.cmnd.dwLun = mscLun->LunNo;
82 ScsiCmnd.cmnd.CBLen = (USBMSC_SUBCLASS_SCSI == mscLun->DiskSubClass) ? SCSI_CDB_6 : UFI_CDB;
83 ScsiCmnd.cmnd.CommandBlock = CB;
84 /* initialize scsi_cnmd */
85 ScsiCmnd.sc_lun = mscLun;
86 ScsiCmnd.allowed = SCSI_CMD_RETRY;
87 ScsiCmnd.DataTransferLength = buffer_len;
88 ScsiCmnd.buffer = buffer;
89 ret = mscBoTransport(mscLun->mscDev, &ScsiCmnd);
90 return ret;
91 }
92
93 /*
94 *******************************************************************************
95 * mscTransportGetSenseData
96 *
97 * Description:
98 *
99 *
100 * Parameters:
101 *
102 *
103 * Return value:
104 *
105 *
106 * note:
107 *
108 *
109 *******************************************************************************
110 */
mscTransportGetSenseData(__mscLun_t * mscLun)111 static int mscTransportGetSenseData(__mscLun_t *mscLun)
112 {
113 __SenseData_t SenseData;
114 int ret = 0;
115 memset(&SenseData, 0, sizeof(__SenseData_t));
116 ret = mscTransportRequestSense(mscLun, (void *)&SenseData, sizeof(__SenseData_t));
117
118 if (ret != USB_STOR_TRANSPORT_GOOD)
119 {
120 printf("ERR: mscTransportGetSenseData failed\n");
121 return USB_ERR_BAD_ARGUMENTS;
122 }
123
124 printf("mscReason:SenseKey = %x, AdditionalSenseCode = %x\n",
125 SenseData.SenseKey, SenseData.AdditionalSenseCode);
126
127 switch (SenseData.SenseKey)
128 {
129 case SENSE_NONE :
130 ret = USB_ERR_SUCCESS;
131 break;
132
133 case SENSE_NOT_READY :
134 switch (SenseData.AdditionalSenseCode)
135 {
136 case ASC_MEDIUM_NOT_PRESENT :
137 printf("ERR: media is not present\n");
138 mscLun->MediaPresent = 0;
139 ret = USB_ERR_MEDIA_NOT_PRESENT;
140 break;
141
142 default:
143 printf("ERR: unkown ASC(%d)\n", SenseData.AdditionalSenseCode);
144 ret = USB_ERR_UNKOWN_ERROR;
145 break;
146 }
147
148 break;
149
150 case SENSE_ILLEGAL_REQUEST :
151 ret = USB_ERR_NOT_SUPPORT_COMMAND;
152 break;
153
154 case SENSE_UNIT_ATTENTION :
155 switch (SenseData.AdditionalSenseCode)
156 {
157 case ASC_MEDIUM_NOT_PRESENT :
158 printf("ERR: media is not present\n");
159 mscLun->MediaPresent = 0;
160 ret = USB_ERR_MEDIA_NOT_PRESENT;
161 break;
162
163 default:
164 printf("ERR: unkown ASC(%d)\n", SenseData.AdditionalSenseCode);
165 ret = USB_ERR_UNKOWN_ERROR;
166 }
167
168 break;
169
170 default:
171 ret = USB_ERR_UNKOWN_ERROR;
172 }
173
174 return ret;
175 }
176
177 /*
178 *******************************************************************************
179 * mscGetDataTransportReason
180 *
181 * Description:
182 *
183 *
184 * Parameters:
185 *
186 *
187 * Return value:
188 *
189 *
190 * note:
191 *
192 *
193 *******************************************************************************
194 */
mscGetDataTransportReason(__mscLun_t * mscLun,__ScsiCmnd_t * ScsiCmnd)195 int mscGetDataTransportReason(__mscLun_t *mscLun, __ScsiCmnd_t *ScsiCmnd)
196 {
197 int ret = USB_ERR_COMMAND_NEED_RETRY;
198 unsigned char Command = 0;
199 int status = 0;
200
201 if (mscLun == NULL || ScsiCmnd == NULL)
202 {
203 printf("ERR: input error\n");
204 return USB_ERR_COMMAND_NEED_RETRY;
205 }
206
207 status = mscTransportGetSenseData(mscLun);
208
209 if (status == USB_ERR_MEDIA_NOT_PRESENT || status == USB_ERR_NOT_SUPPORT_COMMAND)
210 {
211 Command = ((unsigned char *)(ScsiCmnd->cmnd.CommandBlock))[0];
212
213 if (Command == SCSI_READ6 || Command == SCSI_READ10 || Command == SCSI_READ16
214 || Command == SCSI_WRITE6 || Command == SCSI_WRITE10 || Command == SCSI_WRITE16)
215 {
216 printf("ERR: Command(%x) execute failed, for media is not present\n", Command);
217 ret = USB_ERR_COMMAND_EXECUTE_FAILED;
218 }
219 }
220
221 return ret;
222 }
223
224