diff options
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 507 |
1 files changed, 233 insertions, 274 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 681b591fc4c0..4f4c5b7bdef5 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -235,56 +235,11 @@ static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, | |||
235 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, | 235 | static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, |
236 | 0, 0, 0x0, 0x0}; | 236 | 0, 0, 0x0, 0x0}; |
237 | 237 | ||
238 | /* function declarations */ | ||
239 | static int resp_inquiry(struct scsi_cmnd * SCpnt, int target, | ||
240 | struct sdebug_dev_info * devip); | ||
241 | static int resp_requests(struct scsi_cmnd * SCpnt, | ||
242 | struct sdebug_dev_info * devip); | ||
243 | static int resp_start_stop(struct scsi_cmnd * scp, | ||
244 | struct sdebug_dev_info * devip); | ||
245 | static int resp_report_tgtpgs(struct scsi_cmnd * scp, | ||
246 | struct sdebug_dev_info * devip); | ||
247 | static int resp_readcap(struct scsi_cmnd * SCpnt, | ||
248 | struct sdebug_dev_info * devip); | ||
249 | static int resp_readcap16(struct scsi_cmnd * SCpnt, | ||
250 | struct sdebug_dev_info * devip); | ||
251 | static int resp_mode_sense(struct scsi_cmnd * scp, int target, | ||
252 | struct sdebug_dev_info * devip); | ||
253 | static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, | ||
254 | struct sdebug_dev_info * devip); | ||
255 | static int resp_log_sense(struct scsi_cmnd * scp, | ||
256 | struct sdebug_dev_info * devip); | ||
257 | static int resp_read(struct scsi_cmnd * SCpnt, unsigned long long lba, | ||
258 | unsigned int num, struct sdebug_dev_info * devip); | ||
259 | static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba, | ||
260 | unsigned int num, struct sdebug_dev_info * devip); | ||
261 | static int resp_report_luns(struct scsi_cmnd * SCpnt, | ||
262 | struct sdebug_dev_info * devip); | ||
263 | static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, | ||
264 | unsigned int num, struct sdebug_dev_info *devip); | ||
265 | static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | ||
266 | int arr_len); | ||
267 | static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, | ||
268 | int max_arr_len); | ||
269 | static void timer_intr_handler(unsigned long); | ||
270 | static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev); | 238 | static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev); |
271 | static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, | 239 | static void mk_sense_buffer(struct sdebug_dev_info * devip, int key, |
272 | int asc, int asq); | 240 | int asc, int asq); |
273 | static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only, | ||
274 | struct sdebug_dev_info * devip); | ||
275 | static int schedule_resp(struct scsi_cmnd * cmnd, | ||
276 | struct sdebug_dev_info * devip, | ||
277 | done_funct_t done, int scsi_result, int delta_jiff); | ||
278 | static void __init sdebug_build_parts(unsigned char * ramp); | ||
279 | static void __init init_all_queued(void); | ||
280 | static void stop_all_queued(void); | 241 | static void stop_all_queued(void); |
281 | static int stop_queued_cmnd(struct scsi_cmnd * cmnd); | 242 | static int stop_queued_cmnd(struct scsi_cmnd * cmnd); |
282 | static int inquiry_evpd_83(unsigned char * arr, int port_group_id, | ||
283 | int target_dev_id, int dev_id_num, | ||
284 | const char * dev_id_str, int dev_id_str_len); | ||
285 | static int inquiry_evpd_88(unsigned char * arr, int target_dev_id); | ||
286 | static int do_create_driverfs_files(void); | ||
287 | static void do_remove_driverfs_files(void); | ||
288 | 243 | ||
289 | static int sdebug_add_adapter(void); | 244 | static int sdebug_add_adapter(void); |
290 | static void sdebug_remove_adapter(void); | 245 | static void sdebug_remove_adapter(void); |
@@ -330,235 +285,6 @@ static void get_data_transfer_info(unsigned char *cmd, | |||
330 | } | 285 | } |
331 | } | 286 | } |
332 | 287 | ||
333 | static | ||
334 | int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | ||
335 | { | ||
336 | unsigned char *cmd = (unsigned char *) SCpnt->cmnd; | ||
337 | int len, k; | ||
338 | unsigned int num; | ||
339 | unsigned long long lba; | ||
340 | int errsts = 0; | ||
341 | int target = SCpnt->device->id; | ||
342 | struct sdebug_dev_info * devip = NULL; | ||
343 | int inj_recovered = 0; | ||
344 | int inj_transport = 0; | ||
345 | int delay_override = 0; | ||
346 | |||
347 | scsi_set_resid(SCpnt, 0); | ||
348 | if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { | ||
349 | printk(KERN_INFO "scsi_debug: cmd "); | ||
350 | for (k = 0, len = SCpnt->cmd_len; k < len; ++k) | ||
351 | printk("%02x ", (int)cmd[k]); | ||
352 | printk("\n"); | ||
353 | } | ||
354 | |||
355 | if (target == SCpnt->device->host->hostt->this_id) { | ||
356 | printk(KERN_INFO "scsi_debug: initiator's id used as " | ||
357 | "target!\n"); | ||
358 | return schedule_resp(SCpnt, NULL, done, | ||
359 | DID_NO_CONNECT << 16, 0); | ||
360 | } | ||
361 | |||
362 | if ((SCpnt->device->lun >= scsi_debug_max_luns) && | ||
363 | (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) | ||
364 | return schedule_resp(SCpnt, NULL, done, | ||
365 | DID_NO_CONNECT << 16, 0); | ||
366 | devip = devInfoReg(SCpnt->device); | ||
367 | if (NULL == devip) | ||
368 | return schedule_resp(SCpnt, NULL, done, | ||
369 | DID_NO_CONNECT << 16, 0); | ||
370 | |||
371 | if ((scsi_debug_every_nth != 0) && | ||
372 | (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) { | ||
373 | scsi_debug_cmnd_count = 0; | ||
374 | if (scsi_debug_every_nth < -1) | ||
375 | scsi_debug_every_nth = -1; | ||
376 | if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) | ||
377 | return 0; /* ignore command causing timeout */ | ||
378 | else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) | ||
379 | inj_recovered = 1; /* to reads and writes below */ | ||
380 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) | ||
381 | inj_transport = 1; /* to reads and writes below */ | ||
382 | } | ||
383 | |||
384 | if (devip->wlun) { | ||
385 | switch (*cmd) { | ||
386 | case INQUIRY: | ||
387 | case REQUEST_SENSE: | ||
388 | case TEST_UNIT_READY: | ||
389 | case REPORT_LUNS: | ||
390 | break; /* only allowable wlun commands */ | ||
391 | default: | ||
392 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
393 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x " | ||
394 | "not supported for wlun\n", *cmd); | ||
395 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
396 | INVALID_OPCODE, 0); | ||
397 | errsts = check_condition_result; | ||
398 | return schedule_resp(SCpnt, devip, done, errsts, | ||
399 | 0); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | switch (*cmd) { | ||
404 | case INQUIRY: /* mandatory, ignore unit attention */ | ||
405 | delay_override = 1; | ||
406 | errsts = resp_inquiry(SCpnt, target, devip); | ||
407 | break; | ||
408 | case REQUEST_SENSE: /* mandatory, ignore unit attention */ | ||
409 | delay_override = 1; | ||
410 | errsts = resp_requests(SCpnt, devip); | ||
411 | break; | ||
412 | case REZERO_UNIT: /* actually this is REWIND for SSC */ | ||
413 | case START_STOP: | ||
414 | errsts = resp_start_stop(SCpnt, devip); | ||
415 | break; | ||
416 | case ALLOW_MEDIUM_REMOVAL: | ||
417 | if ((errsts = check_readiness(SCpnt, 1, devip))) | ||
418 | break; | ||
419 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
420 | printk(KERN_INFO "scsi_debug: Medium removal %s\n", | ||
421 | cmd[4] ? "inhibited" : "enabled"); | ||
422 | break; | ||
423 | case SEND_DIAGNOSTIC: /* mandatory */ | ||
424 | errsts = check_readiness(SCpnt, 1, devip); | ||
425 | break; | ||
426 | case TEST_UNIT_READY: /* mandatory */ | ||
427 | delay_override = 1; | ||
428 | errsts = check_readiness(SCpnt, 0, devip); | ||
429 | break; | ||
430 | case RESERVE: | ||
431 | errsts = check_readiness(SCpnt, 1, devip); | ||
432 | break; | ||
433 | case RESERVE_10: | ||
434 | errsts = check_readiness(SCpnt, 1, devip); | ||
435 | break; | ||
436 | case RELEASE: | ||
437 | errsts = check_readiness(SCpnt, 1, devip); | ||
438 | break; | ||
439 | case RELEASE_10: | ||
440 | errsts = check_readiness(SCpnt, 1, devip); | ||
441 | break; | ||
442 | case READ_CAPACITY: | ||
443 | errsts = resp_readcap(SCpnt, devip); | ||
444 | break; | ||
445 | case SERVICE_ACTION_IN: | ||
446 | if (SAI_READ_CAPACITY_16 != cmd[1]) { | ||
447 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
448 | INVALID_OPCODE, 0); | ||
449 | errsts = check_condition_result; | ||
450 | break; | ||
451 | } | ||
452 | errsts = resp_readcap16(SCpnt, devip); | ||
453 | break; | ||
454 | case MAINTENANCE_IN: | ||
455 | if (MI_REPORT_TARGET_PGS != cmd[1]) { | ||
456 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
457 | INVALID_OPCODE, 0); | ||
458 | errsts = check_condition_result; | ||
459 | break; | ||
460 | } | ||
461 | errsts = resp_report_tgtpgs(SCpnt, devip); | ||
462 | break; | ||
463 | case READ_16: | ||
464 | case READ_12: | ||
465 | case READ_10: | ||
466 | case READ_6: | ||
467 | if ((errsts = check_readiness(SCpnt, 0, devip))) | ||
468 | break; | ||
469 | if (scsi_debug_fake_rw) | ||
470 | break; | ||
471 | get_data_transfer_info(cmd, &lba, &num); | ||
472 | errsts = resp_read(SCpnt, lba, num, devip); | ||
473 | if (inj_recovered && (0 == errsts)) { | ||
474 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
475 | THRESHOLD_EXCEEDED, 0); | ||
476 | errsts = check_condition_result; | ||
477 | } else if (inj_transport && (0 == errsts)) { | ||
478 | mk_sense_buffer(devip, ABORTED_COMMAND, | ||
479 | TRANSPORT_PROBLEM, ACK_NAK_TO); | ||
480 | errsts = check_condition_result; | ||
481 | } | ||
482 | break; | ||
483 | case REPORT_LUNS: /* mandatory, ignore unit attention */ | ||
484 | delay_override = 1; | ||
485 | errsts = resp_report_luns(SCpnt, devip); | ||
486 | break; | ||
487 | case VERIFY: /* 10 byte SBC-2 command */ | ||
488 | errsts = check_readiness(SCpnt, 0, devip); | ||
489 | break; | ||
490 | case WRITE_16: | ||
491 | case WRITE_12: | ||
492 | case WRITE_10: | ||
493 | case WRITE_6: | ||
494 | if ((errsts = check_readiness(SCpnt, 0, devip))) | ||
495 | break; | ||
496 | if (scsi_debug_fake_rw) | ||
497 | break; | ||
498 | get_data_transfer_info(cmd, &lba, &num); | ||
499 | errsts = resp_write(SCpnt, lba, num, devip); | ||
500 | if (inj_recovered && (0 == errsts)) { | ||
501 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
502 | THRESHOLD_EXCEEDED, 0); | ||
503 | errsts = check_condition_result; | ||
504 | } | ||
505 | break; | ||
506 | case MODE_SENSE: | ||
507 | case MODE_SENSE_10: | ||
508 | errsts = resp_mode_sense(SCpnt, target, devip); | ||
509 | break; | ||
510 | case MODE_SELECT: | ||
511 | errsts = resp_mode_select(SCpnt, 1, devip); | ||
512 | break; | ||
513 | case MODE_SELECT_10: | ||
514 | errsts = resp_mode_select(SCpnt, 0, devip); | ||
515 | break; | ||
516 | case LOG_SENSE: | ||
517 | errsts = resp_log_sense(SCpnt, devip); | ||
518 | break; | ||
519 | case SYNCHRONIZE_CACHE: | ||
520 | delay_override = 1; | ||
521 | errsts = check_readiness(SCpnt, 0, devip); | ||
522 | break; | ||
523 | case WRITE_BUFFER: | ||
524 | errsts = check_readiness(SCpnt, 1, devip); | ||
525 | break; | ||
526 | case XDWRITEREAD_10: | ||
527 | if (!scsi_bidi_cmnd(SCpnt)) { | ||
528 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
529 | INVALID_FIELD_IN_CDB, 0); | ||
530 | errsts = check_condition_result; | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | errsts = check_readiness(SCpnt, 0, devip); | ||
535 | if (errsts) | ||
536 | break; | ||
537 | if (scsi_debug_fake_rw) | ||
538 | break; | ||
539 | get_data_transfer_info(cmd, &lba, &num); | ||
540 | errsts = resp_read(SCpnt, lba, num, devip); | ||
541 | if (errsts) | ||
542 | break; | ||
543 | errsts = resp_write(SCpnt, lba, num, devip); | ||
544 | if (errsts) | ||
545 | break; | ||
546 | errsts = resp_xdwriteread(SCpnt, lba, num, devip); | ||
547 | break; | ||
548 | default: | ||
549 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
550 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " | ||
551 | "supported\n", *cmd); | ||
552 | if ((errsts = check_readiness(SCpnt, 1, devip))) | ||
553 | break; /* Unit attention takes precedence */ | ||
554 | mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0); | ||
555 | errsts = check_condition_result; | ||
556 | break; | ||
557 | } | ||
558 | return schedule_resp(SCpnt, devip, done, errsts, | ||
559 | (delay_override ? 0 : scsi_debug_delay)); | ||
560 | } | ||
561 | |||
562 | static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) | 288 | static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) |
563 | { | 289 | { |
564 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { | 290 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { |
@@ -2999,6 +2725,239 @@ static void sdebug_remove_adapter(void) | |||
2999 | --scsi_debug_add_host; | 2725 | --scsi_debug_add_host; |
3000 | } | 2726 | } |
3001 | 2727 | ||
2728 | static | ||
2729 | int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) | ||
2730 | { | ||
2731 | unsigned char *cmd = (unsigned char *) SCpnt->cmnd; | ||
2732 | int len, k; | ||
2733 | unsigned int num; | ||
2734 | unsigned long long lba; | ||
2735 | int errsts = 0; | ||
2736 | int target = SCpnt->device->id; | ||
2737 | struct sdebug_dev_info *devip = NULL; | ||
2738 | int inj_recovered = 0; | ||
2739 | int inj_transport = 0; | ||
2740 | int delay_override = 0; | ||
2741 | |||
2742 | scsi_set_resid(SCpnt, 0); | ||
2743 | if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { | ||
2744 | printk(KERN_INFO "scsi_debug: cmd "); | ||
2745 | for (k = 0, len = SCpnt->cmd_len; k < len; ++k) | ||
2746 | printk("%02x ", (int)cmd[k]); | ||
2747 | printk("\n"); | ||
2748 | } | ||
2749 | |||
2750 | if (target == SCpnt->device->host->hostt->this_id) { | ||
2751 | printk(KERN_INFO "scsi_debug: initiator's id used as " | ||
2752 | "target!\n"); | ||
2753 | return schedule_resp(SCpnt, NULL, done, | ||
2754 | DID_NO_CONNECT << 16, 0); | ||
2755 | } | ||
2756 | |||
2757 | if ((SCpnt->device->lun >= scsi_debug_max_luns) && | ||
2758 | (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) | ||
2759 | return schedule_resp(SCpnt, NULL, done, | ||
2760 | DID_NO_CONNECT << 16, 0); | ||
2761 | devip = devInfoReg(SCpnt->device); | ||
2762 | if (NULL == devip) | ||
2763 | return schedule_resp(SCpnt, NULL, done, | ||
2764 | DID_NO_CONNECT << 16, 0); | ||
2765 | |||
2766 | if ((scsi_debug_every_nth != 0) && | ||
2767 | (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) { | ||
2768 | scsi_debug_cmnd_count = 0; | ||
2769 | if (scsi_debug_every_nth < -1) | ||
2770 | scsi_debug_every_nth = -1; | ||
2771 | if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) | ||
2772 | return 0; /* ignore command causing timeout */ | ||
2773 | else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) | ||
2774 | inj_recovered = 1; /* to reads and writes below */ | ||
2775 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) | ||
2776 | inj_transport = 1; /* to reads and writes below */ | ||
2777 | } | ||
2778 | |||
2779 | if (devip->wlun) { | ||
2780 | switch (*cmd) { | ||
2781 | case INQUIRY: | ||
2782 | case REQUEST_SENSE: | ||
2783 | case TEST_UNIT_READY: | ||
2784 | case REPORT_LUNS: | ||
2785 | break; /* only allowable wlun commands */ | ||
2786 | default: | ||
2787 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2788 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x " | ||
2789 | "not supported for wlun\n", *cmd); | ||
2790 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2791 | INVALID_OPCODE, 0); | ||
2792 | errsts = check_condition_result; | ||
2793 | return schedule_resp(SCpnt, devip, done, errsts, | ||
2794 | 0); | ||
2795 | } | ||
2796 | } | ||
2797 | |||
2798 | switch (*cmd) { | ||
2799 | case INQUIRY: /* mandatory, ignore unit attention */ | ||
2800 | delay_override = 1; | ||
2801 | errsts = resp_inquiry(SCpnt, target, devip); | ||
2802 | break; | ||
2803 | case REQUEST_SENSE: /* mandatory, ignore unit attention */ | ||
2804 | delay_override = 1; | ||
2805 | errsts = resp_requests(SCpnt, devip); | ||
2806 | break; | ||
2807 | case REZERO_UNIT: /* actually this is REWIND for SSC */ | ||
2808 | case START_STOP: | ||
2809 | errsts = resp_start_stop(SCpnt, devip); | ||
2810 | break; | ||
2811 | case ALLOW_MEDIUM_REMOVAL: | ||
2812 | errsts = check_readiness(SCpnt, 1, devip); | ||
2813 | if (errsts) | ||
2814 | break; | ||
2815 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2816 | printk(KERN_INFO "scsi_debug: Medium removal %s\n", | ||
2817 | cmd[4] ? "inhibited" : "enabled"); | ||
2818 | break; | ||
2819 | case SEND_DIAGNOSTIC: /* mandatory */ | ||
2820 | errsts = check_readiness(SCpnt, 1, devip); | ||
2821 | break; | ||
2822 | case TEST_UNIT_READY: /* mandatory */ | ||
2823 | delay_override = 1; | ||
2824 | errsts = check_readiness(SCpnt, 0, devip); | ||
2825 | break; | ||
2826 | case RESERVE: | ||
2827 | errsts = check_readiness(SCpnt, 1, devip); | ||
2828 | break; | ||
2829 | case RESERVE_10: | ||
2830 | errsts = check_readiness(SCpnt, 1, devip); | ||
2831 | break; | ||
2832 | case RELEASE: | ||
2833 | errsts = check_readiness(SCpnt, 1, devip); | ||
2834 | break; | ||
2835 | case RELEASE_10: | ||
2836 | errsts = check_readiness(SCpnt, 1, devip); | ||
2837 | break; | ||
2838 | case READ_CAPACITY: | ||
2839 | errsts = resp_readcap(SCpnt, devip); | ||
2840 | break; | ||
2841 | case SERVICE_ACTION_IN: | ||
2842 | if (SAI_READ_CAPACITY_16 != cmd[1]) { | ||
2843 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2844 | INVALID_OPCODE, 0); | ||
2845 | errsts = check_condition_result; | ||
2846 | break; | ||
2847 | } | ||
2848 | errsts = resp_readcap16(SCpnt, devip); | ||
2849 | break; | ||
2850 | case MAINTENANCE_IN: | ||
2851 | if (MI_REPORT_TARGET_PGS != cmd[1]) { | ||
2852 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2853 | INVALID_OPCODE, 0); | ||
2854 | errsts = check_condition_result; | ||
2855 | break; | ||
2856 | } | ||
2857 | errsts = resp_report_tgtpgs(SCpnt, devip); | ||
2858 | break; | ||
2859 | case READ_16: | ||
2860 | case READ_12: | ||
2861 | case READ_10: | ||
2862 | case READ_6: | ||
2863 | errsts = check_readiness(SCpnt, 0, devip); | ||
2864 | if (errsts) | ||
2865 | break; | ||
2866 | if (scsi_debug_fake_rw) | ||
2867 | break; | ||
2868 | get_data_transfer_info(cmd, &lba, &num); | ||
2869 | errsts = resp_read(SCpnt, lba, num, devip); | ||
2870 | if (inj_recovered && (0 == errsts)) { | ||
2871 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
2872 | THRESHOLD_EXCEEDED, 0); | ||
2873 | errsts = check_condition_result; | ||
2874 | } else if (inj_transport && (0 == errsts)) { | ||
2875 | mk_sense_buffer(devip, ABORTED_COMMAND, | ||
2876 | TRANSPORT_PROBLEM, ACK_NAK_TO); | ||
2877 | errsts = check_condition_result; | ||
2878 | } | ||
2879 | break; | ||
2880 | case REPORT_LUNS: /* mandatory, ignore unit attention */ | ||
2881 | delay_override = 1; | ||
2882 | errsts = resp_report_luns(SCpnt, devip); | ||
2883 | break; | ||
2884 | case VERIFY: /* 10 byte SBC-2 command */ | ||
2885 | errsts = check_readiness(SCpnt, 0, devip); | ||
2886 | break; | ||
2887 | case WRITE_16: | ||
2888 | case WRITE_12: | ||
2889 | case WRITE_10: | ||
2890 | case WRITE_6: | ||
2891 | errsts = check_readiness(SCpnt, 0, devip); | ||
2892 | if (errsts) | ||
2893 | break; | ||
2894 | if (scsi_debug_fake_rw) | ||
2895 | break; | ||
2896 | get_data_transfer_info(cmd, &lba, &num); | ||
2897 | errsts = resp_write(SCpnt, lba, num, devip); | ||
2898 | if (inj_recovered && (0 == errsts)) { | ||
2899 | mk_sense_buffer(devip, RECOVERED_ERROR, | ||
2900 | THRESHOLD_EXCEEDED, 0); | ||
2901 | errsts = check_condition_result; | ||
2902 | } | ||
2903 | break; | ||
2904 | case MODE_SENSE: | ||
2905 | case MODE_SENSE_10: | ||
2906 | errsts = resp_mode_sense(SCpnt, target, devip); | ||
2907 | break; | ||
2908 | case MODE_SELECT: | ||
2909 | errsts = resp_mode_select(SCpnt, 1, devip); | ||
2910 | break; | ||
2911 | case MODE_SELECT_10: | ||
2912 | errsts = resp_mode_select(SCpnt, 0, devip); | ||
2913 | break; | ||
2914 | case LOG_SENSE: | ||
2915 | errsts = resp_log_sense(SCpnt, devip); | ||
2916 | break; | ||
2917 | case SYNCHRONIZE_CACHE: | ||
2918 | delay_override = 1; | ||
2919 | errsts = check_readiness(SCpnt, 0, devip); | ||
2920 | break; | ||
2921 | case WRITE_BUFFER: | ||
2922 | errsts = check_readiness(SCpnt, 1, devip); | ||
2923 | break; | ||
2924 | case XDWRITEREAD_10: | ||
2925 | if (!scsi_bidi_cmnd(SCpnt)) { | ||
2926 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
2927 | INVALID_FIELD_IN_CDB, 0); | ||
2928 | errsts = check_condition_result; | ||
2929 | break; | ||
2930 | } | ||
2931 | |||
2932 | errsts = check_readiness(SCpnt, 0, devip); | ||
2933 | if (errsts) | ||
2934 | break; | ||
2935 | if (scsi_debug_fake_rw) | ||
2936 | break; | ||
2937 | get_data_transfer_info(cmd, &lba, &num); | ||
2938 | errsts = resp_read(SCpnt, lba, num, devip); | ||
2939 | if (errsts) | ||
2940 | break; | ||
2941 | errsts = resp_write(SCpnt, lba, num, devip); | ||
2942 | if (errsts) | ||
2943 | break; | ||
2944 | errsts = resp_xdwriteread(SCpnt, lba, num, devip); | ||
2945 | break; | ||
2946 | default: | ||
2947 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | ||
2948 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " | ||
2949 | "supported\n", *cmd); | ||
2950 | errsts = check_readiness(SCpnt, 1, devip); | ||
2951 | if (errsts) | ||
2952 | break; /* Unit attention takes precedence */ | ||
2953 | mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0); | ||
2954 | errsts = check_condition_result; | ||
2955 | break; | ||
2956 | } | ||
2957 | return schedule_resp(SCpnt, devip, done, errsts, | ||
2958 | (delay_override ? 0 : scsi_debug_delay)); | ||
2959 | } | ||
2960 | |||
3002 | static struct scsi_host_template sdebug_driver_template = { | 2961 | static struct scsi_host_template sdebug_driver_template = { |
3003 | .proc_info = scsi_debug_proc_info, | 2962 | .proc_info = scsi_debug_proc_info, |
3004 | .proc_name = sdebug_proc_name, | 2963 | .proc_name = sdebug_proc_name, |