aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2007-08-07 12:08:45 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:32 -0400
commitbaf4fdfaaf5cb9f4fb1c341c8cef60a64e580582 (patch)
treef26293a36958a6813bf1353cb07afd3d6be6aa0d /drivers/ata/libata-scsi.c
parent4cc980b34b2a25f600576dcd11de388bc44e1ebd (diff)
libata: add support for ATA_16 on ATAPI
Add support for issuing ATA_16 passthru commands to ATAPI devices managed by libata. It requires the previous CDB length fix patch. A boot/module parameter, "atapi_passthru16=0" can be used to globally disable this feature, if ever desired. tj: restructured __ata_scsi_queuecmd() according to Jeff's suggestion. Signed-off-by: Mark Lord <liml@rtr.ca> Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 58051ee40f1a..7d66c986a54c 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2761,28 +2761,48 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
2761 void (*done)(struct scsi_cmnd *), 2761 void (*done)(struct scsi_cmnd *),
2762 struct ata_device *dev) 2762 struct ata_device *dev)
2763{ 2763{
2764 u8 scsi_op = scmd->cmnd[0];
2765 ata_xlat_func_t xlat_func;
2764 int rc = 0; 2766 int rc = 0;
2765 2767
2766 if (unlikely(!scmd->cmd_len || scmd->cmd_len > dev->cdb_len)) {
2767 DPRINTK("bad CDB len=%u, max=%u\n",
2768 scmd->cmd_len, dev->cdb_len);
2769 scmd->result = DID_ERROR << 16;
2770 done(scmd);
2771 return 0;
2772 }
2773
2774 if (dev->class == ATA_DEV_ATA) { 2768 if (dev->class == ATA_DEV_ATA) {
2775 ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, 2769 if (unlikely(!scmd->cmd_len || scmd->cmd_len > dev->cdb_len))
2776 scmd->cmnd[0]); 2770 goto bad_cdb_len;
2777 2771
2778 if (xlat_func) 2772 xlat_func = ata_get_xlat_func(dev, scsi_op);
2779 rc = ata_scsi_translate(dev, scmd, done, xlat_func); 2773 } else {
2780 else 2774 if (unlikely(!scmd->cmd_len))
2781 ata_scsi_simulate(dev, scmd, done); 2775 goto bad_cdb_len;
2782 } else 2776
2783 rc = ata_scsi_translate(dev, scmd, done, atapi_xlat); 2777 xlat_func = NULL;
2778 if (likely((scsi_op != ATA_16) || !atapi_passthru16)) {
2779 /* relay SCSI command to ATAPI device */
2780 if (unlikely(scmd->cmd_len > dev->cdb_len))
2781 goto bad_cdb_len;
2782
2783 xlat_func = atapi_xlat;
2784 } else {
2785 /* ATA_16 passthru, treat as an ATA command */
2786 if (unlikely(scmd->cmd_len > 16))
2787 goto bad_cdb_len;
2788
2789 xlat_func = ata_get_xlat_func(dev, scsi_op);
2790 }
2791 }
2792
2793 if (xlat_func)
2794 rc = ata_scsi_translate(dev, scmd, done, xlat_func);
2795 else
2796 ata_scsi_simulate(dev, scmd, done);
2784 2797
2785 return rc; 2798 return rc;
2799
2800 bad_cdb_len:
2801 DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n",
2802 scmd->cmd_len, scsi_op, dev->cdb_len);
2803 scmd->result = DID_ERROR << 16;
2804 done(scmd);
2805 return 0;
2786} 2806}
2787 2807
2788/** 2808/**