diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-04-14 20:48:55 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-04-14 20:48:55 -0400 |
| commit | 2acab771b7e676125cb8c96b61dcdefe9ba67e57 (patch) | |
| tree | 86227af3c9ad0d90823e5488a86f7f453ed1837a /drivers/scsi/scsi_ioctl.c | |
| parent | 201e06279823c73242de987f192f43d2b30e5331 (diff) | |
| parent | 64541d19702cfdb7ea946fdc20faee849f6874b1 (diff) | |
Merge branch 'master'
Diffstat (limited to 'drivers/scsi/scsi_ioctl.c')
| -rw-r--r-- | drivers/scsi/scsi_ioctl.c | 176 |
1 files changed, 1 insertions, 175 deletions
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 36e930066649..a89aff61d3d8 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
| @@ -158,180 +158,6 @@ int scsi_set_medium_removal(struct scsi_device *sdev, char state) | |||
| 158 | EXPORT_SYMBOL(scsi_set_medium_removal); | 158 | EXPORT_SYMBOL(scsi_set_medium_removal); |
| 159 | 159 | ||
| 160 | /* | 160 | /* |
| 161 | * This interface is deprecated - users should use the scsi generic (sg) | ||
| 162 | * interface instead, as this is a more flexible approach to performing | ||
| 163 | * generic SCSI commands on a device. | ||
| 164 | * | ||
| 165 | * The structure that we are passed should look like: | ||
| 166 | * | ||
| 167 | * struct sdata { | ||
| 168 | * unsigned int inlen; [i] Length of data to be written to device | ||
| 169 | * unsigned int outlen; [i] Length of data to be read from device | ||
| 170 | * unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12). | ||
| 171 | * [o] Data read from device starts here. | ||
| 172 | * [o] On error, sense buffer starts here. | ||
| 173 | * unsigned char wdata[y]; [i] Data written to device starts here. | ||
| 174 | * }; | ||
| 175 | * Notes: | ||
| 176 | * - The SCSI command length is determined by examining the 1st byte | ||
| 177 | * of the given command. There is no way to override this. | ||
| 178 | * - Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha). | ||
| 179 | * - The length (x + y) must be at least OMAX_SB_LEN bytes long to | ||
| 180 | * accommodate the sense buffer when an error occurs. | ||
| 181 | * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that | ||
| 182 | * old code will not be surprised. | ||
| 183 | * - If a Unix error occurs (e.g. ENOMEM) then the user will receive | ||
| 184 | * a negative return and the Unix error code in 'errno'. | ||
| 185 | * If the SCSI command succeeds then 0 is returned. | ||
| 186 | * Positive numbers returned are the compacted SCSI error codes (4 | ||
| 187 | * bytes in one int) where the lowest byte is the SCSI status. | ||
| 188 | * See the drivers/scsi/scsi.h file for more information on this. | ||
| 189 | * | ||
| 190 | */ | ||
| 191 | #define OMAX_SB_LEN 16 /* Old sense buffer length */ | ||
| 192 | |||
| 193 | int scsi_ioctl_send_command(struct scsi_device *sdev, | ||
| 194 | struct scsi_ioctl_command __user *sic) | ||
| 195 | { | ||
| 196 | char *buf; | ||
| 197 | unsigned char cmd[MAX_COMMAND_SIZE]; | ||
| 198 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; | ||
| 199 | char __user *cmd_in; | ||
| 200 | unsigned char opcode; | ||
| 201 | unsigned int inlen, outlen, cmdlen; | ||
| 202 | unsigned int needed, buf_needed; | ||
| 203 | int timeout, retries, result; | ||
| 204 | int data_direction; | ||
| 205 | gfp_t gfp_mask = GFP_KERNEL; | ||
| 206 | |||
| 207 | if (!sic) | ||
| 208 | return -EINVAL; | ||
| 209 | |||
| 210 | if (sdev->host->unchecked_isa_dma) | ||
| 211 | gfp_mask |= GFP_DMA; | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Verify that we can read at least this much. | ||
| 215 | */ | ||
| 216 | if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command))) | ||
| 217 | return -EFAULT; | ||
| 218 | |||
| 219 | if(__get_user(inlen, &sic->inlen)) | ||
| 220 | return -EFAULT; | ||
| 221 | |||
| 222 | if(__get_user(outlen, &sic->outlen)) | ||
| 223 | return -EFAULT; | ||
| 224 | |||
| 225 | /* | ||
| 226 | * We do not transfer more than MAX_BUF with this interface. | ||
| 227 | * If the user needs to transfer more data than this, they | ||
| 228 | * should use scsi_generics (sg) instead. | ||
| 229 | */ | ||
| 230 | if (inlen > MAX_BUF) | ||
| 231 | return -EINVAL; | ||
| 232 | if (outlen > MAX_BUF) | ||
| 233 | return -EINVAL; | ||
| 234 | |||
| 235 | cmd_in = sic->data; | ||
| 236 | if(get_user(opcode, cmd_in)) | ||
| 237 | return -EFAULT; | ||
| 238 | |||
| 239 | needed = buf_needed = (inlen > outlen ? inlen : outlen); | ||
| 240 | if (buf_needed) { | ||
| 241 | buf_needed = (buf_needed + 511) & ~511; | ||
| 242 | if (buf_needed > MAX_BUF) | ||
| 243 | buf_needed = MAX_BUF; | ||
| 244 | buf = kzalloc(buf_needed, gfp_mask); | ||
| 245 | if (!buf) | ||
| 246 | return -ENOMEM; | ||
| 247 | if (inlen == 0) { | ||
| 248 | data_direction = DMA_FROM_DEVICE; | ||
| 249 | } else if (outlen == 0 ) { | ||
| 250 | data_direction = DMA_TO_DEVICE; | ||
| 251 | } else { | ||
| 252 | /* | ||
| 253 | * Can this ever happen? | ||
| 254 | */ | ||
| 255 | data_direction = DMA_BIDIRECTIONAL; | ||
| 256 | } | ||
| 257 | |||
| 258 | } else { | ||
| 259 | buf = NULL; | ||
| 260 | data_direction = DMA_NONE; | ||
| 261 | } | ||
| 262 | |||
| 263 | /* | ||
| 264 | * Obtain the command from the user's address space. | ||
| 265 | */ | ||
| 266 | cmdlen = COMMAND_SIZE(opcode); | ||
| 267 | |||
| 268 | result = -EFAULT; | ||
| 269 | |||
| 270 | if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen)) | ||
| 271 | goto error; | ||
| 272 | |||
| 273 | if(__copy_from_user(cmd, cmd_in, cmdlen)) | ||
| 274 | goto error; | ||
| 275 | |||
| 276 | /* | ||
| 277 | * Obtain the data to be sent to the device (if any). | ||
| 278 | */ | ||
| 279 | |||
| 280 | if(inlen && copy_from_user(buf, cmd_in + cmdlen, inlen)) | ||
| 281 | goto error; | ||
| 282 | |||
| 283 | switch (opcode) { | ||
| 284 | case SEND_DIAGNOSTIC: | ||
| 285 | case FORMAT_UNIT: | ||
| 286 | timeout = FORMAT_UNIT_TIMEOUT; | ||
| 287 | retries = 1; | ||
| 288 | break; | ||
| 289 | case START_STOP: | ||
| 290 | timeout = START_STOP_TIMEOUT; | ||
| 291 | retries = NORMAL_RETRIES; | ||
| 292 | break; | ||
| 293 | case MOVE_MEDIUM: | ||
| 294 | timeout = MOVE_MEDIUM_TIMEOUT; | ||
| 295 | retries = NORMAL_RETRIES; | ||
| 296 | break; | ||
| 297 | case READ_ELEMENT_STATUS: | ||
| 298 | timeout = READ_ELEMENT_STATUS_TIMEOUT; | ||
| 299 | retries = NORMAL_RETRIES; | ||
| 300 | break; | ||
| 301 | case READ_DEFECT_DATA: | ||
| 302 | timeout = READ_DEFECT_DATA_TIMEOUT; | ||
| 303 | retries = 1; | ||
| 304 | break; | ||
| 305 | default: | ||
| 306 | timeout = IOCTL_NORMAL_TIMEOUT; | ||
| 307 | retries = NORMAL_RETRIES; | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | |||
| 311 | result = scsi_execute(sdev, cmd, data_direction, buf, needed, | ||
| 312 | sense, timeout, retries, 0); | ||
| 313 | |||
| 314 | /* | ||
| 315 | * If there was an error condition, pass the info back to the user. | ||
| 316 | */ | ||
| 317 | if (result) { | ||
| 318 | int sb_len = sizeof(*sense); | ||
| 319 | |||
| 320 | sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; | ||
| 321 | if (copy_to_user(cmd_in, sense, sb_len)) | ||
| 322 | result = -EFAULT; | ||
| 323 | } else { | ||
| 324 | if (outlen && copy_to_user(cmd_in, buf, outlen)) | ||
| 325 | result = -EFAULT; | ||
| 326 | } | ||
| 327 | |||
| 328 | error: | ||
| 329 | kfree(buf); | ||
| 330 | return result; | ||
| 331 | } | ||
| 332 | EXPORT_SYMBOL(scsi_ioctl_send_command); | ||
| 333 | |||
| 334 | /* | ||
| 335 | * The scsi_ioctl_get_pci() function places into arg the value | 161 | * The scsi_ioctl_get_pci() function places into arg the value |
| 336 | * pci_dev::slot_name (8 characters) for the PCI device (if any). | 162 | * pci_dev::slot_name (8 characters) for the PCI device (if any). |
| 337 | * Returns: 0 on success | 163 | * Returns: 0 on success |
| @@ -409,7 +235,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | |||
| 409 | case SCSI_IOCTL_SEND_COMMAND: | 235 | case SCSI_IOCTL_SEND_COMMAND: |
| 410 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | 236 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) |
| 411 | return -EACCES; | 237 | return -EACCES; |
| 412 | return scsi_ioctl_send_command(sdev, arg); | 238 | return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg); |
| 413 | case SCSI_IOCTL_DOORLOCK: | 239 | case SCSI_IOCTL_DOORLOCK: |
| 414 | return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); | 240 | return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); |
| 415 | case SCSI_IOCTL_DOORUNLOCK: | 241 | case SCSI_IOCTL_DOORUNLOCK: |
