patch-2.4.7 linux/drivers/scsi/scsi_ioctl.c
Next file: linux/drivers/scsi/scsi_lib.c
Previous file: linux/drivers/scsi/scsi_error.c
Back to the patch index
Back to the overall index
- Lines: 183
- Date:
Thu Jul 5 11:28:17 2001
- Orig file:
v2.4.6/linux/drivers/scsi/scsi_ioctl.c
- Orig date:
Tue Jul 3 17:08:20 2001
diff -u --recursive --new-file v2.4.6/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
@@ -79,7 +79,7 @@
*
* *(char *) ((int *) arg)[2] the actual command byte.
*
- * Note that if more than MAX_BUF bytes are requested to be transfered,
+ * Note that if more than MAX_BUF bytes are requested to be transferred,
* the ioctl will fail with error EINVAL. MAX_BUF can be increased in
* the future by increasing the size that scsi_malloc will accept.
*
@@ -196,8 +196,8 @@
Scsi_Request *SRpnt;
Scsi_Device *SDpnt;
unsigned char opcode;
- int inlen, outlen, cmdlen;
- int needed, buf_needed;
+ unsigned int inlen, outlen, cmdlen;
+ unsigned int needed, buf_needed;
int timeout, retries, result;
int data_direction;
@@ -209,8 +209,11 @@
if (verify_area(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
return -EFAULT;
- __get_user(inlen, &sic->inlen);
- __get_user(outlen, &sic->outlen);
+ 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.
@@ -223,7 +226,8 @@
return -EINVAL;
cmd_in = sic->data;
- __get_user(opcode, cmd_in);
+ if(get_user(opcode, cmd_in))
+ return -EFAULT;
needed = buf_needed = (inlen > outlen ? inlen : outlen);
if (buf_needed) {
@@ -254,21 +258,27 @@
* Obtain the command from the user's address space.
*/
cmdlen = COMMAND_SIZE(opcode);
+
+ result = -EFAULT;
if (verify_area(VERIFY_READ, cmd_in, cmdlen + inlen))
- return -EFAULT;
+ goto error;
- __copy_from_user(cmd, cmd_in, cmdlen);
+ if(__copy_from_user(cmd, cmd_in, cmdlen))
+ goto error;
/*
* Obtain the data to be sent to the device (if any).
*/
- __copy_from_user(buf, cmd_in + cmdlen, inlen);
+
+ if(copy_from_user(buf, cmd_in + cmdlen, inlen))
+ goto error;
/*
* Set the lun field to the correct value.
*/
- cmd[1] = (cmd[1] & 0x1f) | (dev->lun << 5);
+ if (dev->scsi_level <= SCSI_2)
+ cmd[1] = (cmd[1] & 0x1f) | (dev->lun << 5);
switch (opcode) {
case FORMAT_UNIT:
@@ -303,7 +313,8 @@
SRpnt = scsi_allocate_request(dev);
if( SRpnt == NULL )
{
- return -EINTR;
+ result = -EINTR;
+ goto error;
}
SRpnt->sr_data_direction = data_direction;
@@ -312,7 +323,9 @@
/*
* If there was an error condition, pass the info back to the user.
*/
+
result = SRpnt->sr_result;
+
if (SRpnt->sr_result) {
int sb_len = sizeof(SRpnt->sr_sense_buffer);
@@ -322,12 +335,13 @@
} else {
if (copy_to_user(cmd_in, buf, outlen))
result = -EFAULT;
- }
+ }
SDpnt = SRpnt->sr_device;
scsi_release_request(SRpnt);
SRpnt = NULL;
+error:
if (buf)
scsi_free(buf, buf_needed);
@@ -379,6 +393,7 @@
int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg)
{
char scsi_cmd[MAX_COMMAND_SIZE];
+ char cmd_byte1;
/* No idea how this happens.... */
if (!dev)
@@ -393,14 +408,16 @@
if (!scsi_block_when_processing_errors(dev)) {
return -ENODEV;
}
+ cmd_byte1 = (dev->scsi_level <= SCSI_2) ? (dev->lun << 5) : 0;
+
switch (cmd) {
case SCSI_IOCTL_GET_IDLUN:
if (verify_area(VERIFY_WRITE, arg, sizeof(Scsi_Idlun)))
return -EFAULT;
- __put_user(dev->id
- + (dev->lun << 8)
- + (dev->channel << 16)
+ __put_user((dev->id & 0xff)
+ + ((dev->lun & 0xff) << 8)
+ + ((dev->channel & 0xff) << 16)
+ ((dev->host->host_no & 0xff) << 24),
&((Scsi_Idlun *) arg)->dev_id);
__put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id);
@@ -434,7 +451,7 @@
if (!dev->removable || !dev->lockable)
return 0;
scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
- scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[1] = cmd_byte1;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
@@ -444,14 +461,14 @@
if (!dev->removable || !dev->lockable)
return 0;
scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
- scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[1] = cmd_byte1;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
case SCSI_IOCTL_TEST_UNIT_READY:
scsi_cmd[0] = TEST_UNIT_READY;
- scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[1] = cmd_byte1;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 0;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
@@ -459,7 +476,7 @@
break;
case SCSI_IOCTL_START_UNIT:
scsi_cmd[0] = START_STOP;
- scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[1] = cmd_byte1;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 1;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
@@ -467,7 +484,7 @@
break;
case SCSI_IOCTL_STOP_UNIT:
scsi_cmd[0] = START_STOP;
- scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[1] = cmd_byte1;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 0;
return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)