This source file includes following definitions.
- ioctl_probe
- scsi_ioctl_done
- ioctl_internal_command
- ioctl_command
- scsi_ioctl
- kernel_scsi_ioctl
1 #ifdef MODULE
2
3
4
5
6 #define _SCSI_SYMS_VER_
7 #include <linux/autoconf.h>
8 #include <linux/module.h>
9 #include <linux/version.h>
10 #else
11 #define MOD_INC_USE_COUNT
12 #define MOD_DEC_USE_COUNT
13 #endif
14
15 #include <asm/io.h>
16 #include <asm/segment.h>
17 #include <asm/system.h>
18
19 #include <linux/errno.h>
20 #include <linux/kernel.h>
21 #include <linux/sched.h>
22 #include <linux/mm.h>
23 #include <linux/string.h>
24
25 #include <linux/blk.h>
26 #include "scsi.h"
27 #include "hosts.h"
28 #include "scsi_ioctl.h"
29
30 #define MAX_RETRIES 5
31 #define MAX_TIMEOUT 900
32 #define MAX_BUF 4096
33
34 #define max(a,b) (((a) > (b)) ? (a) : (b))
35
36
37
38
39
40
41
42
43 static int ioctl_probe(struct Scsi_Host * host, void *buffer)
44 {
45 int temp, result;
46 unsigned int len,slen;
47 const char * string;
48
49 if ((temp = host->hostt->present) && buffer) {
50 result = verify_area(VERIFY_READ, buffer, sizeof(long));
51 if (result) return result;
52
53 len = get_user ((unsigned int *) buffer);
54 if(host->hostt->info)
55 string = host->hostt->info(host);
56 else
57 string = host->hostt->name;
58 if(string) {
59 slen = strlen(string);
60 if (len > slen)
61 len = slen + 1;
62 result = verify_area(VERIFY_WRITE, buffer, len);
63 if (result) return result;
64
65 memcpy_tofs (buffer, string, len);
66 }
67 }
68 return temp;
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98 static void scsi_ioctl_done (Scsi_Cmnd * SCpnt)
99 {
100 struct request * req;
101
102 req = &SCpnt->request;
103 req->rq_status = RQ_SCSI_DONE;
104
105 if (req->sem != NULL) {
106 up(req->sem);
107 }
108 }
109
110 static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
111 {
112 int result;
113 Scsi_Cmnd * SCpnt;
114
115 SCpnt = allocate_device(NULL, dev, 1);
116 {
117 struct semaphore sem = MUTEX_LOCKED;
118 SCpnt->request.sem = &sem;
119 scsi_do_cmd(SCpnt, cmd, NULL, 0,
120 scsi_ioctl_done, MAX_TIMEOUT,
121 MAX_RETRIES);
122 down(&sem);
123 }
124
125 if(driver_byte(SCpnt->result) != 0)
126 switch(SCpnt->sense_buffer[2] & 0xf) {
127 case ILLEGAL_REQUEST:
128 if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0;
129 else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
130 break;
131 case NOT_READY:
132 if(dev->removable){
133 printk("Device not ready. Make sure there is a disc in the drive.\n");
134 break;
135 };
136 case UNIT_ATTENTION:
137 if (dev->removable){
138 dev->changed = 1;
139 SCpnt->result = 0;
140 printk("Disc change detected.\n");
141 break;
142 };
143 default:
144 printk("SCSI error: host %d id %d lun %d return code = %x\n",
145 dev->host->host_no,
146 dev->id,
147 dev->lun,
148 SCpnt->result);
149 printk("\tSense class %x, sense error %x, extended sense %x\n",
150 sense_class(SCpnt->sense_buffer[0]),
151 sense_error(SCpnt->sense_buffer[0]),
152 SCpnt->sense_buffer[2] & 0xf);
153
154 };
155
156 result = SCpnt->result;
157 SCpnt->request.rq_status = RQ_INACTIVE;
158 wake_up(&SCpnt->device->device_wait);
159 return result;
160 }
161
162
163
164
165
166
167 static int ioctl_command(Scsi_Device *dev, void *buffer)
168 {
169 char * buf;
170 char cmd[12];
171 char * cmd_in;
172 Scsi_Cmnd * SCpnt;
173 unsigned char opcode;
174 int inlen, outlen, cmdlen;
175 int needed, buf_needed;
176 int result;
177
178 if (!buffer)
179 return -EINVAL;
180
181
182
183
184
185 result = verify_area(VERIFY_READ, buffer, 2*sizeof(long) + 1);
186 if (result) return result;
187
188
189
190
191
192
193
194
195
196
197 inlen = get_user((unsigned int *) buffer);
198 outlen = get_user( ((unsigned int *) buffer) + 1);
199
200
201
202
203
204
205 if( inlen > MAX_BUF ) inlen = MAX_BUF;
206 if( outlen > MAX_BUF ) outlen = MAX_BUF;
207
208 cmd_in = (char *) ( ((int *)buffer) + 2);
209 opcode = get_user(cmd_in);
210
211 needed = buf_needed = (inlen > outlen ? inlen : outlen);
212 if(buf_needed){
213 buf_needed = (buf_needed + 511) & ~511;
214 if (buf_needed > MAX_BUF) buf_needed = MAX_BUF;
215 buf = (char *) scsi_malloc(buf_needed);
216 if (!buf) return -ENOMEM;
217 memset(buf, 0, buf_needed);
218 } else
219 buf = NULL;
220
221
222
223
224 cmdlen = COMMAND_SIZE(opcode);
225
226 result = verify_area(VERIFY_READ, cmd_in,
227 cmdlen + inlen > MAX_BUF ? MAX_BUF : inlen);
228 if (result) return result;
229
230 memcpy_fromfs ((void *) cmd, cmd_in, cmdlen);
231
232
233
234
235 memcpy_fromfs ((void *) buf,
236 (void *) (cmd_in + cmdlen),
237 inlen);
238
239
240
241
242 cmd[1] = ( cmd[1] & 0x1f ) | (dev->lun << 5);
243
244 #ifndef DEBUG_NO_CMD
245
246 SCpnt = allocate_device(NULL, dev, 1);
247
248 {
249 struct semaphore sem = MUTEX_LOCKED;
250 SCpnt->request.sem = &sem;
251 scsi_do_cmd(SCpnt, cmd, buf, needed, scsi_ioctl_done, MAX_TIMEOUT,
252 MAX_RETRIES);
253 down(&sem);
254 }
255
256
257
258
259 if(SCpnt->result) {
260 result = verify_area(VERIFY_WRITE,
261 cmd_in,
262 sizeof(SCpnt->sense_buffer));
263 if (result) return result;
264 memcpy_tofs((void *) cmd_in,
265 SCpnt->sense_buffer,
266 sizeof(SCpnt->sense_buffer));
267 } else {
268 result = verify_area(VERIFY_WRITE, cmd_in, outlen);
269 if (result) return result;
270 memcpy_tofs ((void *) cmd_in, buf, outlen);
271 }
272 result = SCpnt->result;
273
274 SCpnt->request.rq_status = RQ_INACTIVE;
275
276 if (buf) scsi_free(buf, buf_needed);
277
278 if(SCpnt->device->scsi_request_fn)
279 (*SCpnt->device->scsi_request_fn)();
280
281 wake_up(&SCpnt->device->device_wait);
282 return result;
283 #else
284 {
285 int i;
286 printk("scsi_ioctl : device %d. command = ", dev->id);
287 for (i = 0; i < 12; ++i)
288 printk("%02x ", cmd[i]);
289 printk("\nbuffer =");
290 for (i = 0; i < 20; ++i)
291 printk("%02x ", buf[i]);
292 printk("\n");
293 printk("inlen = %d, outlen = %d, cmdlen = %d\n",
294 inlen, outlen, cmdlen);
295 printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in);
296 }
297 return 0;
298 #endif
299 }
300
301
302
303
304
305
306 int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
307 {
308 int result;
309 char scsi_cmd[12];
310
311
312 if (!dev) return -ENXIO;
313
314 switch (cmd) {
315 case SCSI_IOCTL_GET_IDLUN:
316 result = verify_area(VERIFY_WRITE, (void *) arg, 2*sizeof(long));
317 if (result) return result;
318
319 put_user(dev->id
320 + (dev->lun << 8)
321 + (dev->channel << 16)
322 + ((dev->host->hostt->proc_dir->low_ino & 0xff) << 24),
323 (unsigned long *) arg);
324 put_user( dev->host->unique_id, (unsigned long *) arg+1);
325 return 0;
326 case SCSI_IOCTL_TAGGED_ENABLE:
327 if(!suser()) return -EACCES;
328 if(!dev->tagged_supported) return -EINVAL;
329 dev->tagged_queue = 1;
330 dev->current_tag = 1;
331 break;
332 case SCSI_IOCTL_TAGGED_DISABLE:
333 if(!suser()) return -EACCES;
334 if(!dev->tagged_supported) return -EINVAL;
335 dev->tagged_queue = 0;
336 dev->current_tag = 0;
337 break;
338 case SCSI_IOCTL_PROBE_HOST:
339 return ioctl_probe(dev->host, arg);
340 case SCSI_IOCTL_SEND_COMMAND:
341 if(!suser()) return -EACCES;
342 return ioctl_command((Scsi_Device *) dev, arg);
343 case SCSI_IOCTL_DOORLOCK:
344 if (!dev->removable || !dev->lockable) return 0;
345 scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
346 scsi_cmd[1] = dev->lun << 5;
347 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
348 scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
349 return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
350 break;
351 case SCSI_IOCTL_DOORUNLOCK:
352 if (!dev->removable || !dev->lockable) return 0;
353 scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
354 scsi_cmd[1] = dev->lun << 5;
355 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
356 scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
357 return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
358 case SCSI_IOCTL_TEST_UNIT_READY:
359 scsi_cmd[0] = TEST_UNIT_READY;
360 scsi_cmd[1] = dev->lun << 5;
361 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
362 scsi_cmd[4] = 0;
363 return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
364 break;
365 default :
366 return -EINVAL;
367 }
368 return -EINVAL;
369 }
370
371
372
373
374
375
376 int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) {
377 unsigned long oldfs;
378 int tmp;
379 oldfs = get_fs();
380 set_fs(get_ds());
381 tmp = scsi_ioctl (dev, cmd, arg);
382 set_fs(oldfs);
383 return tmp;
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403