Commit | Line | Data |
---|---|---|
126bb03b AC |
1 | #include <linux/sched.h> |
2 | #include <linux/errno.h> | |
3 | #include <linux/slab.h> | |
4 | ||
5 | #include <scsi/scsi.h> | |
6 | #include <scsi/scsi_eh.h> | |
7 | #include <scsi/scsi_device.h> | |
8 | ||
9 | #include "usb.h" | |
10 | #include "scsiglue.h" | |
11 | #include "transport.h" | |
12 | ||
13 | /*********************************************************************** | |
14 | * Data transfer routines | |
15 | ***********************************************************************/ | |
16 | //----- usb_stor_blocking_completion() --------------------- | |
17 | static void usb_stor_blocking_completion(struct urb *urb) | |
18 | { | |
19 | struct completion *urb_done_ptr = urb->context; | |
20 | ||
21 | //printk("transport --- usb_stor_blocking_completion\n"); | |
22 | complete(urb_done_ptr); | |
23 | } | |
24 | ||
25 | //----- usb_stor_msg_common() --------------------- | |
26 | static int usb_stor_msg_common(struct us_data *us, int timeout) | |
27 | { | |
28 | struct completion urb_done; | |
29 | long timeleft; | |
30 | int status; | |
31 | ||
32 | //printk("transport --- usb_stor_msg_common\n"); | |
33 | if (test_bit(US_FLIDX_ABORTING, &us->dflags)) | |
34 | return -EIO; | |
35 | ||
36 | init_completion(&urb_done); | |
37 | ||
38 | us->current_urb->context = &urb_done; | |
39 | us->current_urb->actual_length = 0; | |
40 | us->current_urb->error_count = 0; | |
41 | us->current_urb->status = 0; | |
42 | ||
43 | // us->current_urb->transfer_flags = URB_NO_SETUP_DMA_MAP; | |
44 | if (us->current_urb->transfer_buffer == us->iobuf) | |
45 | us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
46 | us->current_urb->transfer_dma = us->iobuf_dma; | |
47 | us->current_urb->setup_dma = us->cr_dma; | |
48 | ||
49 | status = usb_submit_urb(us->current_urb, GFP_NOIO); | |
50 | if (status) | |
51 | return status; | |
52 | ||
53 | set_bit(US_FLIDX_URB_ACTIVE, &us->dflags); | |
54 | ||
55 | if (test_bit(US_FLIDX_ABORTING, &us->dflags)) | |
56 | { | |
57 | if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) | |
58 | { | |
59 | //printk("-- cancelling URB\n"); | |
60 | usb_unlink_urb(us->current_urb); | |
61 | } | |
62 | } | |
63 | ||
64 | timeleft = wait_for_completion_interruptible_timeout(&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); | |
65 | clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags); | |
66 | ||
67 | if (timeleft <= 0) | |
68 | { | |
69 | //printk("%s -- cancelling URB\n", timeleft == 0 ? "Timeout" : "Signal"); | |
70 | usb_kill_urb(us->current_urb); | |
71 | } | |
72 | ||
73 | return us->current_urb->status; | |
74 | } | |
75 | ||
76 | //----- usb_stor_control_msg() --------------------- | |
77 | int usb_stor_control_msg(struct us_data *us, unsigned int pipe, | |
78 | u8 request, u8 requesttype, u16 value, u16 index, | |
79 | void *data, u16 size, int timeout) | |
80 | { | |
81 | int status; | |
82 | ||
83 | //printk("transport --- usb_stor_control_msg\n"); | |
84 | ||
85 | /* fill in the devrequest structure */ | |
86 | us->cr->bRequestType = requesttype; | |
87 | us->cr->bRequest = request; | |
88 | us->cr->wValue = cpu_to_le16(value); | |
89 | us->cr->wIndex = cpu_to_le16(index); | |
90 | us->cr->wLength = cpu_to_le16(size); | |
91 | ||
92 | /* fill and submit the URB */ | |
93 | usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, | |
94 | (unsigned char*) us->cr, data, size, | |
95 | usb_stor_blocking_completion, NULL); | |
96 | status = usb_stor_msg_common(us, timeout); | |
97 | ||
98 | /* return the actual length of the data transferred if no error */ | |
99 | if (status == 0) | |
100 | status = us->current_urb->actual_length; | |
101 | return status; | |
102 | } | |
103 | ||
104 | //----- usb_stor_clear_halt() --------------------- | |
105 | int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) | |
106 | { | |
107 | int result; | |
108 | int endp = usb_pipeendpoint(pipe); | |
109 | ||
110 | //printk("transport --- usb_stor_clear_halt\n"); | |
111 | if (usb_pipein (pipe)) | |
112 | endp |= USB_DIR_IN; | |
113 | ||
114 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, | |
115 | USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, | |
116 | USB_ENDPOINT_HALT, endp, | |
117 | NULL, 0, 3*HZ); | |
118 | ||
119 | /* reset the endpoint toggle */ | |
120 | if (result >= 0) | |
121 | //usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); | |
122 | usb_reset_endpoint(us->pusb_dev, endp); | |
123 | ||
124 | return result; | |
125 | } | |
126 | ||
127 | //----- interpret_urb_result() --------------------- | |
128 | static int interpret_urb_result(struct us_data *us, unsigned int pipe, | |
129 | unsigned int length, int result, unsigned int partial) | |
130 | { | |
131 | //printk("transport --- interpret_urb_result\n"); | |
132 | switch (result) { | |
133 | /* no error code; did we send all the data? */ | |
134 | case 0: | |
135 | if (partial != length) | |
136 | { | |
137 | //printk("-- short transfer\n"); | |
138 | return USB_STOR_XFER_SHORT; | |
139 | } | |
140 | //printk("-- transfer complete\n"); | |
141 | return USB_STOR_XFER_GOOD; | |
142 | case -EPIPE: | |
143 | if (usb_pipecontrol(pipe)) | |
144 | { | |
145 | //printk("-- stall on control pipe\n"); | |
146 | return USB_STOR_XFER_STALLED; | |
147 | } | |
148 | //printk("clearing endpoint halt for pipe 0x%x\n", pipe); | |
149 | if (usb_stor_clear_halt(us, pipe) < 0) | |
150 | return USB_STOR_XFER_ERROR; | |
151 | return USB_STOR_XFER_STALLED; | |
152 | case -EOVERFLOW: | |
153 | //printk("-- babble\n"); | |
154 | return USB_STOR_XFER_LONG; | |
155 | case -ECONNRESET: | |
156 | //printk("-- transfer cancelled\n"); | |
157 | return USB_STOR_XFER_ERROR; | |
158 | case -EREMOTEIO: | |
159 | //printk("-- short read transfer\n"); | |
160 | return USB_STOR_XFER_SHORT; | |
161 | case -EIO: | |
162 | //printk("-- abort or disconnect in progress\n"); | |
163 | return USB_STOR_XFER_ERROR; | |
164 | default: | |
165 | //printk("-- unknown error\n"); | |
166 | return USB_STOR_XFER_ERROR; | |
167 | } | |
168 | } | |
169 | ||
170 | //----- usb_stor_bulk_transfer_buf() --------------------- | |
171 | int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, | |
172 | void *buf, unsigned int length, unsigned int *act_len) | |
173 | { | |
174 | int result; | |
175 | ||
176 | //printk("transport --- usb_stor_bulk_transfer_buf\n"); | |
177 | ||
178 | /* fill and submit the URB */ | |
179 | usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length, usb_stor_blocking_completion, NULL); | |
180 | result = usb_stor_msg_common(us, 0); | |
181 | ||
182 | /* store the actual length of the data transferred */ | |
183 | if (act_len) | |
184 | *act_len = us->current_urb->actual_length; | |
185 | ||
186 | return interpret_urb_result(us, pipe, length, result, us->current_urb->actual_length); | |
187 | } | |
188 | ||
189 | //----- usb_stor_bulk_transfer_sglist() --------------------- | |
190 | static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, | |
191 | struct scatterlist *sg, int num_sg, unsigned int length, | |
192 | unsigned int *act_len) | |
193 | { | |
194 | int result; | |
195 | ||
196 | //printk("transport --- usb_stor_bulk_transfer_sglist\n"); | |
197 | if (test_bit(US_FLIDX_ABORTING, &us->dflags)) | |
198 | return USB_STOR_XFER_ERROR; | |
199 | ||
200 | /* initialize the scatter-gather request block */ | |
201 | result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0, sg, num_sg, length, GFP_NOIO); | |
202 | if (result) | |
203 | { | |
204 | //printk("usb_sg_init returned %d\n", result); | |
205 | return USB_STOR_XFER_ERROR; | |
206 | } | |
207 | ||
208 | /* since the block has been initialized successfully, it's now okay to cancel it */ | |
209 | set_bit(US_FLIDX_SG_ACTIVE, &us->dflags); | |
210 | ||
211 | /* did an abort/disconnect occur during the submission? */ | |
212 | if (test_bit(US_FLIDX_ABORTING, &us->dflags)) | |
213 | { | |
214 | /* cancel the request, if it hasn't been cancelled already */ | |
215 | if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) | |
216 | { | |
217 | //printk("-- cancelling sg request\n"); | |
218 | usb_sg_cancel(&us->current_sg); | |
219 | } | |
220 | } | |
221 | ||
222 | /* wait for the completion of the transfer */ | |
223 | usb_sg_wait(&us->current_sg); | |
224 | clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags); | |
225 | ||
226 | result = us->current_sg.status; | |
227 | if (act_len) | |
228 | *act_len = us->current_sg.bytes; | |
229 | ||
230 | return interpret_urb_result(us, pipe, length, result, us->current_sg.bytes); | |
231 | } | |
232 | ||
233 | //----- usb_stor_bulk_srb() --------------------- | |
234 | int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, struct scsi_cmnd* srb) | |
235 | { | |
236 | unsigned int partial; | |
237 | int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb), | |
238 | scsi_sg_count(srb), scsi_bufflen(srb), | |
239 | &partial); | |
240 | ||
241 | scsi_set_resid(srb, scsi_bufflen(srb) - partial); | |
242 | return result; | |
243 | } | |
244 | ||
245 | //----- usb_stor_bulk_transfer_sg() --------------------- | |
246 | int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, | |
247 | void *buf, unsigned int length_left, int use_sg, int *residual) | |
248 | { | |
249 | int result; | |
250 | unsigned int partial; | |
251 | ||
252 | //printk("transport --- usb_stor_bulk_transfer_sg\n"); | |
253 | /* are we scatter-gathering? */ | |
254 | if (use_sg) | |
255 | { | |
256 | /* use the usb core scatter-gather primitives */ | |
257 | result = usb_stor_bulk_transfer_sglist(us, pipe, | |
258 | (struct scatterlist *) buf, use_sg, | |
259 | length_left, &partial); | |
260 | length_left -= partial; | |
261 | } | |
262 | else | |
263 | { | |
264 | /* no scatter-gather, just make the request */ | |
265 | result = usb_stor_bulk_transfer_buf(us, pipe, buf, length_left, &partial); | |
266 | length_left -= partial; | |
267 | } | |
268 | ||
269 | /* store the residual and return the error code */ | |
270 | if (residual) | |
271 | *residual = length_left; | |
272 | return result; | |
273 | } | |
274 | ||
275 | /*********************************************************************** | |
276 | * Transport routines | |
277 | ***********************************************************************/ | |
278 | //----- usb_stor_invoke_transport() --------------------- | |
279 | void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |
280 | { | |
281 | int need_auto_sense; | |
282 | int result; | |
283 | ||
284 | //printk("transport --- usb_stor_invoke_transport\n"); | |
285 | usb_stor_print_cmd(srb); | |
286 | /* send the command to the transport layer */ | |
287 | scsi_set_resid(srb, 0); | |
288 | result = us->transport(srb, us); //usb_stor_Bulk_transport; | |
289 | ||
290 | /* if the command gets aborted by the higher layers, we need to short-circuit all other processing */ | |
291 | if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) | |
292 | { | |
293 | //printk("-- command was aborted\n"); | |
294 | srb->result = DID_ABORT << 16; | |
295 | goto Handle_Errors; | |
296 | } | |
297 | ||
298 | /* if there is a transport error, reset and don't auto-sense */ | |
299 | if (result == USB_STOR_TRANSPORT_ERROR) | |
300 | { | |
301 | //printk("-- transport indicates error, resetting\n"); | |
302 | srb->result = DID_ERROR << 16; | |
303 | goto Handle_Errors; | |
304 | } | |
305 | ||
306 | /* if the transport provided its own sense data, don't auto-sense */ | |
307 | if (result == USB_STOR_TRANSPORT_NO_SENSE) | |
308 | { | |
309 | srb->result = SAM_STAT_CHECK_CONDITION; | |
310 | return; | |
311 | } | |
312 | ||
313 | srb->result = SAM_STAT_GOOD; | |
314 | ||
315 | /* Determine if we need to auto-sense */ | |
316 | need_auto_sense = 0; | |
317 | ||
318 | if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && srb->sc_data_direction != DMA_FROM_DEVICE) | |
319 | { | |
320 | //printk("-- CB transport device requiring auto-sense\n"); | |
321 | need_auto_sense = 1; | |
322 | } | |
323 | ||
324 | if (result == USB_STOR_TRANSPORT_FAILED) | |
325 | { | |
326 | //printk("-- transport indicates command failure\n"); | |
327 | need_auto_sense = 1; | |
328 | } | |
329 | ||
330 | /* Now, if we need to do the auto-sense, let's do it */ | |
331 | if (need_auto_sense) | |
332 | { | |
333 | int temp_result; | |
334 | struct scsi_eh_save ses; | |
335 | ||
336 | printk("Issuing auto-REQUEST_SENSE\n"); | |
337 | ||
338 | scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE); | |
339 | ||
340 | /* we must do the protocol translation here */ | |
341 | if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI || us->subclass == US_SC_CYP_ATACB) | |
342 | srb->cmd_len = 6; | |
343 | else | |
344 | srb->cmd_len = 12; | |
345 | ||
346 | /* issue the auto-sense command */ | |
347 | scsi_set_resid(srb, 0); | |
348 | temp_result = us->transport(us->srb, us); | |
349 | ||
350 | /* let's clean up right away */ | |
351 | scsi_eh_restore_cmnd(srb, &ses); | |
352 | ||
353 | if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) | |
354 | { | |
355 | //printk("-- auto-sense aborted\n"); | |
356 | srb->result = DID_ABORT << 16; | |
357 | goto Handle_Errors; | |
358 | } | |
359 | if (temp_result != USB_STOR_TRANSPORT_GOOD) | |
360 | { | |
361 | //printk("-- auto-sense failure\n"); | |
362 | srb->result = DID_ERROR << 16; | |
363 | if (!(us->fflags & US_FL_SCM_MULT_TARG)) | |
364 | goto Handle_Errors; | |
365 | return; | |
366 | } | |
367 | ||
368 | /* set the result so the higher layers expect this data */ | |
369 | srb->result = SAM_STAT_CHECK_CONDITION; | |
370 | ||
371 | if (result == USB_STOR_TRANSPORT_GOOD && | |
372 | (srb->sense_buffer[2] & 0xaf) == 0 && | |
373 | srb->sense_buffer[12] == 0 && | |
374 | srb->sense_buffer[13] == 0) | |
375 | { | |
376 | srb->result = SAM_STAT_GOOD; | |
377 | srb->sense_buffer[0] = 0x0; | |
378 | } | |
379 | } | |
380 | ||
381 | /* Did we transfer less than the minimum amount required? */ | |
382 | if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) | |
383 | srb->result = (DID_ERROR << 16);//v02 | (SUGGEST_RETRY << 24); | |
384 | ||
385 | return; | |
386 | ||
387 | Handle_Errors: | |
388 | scsi_lock(us_to_host(us)); | |
389 | set_bit(US_FLIDX_RESETTING, &us->dflags); | |
390 | clear_bit(US_FLIDX_ABORTING, &us->dflags); | |
391 | scsi_unlock(us_to_host(us)); | |
392 | ||
393 | mutex_unlock(&us->dev_mutex); | |
394 | result = usb_stor_port_reset(us); | |
395 | mutex_lock(&us->dev_mutex); | |
396 | ||
397 | if (result < 0) | |
398 | { | |
399 | scsi_lock(us_to_host(us)); | |
400 | usb_stor_report_device_reset(us); | |
401 | scsi_unlock(us_to_host(us)); | |
402 | us->transport_reset(us); | |
403 | } | |
404 | clear_bit(US_FLIDX_RESETTING, &us->dflags); | |
405 | } | |
406 | ||
407 | //----- ENE_stor_invoke_transport() --------------------- | |
408 | void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |
409 | { | |
410 | int result=0; | |
411 | ||
412 | //printk("transport --- ENE_stor_invoke_transport\n"); | |
413 | usb_stor_print_cmd(srb); | |
414 | /* send the command to the transport layer */ | |
415 | scsi_set_resid(srb, 0); | |
416 | if ( !(us->SD_Status.Ready || us->MS_Status.Ready || us->SM_Status.Ready) ) | |
417 | result = ENE_InitMedia(us); | |
418 | ||
419 | if (us->Power_IsResum == true) { | |
420 | result = ENE_InitMedia(us); | |
421 | us->Power_IsResum = false; | |
422 | } | |
423 | ||
424 | if (us->SD_Status.Ready) result = SD_SCSIIrp(us, srb); | |
425 | if (us->MS_Status.Ready) result = MS_SCSIIrp(us, srb); | |
426 | if (us->SM_Status.Ready) result = SM_SCSIIrp(us, srb); | |
427 | ||
428 | /* if the command gets aborted by the higher layers, we need to short-circuit all other processing */ | |
429 | if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) | |
430 | { | |
431 | //printk("-- command was aborted\n"); | |
432 | srb->result = DID_ABORT << 16; | |
433 | goto Handle_Errors; | |
434 | } | |
435 | ||
436 | /* if there is a transport error, reset and don't auto-sense */ | |
437 | if (result == USB_STOR_TRANSPORT_ERROR) | |
438 | { | |
439 | //printk("-- transport indicates error, resetting\n"); | |
440 | srb->result = DID_ERROR << 16; | |
441 | goto Handle_Errors; | |
442 | } | |
443 | ||
444 | /* if the transport provided its own sense data, don't auto-sense */ | |
445 | if (result == USB_STOR_TRANSPORT_NO_SENSE) | |
446 | { | |
447 | srb->result = SAM_STAT_CHECK_CONDITION; | |
448 | return; | |
449 | } | |
450 | ||
451 | srb->result = SAM_STAT_GOOD; | |
452 | if (result == USB_STOR_TRANSPORT_FAILED) | |
453 | { | |
454 | //printk("-- transport indicates command failure\n"); | |
455 | //need_auto_sense = 1; | |
456 | BuildSenseBuffer(srb, us->SrbStatus); | |
457 | srb->result = SAM_STAT_CHECK_CONDITION; | |
458 | } | |
459 | ||
460 | /* Did we transfer less than the minimum amount required? */ | |
461 | if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) | |
462 | srb->result = (DID_ERROR << 16);//v02 | (SUGGEST_RETRY << 24); | |
463 | ||
464 | return; | |
465 | ||
466 | Handle_Errors: | |
467 | scsi_lock(us_to_host(us)); | |
468 | set_bit(US_FLIDX_RESETTING, &us->dflags); | |
469 | clear_bit(US_FLIDX_ABORTING, &us->dflags); | |
470 | scsi_unlock(us_to_host(us)); | |
471 | ||
472 | mutex_unlock(&us->dev_mutex); | |
473 | result = usb_stor_port_reset(us); | |
474 | mutex_lock(&us->dev_mutex); | |
475 | ||
476 | if (result < 0) | |
477 | { | |
478 | scsi_lock(us_to_host(us)); | |
479 | usb_stor_report_device_reset(us); | |
480 | scsi_unlock(us_to_host(us)); | |
481 | us->transport_reset(us); | |
482 | } | |
483 | clear_bit(US_FLIDX_RESETTING, &us->dflags); | |
484 | } | |
485 | ||
486 | //----- BuildSenseBuffer() ------------------------------------------- | |
487 | void BuildSenseBuffer(struct scsi_cmnd *srb, int SrbStatus) | |
488 | { | |
489 | BYTE *buf = srb->sense_buffer; | |
490 | BYTE asc; | |
491 | ||
492 | printk("transport --- BuildSenseBuffer\n"); | |
493 | switch (SrbStatus) | |
494 | { | |
495 | case SS_NOT_READY: asc = 0x3a; break; // sense key = 0x02 | |
496 | case SS_MEDIUM_ERR: asc = 0x0c; break; // sense key = 0x03 | |
497 | case SS_ILLEGAL_REQUEST: asc = 0x20; break; // sense key = 0x05 | |
498 | default: asc = 0x00; break; // ?? | |
499 | } | |
500 | ||
501 | memset(buf, 0, 18); | |
502 | buf[0x00] = 0xf0; | |
503 | buf[0x02] = SrbStatus; | |
504 | buf[0x07] = 0x0b; | |
505 | buf[0x0c] = asc; | |
506 | } | |
507 | ||
508 | //----- usb_stor_stop_transport() --------------------- | |
509 | void usb_stor_stop_transport(struct us_data *us) | |
510 | { | |
511 | //printk("transport --- usb_stor_stop_transport\n"); | |
512 | ||
513 | if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) | |
514 | { | |
515 | //printk("-- cancelling URB\n"); | |
516 | usb_unlink_urb(us->current_urb); | |
517 | } | |
518 | ||
519 | if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) | |
520 | { | |
521 | //printk("-- cancelling sg request\n"); | |
522 | usb_sg_cancel(&us->current_sg); | |
523 | } | |
524 | } | |
525 | ||
526 | //----- usb_stor_Bulk_max_lun() --------------------- | |
527 | int usb_stor_Bulk_max_lun(struct us_data *us) | |
528 | { | |
529 | int result; | |
530 | ||
531 | //printk("transport --- usb_stor_Bulk_max_lun\n"); | |
532 | /* issue the command */ | |
533 | us->iobuf[0] = 0; | |
534 | result = usb_stor_control_msg(us, us->recv_ctrl_pipe, | |
535 | US_BULK_GET_MAX_LUN, | |
536 | USB_DIR_IN | USB_TYPE_CLASS | | |
537 | USB_RECIP_INTERFACE, | |
538 | 0, us->ifnum, us->iobuf, 1, HZ); | |
539 | ||
540 | //printk("GetMaxLUN command result is %d, data is %d\n", result, us->iobuf[0]); | |
541 | ||
542 | /* if we have a successful request, return the result */ | |
543 | if (result > 0) | |
544 | return us->iobuf[0]; | |
545 | ||
546 | return 0; | |
547 | } | |
548 | ||
549 | //----- usb_stor_Bulk_transport() --------------------- | |
550 | int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) | |
551 | { | |
552 | struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; | |
553 | struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; | |
554 | unsigned int transfer_length = scsi_bufflen(srb); | |
555 | unsigned int residue; | |
556 | int result; | |
557 | int fake_sense = 0; | |
558 | unsigned int cswlen; | |
559 | unsigned int cbwlen = US_BULK_CB_WRAP_LEN; | |
560 | ||
561 | //printk("transport --- usb_stor_Bulk_transport\n"); | |
562 | /* Take care of BULK32 devices; set extra byte to 0 */ | |
563 | if (unlikely(us->fflags & US_FL_BULK32)) | |
564 | { | |
565 | cbwlen = 32; | |
566 | us->iobuf[31] = 0; | |
567 | } | |
568 | ||
569 | /* set up the command wrapper */ | |
570 | bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); | |
571 | bcb->DataTransferLength = cpu_to_le32(transfer_length); | |
572 | bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0; | |
573 | bcb->Tag = ++us->tag; | |
574 | bcb->Lun = srb->device->lun; | |
575 | if (us->fflags & US_FL_SCM_MULT_TARG) | |
576 | bcb->Lun |= srb->device->id << 4; | |
577 | bcb->Length = srb->cmd_len; | |
578 | ||
579 | /* copy the command payload */ | |
580 | memset(bcb->CDB, 0, sizeof(bcb->CDB)); | |
581 | memcpy(bcb->CDB, srb->cmnd, bcb->Length); | |
582 | ||
583 | // send command | |
584 | /* send it to out endpoint */ | |
585 | /*printk("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n", | |
586 | le32_to_cpu(bcb->Signature), bcb->Tag, | |
587 | le32_to_cpu(bcb->DataTransferLength), bcb->Flags, | |
588 | (bcb->Lun >> 4), (bcb->Lun & 0x0F), | |
589 | bcb->Length);*/ | |
590 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, cbwlen, NULL); | |
591 | //printk("Bulk command transfer result=%d\n", result); | |
592 | if (result != USB_STOR_XFER_GOOD) | |
593 | return USB_STOR_TRANSPORT_ERROR; | |
594 | ||
595 | if (unlikely(us->fflags & US_FL_GO_SLOW)) | |
596 | udelay(125); | |
597 | ||
598 | // R/W data | |
599 | if (transfer_length) | |
600 | { | |
601 | unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; | |
602 | result = usb_stor_bulk_srb(us, pipe, srb); | |
603 | //printk("Bulk data transfer result 0x%x\n", result); | |
604 | if (result == USB_STOR_XFER_ERROR) | |
605 | return USB_STOR_TRANSPORT_ERROR; | |
606 | ||
607 | if (result == USB_STOR_XFER_LONG) | |
608 | fake_sense = 1; | |
609 | } | |
610 | ||
611 | /* get CSW for device status */ | |
612 | //printk("Attempting to get CSW...\n"); | |
613 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen); | |
614 | ||
615 | if (result == USB_STOR_XFER_SHORT && cswlen == 0) | |
616 | { | |
617 | //printk("Received 0-length CSW; retrying...\n"); | |
618 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &cswlen); | |
619 | } | |
620 | ||
621 | /* did the attempt to read the CSW fail? */ | |
622 | if (result == USB_STOR_XFER_STALLED) | |
623 | { | |
624 | /* get the status again */ | |
625 | //printk("Attempting to get CSW (2nd try)...\n"); | |
626 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, NULL); | |
627 | } | |
628 | ||
629 | /* if we still have a failure at this point, we're in trouble */ | |
630 | //printk("Bulk status result = %d\n", result); | |
631 | if (result != USB_STOR_XFER_GOOD) | |
632 | return USB_STOR_TRANSPORT_ERROR; | |
633 | ||
634 | /* check bulk status */ | |
635 | residue = le32_to_cpu(bcs->Residue); | |
636 | //printk("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status); | |
637 | if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) || bcs->Status > US_BULK_STAT_PHASE) | |
638 | { | |
639 | //printk("Bulk logical error\n"); | |
640 | return USB_STOR_TRANSPORT_ERROR; | |
641 | } | |
642 | ||
643 | if (!us->bcs_signature) | |
644 | { | |
645 | us->bcs_signature = bcs->Signature; | |
646 | //if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN)) | |
647 | // printk("Learnt BCS signature 0x%08X\n", le32_to_cpu(us->bcs_signature)); | |
648 | } | |
649 | else if (bcs->Signature != us->bcs_signature) | |
650 | { | |
651 | /*printk("Signature mismatch: got %08X, expecting %08X\n", | |
652 | le32_to_cpu(bcs->Signature), | |
653 | le32_to_cpu(us->bcs_signature));*/ | |
654 | return USB_STOR_TRANSPORT_ERROR; | |
655 | } | |
656 | ||
657 | /* try to compute the actual residue, based on how much data | |
658 | * was really transferred and what the device tells us */ | |
659 | if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) | |
660 | { | |
661 | ||
662 | /* Heuristically detect devices that generate bogus residues | |
663 | * by seeing what happens with INQUIRY and READ CAPACITY | |
664 | * commands. | |
665 | */ | |
666 | if (bcs->Status == US_BULK_STAT_OK && | |
667 | scsi_get_resid(srb) == 0 && | |
668 | ((srb->cmnd[0] == INQUIRY && | |
669 | transfer_length == 36) || | |
670 | (srb->cmnd[0] == READ_CAPACITY && | |
671 | transfer_length == 8))) | |
672 | { | |
673 | us->fflags |= US_FL_IGNORE_RESIDUE; | |
674 | ||
675 | } | |
676 | else | |
677 | { | |
678 | residue = min(residue, transfer_length); | |
679 | scsi_set_resid(srb, max(scsi_get_resid(srb), (int) residue)); | |
680 | } | |
681 | } | |
682 | ||
683 | /* based on the status code, we report good or bad */ | |
684 | switch (bcs->Status) | |
685 | { | |
686 | case US_BULK_STAT_OK: | |
687 | if (fake_sense) | |
688 | { | |
689 | memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB, sizeof(usb_stor_sense_invalidCDB)); | |
690 | return USB_STOR_TRANSPORT_NO_SENSE; | |
691 | } | |
692 | return USB_STOR_TRANSPORT_GOOD; | |
693 | ||
694 | case US_BULK_STAT_FAIL: | |
695 | return USB_STOR_TRANSPORT_FAILED; | |
696 | ||
697 | case US_BULK_STAT_PHASE: | |
698 | return USB_STOR_TRANSPORT_ERROR; | |
699 | } | |
700 | return USB_STOR_TRANSPORT_ERROR; | |
701 | } | |
702 | ||
703 | /*********************************************************************** | |
704 | * Reset routines | |
705 | ***********************************************************************/ | |
706 | //----- usb_stor_reset_common() --------------------- | |
707 | static int usb_stor_reset_common(struct us_data *us, | |
708 | u8 request, u8 requesttype, | |
709 | u16 value, u16 index, void *data, u16 size) | |
710 | { | |
711 | int result; | |
712 | int result2; | |
713 | ||
714 | //printk("transport --- usb_stor_reset_common\n"); | |
715 | if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) | |
716 | { | |
717 | //printk("No reset during disconnect\n"); | |
718 | return -EIO; | |
719 | } | |
720 | ||
721 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, request, requesttype, value, index, data, size, 5*HZ); | |
722 | if (result < 0) | |
723 | { | |
724 | //printk("Soft reset failed: %d\n", result); | |
725 | return result; | |
726 | } | |
727 | ||
728 | wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->dflags), HZ*6); | |
729 | if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) | |
730 | { | |
731 | //printk("Reset interrupted by disconnect\n"); | |
732 | return -EIO; | |
733 | } | |
734 | ||
735 | //printk("Soft reset: clearing bulk-in endpoint halt\n"); | |
736 | result = usb_stor_clear_halt(us, us->recv_bulk_pipe); | |
737 | ||
738 | //printk("Soft reset: clearing bulk-out endpoint halt\n"); | |
739 | result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); | |
740 | ||
741 | /* return a result code based on the result of the clear-halts */ | |
742 | if (result >= 0) | |
743 | result = result2; | |
744 | //if (result < 0) | |
745 | // printk("Soft reset failed\n"); | |
746 | //else | |
747 | // printk("Soft reset done\n"); | |
748 | return result; | |
749 | } | |
750 | ||
751 | //----- usb_stor_Bulk_reset() --------------------- | |
752 | int usb_stor_Bulk_reset(struct us_data *us) | |
753 | { | |
754 | //printk("transport --- usb_stor_Bulk_reset\n"); | |
755 | return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, | |
756 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | |
757 | 0, us->ifnum, NULL, 0); | |
758 | } | |
759 | ||
760 | //----- usb_stor_port_reset() --------------------- | |
761 | int usb_stor_port_reset(struct us_data *us) | |
762 | { | |
763 | int result, rc_lock; | |
764 | ||
765 | //printk("transport --- usb_stor_port_reset\n"); | |
e1049604 | 766 | result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); |
126bb03b AC |
767 | if (result < 0) |
768 | printk("unable to lock device for reset: %d\n", result); | |
e1049604 | 769 | else { |
126bb03b | 770 | /* Were we disconnected while waiting for the lock? */ |
e1049604 | 771 | if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) { |
126bb03b AC |
772 | result = -EIO; |
773 | //printk("No reset during disconnect\n"); | |
e1049604 | 774 | } else { |
126bb03b AC |
775 | result = usb_reset_device(us->pusb_dev); |
776 | //printk("usb_reset_composite_device returns %d\n", result); | |
777 | } | |
e1049604 | 778 | usb_unlock_device(us->pusb_dev); |
126bb03b AC |
779 | } |
780 | return result; | |
781 | } | |
782 | ||
783 |