aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/ata/libata-core.c4
-rw-r--r--drivers/ata/libata-scsi.c52
-rw-r--r--drivers/ata/libata.h1
3 files changed, 41 insertions, 16 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index fc0679370638..75ccf46972d8 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -86,6 +86,10 @@ int atapi_dmadir = 0;
86module_param(atapi_dmadir, int, 0444); 86module_param(atapi_dmadir, int, 0444);
87MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)"); 87MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)");
88 88
89int atapi_passthru16 = 1;
90module_param(atapi_passthru16, int, 0444);
91MODULE_PARM_DESC(atapi_passthru16, "Enable ATA_16 passthru for ATAPI devices; on by default (0=off, 1=on)");
92
89int libata_fua = 0; 93int libata_fua = 0;
90module_param_named(fua, libata_fua, int, 0444); 94module_param_named(fua, libata_fua, int, 0444);
91MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)"); 95MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
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/**
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 6d85edefa7c6..11f64a43b38a 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -56,6 +56,7 @@ extern unsigned int ata_print_id;
56extern struct workqueue_struct *ata_aux_wq; 56extern struct workqueue_struct *ata_aux_wq;
57extern int atapi_enabled; 57extern int atapi_enabled;
58extern int atapi_dmadir; 58extern int atapi_dmadir;
59extern int atapi_passthru16;
59extern int libata_fua; 60extern int libata_fua;
60extern int libata_noacpi; 61extern int libata_noacpi;
61extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); 62extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);