Loading drivers/ata/libata-scsi.c +108 −47 Original line number Original line Diff line number Diff line Loading @@ -300,6 +300,15 @@ void ata_scsi_set_sense_information(struct ata_device *dev, SCSI_SENSE_BUFFERSIZE, information); SCSI_SENSE_BUFFERSIZE, information); } } static void ata_scsi_set_invalid_field(struct ata_device *dev, struct scsi_cmnd *cmd, u16 field) { ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, field, 0xff, 1); } static ssize_t static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) const char *buf, size_t count) Loading Loading @@ -388,10 +397,9 @@ struct device_attribute *ata_common_sdev_attrs[] = { EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); static void ata_scsi_invalid_field(struct ata_device *dev, static void ata_scsi_invalid_field(struct ata_device *dev, struct scsi_cmnd *cmd) struct scsi_cmnd *cmd, u16 field) { { ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(dev, cmd, field); /* "Invalid field in cbd" */ cmd->scsi_done(cmd); cmd->scsi_done(cmd); } } Loading Loading @@ -1386,19 +1394,26 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; struct scsi_cmnd *scmd = qc->scsicmd; struct ata_taskfile *tf = &qc->tf; struct ata_taskfile *tf = &qc->tf; const u8 *cdb = scmd->cmnd; const u8 *cdb = scmd->cmnd; u16 fp; if (scmd->cmd_len < 5) if (scmd->cmd_len < 5) { fp = 4; goto invalid_fld; goto invalid_fld; } tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; tf->protocol = ATA_PROT_NODATA; tf->protocol = ATA_PROT_NODATA; if (cdb[1] & 0x1) { if (cdb[1] & 0x1) { ; /* ignore IMMED bit, violates sat-r05 */ ; /* ignore IMMED bit, violates sat-r05 */ } } if (cdb[4] & 0x2) if (cdb[4] & 0x2) { fp = 4; goto invalid_fld; /* LOEJ bit set not supported */ goto invalid_fld; /* LOEJ bit set not supported */ if (((cdb[4] >> 4) & 0xf) != 0) } if (((cdb[4] >> 4) & 0xf) != 0) { fp = 4; goto invalid_fld; /* power conditions not supported */ goto invalid_fld; /* power conditions not supported */ } if (cdb[4] & 0x1) { if (cdb[4] & 0x1) { tf->nsect = 1; /* 1 sector, lba=0 */ tf->nsect = 1; /* 1 sector, lba=0 */ Loading Loading @@ -1444,8 +1459,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(qc->dev, scmd, fp); /* "Invalid field in cbd" */ return 1; return 1; skip: skip: scmd->result = SAM_STAT_GOOD; scmd->result = SAM_STAT_GOOD; Loading Loading @@ -1596,20 +1610,27 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) const u8 *cdb = scmd->cmnd; const u8 *cdb = scmd->cmnd; u64 block; u64 block; u32 n_block; u32 n_block; u16 fp; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; tf->protocol = ATA_PROT_NODATA; if (cdb[0] == VERIFY) { if (cdb[0] == VERIFY) { if (scmd->cmd_len < 10) if (scmd->cmd_len < 10) { fp = 9; goto invalid_fld; goto invalid_fld; } scsi_10_lba_len(cdb, &block, &n_block); scsi_10_lba_len(cdb, &block, &n_block); } else if (cdb[0] == VERIFY_16) { } else if (cdb[0] == VERIFY_16) { if (scmd->cmd_len < 16) if (scmd->cmd_len < 16) { fp = 15; goto invalid_fld; goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); scsi_16_lba_len(cdb, &block, &n_block); } else } else { fp = 0; goto invalid_fld; goto invalid_fld; } if (!n_block) if (!n_block) goto nothing_to_do; goto nothing_to_do; Loading Loading @@ -1683,8 +1704,7 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(qc->dev, scmd, fp); /* "Invalid field in cbd" */ return 1; return 1; out_of_range: out_of_range: Loading Loading @@ -1723,6 +1743,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) u64 block; u64 block; u32 n_block; u32 n_block; int rc; int rc; u16 fp = 0; if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16) if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16) tf_flags |= ATA_TFLAG_WRITE; tf_flags |= ATA_TFLAG_WRITE; Loading @@ -1731,16 +1752,20 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) switch (cdb[0]) { switch (cdb[0]) { case READ_10: case READ_10: case WRITE_10: case WRITE_10: if (unlikely(scmd->cmd_len < 10)) if (unlikely(scmd->cmd_len < 10)) { fp = 9; goto invalid_fld; goto invalid_fld; } scsi_10_lba_len(cdb, &block, &n_block); scsi_10_lba_len(cdb, &block, &n_block); if (cdb[1] & (1 << 3)) if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; tf_flags |= ATA_TFLAG_FUA; break; break; case READ_6: case READ_6: case WRITE_6: case WRITE_6: if (unlikely(scmd->cmd_len < 6)) if (unlikely(scmd->cmd_len < 6)) { fp = 5; goto invalid_fld; goto invalid_fld; } scsi_6_lba_len(cdb, &block, &n_block); scsi_6_lba_len(cdb, &block, &n_block); /* for 6-byte r/w commands, transfer length 0 /* for 6-byte r/w commands, transfer length 0 Loading @@ -1751,14 +1776,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) break; break; case READ_16: case READ_16: case WRITE_16: case WRITE_16: if (unlikely(scmd->cmd_len < 16)) if (unlikely(scmd->cmd_len < 16)) { fp = 15; goto invalid_fld; goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); scsi_16_lba_len(cdb, &block, &n_block); if (cdb[1] & (1 << 3)) if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; tf_flags |= ATA_TFLAG_FUA; break; break; default: default: DPRINTK("no-byte command\n"); DPRINTK("no-byte command\n"); fp = 0; goto invalid_fld; goto invalid_fld; } } Loading @@ -1785,8 +1813,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto out_of_range; goto out_of_range; /* treat all other errors as -EINVAL, fall through */ /* treat all other errors as -EINVAL, fall through */ invalid_fld: invalid_fld: ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(qc->dev, scmd, fp); /* "Invalid field in cbd" */ return 1; return 1; out_of_range: out_of_range: Loading Loading @@ -2445,6 +2472,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) u8 pg, spg; u8 pg, spg; unsigned int ebd, page_control, six_byte; unsigned int ebd, page_control, six_byte; u8 dpofua; u8 dpofua; u16 fp; VPRINTK("ENTER\n"); VPRINTK("ENTER\n"); Loading @@ -2463,6 +2491,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) case 3: /* saved */ case 3: /* saved */ goto saving_not_supp; goto saving_not_supp; default: default: fp = 2; goto invalid_fld; goto invalid_fld; } } Loading @@ -2477,8 +2506,10 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) * No mode subpages supported (yet) but asking for _all_ * No mode subpages supported (yet) but asking for _all_ * subpages may be valid * subpages may be valid */ */ if (spg && (spg != ALL_SUB_MPAGES)) if (spg && (spg != ALL_SUB_MPAGES)) { fp = 3; goto invalid_fld; goto invalid_fld; } switch(pg) { switch(pg) { case RW_RECOVERY_MPAGE: case RW_RECOVERY_MPAGE: Loading @@ -2500,6 +2531,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) break; break; default: /* invalid page code */ default: /* invalid page code */ fp = 2; goto invalid_fld; goto invalid_fld; } } Loading Loading @@ -2529,8 +2561,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(dev, args->cmd, fp); /* "Invalid field in cbd" */ return 1; return 1; saving_not_supp: saving_not_supp: Loading Loading @@ -2991,9 +3022,12 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; struct scsi_cmnd *scmd = qc->scsicmd; struct ata_device *dev = qc->dev; struct ata_device *dev = qc->dev; const u8 *cdb = scmd->cmnd; const u8 *cdb = scmd->cmnd; u16 fp; if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) { fp = 1; goto invalid_fld; goto invalid_fld; } /* enable LBA */ /* enable LBA */ tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA; Loading Loading @@ -3057,8 +3091,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) case ATA_CMD_READ_LONG_ONCE: case ATA_CMD_READ_LONG_ONCE: case ATA_CMD_WRITE_LONG: case ATA_CMD_WRITE_LONG: case ATA_CMD_WRITE_LONG_ONCE: case ATA_CMD_WRITE_LONG_ONCE: if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) { fp = 1; goto invalid_fld; goto invalid_fld; } qc->sect_size = scsi_bufflen(scmd); qc->sect_size = scsi_bufflen(scmd); break; break; Loading Loading @@ -3121,12 +3157,16 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) ata_qc_set_pc_nbytes(qc); ata_qc_set_pc_nbytes(qc); /* We may not issue DMA commands if no DMA mode is set */ /* We may not issue DMA commands if no DMA mode is set */ if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) { fp = 1; goto invalid_fld; goto invalid_fld; } /* sanity check for pio multi commands */ /* sanity check for pio multi commands */ if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) { fp = 1; goto invalid_fld; goto invalid_fld; } if (is_multi_taskfile(tf)) { if (is_multi_taskfile(tf)) { unsigned int multi_count = 1 << (cdb[1] >> 5); unsigned int multi_count = 1 << (cdb[1] >> 5); Loading @@ -3147,8 +3187,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * ->set_dmamode(), and ->post_set_mode() hooks). * ->set_dmamode(), and ->post_set_mode() hooks). */ */ if (tf->command == ATA_CMD_SET_FEATURES && if (tf->command == ATA_CMD_SET_FEATURES && tf->feature == SETFEATURES_XFER) tf->feature == SETFEATURES_XFER) { fp = (cdb[0] == ATA_16) ? 4 : 3; goto invalid_fld; goto invalid_fld; } /* /* * Filter TPM commands by default. These provide an * Filter TPM commands by default. These provide an Loading @@ -3165,14 +3207,15 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * so that we comply with the TC consortium stated goal that the user * so that we comply with the TC consortium stated goal that the user * can turn off TC features of their system. * can turn off TC features of their system. */ */ if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) { fp = (cdb[0] == ATA_16) ? 14 : 9; goto invalid_fld; goto invalid_fld; } return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); ata_scsi_set_invalid_field(dev, scmd, fp); /* "Invalid field in cdb" */ return 1; return 1; } } Loading @@ -3186,25 +3229,30 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) u32 n_block; u32 n_block; u32 size; u32 size; void *buf; void *buf; u16 fp; /* we may not issue DMA commands if no DMA mode is set */ /* we may not issue DMA commands if no DMA mode is set */ if (unlikely(!dev->dma_mode)) if (unlikely(!dev->dma_mode)) goto invalid_fld; goto invalid_opcode; if (unlikely(scmd->cmd_len < 16)) if (unlikely(scmd->cmd_len < 16)) { fp = 15; goto invalid_fld; goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); scsi_16_lba_len(cdb, &block, &n_block); /* for now we only support WRITE SAME with the unmap bit set */ /* for now we only support WRITE SAME with the unmap bit set */ if (unlikely(!(cdb[1] & 0x8))) if (unlikely(!(cdb[1] & 0x8))) { fp = 1; goto invalid_fld; goto invalid_fld; } /* /* * WRITE SAME always has a sector sized buffer as payload, this * WRITE SAME always has a sector sized buffer as payload, this * should never be a multiple entry S/G list. * should never be a multiple entry S/G list. */ */ if (!scsi_sg_count(scmd)) if (!scsi_sg_count(scmd)) goto invalid_fld; goto invalid_param_len; buf = page_address(sg_page(scsi_sglist(scmd))); buf = page_address(sg_page(scsi_sglist(scmd))); size = ata_set_lba_range_entries(buf, 512, block, n_block); size = ata_set_lba_range_entries(buf, 512, block, n_block); Loading Loading @@ -3236,8 +3284,15 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); ata_scsi_set_invalid_field(dev, scmd, fp); /* "Invalid field in cdb" */ return 1; invalid_param_len: /* "Parameter list length error" */ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); return 1; invalid_opcode: /* "Invalid command operation code" */ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0); return 1; return 1; } } Loading Loading @@ -3351,27 +3406,34 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) u8 pg, spg; u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; unsigned six_byte, pg_len, hdr_len, bd_len; int len; int len; u16 fp; VPRINTK("ENTER\n"); VPRINTK("ENTER\n"); six_byte = (cdb[0] == MODE_SELECT); six_byte = (cdb[0] == MODE_SELECT); if (six_byte) { if (six_byte) { if (scmd->cmd_len < 5) if (scmd->cmd_len < 5) { fp = 4; goto invalid_fld; goto invalid_fld; } len = cdb[4]; len = cdb[4]; hdr_len = 4; hdr_len = 4; } else { } else { if (scmd->cmd_len < 9) if (scmd->cmd_len < 9) { fp = 8; goto invalid_fld; goto invalid_fld; } len = (cdb[7] << 8) + cdb[8]; len = (cdb[7] << 8) + cdb[8]; hdr_len = 8; hdr_len = 8; } } /* We only support PF=1, SP=0. */ /* We only support PF=1, SP=0. */ if ((cdb[1] & 0x11) != 0x10) if ((cdb[1] & 0x11) != 0x10) { fp = 1; goto invalid_fld; goto invalid_fld; } /* Test early for possible overrun. */ /* Test early for possible overrun. */ if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) Loading Loading @@ -3452,8 +3514,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: /* "Invalid field in CDB" */ ata_scsi_set_invalid_field(qc->dev, scmd, fp); ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); return 1; return 1; invalid_param: invalid_param: Loading Loading @@ -3667,12 +3728,12 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) switch(scsicmd[0]) { switch(scsicmd[0]) { /* TODO: worth improving? */ /* TODO: worth improving? */ case FORMAT_UNIT: case FORMAT_UNIT: ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 0); break; break; case INQUIRY: case INQUIRY: if (scsicmd[1] & 2) /* is CmdDt set? */ if (scsicmd[1] & 2) /* is CmdDt set? */ ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 1); else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); else switch (scsicmd[2]) { else switch (scsicmd[2]) { Loading @@ -3698,7 +3759,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); break; break; default: default: ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 2); break; break; } } break; break; Loading @@ -3716,7 +3777,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); else else ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 1); break; break; case REPORT_LUNS: case REPORT_LUNS: Loading Loading @@ -3748,7 +3809,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4])) if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4])) ata_scsi_rbuf_fill(&args, ata_scsiop_noop); ata_scsi_rbuf_fill(&args, ata_scsiop_noop); else else ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 1); break; break; /* all other commands */ /* all other commands */ Loading Loading
drivers/ata/libata-scsi.c +108 −47 Original line number Original line Diff line number Diff line Loading @@ -300,6 +300,15 @@ void ata_scsi_set_sense_information(struct ata_device *dev, SCSI_SENSE_BUFFERSIZE, information); SCSI_SENSE_BUFFERSIZE, information); } } static void ata_scsi_set_invalid_field(struct ata_device *dev, struct scsi_cmnd *cmd, u16 field) { ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); /* "Invalid field in cbd" */ scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, field, 0xff, 1); } static ssize_t static ssize_t ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) const char *buf, size_t count) Loading Loading @@ -388,10 +397,9 @@ struct device_attribute *ata_common_sdev_attrs[] = { EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); static void ata_scsi_invalid_field(struct ata_device *dev, static void ata_scsi_invalid_field(struct ata_device *dev, struct scsi_cmnd *cmd) struct scsi_cmnd *cmd, u16 field) { { ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(dev, cmd, field); /* "Invalid field in cbd" */ cmd->scsi_done(cmd); cmd->scsi_done(cmd); } } Loading Loading @@ -1386,19 +1394,26 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; struct scsi_cmnd *scmd = qc->scsicmd; struct ata_taskfile *tf = &qc->tf; struct ata_taskfile *tf = &qc->tf; const u8 *cdb = scmd->cmnd; const u8 *cdb = scmd->cmnd; u16 fp; if (scmd->cmd_len < 5) if (scmd->cmd_len < 5) { fp = 4; goto invalid_fld; goto invalid_fld; } tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; tf->protocol = ATA_PROT_NODATA; tf->protocol = ATA_PROT_NODATA; if (cdb[1] & 0x1) { if (cdb[1] & 0x1) { ; /* ignore IMMED bit, violates sat-r05 */ ; /* ignore IMMED bit, violates sat-r05 */ } } if (cdb[4] & 0x2) if (cdb[4] & 0x2) { fp = 4; goto invalid_fld; /* LOEJ bit set not supported */ goto invalid_fld; /* LOEJ bit set not supported */ if (((cdb[4] >> 4) & 0xf) != 0) } if (((cdb[4] >> 4) & 0xf) != 0) { fp = 4; goto invalid_fld; /* power conditions not supported */ goto invalid_fld; /* power conditions not supported */ } if (cdb[4] & 0x1) { if (cdb[4] & 0x1) { tf->nsect = 1; /* 1 sector, lba=0 */ tf->nsect = 1; /* 1 sector, lba=0 */ Loading Loading @@ -1444,8 +1459,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(qc->dev, scmd, fp); /* "Invalid field in cbd" */ return 1; return 1; skip: skip: scmd->result = SAM_STAT_GOOD; scmd->result = SAM_STAT_GOOD; Loading Loading @@ -1596,20 +1610,27 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) const u8 *cdb = scmd->cmnd; const u8 *cdb = scmd->cmnd; u64 block; u64 block; u32 n_block; u32 n_block; u16 fp; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->protocol = ATA_PROT_NODATA; tf->protocol = ATA_PROT_NODATA; if (cdb[0] == VERIFY) { if (cdb[0] == VERIFY) { if (scmd->cmd_len < 10) if (scmd->cmd_len < 10) { fp = 9; goto invalid_fld; goto invalid_fld; } scsi_10_lba_len(cdb, &block, &n_block); scsi_10_lba_len(cdb, &block, &n_block); } else if (cdb[0] == VERIFY_16) { } else if (cdb[0] == VERIFY_16) { if (scmd->cmd_len < 16) if (scmd->cmd_len < 16) { fp = 15; goto invalid_fld; goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); scsi_16_lba_len(cdb, &block, &n_block); } else } else { fp = 0; goto invalid_fld; goto invalid_fld; } if (!n_block) if (!n_block) goto nothing_to_do; goto nothing_to_do; Loading Loading @@ -1683,8 +1704,7 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(qc->dev, scmd, fp); /* "Invalid field in cbd" */ return 1; return 1; out_of_range: out_of_range: Loading Loading @@ -1723,6 +1743,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) u64 block; u64 block; u32 n_block; u32 n_block; int rc; int rc; u16 fp = 0; if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16) if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16) tf_flags |= ATA_TFLAG_WRITE; tf_flags |= ATA_TFLAG_WRITE; Loading @@ -1731,16 +1752,20 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) switch (cdb[0]) { switch (cdb[0]) { case READ_10: case READ_10: case WRITE_10: case WRITE_10: if (unlikely(scmd->cmd_len < 10)) if (unlikely(scmd->cmd_len < 10)) { fp = 9; goto invalid_fld; goto invalid_fld; } scsi_10_lba_len(cdb, &block, &n_block); scsi_10_lba_len(cdb, &block, &n_block); if (cdb[1] & (1 << 3)) if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; tf_flags |= ATA_TFLAG_FUA; break; break; case READ_6: case READ_6: case WRITE_6: case WRITE_6: if (unlikely(scmd->cmd_len < 6)) if (unlikely(scmd->cmd_len < 6)) { fp = 5; goto invalid_fld; goto invalid_fld; } scsi_6_lba_len(cdb, &block, &n_block); scsi_6_lba_len(cdb, &block, &n_block); /* for 6-byte r/w commands, transfer length 0 /* for 6-byte r/w commands, transfer length 0 Loading @@ -1751,14 +1776,17 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) break; break; case READ_16: case READ_16: case WRITE_16: case WRITE_16: if (unlikely(scmd->cmd_len < 16)) if (unlikely(scmd->cmd_len < 16)) { fp = 15; goto invalid_fld; goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); scsi_16_lba_len(cdb, &block, &n_block); if (cdb[1] & (1 << 3)) if (cdb[1] & (1 << 3)) tf_flags |= ATA_TFLAG_FUA; tf_flags |= ATA_TFLAG_FUA; break; break; default: default: DPRINTK("no-byte command\n"); DPRINTK("no-byte command\n"); fp = 0; goto invalid_fld; goto invalid_fld; } } Loading @@ -1785,8 +1813,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) goto out_of_range; goto out_of_range; /* treat all other errors as -EINVAL, fall through */ /* treat all other errors as -EINVAL, fall through */ invalid_fld: invalid_fld: ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(qc->dev, scmd, fp); /* "Invalid field in cbd" */ return 1; return 1; out_of_range: out_of_range: Loading Loading @@ -2445,6 +2472,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) u8 pg, spg; u8 pg, spg; unsigned int ebd, page_control, six_byte; unsigned int ebd, page_control, six_byte; u8 dpofua; u8 dpofua; u16 fp; VPRINTK("ENTER\n"); VPRINTK("ENTER\n"); Loading @@ -2463,6 +2491,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) case 3: /* saved */ case 3: /* saved */ goto saving_not_supp; goto saving_not_supp; default: default: fp = 2; goto invalid_fld; goto invalid_fld; } } Loading @@ -2477,8 +2506,10 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) * No mode subpages supported (yet) but asking for _all_ * No mode subpages supported (yet) but asking for _all_ * subpages may be valid * subpages may be valid */ */ if (spg && (spg != ALL_SUB_MPAGES)) if (spg && (spg != ALL_SUB_MPAGES)) { fp = 3; goto invalid_fld; goto invalid_fld; } switch(pg) { switch(pg) { case RW_RECOVERY_MPAGE: case RW_RECOVERY_MPAGE: Loading @@ -2500,6 +2531,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) break; break; default: /* invalid page code */ default: /* invalid page code */ fp = 2; goto invalid_fld; goto invalid_fld; } } Loading Loading @@ -2529,8 +2561,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_invalid_field(dev, args->cmd, fp); /* "Invalid field in cbd" */ return 1; return 1; saving_not_supp: saving_not_supp: Loading Loading @@ -2991,9 +3022,12 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) struct scsi_cmnd *scmd = qc->scsicmd; struct scsi_cmnd *scmd = qc->scsicmd; struct ata_device *dev = qc->dev; struct ata_device *dev = qc->dev; const u8 *cdb = scmd->cmnd; const u8 *cdb = scmd->cmnd; u16 fp; if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) { fp = 1; goto invalid_fld; goto invalid_fld; } /* enable LBA */ /* enable LBA */ tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA; Loading Loading @@ -3057,8 +3091,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) case ATA_CMD_READ_LONG_ONCE: case ATA_CMD_READ_LONG_ONCE: case ATA_CMD_WRITE_LONG: case ATA_CMD_WRITE_LONG: case ATA_CMD_WRITE_LONG_ONCE: case ATA_CMD_WRITE_LONG_ONCE: if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) { fp = 1; goto invalid_fld; goto invalid_fld; } qc->sect_size = scsi_bufflen(scmd); qc->sect_size = scsi_bufflen(scmd); break; break; Loading Loading @@ -3121,12 +3157,16 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) ata_qc_set_pc_nbytes(qc); ata_qc_set_pc_nbytes(qc); /* We may not issue DMA commands if no DMA mode is set */ /* We may not issue DMA commands if no DMA mode is set */ if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) { fp = 1; goto invalid_fld; goto invalid_fld; } /* sanity check for pio multi commands */ /* sanity check for pio multi commands */ if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) { fp = 1; goto invalid_fld; goto invalid_fld; } if (is_multi_taskfile(tf)) { if (is_multi_taskfile(tf)) { unsigned int multi_count = 1 << (cdb[1] >> 5); unsigned int multi_count = 1 << (cdb[1] >> 5); Loading @@ -3147,8 +3187,10 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * ->set_dmamode(), and ->post_set_mode() hooks). * ->set_dmamode(), and ->post_set_mode() hooks). */ */ if (tf->command == ATA_CMD_SET_FEATURES && if (tf->command == ATA_CMD_SET_FEATURES && tf->feature == SETFEATURES_XFER) tf->feature == SETFEATURES_XFER) { fp = (cdb[0] == ATA_16) ? 4 : 3; goto invalid_fld; goto invalid_fld; } /* /* * Filter TPM commands by default. These provide an * Filter TPM commands by default. These provide an Loading @@ -3165,14 +3207,15 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) * so that we comply with the TC consortium stated goal that the user * so that we comply with the TC consortium stated goal that the user * can turn off TC features of their system. * can turn off TC features of their system. */ */ if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) { fp = (cdb[0] == ATA_16) ? 14 : 9; goto invalid_fld; goto invalid_fld; } return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); ata_scsi_set_invalid_field(dev, scmd, fp); /* "Invalid field in cdb" */ return 1; return 1; } } Loading @@ -3186,25 +3229,30 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) u32 n_block; u32 n_block; u32 size; u32 size; void *buf; void *buf; u16 fp; /* we may not issue DMA commands if no DMA mode is set */ /* we may not issue DMA commands if no DMA mode is set */ if (unlikely(!dev->dma_mode)) if (unlikely(!dev->dma_mode)) goto invalid_fld; goto invalid_opcode; if (unlikely(scmd->cmd_len < 16)) if (unlikely(scmd->cmd_len < 16)) { fp = 15; goto invalid_fld; goto invalid_fld; } scsi_16_lba_len(cdb, &block, &n_block); scsi_16_lba_len(cdb, &block, &n_block); /* for now we only support WRITE SAME with the unmap bit set */ /* for now we only support WRITE SAME with the unmap bit set */ if (unlikely(!(cdb[1] & 0x8))) if (unlikely(!(cdb[1] & 0x8))) { fp = 1; goto invalid_fld; goto invalid_fld; } /* /* * WRITE SAME always has a sector sized buffer as payload, this * WRITE SAME always has a sector sized buffer as payload, this * should never be a multiple entry S/G list. * should never be a multiple entry S/G list. */ */ if (!scsi_sg_count(scmd)) if (!scsi_sg_count(scmd)) goto invalid_fld; goto invalid_param_len; buf = page_address(sg_page(scsi_sglist(scmd))); buf = page_address(sg_page(scsi_sglist(scmd))); size = ata_set_lba_range_entries(buf, 512, block, n_block); size = ata_set_lba_range_entries(buf, 512, block, n_block); Loading Loading @@ -3236,8 +3284,15 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x24, 0x00); ata_scsi_set_invalid_field(dev, scmd, fp); /* "Invalid field in cdb" */ return 1; invalid_param_len: /* "Parameter list length error" */ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0); return 1; invalid_opcode: /* "Invalid command operation code" */ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0); return 1; return 1; } } Loading Loading @@ -3351,27 +3406,34 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) u8 pg, spg; u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; unsigned six_byte, pg_len, hdr_len, bd_len; int len; int len; u16 fp; VPRINTK("ENTER\n"); VPRINTK("ENTER\n"); six_byte = (cdb[0] == MODE_SELECT); six_byte = (cdb[0] == MODE_SELECT); if (six_byte) { if (six_byte) { if (scmd->cmd_len < 5) if (scmd->cmd_len < 5) { fp = 4; goto invalid_fld; goto invalid_fld; } len = cdb[4]; len = cdb[4]; hdr_len = 4; hdr_len = 4; } else { } else { if (scmd->cmd_len < 9) if (scmd->cmd_len < 9) { fp = 8; goto invalid_fld; goto invalid_fld; } len = (cdb[7] << 8) + cdb[8]; len = (cdb[7] << 8) + cdb[8]; hdr_len = 8; hdr_len = 8; } } /* We only support PF=1, SP=0. */ /* We only support PF=1, SP=0. */ if ((cdb[1] & 0x11) != 0x10) if ((cdb[1] & 0x11) != 0x10) { fp = 1; goto invalid_fld; goto invalid_fld; } /* Test early for possible overrun. */ /* Test early for possible overrun. */ if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) Loading Loading @@ -3452,8 +3514,7 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) return 0; return 0; invalid_fld: invalid_fld: /* "Invalid field in CDB" */ ata_scsi_set_invalid_field(qc->dev, scmd, fp); ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x24, 0x0); return 1; return 1; invalid_param: invalid_param: Loading Loading @@ -3667,12 +3728,12 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) switch(scsicmd[0]) { switch(scsicmd[0]) { /* TODO: worth improving? */ /* TODO: worth improving? */ case FORMAT_UNIT: case FORMAT_UNIT: ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 0); break; break; case INQUIRY: case INQUIRY: if (scsicmd[1] & 2) /* is CmdDt set? */ if (scsicmd[1] & 2) /* is CmdDt set? */ ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 1); else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); else switch (scsicmd[2]) { else switch (scsicmd[2]) { Loading @@ -3698,7 +3759,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2); break; break; default: default: ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 2); break; break; } } break; break; Loading @@ -3716,7 +3777,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16) ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap); else else ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 1); break; break; case REPORT_LUNS: case REPORT_LUNS: Loading Loading @@ -3748,7 +3809,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4])) if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4])) ata_scsi_rbuf_fill(&args, ata_scsiop_noop); ata_scsi_rbuf_fill(&args, ata_scsiop_noop); else else ata_scsi_invalid_field(dev, cmd); ata_scsi_invalid_field(dev, cmd, 1); break; break; /* all other commands */ /* all other commands */ Loading