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 "../block/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;
46 unsigned int len,slen;
47 const char * string;
48
49 if ((temp = host->hostt->present) && buffer) {
50 len = get_user ((unsigned int *) buffer);
51 if(host->hostt->info)
52 string = host->hostt->info(host);
53 else
54 string = host->hostt->name;
55 if(string) {
56 slen = strlen(string);
57 if (len > slen)
58 len = slen + 1;
59 verify_area(VERIFY_WRITE, buffer, len);
60 memcpy_tofs (buffer, string, len);
61 }
62 }
63 return temp;
64 }
65
66
67
68
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 static void scsi_ioctl_done (Scsi_Cmnd * SCpnt)
94 {
95 struct request * req;
96
97 req = &SCpnt->request;
98 req->dev = 0xfffe;
99
100 if (req->sem != NULL) {
101 up(req->sem);
102 }
103 }
104
105 static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
106 {
107 int result;
108 Scsi_Cmnd * SCpnt;
109
110 SCpnt = allocate_device(NULL, dev, 1);
111 scsi_do_cmd(SCpnt, cmd, NULL, 0,
112 scsi_ioctl_done, MAX_TIMEOUT,
113 MAX_RETRIES);
114
115 if (SCpnt->request.dev != 0xfffe){
116 struct semaphore sem = MUTEX_LOCKED;
117 SCpnt->request.sem = &sem;
118 down(&sem);
119
120 while (SCpnt->request.dev != 0xfffe) schedule();
121 };
122
123 if(driver_byte(SCpnt->result) != 0)
124 switch(SCpnt->sense_buffer[2] & 0xf) {
125 case ILLEGAL_REQUEST:
126 if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0;
127 else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
128 break;
129 case NOT_READY:
130 if(dev->removable){
131 printk("Device not ready. Make sure there is a disc in the drive.\n");
132 break;
133 };
134 case UNIT_ATTENTION:
135 if (dev->removable){
136 dev->changed = 1;
137 SCpnt->result = 0;
138 printk("Disc change detected.\n");
139 break;
140 };
141 default:
142 printk("SCSI CD error: host %d id %d lun %d return code = %x\n",
143 dev->host->host_no,
144 dev->id,
145 dev->lun,
146 SCpnt->result);
147 printk("\tSense class %x, sense error %x, extended sense %x\n",
148 sense_class(SCpnt->sense_buffer[0]),
149 sense_error(SCpnt->sense_buffer[0]),
150 SCpnt->sense_buffer[2] & 0xf);
151
152 };
153
154 result = SCpnt->result;
155 SCpnt->request.dev = -1;
156 wake_up(&SCpnt->device->device_wait);
157 return result;
158 }
159
160 static int ioctl_command(Scsi_Device *dev, void *buffer)
161 {
162 char * buf;
163 char cmd[12];
164 char * cmd_in;
165 Scsi_Cmnd * SCpnt;
166 unsigned char opcode;
167 int inlen, outlen, cmdlen;
168 int needed, buf_needed;
169 int result;
170
171 if (!buffer)
172 return -EINVAL;
173
174 inlen = get_user((unsigned int *) buffer);
175 outlen = get_user( ((unsigned int *) buffer) + 1);
176
177 cmd_in = (char *) ( ((int *)buffer) + 2);
178 opcode = get_user(cmd_in);
179
180 needed = buf_needed = (inlen > outlen ? inlen : outlen);
181 if(buf_needed){
182 buf_needed = (buf_needed + 511) & ~511;
183 if (buf_needed > MAX_BUF) buf_needed = MAX_BUF;
184 buf = (char *) scsi_malloc(buf_needed);
185 if (!buf) return -ENOMEM;
186 memset(buf, 0, buf_needed);
187 } else
188 buf = NULL;
189
190 memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode));
191 memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen > MAX_BUF ? MAX_BUF : inlen);
192
193 cmd[1] = ( cmd[1] & 0x1f ) | (dev->lun << 5);
194
195 #ifndef DEBUG_NO_CMD
196
197 SCpnt = allocate_device(NULL, dev, 1);
198
199 scsi_do_cmd(SCpnt, cmd, buf, needed, scsi_ioctl_done, MAX_TIMEOUT,
200 MAX_RETRIES);
201
202 if (SCpnt->request.dev != 0xfffe){
203 struct semaphore sem = MUTEX_LOCKED;
204 SCpnt->request.sem = &sem;
205 down(&sem);
206
207 while (SCpnt->request.dev != 0xfffe) schedule();
208 };
209
210
211
212 if(SCpnt->result) {
213 result = verify_area(VERIFY_WRITE, cmd_in, sizeof(SCpnt->sense_buffer));
214 if (result)
215 return result;
216 memcpy_tofs((void *) cmd_in, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
217 } else {
218
219 result = verify_area(VERIFY_WRITE, cmd_in, (outlen > MAX_BUF) ? MAX_BUF : outlen);
220 if (result)
221 return result;
222 memcpy_tofs ((void *) cmd_in, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen);
223 };
224 result = SCpnt->result;
225 SCpnt->request.dev = -1;
226 if (buf) scsi_free(buf, buf_needed);
227
228 if(SCpnt->device->scsi_request_fn)
229 (*SCpnt->device->scsi_request_fn)();
230
231 wake_up(&SCpnt->device->device_wait);
232 return result;
233 #else
234 {
235 int i;
236 printk("scsi_ioctl : device %d. command = ", dev->id);
237 for (i = 0; i < 12; ++i)
238 printk("%02x ", cmd[i]);
239 printk("\nbuffer =");
240 for (i = 0; i < 20; ++i)
241 printk("%02x ", buf[i]);
242 printk("\n");
243 printk("inlen = %d, outlen = %d, cmdlen = %d\n",
244 inlen, outlen, cmdlen);
245 printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in);
246 }
247 return 0;
248 #endif
249 }
250
251
252
253
254
255
256 int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
257 {
258 char scsi_cmd[12];
259
260
261 if (!dev) return -ENXIO;
262
263 switch (cmd) {
264 case SCSI_IOCTL_GET_IDLUN:
265 verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
266 put_user(dev->id + (dev->lun << 8) + (dev->host->host_no << 16) +
267
268
269
270 (dev->channel << 24),
271 (unsigned long *) arg);
272 return 0;
273 case SCSI_IOCTL_TAGGED_ENABLE:
274 if(!suser()) return -EACCES;
275 if(!dev->tagged_supported) return -EINVAL;
276 dev->tagged_queue = 1;
277 dev->current_tag = 1;
278 break;
279 case SCSI_IOCTL_TAGGED_DISABLE:
280 if(!suser()) return -EACCES;
281 if(!dev->tagged_supported) return -EINVAL;
282 dev->tagged_queue = 0;
283 dev->current_tag = 0;
284 break;
285 case SCSI_IOCTL_PROBE_HOST:
286 return ioctl_probe(dev->host, arg);
287 case SCSI_IOCTL_SEND_COMMAND:
288 if(!suser()) return -EACCES;
289 return ioctl_command((Scsi_Device *) dev, arg);
290 case SCSI_IOCTL_DOORLOCK:
291 if (!dev->removable || !dev->lockable) return 0;
292 scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
293 scsi_cmd[1] = dev->lun << 5;
294 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
295 scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
296 return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
297 break;
298 case SCSI_IOCTL_DOORUNLOCK:
299 if (!dev->removable || !dev->lockable) return 0;
300 scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
301 scsi_cmd[1] = dev->lun << 5;
302 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
303 scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
304 return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
305 case SCSI_IOCTL_TEST_UNIT_READY:
306 scsi_cmd[0] = TEST_UNIT_READY;
307 scsi_cmd[1] = dev->lun << 5;
308 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
309 scsi_cmd[4] = 0;
310 return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
311 break;
312 default :
313 return -EINVAL;
314 }
315 return -EINVAL;
316 }
317
318
319
320
321
322
323 int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) {
324 unsigned long oldfs;
325 int tmp;
326 oldfs = get_fs();
327 set_fs(get_ds());
328 tmp = scsi_ioctl (dev, cmd, arg);
329 set_fs(oldfs);
330 return tmp;
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350