Commit 815b472b authored by Jeff Garzik's avatar Jeff Garzik

[libata] add ioctl infrastructure

Mainly adding the infrastructure for various ATA ioctls.  Currently
only supports two ATA-specific ioctls:
HDIO_GET_32BIT and HDIO_SET_32BIT (hdparm -c)
parent 7af09f97
...@@ -104,6 +104,7 @@ static struct pci_driver piix_pci_driver = { ...@@ -104,6 +104,7 @@ static struct pci_driver piix_pci_driver = {
static Scsi_Host_Template piix_sht = { static Scsi_Host_Template piix_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -59,7 +59,6 @@ static int ata_choose_xfer_mode(struct ata_port *ap, ...@@ -59,7 +59,6 @@ static int ata_choose_xfer_mode(struct ata_port *ap,
u8 *xfer_mode_out, u8 *xfer_mode_out,
unsigned int *xfer_shift_out); unsigned int *xfer_shift_out);
static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat); static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
static void swap_buf_le16(u16 *buf, unsigned int buf_words);
static unsigned int ata_unique_id = 1; static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq; static struct workqueue_struct *ata_wq;
...@@ -2066,7 +2065,7 @@ static void ata_pio_complete (struct ata_port *ap) ...@@ -2066,7 +2065,7 @@ static void ata_pio_complete (struct ata_port *ap)
ata_qc_complete(qc, drv_stat); ata_qc_complete(qc, drv_stat);
} }
static void swap_buf_le16(u16 *buf, unsigned int buf_words) void swap_buf_le16(u16 *buf, unsigned int buf_words)
{ {
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
unsigned int i; unsigned int i;
...@@ -3561,6 +3560,7 @@ EXPORT_SYMBOL_GPL(ata_bus_reset); ...@@ -3561,6 +3560,7 @@ EXPORT_SYMBOL_GPL(ata_bus_reset);
EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "scsi.h" #include "scsi.h"
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include <linux/libata.h> #include <linux/libata.h>
#include <asm/uaccess.h>
#include "libata.h" #include "libata.h"
...@@ -36,6 +37,8 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd); ...@@ -36,6 +37,8 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd);
static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
struct scsi_cmnd *cmd, struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *)); void (*done)(struct scsi_cmnd *));
static struct ata_device *
ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
/** /**
...@@ -67,6 +70,43 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, ...@@ -67,6 +70,43 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
return 0; return 0;
} }
int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
{
struct ata_port *ap;
struct ata_device *dev;
int val = -EINVAL, rc = -EINVAL;
ap = (struct ata_port *) &scsidev->host->hostdata[0];
if (!ap)
goto out;
dev = ata_scsi_find_dev(ap, scsidev);
if (!dev) {
rc = -ENODEV;
goto out;
}
switch (cmd) {
case ATA_IOC_GET_IO32:
val = 0;
if (copy_to_user(arg, &val, 1))
return -EFAULT;
return 0;
case ATA_IOC_SET_IO32:
val = (long) arg;
if (val != 0)
return -EINVAL;
return 0;
default:
rc = -EOPNOTSUPP;
break;
}
out:
return rc;
}
/** /**
* ata_scsi_qc_new - acquire new ata_queued_cmd reference * ata_scsi_qc_new - acquire new ata_queued_cmd reference
...@@ -1172,19 +1212,19 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) ...@@ -1172,19 +1212,19 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
* Associated ATA device, or %NULL if not found. * Associated ATA device, or %NULL if not found.
*/ */
static inline struct ata_device * static struct ata_device *
ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd) ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
{ {
struct ata_device *dev; struct ata_device *dev;
/* skip commands not addressed to targets we simulate */ /* skip commands not addressed to targets we simulate */
if (likely(cmd->device->id < ATA_MAX_DEVICES)) if (likely(scsidev->id < ATA_MAX_DEVICES))
dev = &ap->device[cmd->device->id]; dev = &ap->device[scsidev->id];
else else
return NULL; return NULL;
if (unlikely((cmd->device->channel != 0) || if (unlikely((scsidev->channel != 0) ||
(cmd->device->lun != 0))) (scsidev->lun != 0)))
return NULL; return NULL;
if (unlikely(!ata_dev_present(dev))) if (unlikely(!ata_dev_present(dev)))
...@@ -1247,11 +1287,12 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap, ...@@ -1247,11 +1287,12 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
struct scsi_cmnd *cmd) struct scsi_cmnd *cmd)
{ {
#ifdef ATA_DEBUG #ifdef ATA_DEBUG
struct scsi_device *scsidev = cmd->device;
u8 *scsicmd = cmd->cmnd; u8 *scsicmd = cmd->cmnd;
DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
ap->id, ap->id,
cmd->device->channel, cmd->device->id, cmd->device->lun, scsidev->channel, scsidev->id, scsidev->lun,
scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3], scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7], scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
scsicmd[8]); scsicmd[8]);
...@@ -1281,12 +1322,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) ...@@ -1281,12 +1322,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{ {
struct ata_port *ap; struct ata_port *ap;
struct ata_device *dev; struct ata_device *dev;
struct scsi_device *scsidev = cmd->device;
ap = (struct ata_port *) &cmd->device->host->hostdata[0]; ap = (struct ata_port *) &scsidev->host->hostdata[0];
ata_scsi_dump_cdb(ap, cmd); ata_scsi_dump_cdb(ap, cmd);
dev = ata_scsi_find_dev(ap, cmd); dev = ata_scsi_find_dev(ap, scsidev);
if (unlikely(!dev)) { if (unlikely(!dev)) {
cmd->result = (DID_BAD_TARGET << 16); cmd->result = (DID_BAD_TARGET << 16);
done(cmd); done(cmd);
......
...@@ -42,6 +42,7 @@ extern int ata_qc_issue(struct ata_queued_cmd *qc); ...@@ -42,6 +42,7 @@ extern int ata_qc_issue(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device, extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep); unsigned int wait, unsigned int can_sleep);
extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf); extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
/* libata-scsi.c */ /* libata-scsi.c */
......
...@@ -178,6 +178,7 @@ static struct pci_driver nv_pci_driver = { ...@@ -178,6 +178,7 @@ static struct pci_driver nv_pci_driver = {
static Scsi_Host_Template nv_sht = { static Scsi_Host_Template nv_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -88,6 +88,7 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); ...@@ -88,6 +88,7 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
static Scsi_Host_Template pdc_sata_sht = { static Scsi_Host_Template pdc_sata_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -106,6 +106,7 @@ static struct pci_driver sil_pci_driver = { ...@@ -106,6 +106,7 @@ static struct pci_driver sil_pci_driver = {
static Scsi_Host_Template sil_sht = { static Scsi_Host_Template sil_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -76,6 +76,7 @@ static struct pci_driver sis_pci_driver = { ...@@ -76,6 +76,7 @@ static struct pci_driver sis_pci_driver = {
static Scsi_Host_Template sis_sht = { static Scsi_Host_Template sis_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -205,6 +205,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, ...@@ -205,6 +205,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
static Scsi_Host_Template k2_sata_sht = { static Scsi_Host_Template k2_sata_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -174,6 +174,7 @@ static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); ...@@ -174,6 +174,7 @@ static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
static Scsi_Host_Template pdc_sata_sht = { static Scsi_Host_Template pdc_sata_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -81,6 +81,7 @@ static struct pci_driver svia_pci_driver = { ...@@ -81,6 +81,7 @@ static struct pci_driver svia_pci_driver = {
static Scsi_Host_Template svia_sht = { static Scsi_Host_Template svia_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -190,6 +190,7 @@ irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *reg ...@@ -190,6 +190,7 @@ irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *reg
static Scsi_Host_Template vsc_sata_sht = { static Scsi_Host_Template vsc_sata_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd, .queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error, .eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE, .can_queue = ATA_DEF_QUEUE,
......
...@@ -182,6 +182,11 @@ enum ata_tf_protocols { ...@@ -182,6 +182,11 @@ enum ata_tf_protocols {
ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */
}; };
enum ata_ioctls {
ATA_IOC_GET_IO32 = 0x309,
ATA_IOC_SET_IO32 = 0x324,
};
/* core structures */ /* core structures */
struct ata_prd { struct ata_prd {
......
...@@ -371,6 +371,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i ...@@ -371,6 +371,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
extern void ata_pci_remove_one (struct pci_dev *pdev); extern void ata_pci_remove_one (struct pci_dev *pdev);
extern int ata_device_add(struct ata_probe_ent *ent); extern int ata_device_add(struct ata_probe_ent *ent);
extern int ata_scsi_detect(Scsi_Host_Template *sht); extern int ata_scsi_detect(Scsi_Host_Template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_error(struct Scsi_Host *host);
extern int ata_scsi_release(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment