diff options
author | Douglas Gilbert <dougg@torque.net> | 2005-10-09 09:09:35 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-09 09:09:35 -0400 |
commit | ae00651020413bd7eb5fa3bd0abbd78d7cf1abb2 (patch) | |
tree | d30e0682d43a81803254cf4ae33a1f21bc1de207 /drivers/scsi/libata-scsi.c | |
parent | 845c5834d0aa60eb1588397696e7fabbaab2d3b0 (diff) |
[libata scsi] improve scsi error handling with ata_scsi_set_sense()
- change "xlat" and "fill" actors in libata-scsi so
they are responsible for SCSI status and sense data
when they return 1. This allows GOOD status or a
specialized error to be set.
- yield an error for mode sense requests for saved
values [sat-r06]
- remove static inlines for ata_bad_scsiop() and
ata_bad_cdb() which are no longer used
Signed-off-by: Douglas Gilbert <dougg@torque.net>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 184 |
1 files changed, 121 insertions, 63 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index bca9a5016b17..c64169ca7ff0 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -49,6 +49,14 @@ static struct ata_device * | |||
49 | ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev); | 49 | ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev); |
50 | 50 | ||
51 | 51 | ||
52 | static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, | ||
53 | void (*done)(struct scsi_cmnd *)) | ||
54 | { | ||
55 | ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0); | ||
56 | /* "Invalid field in cbd" */ | ||
57 | done(cmd); | ||
58 | } | ||
59 | |||
52 | /** | 60 | /** |
53 | * ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd. | 61 | * ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd. |
54 | * @sdev: SCSI device for which BIOS geometry is to be determined | 62 | * @sdev: SCSI device for which BIOS geometry is to be determined |
@@ -182,7 +190,6 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) | |||
182 | { | 190 | { |
183 | struct scsi_cmnd *cmd = qc->scsicmd; | 191 | struct scsi_cmnd *cmd = qc->scsicmd; |
184 | u8 err = 0; | 192 | u8 err = 0; |
185 | unsigned char *sb = cmd->sense_buffer; | ||
186 | /* Based on the 3ware driver translation table */ | 193 | /* Based on the 3ware driver translation table */ |
187 | static unsigned char sense_table[][4] = { | 194 | static unsigned char sense_table[][4] = { |
188 | /* BBD|ECC|ID|MAR */ | 195 | /* BBD|ECC|ID|MAR */ |
@@ -225,8 +232,6 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) | |||
225 | }; | 232 | }; |
226 | int i = 0; | 233 | int i = 0; |
227 | 234 | ||
228 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; | ||
229 | |||
230 | /* | 235 | /* |
231 | * Is this an error we can process/parse | 236 | * Is this an error we can process/parse |
232 | */ | 237 | */ |
@@ -281,11 +286,9 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) | |||
281 | /* Look for best matches first */ | 286 | /* Look for best matches first */ |
282 | if((sense_table[i][0] & err) == sense_table[i][0]) | 287 | if((sense_table[i][0] & err) == sense_table[i][0]) |
283 | { | 288 | { |
284 | sb[0] = 0x70; | 289 | ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */, |
285 | sb[2] = sense_table[i][1]; | 290 | sense_table[i][2] /* asc */, |
286 | sb[7] = 0x0a; | 291 | sense_table[i][3] /* ascq */ ); |
287 | sb[12] = sense_table[i][2]; | ||
288 | sb[13] = sense_table[i][3]; | ||
289 | return; | 292 | return; |
290 | } | 293 | } |
291 | i++; | 294 | i++; |
@@ -300,11 +303,9 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) | |||
300 | { | 303 | { |
301 | if(stat_table[i][0] & drv_stat) | 304 | if(stat_table[i][0] & drv_stat) |
302 | { | 305 | { |
303 | sb[0] = 0x70; | 306 | ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */, |
304 | sb[2] = stat_table[i][1]; | 307 | sense_table[i][2] /* asc */, |
305 | sb[7] = 0x0a; | 308 | sense_table[i][3] /* ascq */ ); |
306 | sb[12] = stat_table[i][2]; | ||
307 | sb[13] = stat_table[i][3]; | ||
308 | return; | 309 | return; |
309 | } | 310 | } |
310 | i++; | 311 | i++; |
@@ -313,15 +314,12 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) | |||
313 | printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat); | 314 | printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat); |
314 | /* additional-sense-code[-qualifier] */ | 315 | /* additional-sense-code[-qualifier] */ |
315 | 316 | ||
316 | sb[0] = 0x70; | ||
317 | sb[2] = MEDIUM_ERROR; | ||
318 | sb[7] = 0x0A; | ||
319 | if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | 317 | if (cmd->sc_data_direction == DMA_FROM_DEVICE) { |
320 | sb[12] = 0x11; /* "unrecovered read error" */ | 318 | ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0x11, 0x4); |
321 | sb[13] = 0x04; | 319 | /* "unrecovered read error" */ |
322 | } else { | 320 | } else { |
323 | sb[12] = 0x0C; /* "write error - */ | 321 | ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0xc, 0x2); |
324 | sb[13] = 0x02; /* auto-reallocation failed" */ | 322 | /* "write error - auto-reallocation failed" */ |
325 | } | 323 | } |
326 | } | 324 | } |
327 | 325 | ||
@@ -430,9 +428,9 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc, | |||
430 | ; /* ignore IMMED bit, violates sat-r05 */ | 428 | ; /* ignore IMMED bit, violates sat-r05 */ |
431 | } | 429 | } |
432 | if (scsicmd[4] & 0x2) | 430 | if (scsicmd[4] & 0x2) |
433 | return 1; /* LOEJ bit set not supported */ | 431 | goto invalid_fld; /* LOEJ bit set not supported */ |
434 | if (((scsicmd[4] >> 4) & 0xf) != 0) | 432 | if (((scsicmd[4] >> 4) & 0xf) != 0) |
435 | return 1; /* power conditions not supported */ | 433 | goto invalid_fld; /* power conditions not supported */ |
436 | if (scsicmd[4] & 0x1) { | 434 | if (scsicmd[4] & 0x1) { |
437 | tf->nsect = 1; /* 1 sector, lba=0 */ | 435 | tf->nsect = 1; /* 1 sector, lba=0 */ |
438 | 436 | ||
@@ -464,6 +462,11 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc, | |||
464 | */ | 462 | */ |
465 | 463 | ||
466 | return 0; | 464 | return 0; |
465 | |||
466 | invalid_fld: | ||
467 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0); | ||
468 | /* "Invalid field in cbd" */ | ||
469 | return 1; | ||
467 | } | 470 | } |
468 | 471 | ||
469 | 472 | ||
@@ -623,20 +626,20 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
623 | else if (scsicmd[0] == VERIFY_16) | 626 | else if (scsicmd[0] == VERIFY_16) |
624 | scsi_16_lba_len(scsicmd, &block, &n_block); | 627 | scsi_16_lba_len(scsicmd, &block, &n_block); |
625 | else | 628 | else |
626 | return 1; | 629 | goto invalid_fld; |
627 | 630 | ||
628 | if (!n_block) | 631 | if (!n_block) |
629 | return 1; | 632 | goto nothing_to_do; |
630 | if (block >= dev_sectors) | 633 | if (block >= dev_sectors) |
631 | return 1; | 634 | goto out_of_range; |
632 | if ((block + n_block) > dev_sectors) | 635 | if ((block + n_block) > dev_sectors) |
633 | return 1; | 636 | goto out_of_range; |
634 | if (lba48) { | 637 | if (lba48) { |
635 | if (n_block > (64 * 1024)) | 638 | if (n_block > (64 * 1024)) |
636 | return 1; | 639 | goto invalid_fld; |
637 | } else { | 640 | } else { |
638 | if (n_block > 256) | 641 | if (n_block > 256) |
639 | return 1; | 642 | goto invalid_fld; |
640 | } | 643 | } |
641 | 644 | ||
642 | if (lba) { | 645 | if (lba) { |
@@ -679,7 +682,7 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
679 | Head: 0-15 | 682 | Head: 0-15 |
680 | Sector: 1-255*/ | 683 | Sector: 1-255*/ |
681 | if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) | 684 | if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) |
682 | return 1; | 685 | goto out_of_range; |
683 | 686 | ||
684 | tf->command = ATA_CMD_VERIFY; | 687 | tf->command = ATA_CMD_VERIFY; |
685 | tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ | 688 | tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ |
@@ -690,6 +693,20 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
690 | } | 693 | } |
691 | 694 | ||
692 | return 0; | 695 | return 0; |
696 | |||
697 | invalid_fld: | ||
698 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0); | ||
699 | /* "Invalid field in cbd" */ | ||
700 | return 1; | ||
701 | |||
702 | out_of_range: | ||
703 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0); | ||
704 | /* "Logical Block Address out of range" */ | ||
705 | return 1; | ||
706 | |||
707 | nothing_to_do: | ||
708 | qc->scsicmd->result = SAM_STAT_GOOD; | ||
709 | return 1; | ||
693 | } | 710 | } |
694 | 711 | ||
695 | /** | 712 | /** |
@@ -754,7 +771,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
754 | break; | 771 | break; |
755 | default: | 772 | default: |
756 | DPRINTK("no-byte command\n"); | 773 | DPRINTK("no-byte command\n"); |
757 | return 1; | 774 | goto invalid_fld; |
758 | } | 775 | } |
759 | 776 | ||
760 | /* Check and compose ATA command */ | 777 | /* Check and compose ATA command */ |
@@ -764,13 +781,13 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
764 | * However, for ATA R/W commands, sector count 0 means | 781 | * However, for ATA R/W commands, sector count 0 means |
765 | * 256 or 65536 sectors, not 0 sectors as in SCSI. | 782 | * 256 or 65536 sectors, not 0 sectors as in SCSI. |
766 | */ | 783 | */ |
767 | return 1; | 784 | goto nothing_to_do; |
768 | 785 | ||
769 | if (lba) { | 786 | if (lba) { |
770 | if (lba48) { | 787 | if (lba48) { |
771 | /* The request -may- be too large for LBA48. */ | 788 | /* The request -may- be too large for LBA48. */ |
772 | if ((block >> 48) || (n_block > 65536)) | 789 | if ((block >> 48) || (n_block > 65536)) |
773 | return 1; | 790 | goto out_of_range; |
774 | 791 | ||
775 | tf->hob_nsect = (n_block >> 8) & 0xff; | 792 | tf->hob_nsect = (n_block >> 8) & 0xff; |
776 | 793 | ||
@@ -782,7 +799,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
782 | 799 | ||
783 | /* The request -may- be too large for LBA28. */ | 800 | /* The request -may- be too large for LBA28. */ |
784 | if ((block >> 28) || (n_block > 256)) | 801 | if ((block >> 28) || (n_block > 256)) |
785 | return 1; | 802 | goto out_of_range; |
786 | 803 | ||
787 | tf->device |= (block >> 24) & 0xf; | 804 | tf->device |= (block >> 24) & 0xf; |
788 | } | 805 | } |
@@ -801,7 +818,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
801 | 818 | ||
802 | /* The request -may- be too large for CHS addressing. */ | 819 | /* The request -may- be too large for CHS addressing. */ |
803 | if ((block >> 28) || (n_block > 256)) | 820 | if ((block >> 28) || (n_block > 256)) |
804 | return 1; | 821 | goto out_of_range; |
805 | 822 | ||
806 | /* Convert LBA to CHS */ | 823 | /* Convert LBA to CHS */ |
807 | track = (u32)block / dev->sectors; | 824 | track = (u32)block / dev->sectors; |
@@ -817,7 +834,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
817 | Head: 0-15 | 834 | Head: 0-15 |
818 | Sector: 1-255*/ | 835 | Sector: 1-255*/ |
819 | if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) | 836 | if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) |
820 | return 1; | 837 | goto out_of_range; |
821 | 838 | ||
822 | qc->nsect = n_block; | 839 | qc->nsect = n_block; |
823 | tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ | 840 | tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */ |
@@ -828,6 +845,20 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
828 | } | 845 | } |
829 | 846 | ||
830 | return 0; | 847 | return 0; |
848 | |||
849 | invalid_fld: | ||
850 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x0); | ||
851 | /* "Invalid field in cbd" */ | ||
852 | return 1; | ||
853 | |||
854 | out_of_range: | ||
855 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x21, 0x0); | ||
856 | /* "Logical Block Address out of range" */ | ||
857 | return 1; | ||
858 | |||
859 | nothing_to_do: | ||
860 | qc->scsicmd->result = SAM_STAT_GOOD; | ||
861 | return 1; | ||
831 | } | 862 | } |
832 | 863 | ||
833 | static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) | 864 | static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) |
@@ -859,6 +890,12 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) | |||
859 | * This function sets up an ata_queued_cmd structure for the | 890 | * This function sets up an ata_queued_cmd structure for the |
860 | * SCSI command, and sends that ata_queued_cmd to the hardware. | 891 | * SCSI command, and sends that ata_queued_cmd to the hardware. |
861 | * | 892 | * |
893 | * The xlat_func argument (actor) returns 0 if ready to execute | ||
894 | * ATA command, else 1 to finish translation. If 1 is returned | ||
895 | * then cmd->result (and possibly cmd->sense_buffer) are assumed | ||
896 | * to be set reflecting an error condition or clean (early) | ||
897 | * termination. | ||
898 | * | ||
862 | * LOCKING: | 899 | * LOCKING: |
863 | * spin_lock_irqsave(host_set lock) | 900 | * spin_lock_irqsave(host_set lock) |
864 | */ | 901 | */ |
@@ -875,7 +912,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, | |||
875 | 912 | ||
876 | qc = ata_scsi_qc_new(ap, dev, cmd, done); | 913 | qc = ata_scsi_qc_new(ap, dev, cmd, done); |
877 | if (!qc) | 914 | if (!qc) |
878 | return; | 915 | goto err_mem; |
879 | 916 | ||
880 | /* data is present; dma-map it */ | 917 | /* data is present; dma-map it */ |
881 | if (cmd->sc_data_direction == DMA_FROM_DEVICE || | 918 | if (cmd->sc_data_direction == DMA_FROM_DEVICE || |
@@ -883,7 +920,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, | |||
883 | if (unlikely(cmd->request_bufflen < 1)) { | 920 | if (unlikely(cmd->request_bufflen < 1)) { |
884 | printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", | 921 | printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", |
885 | ap->id, dev->devno); | 922 | ap->id, dev->devno); |
886 | goto err_out; | 923 | goto err_did; |
887 | } | 924 | } |
888 | 925 | ||
889 | if (cmd->use_sg) | 926 | if (cmd->use_sg) |
@@ -898,19 +935,28 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, | |||
898 | qc->complete_fn = ata_scsi_qc_complete; | 935 | qc->complete_fn = ata_scsi_qc_complete; |
899 | 936 | ||
900 | if (xlat_func(qc, scsicmd)) | 937 | if (xlat_func(qc, scsicmd)) |
901 | goto err_out; | 938 | goto early_finish; |
902 | 939 | ||
903 | /* select device, send command to hardware */ | 940 | /* select device, send command to hardware */ |
904 | if (ata_qc_issue(qc)) | 941 | if (ata_qc_issue(qc)) |
905 | goto err_out; | 942 | goto err_did; |
906 | 943 | ||
907 | VPRINTK("EXIT\n"); | 944 | VPRINTK("EXIT\n"); |
908 | return; | 945 | return; |
909 | 946 | ||
910 | err_out: | 947 | early_finish: |
948 | ata_qc_free(qc); | ||
949 | done(cmd); | ||
950 | DPRINTK("EXIT - early finish (good or error)\n"); | ||
951 | return; | ||
952 | |||
953 | err_did: | ||
911 | ata_qc_free(qc); | 954 | ata_qc_free(qc); |
912 | ata_bad_cdb(cmd, done); | 955 | err_mem: |
913 | DPRINTK("EXIT - badcmd\n"); | 956 | cmd->result = (DID_ERROR << 16); |
957 | done(cmd); | ||
958 | DPRINTK("EXIT - internal\n"); | ||
959 | return; | ||
914 | } | 960 | } |
915 | 961 | ||
916 | /** | 962 | /** |
@@ -977,7 +1023,8 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf) | |||
977 | * Mapping the response buffer, calling the command's handler, | 1023 | * Mapping the response buffer, calling the command's handler, |
978 | * and handling the handler's return value. This return value | 1024 | * and handling the handler's return value. This return value |
979 | * indicates whether the handler wishes the SCSI command to be | 1025 | * indicates whether the handler wishes the SCSI command to be |
980 | * completed successfully, or not. | 1026 | * completed successfully (0), or not (in which case cmd->result |
1027 | * and sense buffer are assumed to be set). | ||
981 | * | 1028 | * |
982 | * LOCKING: | 1029 | * LOCKING: |
983 | * spin_lock_irqsave(host_set lock) | 1030 | * spin_lock_irqsave(host_set lock) |
@@ -996,12 +1043,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, | |||
996 | rc = actor(args, rbuf, buflen); | 1043 | rc = actor(args, rbuf, buflen); |
997 | ata_scsi_rbuf_put(cmd, rbuf); | 1044 | ata_scsi_rbuf_put(cmd, rbuf); |
998 | 1045 | ||
999 | if (rc) | 1046 | if (rc == 0) |
1000 | ata_bad_cdb(cmd, args->done); | ||
1001 | else { | ||
1002 | cmd->result = SAM_STAT_GOOD; | 1047 | cmd->result = SAM_STAT_GOOD; |
1003 | args->done(cmd); | 1048 | args->done(cmd); |
1004 | } | ||
1005 | } | 1049 | } |
1006 | 1050 | ||
1007 | /** | 1051 | /** |
@@ -1307,8 +1351,16 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
1307 | * in the same manner) | 1351 | * in the same manner) |
1308 | */ | 1352 | */ |
1309 | page_control = scsicmd[2] >> 6; | 1353 | page_control = scsicmd[2] >> 6; |
1310 | if ((page_control != 0) && (page_control != 3)) | 1354 | switch (page_control) { |
1311 | return 1; | 1355 | case 0: /* current */ |
1356 | break; /* supported */ | ||
1357 | case 3: /* saved */ | ||
1358 | goto saving_not_supp; | ||
1359 | case 1: /* changeable */ | ||
1360 | case 2: /* defaults */ | ||
1361 | default: | ||
1362 | goto invalid_fld; | ||
1363 | } | ||
1312 | 1364 | ||
1313 | if (six_byte) | 1365 | if (six_byte) |
1314 | output_len = 4; | 1366 | output_len = 4; |
@@ -1339,7 +1391,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
1339 | break; | 1391 | break; |
1340 | 1392 | ||
1341 | default: /* invalid page code */ | 1393 | default: /* invalid page code */ |
1342 | return 1; | 1394 | goto invalid_fld; |
1343 | } | 1395 | } |
1344 | 1396 | ||
1345 | if (six_byte) { | 1397 | if (six_byte) { |
@@ -1352,6 +1404,16 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
1352 | } | 1404 | } |
1353 | 1405 | ||
1354 | return 0; | 1406 | return 0; |
1407 | |||
1408 | invalid_fld: | ||
1409 | ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0); | ||
1410 | /* "Invalid field in cbd" */ | ||
1411 | return 1; | ||
1412 | |||
1413 | saving_not_supp: | ||
1414 | ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0); | ||
1415 | /* "Saving parameters not supported" */ | ||
1416 | return 1; | ||
1355 | } | 1417 | } |
1356 | 1418 | ||
1357 | /** | 1419 | /** |
@@ -1496,13 +1558,7 @@ void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) | |||
1496 | void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq) | 1558 | void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq) |
1497 | { | 1559 | { |
1498 | DPRINTK("ENTER\n"); | 1560 | DPRINTK("ENTER\n"); |
1499 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; | 1561 | ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq); |
1500 | |||
1501 | cmd->sense_buffer[0] = 0x70; | ||
1502 | cmd->sense_buffer[2] = ILLEGAL_REQUEST; | ||
1503 | cmd->sense_buffer[7] = 14 - 8; /* addnl. sense len. FIXME: correct? */ | ||
1504 | cmd->sense_buffer[12] = asc; | ||
1505 | cmd->sense_buffer[13] = ascq; | ||
1506 | 1562 | ||
1507 | done(cmd); | 1563 | done(cmd); |
1508 | } | 1564 | } |
@@ -1871,7 +1927,7 @@ void ata_scsi_simulate(u16 *id, | |||
1871 | 1927 | ||
1872 | case INQUIRY: | 1928 | case INQUIRY: |
1873 | if (scsicmd[1] & 2) /* is CmdDt set? */ | 1929 | if (scsicmd[1] & 2) /* is CmdDt set? */ |
1874 | ata_bad_cdb(cmd, done); | 1930 | ata_scsi_invalid_field(cmd, done); |
1875 | else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ | 1931 | else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ |
1876 | ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); | 1932 | ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); |
1877 | else if (scsicmd[2] == 0x00) | 1933 | else if (scsicmd[2] == 0x00) |
@@ -1881,7 +1937,7 @@ void ata_scsi_simulate(u16 *id, | |||
1881 | else if (scsicmd[2] == 0x83) | 1937 | else if (scsicmd[2] == 0x83) |
1882 | ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83); | 1938 | ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83); |
1883 | else | 1939 | else |
1884 | ata_bad_cdb(cmd, done); | 1940 | ata_scsi_invalid_field(cmd, done); |
1885 | break; | 1941 | break; |
1886 | 1942 | ||
1887 | case MODE_SENSE: | 1943 | case MODE_SENSE: |
@@ -1891,7 +1947,7 @@ void ata_scsi_simulate(u16 *id, | |||
1891 | 1947 | ||
1892 | case MODE_SELECT: /* unconditionally return */ | 1948 | case MODE_SELECT: /* unconditionally return */ |
1893 | case MODE_SELECT_10: /* bad-field-in-cdb */ | 1949 | case MODE_SELECT_10: /* bad-field-in-cdb */ |
1894 | ata_bad_cdb(cmd, done); | 1950 | ata_scsi_invalid_field(cmd, done); |
1895 | break; | 1951 | break; |
1896 | 1952 | ||
1897 | case READ_CAPACITY: | 1953 | case READ_CAPACITY: |
@@ -1902,7 +1958,7 @@ void ata_scsi_simulate(u16 *id, | |||
1902 | if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) | 1958 | if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) |
1903 | ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); | 1959 | ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); |
1904 | else | 1960 | else |
1905 | ata_bad_cdb(cmd, done); | 1961 | ata_scsi_invalid_field(cmd, done); |
1906 | break; | 1962 | break; |
1907 | 1963 | ||
1908 | case REPORT_LUNS: | 1964 | case REPORT_LUNS: |
@@ -1914,7 +1970,9 @@ void ata_scsi_simulate(u16 *id, | |||
1914 | 1970 | ||
1915 | /* all other commands */ | 1971 | /* all other commands */ |
1916 | default: | 1972 | default: |
1917 | ata_bad_scsiop(cmd, done); | 1973 | ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0); |
1974 | /* "Invalid command operation code" */ | ||
1975 | done(cmd); | ||
1918 | break; | 1976 | break; |
1919 | } | 1977 | } |
1920 | } | 1978 | } |