Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Changes: | |
3 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 08/23/2000 | |
4 | * - get rid of some verify_areas and use __copy*user and __get/put_user | |
5 | * for the ones that remain | |
6 | */ | |
7 | #include <linux/module.h> | |
8 | #include <linux/blkdev.h> | |
9 | #include <linux/interrupt.h> | |
10 | #include <linux/errno.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/sched.h> | |
13 | #include <linux/mm.h> | |
14 | #include <linux/string.h> | |
15 | #include <asm/uaccess.h> | |
16 | ||
17 | #include <scsi/scsi.h> | |
beb40487 | 18 | #include <scsi/scsi_cmnd.h> |
1da177e4 LT |
19 | #include <scsi/scsi_device.h> |
20 | #include <scsi/scsi_eh.h> | |
21 | #include <scsi/scsi_host.h> | |
22 | #include <scsi/scsi_ioctl.h> | |
1da177e4 LT |
23 | #include <scsi/sg.h> |
24 | #include <scsi/scsi_dbg.h> | |
25 | ||
26 | #include "scsi_logging.h" | |
27 | ||
28 | #define NORMAL_RETRIES 5 | |
29 | #define IOCTL_NORMAL_TIMEOUT (10 * HZ) | |
1da177e4 LT |
30 | |
31 | #define MAX_BUF PAGE_SIZE | |
32 | ||
32993523 CH |
33 | /** |
34 | * ioctl_probe -- return host identification | |
35 | * @host: host to identify | |
36 | * @buffer: userspace buffer for identification | |
37 | * | |
38 | * Return an identifying string at @buffer, if @buffer is non-NULL, filling | |
39 | * to the length stored at * (int *) @buffer. | |
1da177e4 | 40 | */ |
1da177e4 LT |
41 | static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) |
42 | { | |
43 | unsigned int len, slen; | |
44 | const char *string; | |
1da177e4 | 45 | |
32993523 | 46 | if (buffer) { |
1da177e4 LT |
47 | if (get_user(len, (unsigned int __user *) buffer)) |
48 | return -EFAULT; | |
49 | ||
50 | if (host->hostt->info) | |
51 | string = host->hostt->info(host); | |
52 | else | |
53 | string = host->hostt->name; | |
54 | if (string) { | |
55 | slen = strlen(string); | |
56 | if (len > slen) | |
57 | len = slen + 1; | |
58 | if (copy_to_user(buffer, string, len)) | |
59 | return -EFAULT; | |
60 | } | |
61 | } | |
32993523 | 62 | return 1; |
1da177e4 LT |
63 | } |
64 | ||
65 | /* | |
66 | ||
67 | * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host. | |
68 | * The IOCTL_NORMAL_TIMEOUT and NORMAL_RETRIES variables are used. | |
69 | * | |
70 | * dev is the SCSI device struct ptr, *(int *) arg is the length of the | |
71 | * input data, if any, not including the command string & counts, | |
72 | * *((int *)arg + 1) is the output buffer size in bytes. | |
73 | * | |
74 | * *(char *) ((int *) arg)[2] the actual command byte. | |
75 | * | |
76 | * Note that if more than MAX_BUF bytes are requested to be transferred, | |
77 | * the ioctl will fail with error EINVAL. | |
78 | * | |
79 | * This size *does not* include the initial lengths that were passed. | |
80 | * | |
81 | * The SCSI command is read from the memory location immediately after the | |
82 | * length words, and the input data is right after the command. The SCSI | |
83 | * routines know the command size based on the opcode decode. | |
84 | * | |
85 | * The output area is then filled in starting from the command byte. | |
86 | */ | |
87 | ||
88 | static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, | |
89 | int timeout, int retries) | |
90 | { | |
1da177e4 LT |
91 | int result; |
92 | struct scsi_sense_hdr sshdr; | |
93 | ||
e5f73ce3 HR |
94 | SCSI_LOG_IOCTL(1, sdev_printk(KERN_INFO, sdev, |
95 | "Trying ioctl with scsi command %d\n", *cmd)); | |
1da177e4 | 96 | |
1cf72699 | 97 | result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, |
f4f4e47e | 98 | &sshdr, timeout, retries, NULL); |
1da177e4 | 99 | |
e5f73ce3 HR |
100 | SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, |
101 | "Ioctl returned 0x%x\n", result)); | |
1da177e4 | 102 | |
1cf72699 | 103 | if ((driver_byte(result) & DRIVER_SENSE) && |
ea73a9f2 | 104 | (scsi_sense_valid(&sshdr))) { |
1da177e4 LT |
105 | switch (sshdr.sense_key) { |
106 | case ILLEGAL_REQUEST: | |
107 | if (cmd[0] == ALLOW_MEDIUM_REMOVAL) | |
108 | sdev->lockable = 0; | |
109 | else | |
e5f73ce3 HR |
110 | sdev_printk(KERN_INFO, sdev, |
111 | "ioctl_internal_command: " | |
112 | "ILLEGAL REQUEST " | |
113 | "asc=0x%x ascq=0x%x\n", | |
114 | sshdr.asc, sshdr.ascq); | |
1da177e4 LT |
115 | break; |
116 | case NOT_READY: /* This happens if there is no disc in drive */ | |
a75ad3c2 | 117 | if (sdev->removable) |
1da177e4 | 118 | break; |
1da177e4 LT |
119 | case UNIT_ATTENTION: |
120 | if (sdev->removable) { | |
121 | sdev->changed = 1; | |
1cf72699 | 122 | result = 0; /* This is no longer considered an error */ |
1da177e4 LT |
123 | break; |
124 | } | |
125 | default: /* Fall through for non-removable media */ | |
9ccfc756 JB |
126 | sdev_printk(KERN_INFO, sdev, |
127 | "ioctl_internal_command return code = %x\n", | |
128 | result); | |
ea73a9f2 | 129 | scsi_print_sense_hdr(" ", &sshdr); |
1da177e4 LT |
130 | break; |
131 | } | |
132 | } | |
133 | ||
e5f73ce3 HR |
134 | SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, |
135 | "IOCTL Releasing command\n")); | |
1da177e4 LT |
136 | return result; |
137 | } | |
138 | ||
139 | int scsi_set_medium_removal(struct scsi_device *sdev, char state) | |
140 | { | |
141 | char scsi_cmd[MAX_COMMAND_SIZE]; | |
142 | int ret; | |
143 | ||
144 | if (!sdev->removable || !sdev->lockable) | |
145 | return 0; | |
146 | ||
147 | scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; | |
148 | scsi_cmd[1] = 0; | |
149 | scsi_cmd[2] = 0; | |
150 | scsi_cmd[3] = 0; | |
151 | scsi_cmd[4] = state; | |
152 | scsi_cmd[5] = 0; | |
153 | ||
154 | ret = ioctl_internal_command(sdev, scsi_cmd, | |
155 | IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); | |
156 | if (ret == 0) | |
157 | sdev->locked = (state == SCSI_REMOVAL_PREVENT); | |
158 | return ret; | |
159 | } | |
160 | EXPORT_SYMBOL(scsi_set_medium_removal); | |
161 | ||
1da177e4 LT |
162 | /* |
163 | * The scsi_ioctl_get_pci() function places into arg the value | |
164 | * pci_dev::slot_name (8 characters) for the PCI device (if any). | |
165 | * Returns: 0 on success | |
166 | * -ENXIO if there isn't a PCI device pointer | |
167 | * (could be because the SCSI driver hasn't been | |
168 | * updated yet, or because it isn't a SCSI | |
169 | * device) | |
170 | * any copy_to_user() error on failure there | |
171 | */ | |
172 | static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg) | |
173 | { | |
174 | struct device *dev = scsi_get_device(sdev->host); | |
71610f55 | 175 | const char *name; |
1da177e4 LT |
176 | |
177 | if (!dev) | |
178 | return -ENXIO; | |
71610f55 KS |
179 | |
180 | name = dev_name(dev); | |
181 | ||
182 | /* compatibility with old ioctl which only returned | |
183 | * 20 characters */ | |
184 | return copy_to_user(arg, name, min(strlen(name), (size_t)20)) | |
185 | ? -EFAULT: 0; | |
1da177e4 LT |
186 | } |
187 | ||
188 | ||
eb44820c RL |
189 | /** |
190 | * scsi_ioctl - Dispatch ioctl to scsi device | |
191 | * @sdev: scsi device receiving ioctl | |
192 | * @cmd: which ioctl is it | |
193 | * @arg: data associated with ioctl | |
194 | * | |
195 | * Description: The scsi_ioctl() function differs from most ioctls in that it | |
196 | * does not take a major/minor number as the dev field. Rather, it takes | |
197 | * a pointer to a &struct scsi_device. | |
1da177e4 LT |
198 | */ |
199 | int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | |
200 | { | |
201 | char scsi_cmd[MAX_COMMAND_SIZE]; | |
202 | ||
203 | /* No idea how this happens.... */ | |
204 | if (!sdev) | |
205 | return -ENXIO; | |
206 | ||
207 | /* | |
208 | * If we are in the middle of error recovery, don't let anyone | |
209 | * else try and use this device. Also, if error recovery fails, it | |
210 | * may try and take the device offline, in which case all further | |
211 | * access to the device is prohibited. | |
212 | */ | |
213 | if (!scsi_block_when_processing_errors(sdev)) | |
214 | return -ENODEV; | |
215 | ||
216 | /* Check for deprecated ioctls ... all the ioctls which don't | |
217 | * follow the new unique numbering scheme are deprecated */ | |
218 | switch (cmd) { | |
219 | case SCSI_IOCTL_SEND_COMMAND: | |
220 | case SCSI_IOCTL_TEST_UNIT_READY: | |
221 | case SCSI_IOCTL_BENCHMARK_COMMAND: | |
222 | case SCSI_IOCTL_SYNC: | |
223 | case SCSI_IOCTL_START_UNIT: | |
224 | case SCSI_IOCTL_STOP_UNIT: | |
225 | printk(KERN_WARNING "program %s is using a deprecated SCSI " | |
226 | "ioctl, please convert it to SG_IO\n", current->comm); | |
227 | break; | |
228 | default: | |
229 | break; | |
230 | } | |
231 | ||
232 | switch (cmd) { | |
233 | case SCSI_IOCTL_GET_IDLUN: | |
234 | if (!access_ok(VERIFY_WRITE, arg, sizeof(struct scsi_idlun))) | |
235 | return -EFAULT; | |
236 | ||
237 | __put_user((sdev->id & 0xff) | |
238 | + ((sdev->lun & 0xff) << 8) | |
239 | + ((sdev->channel & 0xff) << 16) | |
240 | + ((sdev->host->host_no & 0xff) << 24), | |
241 | &((struct scsi_idlun __user *)arg)->dev_id); | |
242 | __put_user(sdev->host->unique_id, | |
243 | &((struct scsi_idlun __user *)arg)->host_unique_id); | |
244 | return 0; | |
245 | case SCSI_IOCTL_GET_BUS_NUMBER: | |
246 | return put_user(sdev->host->host_no, (int __user *)arg); | |
247 | case SCSI_IOCTL_PROBE_HOST: | |
248 | return ioctl_probe(sdev->host, arg); | |
249 | case SCSI_IOCTL_SEND_COMMAND: | |
250 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | |
251 | return -EACCES; | |
e915e872 | 252 | return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg); |
1da177e4 LT |
253 | case SCSI_IOCTL_DOORLOCK: |
254 | return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); | |
255 | case SCSI_IOCTL_DOORUNLOCK: | |
256 | return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); | |
257 | case SCSI_IOCTL_TEST_UNIT_READY: | |
258 | return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT, | |
001aac25 | 259 | NORMAL_RETRIES, NULL); |
1da177e4 LT |
260 | case SCSI_IOCTL_START_UNIT: |
261 | scsi_cmd[0] = START_STOP; | |
262 | scsi_cmd[1] = 0; | |
263 | scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; | |
264 | scsi_cmd[4] = 1; | |
265 | return ioctl_internal_command(sdev, scsi_cmd, | |
266 | START_STOP_TIMEOUT, NORMAL_RETRIES); | |
267 | case SCSI_IOCTL_STOP_UNIT: | |
268 | scsi_cmd[0] = START_STOP; | |
269 | scsi_cmd[1] = 0; | |
270 | scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; | |
271 | scsi_cmd[4] = 0; | |
272 | return ioctl_internal_command(sdev, scsi_cmd, | |
273 | START_STOP_TIMEOUT, NORMAL_RETRIES); | |
274 | case SCSI_IOCTL_GET_PCI: | |
275 | return scsi_ioctl_get_pci(sdev, arg); | |
276 | default: | |
277 | if (sdev->host->hostt->ioctl) | |
278 | return sdev->host->hostt->ioctl(sdev, cmd, arg); | |
279 | } | |
280 | return -EINVAL; | |
281 | } | |
282 | EXPORT_SYMBOL(scsi_ioctl); | |
283 | ||
eb44820c | 284 | /** |
decf67e3 | 285 | * scsi_nonblockable_ioctl() - Handle SG_SCSI_RESET |
eb44820c RL |
286 | * @sdev: scsi device receiving ioctl |
287 | * @cmd: Must be SC_SCSI_RESET | |
288 | * @arg: pointer to int containing SG_SCSI_RESET_{DEVICE,BUS,HOST} | |
decf67e3 | 289 | * @ndelay: file mode O_NDELAY flag |
1da177e4 LT |
290 | */ |
291 | int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | |
83ff6fe8 | 292 | void __user *arg, int ndelay) |
1da177e4 LT |
293 | { |
294 | int val, result; | |
295 | ||
296 | /* The first set of iocts may be executed even if we're doing | |
297 | * error processing, as long as the device was opened | |
298 | * non-blocking */ | |
83ff6fe8 | 299 | if (ndelay) { |
939647ee | 300 | if (scsi_host_in_recovery(sdev->host)) |
1da177e4 LT |
301 | return -ENODEV; |
302 | } else if (!scsi_block_when_processing_errors(sdev)) | |
303 | return -ENODEV; | |
304 | ||
305 | switch (cmd) { | |
306 | case SG_SCSI_RESET: | |
307 | result = get_user(val, (int __user *)arg); | |
308 | if (result) | |
309 | return result; | |
310 | if (val == SG_SCSI_RESET_NOTHING) | |
311 | return 0; | |
312 | switch (val) { | |
313 | case SG_SCSI_RESET_DEVICE: | |
314 | val = SCSI_TRY_RESET_DEVICE; | |
315 | break; | |
3f9daedf MC |
316 | case SG_SCSI_RESET_TARGET: |
317 | val = SCSI_TRY_RESET_TARGET; | |
318 | break; | |
1da177e4 LT |
319 | case SG_SCSI_RESET_BUS: |
320 | val = SCSI_TRY_RESET_BUS; | |
321 | break; | |
322 | case SG_SCSI_RESET_HOST: | |
323 | val = SCSI_TRY_RESET_HOST; | |
324 | break; | |
325 | default: | |
326 | return -EINVAL; | |
327 | } | |
328 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | |
329 | return -EACCES; | |
330 | return (scsi_reset_provider(sdev, val) == | |
331 | SUCCESS) ? 0 : -EIO; | |
332 | } | |
333 | return -ENODEV; | |
334 | } | |
335 | EXPORT_SYMBOL(scsi_nonblockable_ioctl); |