diff options
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: |