|
@@ -157,180 +157,6 @@ int scsi_set_medium_removal(struct scsi_device *sdev, char state)
|
|
|
}
|
|
|
EXPORT_SYMBOL(scsi_set_medium_removal);
|
|
|
|
|
|
-/*
|
|
|
- * This interface is deprecated - users should use the scsi generic (sg)
|
|
|
- * interface instead, as this is a more flexible approach to performing
|
|
|
- * generic SCSI commands on a device.
|
|
|
- *
|
|
|
- * The structure that we are passed should look like:
|
|
|
- *
|
|
|
- * struct sdata {
|
|
|
- * unsigned int inlen; [i] Length of data to be written to device
|
|
|
- * unsigned int outlen; [i] Length of data to be read from device
|
|
|
- * unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12).
|
|
|
- * [o] Data read from device starts here.
|
|
|
- * [o] On error, sense buffer starts here.
|
|
|
- * unsigned char wdata[y]; [i] Data written to device starts here.
|
|
|
- * };
|
|
|
- * Notes:
|
|
|
- * - The SCSI command length is determined by examining the 1st byte
|
|
|
- * of the given command. There is no way to override this.
|
|
|
- * - Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha).
|
|
|
- * - The length (x + y) must be at least OMAX_SB_LEN bytes long to
|
|
|
- * accommodate the sense buffer when an error occurs.
|
|
|
- * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
|
|
|
- * old code will not be surprised.
|
|
|
- * - If a Unix error occurs (e.g. ENOMEM) then the user will receive
|
|
|
- * a negative return and the Unix error code in 'errno'.
|
|
|
- * If the SCSI command succeeds then 0 is returned.
|
|
|
- * Positive numbers returned are the compacted SCSI error codes (4
|
|
|
- * bytes in one int) where the lowest byte is the SCSI status.
|
|
|
- * See the drivers/scsi/scsi.h file for more information on this.
|
|
|
- *
|
|
|
- */
|
|
|
-#define OMAX_SB_LEN 16 /* Old sense buffer length */
|
|
|
-
|
|
|
-int scsi_ioctl_send_command(struct scsi_device *sdev,
|
|
|
- struct scsi_ioctl_command __user *sic)
|
|
|
-{
|
|
|
- char *buf;
|
|
|
- unsigned char cmd[MAX_COMMAND_SIZE];
|
|
|
- unsigned char sense[SCSI_SENSE_BUFFERSIZE];
|
|
|
- char __user *cmd_in;
|
|
|
- unsigned char opcode;
|
|
|
- unsigned int inlen, outlen, cmdlen;
|
|
|
- unsigned int needed, buf_needed;
|
|
|
- int timeout, retries, result;
|
|
|
- int data_direction;
|
|
|
- gfp_t gfp_mask = GFP_KERNEL;
|
|
|
-
|
|
|
- if (!sic)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (sdev->host->unchecked_isa_dma)
|
|
|
- gfp_mask |= GFP_DMA;
|
|
|
-
|
|
|
- /*
|
|
|
- * Verify that we can read at least this much.
|
|
|
- */
|
|
|
- if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- if(__get_user(inlen, &sic->inlen))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- if(__get_user(outlen, &sic->outlen))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- /*
|
|
|
- * We do not transfer more than MAX_BUF with this interface.
|
|
|
- * If the user needs to transfer more data than this, they
|
|
|
- * should use scsi_generics (sg) instead.
|
|
|
- */
|
|
|
- if (inlen > MAX_BUF)
|
|
|
- return -EINVAL;
|
|
|
- if (outlen > MAX_BUF)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- cmd_in = sic->data;
|
|
|
- if(get_user(opcode, cmd_in))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- needed = buf_needed = (inlen > outlen ? inlen : outlen);
|
|
|
- if (buf_needed) {
|
|
|
- buf_needed = (buf_needed + 511) & ~511;
|
|
|
- if (buf_needed > MAX_BUF)
|
|
|
- buf_needed = MAX_BUF;
|
|
|
- buf = kzalloc(buf_needed, gfp_mask);
|
|
|
- if (!buf)
|
|
|
- return -ENOMEM;
|
|
|
- if (inlen == 0) {
|
|
|
- data_direction = DMA_FROM_DEVICE;
|
|
|
- } else if (outlen == 0 ) {
|
|
|
- data_direction = DMA_TO_DEVICE;
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * Can this ever happen?
|
|
|
- */
|
|
|
- data_direction = DMA_BIDIRECTIONAL;
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- buf = NULL;
|
|
|
- data_direction = DMA_NONE;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Obtain the command from the user's address space.
|
|
|
- */
|
|
|
- cmdlen = COMMAND_SIZE(opcode);
|
|
|
-
|
|
|
- result = -EFAULT;
|
|
|
-
|
|
|
- if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen))
|
|
|
- goto error;
|
|
|
-
|
|
|
- if(__copy_from_user(cmd, cmd_in, cmdlen))
|
|
|
- goto error;
|
|
|
-
|
|
|
- /*
|
|
|
- * Obtain the data to be sent to the device (if any).
|
|
|
- */
|
|
|
-
|
|
|
- if(inlen && copy_from_user(buf, cmd_in + cmdlen, inlen))
|
|
|
- goto error;
|
|
|
-
|
|
|
- switch (opcode) {
|
|
|
- case SEND_DIAGNOSTIC:
|
|
|
- case FORMAT_UNIT:
|
|
|
- timeout = FORMAT_UNIT_TIMEOUT;
|
|
|
- retries = 1;
|
|
|
- break;
|
|
|
- case START_STOP:
|
|
|
- timeout = START_STOP_TIMEOUT;
|
|
|
- retries = NORMAL_RETRIES;
|
|
|
- break;
|
|
|
- case MOVE_MEDIUM:
|
|
|
- timeout = MOVE_MEDIUM_TIMEOUT;
|
|
|
- retries = NORMAL_RETRIES;
|
|
|
- break;
|
|
|
- case READ_ELEMENT_STATUS:
|
|
|
- timeout = READ_ELEMENT_STATUS_TIMEOUT;
|
|
|
- retries = NORMAL_RETRIES;
|
|
|
- break;
|
|
|
- case READ_DEFECT_DATA:
|
|
|
- timeout = READ_DEFECT_DATA_TIMEOUT;
|
|
|
- retries = 1;
|
|
|
- break;
|
|
|
- default:
|
|
|
- timeout = IOCTL_NORMAL_TIMEOUT;
|
|
|
- retries = NORMAL_RETRIES;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- result = scsi_execute(sdev, cmd, data_direction, buf, needed,
|
|
|
- sense, timeout, retries, 0);
|
|
|
-
|
|
|
- /*
|
|
|
- * If there was an error condition, pass the info back to the user.
|
|
|
- */
|
|
|
- if (result) {
|
|
|
- int sb_len = sizeof(*sense);
|
|
|
-
|
|
|
- sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
|
|
|
- if (copy_to_user(cmd_in, sense, sb_len))
|
|
|
- result = -EFAULT;
|
|
|
- } else {
|
|
|
- if (outlen && copy_to_user(cmd_in, buf, outlen))
|
|
|
- result = -EFAULT;
|
|
|
- }
|
|
|
-
|
|
|
-error:
|
|
|
- kfree(buf);
|
|
|
- return result;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(scsi_ioctl_send_command);
|
|
|
-
|
|
|
/*
|
|
|
* The scsi_ioctl_get_pci() function places into arg the value
|
|
|
* pci_dev::slot_name (8 characters) for the PCI device (if any).
|
|
@@ -409,7 +235,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
|
|
|
case SCSI_IOCTL_SEND_COMMAND:
|
|
|
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
|
|
|
return -EACCES;
|
|
|
- return scsi_ioctl_send_command(sdev, arg);
|
|
|
+ return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg);
|
|
|
case SCSI_IOCTL_DOORLOCK:
|
|
|
return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
|
|
|
case SCSI_IOCTL_DOORUNLOCK:
|