This source file includes following definitions.
- ioctl_probe
- scsi_ioctl_done
- ioctl_internal_command
- ioctl_command
- scsi_ioctl
1 #include <linux/config.h>
2 #ifdef CONFIG_SCSI
3
4 #include <asm/io.h>
5 #include <asm/segment.h>
6 #include <asm/system.h>
7
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/sched.h>
11 #include <linux/string.h>
12
13 #include "scsi.h"
14 #include "hosts.h"
15 #include "scsi_ioctl.h"
16
17 #define MAX_RETRIES 5
18 #define MAX_TIMEOUT 200
19 #define MAX_BUF 8192
20
21 #define max(a,b) (((a) > (b)) ? (a) : (b))
22
23
24
25
26
27
28
29
30 static int ioctl_probe(int dev, void *buffer)
31 {
32 int temp;
33 int len;
34
35 if ((temp = scsi_hosts[dev].present) && buffer) {
36 len = get_fs_long ((int *) buffer);
37 memcpy_tofs (buffer, scsi_hosts[dev].info(), len);
38 }
39 return temp;
40 }
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 static int the_result[MAX_SCSI_HOSTS] = {0,};
67
68 static void scsi_ioctl_done (int host, int result)
69 {
70 the_result[host] = result;
71 }
72
73
74
75 static int ioctl_internal_command(Scsi_Device *dev, char ** command)
76 {
77 char * cmd;
78 int temp, host;
79 char sense_buffer[256];
80
81 host = dev->host_no;
82 cmd = command[0];
83
84 do {
85 cli();
86 if (the_result[host]) {
87 sti();
88 while(the_result[host])
89 ;
90 } else {
91 the_result[host]=-1;
92 sti();
93 break;
94 }
95 } while (1);
96
97 scsi_do_cmd(host, dev->id, cmd, NULL, 0,
98 scsi_ioctl_done, MAX_TIMEOUT,
99 sense_buffer, MAX_RETRIES);
100
101 while (the_result[host] == -1)
102 ;
103 temp = the_result[host];
104
105 if(driver_byte(the_result[host]) != 0)
106 switch(sense_buffer[2] & 0xf) {
107 case ILLEGAL_REQUEST:
108 printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
109 break;
110 case NOT_READY:
111 if(dev->removable){
112 printk("Device not ready. Make sure there is a disc in the drive.\n");
113 break;
114 };
115 case UNIT_ATTENTION:
116 if (dev->removable){
117 dev->changed = 1;
118 temp = 0;
119 printk("Disc change detected.\n");
120 break;
121 };
122 default:
123 printk("SCSI CD error: host %d id %d lun %d return code = %x\n",
124 dev->host_no,
125 dev->id,
126 dev->lun,
127 the_result);
128 printk("\tSense class %x, sense error %x, extended sense %x\n",
129 sense_class(sense_buffer[0]),
130 sense_error(sense_buffer[0]),
131 sense_buffer[2] & 0xf);
132
133 };
134
135 the_result[host] = 0;
136 return temp;
137 }
138
139 static int ioctl_command(Scsi_Device *dev, void *buffer)
140 {
141 char buf[MAX_BUF];
142 char cmd[10];
143 char * cmd_in;
144 unsigned char opcode;
145 int inlen, outlen, cmdlen, temp, host;
146
147 if (!buffer)
148 return -EINVAL;
149
150 inlen = get_fs_long((int *) buffer);
151 outlen = get_fs_long( ((int *) buffer) + 1);
152
153 cmd_in = (char *) ( ((int *)buffer) + 2);
154 opcode = get_fs_byte(cmd_in);
155
156 memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode));
157 memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen);
158 host = dev->host_no;
159
160 #ifndef DEBUG_NO_CMD
161 do {
162 cli();
163 if (the_result[host]) {
164 sti();
165 while(the_result[host])
166 ;
167 } else {
168 the_result[host]=-1;
169 sti();
170 break;
171 }
172 } while (1);
173
174 scsi_do_cmd(host, dev->id, cmd, buf, ((outlen > MAX_BUF) ?
175 MAX_BUF : outlen), scsi_ioctl_done, MAX_TIMEOUT,
176 buf, MAX_RETRIES);
177
178 while (the_result[host] == -1)
179 ;
180 temp = the_result[host];
181 the_result[host] = 0;
182 memcpy_tofs ((void *) cmd_in, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen);
183 return temp;
184 #else
185 {
186 int i;
187 printk("scsi_ioctl : device %d. command = ", dev->id);
188 for (i = 0; i < 10; ++i)
189 printk("%02x ", cmd[i]);
190 printk("\r\nbuffer =");
191 for (i = 0; i < 20; ++i)
192 printk("%02x ", buf[i]);
193 printk("\r\n");
194 printk("inlen = %d, outlen = %d, cmdlen = %d\n",
195 inlen, outlen, cmdlen);
196 printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in);
197 }
198 return 0;
199 #endif
200 }
201
202
203
204
205
206
207
208 int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
209 {
210 char scsi_cmd[10];
211 char * command[2];
212
213 if ((cmd != 0 && dev->id > NR_SCSI_DEVICES))
214 return -ENODEV;
215 if ((cmd == 0 && dev->host_no > MAX_SCSI_HOSTS))
216 return -ENODEV;
217
218 switch (cmd) {
219 case SCSI_IOCTL_PROBE_HOST:
220 return ioctl_probe(dev->host_no, arg);
221 case SCSI_IOCTL_SEND_COMMAND:
222 return ioctl_command((Scsi_Device *) dev, arg);
223 case SCSI_IOCTL_DOORLOCK:
224 if (!dev->removable) return 0;
225 scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
226 scsi_cmd[1] = dev->lun << 5;
227 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
228 scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
229 command[0] = scsi_cmd;
230 return ioctl_internal_command((Scsi_Device *) dev, command);
231 break;
232 case SCSI_IOCTL_DOORUNLOCK:
233 if (!dev->removable) return 0;
234 scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
235 scsi_cmd[1] = dev->lun << 5;
236 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
237 scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
238 command[0] = scsi_cmd;
239 return ioctl_internal_command((Scsi_Device *) dev, command);
240 case SCSI_IOCTL_TEST_UNIT_READY:
241 scsi_cmd[0] = TEST_UNIT_READY;
242 scsi_cmd[1] = dev->lun << 5;
243 scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
244 scsi_cmd[4] = 0;
245 command[0] = scsi_cmd;
246 return ioctl_internal_command((Scsi_Device *) dev, command);
247 break;
248 default :
249 return -EINVAL;
250 }
251 }
252 #endif