This source file includes following definitions.
- sr_ioctl_done
- do_ioctl
- sr_ioctl
1 #include <linux/kernel.h>
2 #include <linux/sched.h>
3 #include <linux/fs.h>
4 #include <asm/segment.h>
5 #include <linux/errno.h>
6
7 #include "../blk.h"
8 #include "scsi.h"
9 #include "sr.h"
10 #include "scsi_ioctl.h"
11
12 #include <linux/cdrom.h>
13
14 #define IOCTL_RETRIES 3
15
16 #define IOCTL_TIMEOUT 200
17
18 extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
19
20 static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
21 {
22 struct request * req;
23 struct task_struct * p;
24
25 req = &SCpnt->request;
26 req->dev = 0xfffe;
27
28 if ((p = req->waiting) != NULL) {
29 req->waiting = NULL;
30 p->state = TASK_RUNNING;
31 if (p->counter > current->counter)
32 need_resched = 1;
33 }
34 }
35
36
37
38
39
40 static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength)
41 {
42 Scsi_Cmnd * SCpnt;
43 int result;
44
45 SCpnt = allocate_device(NULL, scsi_CDs[target].device->index, 1);
46 scsi_do_cmd(SCpnt,
47 (void *) sr_cmd, buffer, buflength, sr_ioctl_done,
48 IOCTL_TIMEOUT, IOCTL_RETRIES);
49
50
51 if (SCpnt->request.dev != 0xfffe){
52 SCpnt->request.waiting = current;
53 current->state = TASK_UNINTERRUPTIBLE;
54 while (SCpnt->request.dev != 0xfffe) schedule();
55 };
56
57 result = SCpnt->result;
58
59
60 if(driver_byte(result) != 0)
61 switch(SCpnt->sense_buffer[2] & 0xf) {
62 case UNIT_ATTENTION:
63 scsi_CDs[target].device->changed = 1;
64 printk("Disc change detected.\n");
65 break;
66 case NOT_READY:
67 printk("CDROM not ready. Make sure there is a disc in the drive.\n");
68 break;
69 case ILLEGAL_REQUEST:
70 printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");
71 break;
72 default:
73 printk("SCSI CD error: host %d id %d lun %d return code = %03x\n",
74 scsi_CDs[target].device->host_no,
75 scsi_CDs[target].device->id,
76 scsi_CDs[target].device->lun,
77 result);
78 printk("\tSense class %x, sense error %x, extended sense %x\n",
79 sense_class(SCpnt->sense_buffer[0]),
80 sense_error(SCpnt->sense_buffer[0]),
81 SCpnt->sense_buffer[2] & 0xf);
82
83 };
84
85 result = SCpnt->result;
86 SCpnt->request.dev = -1;
87 wake_up(&scsi_devices[SCpnt->index].device_wait);
88
89 return result;
90 }
91
92 int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
93 {
94 u_char sr_cmd[10];
95
96 int dev = inode->i_rdev;
97 int result, target;
98
99 target = MINOR(dev);
100 if (target >= NR_SR) return -ENODEV;
101
102 switch (cmd)
103 {
104
105 case CDROMPAUSE:
106
107 sr_cmd[0] = SCMD_PAUSE_RESUME;
108 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
109 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
110 sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
111 sr_cmd[8] = 0;
112 sr_cmd[9] = 0;
113
114 result = do_ioctl(target, sr_cmd, NULL, 255);
115 return result;
116
117 case CDROMRESUME:
118
119 sr_cmd[0] = SCMD_PAUSE_RESUME;
120 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
121 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
122 sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
123 sr_cmd[8] = 1;
124 sr_cmd[9] = 0;
125
126 result = do_ioctl(target, sr_cmd, NULL, 255);
127
128 return result;
129
130 case CDROMPLAYMSF:
131 {
132 struct cdrom_msf msf;
133 memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
134
135 sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
136 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
137 sr_cmd[2] = 0;
138 sr_cmd[3] = msf.cdmsf_min0;
139 sr_cmd[4] = msf.cdmsf_sec0;
140 sr_cmd[5] = msf.cdmsf_frame0;
141 sr_cmd[6] = msf.cdmsf_min1;
142 sr_cmd[7] = msf.cdmsf_sec1;
143 sr_cmd[8] = msf.cdmsf_frame1;
144 sr_cmd[9] = 0;
145
146 result = do_ioctl(target, sr_cmd, NULL, 255);
147 return result;
148 }
149
150 case CDROMPLAYTRKIND:
151 {
152 struct cdrom_ti ti;
153 memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
154
155 sr_cmd[0] = SCMD_PLAYAUDIO_TI;
156 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
157 sr_cmd[2] = 0;
158 sr_cmd[3] = 0;
159 sr_cmd[4] = ti.cdti_trk0;
160 sr_cmd[5] = ti.cdti_ind0;
161 sr_cmd[6] = 0;
162 sr_cmd[7] = ti.cdti_trk1;
163 sr_cmd[8] = ti.cdti_ind1;
164 sr_cmd[9] = 0;
165
166 result = do_ioctl(target, sr_cmd, NULL, 255);
167
168 return result;
169 }
170
171 case CDROMREADTOCHDR:
172 {
173 struct cdrom_tochdr tochdr;
174 char buffer[12];
175
176 sr_cmd[0] = SCMD_READ_TOC;
177 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
178 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
179 sr_cmd[6] = 0;
180 sr_cmd[7] = 0;
181 sr_cmd[8] = 12;
182 sr_cmd[9] = 0;
183
184 result = do_ioctl(target, sr_cmd, buffer, sizeof (buffer));
185
186 tochdr.cdth_trk0 = buffer[2];
187 tochdr.cdth_trk1 = buffer[3];
188
189 verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));
190 memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));
191
192 return result;
193 }
194
195 case CDROMREADTOCENTRY:
196 {
197 struct cdrom_tocentry tocentry;
198 char buffer[12];
199
200 verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry));
201 memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));
202
203 sr_cmd[0] = SCMD_READ_TOC;
204 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
205 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
206 sr_cmd[6] = tocentry.cdte_track;
207 sr_cmd[7] = 0;
208 sr_cmd[8] = 12;
209 sr_cmd[9] = 0;
210
211 result = do_ioctl (target, sr_cmd, buffer, sizeof (buffer));
212
213 if (tocentry.cdte_format == CDROM_MSF) {
214 tocentry.cdte_addr.msf.minute = buffer[9];
215 tocentry.cdte_addr.msf.second = buffer[10];
216 tocentry.cdte_addr.msf.frame = buffer[11];
217 tocentry.cdte_ctrl = buffer[5] & 0xf;
218 }
219 else
220 tocentry.cdte_addr.lba = (int) buffer[0];
221
222 verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry));
223 memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));
224
225 return result;
226 }
227
228 case CDROMSTOP:
229 sr_cmd[0] = START_STOP;
230 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
231 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
232 sr_cmd[4] = 0;
233
234 result = do_ioctl(target, sr_cmd, NULL, 255);
235 return result;
236
237 case CDROMSTART:
238 sr_cmd[0] = START_STOP;
239 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
240 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
241 sr_cmd[4] = 1;
242
243 result = do_ioctl(target, sr_cmd, NULL, 255);
244 return result;
245
246 case CDROMEJECT:
247 if (scsi_CDs[target].device -> access_count == 1)
248 sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
249
250 sr_cmd[0] = START_STOP;
251 sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1;
252 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
253 sr_cmd[4] = 0x02;
254
255 if (!(result = do_ioctl(target, sr_cmd, NULL, 255)))
256 scsi_CDs[target].device -> changed = 1;
257
258 return result;
259
260 case CDROMVOLCTRL:
261 {
262 char buffer[28], mask[28];
263 struct cdrom_volctrl volctrl;
264
265 verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl));
266 memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));
267
268
269
270 sr_cmd[0] = MODE_SENSE;
271 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
272 sr_cmd[2] = 0xe;
273 sr_cmd[3] = 0;
274 sr_cmd[4] = 28;
275 sr_cmd[5] = 0;
276
277 if ((result = do_ioctl (target, sr_cmd, buffer, sizeof (buffer)))) {
278 printk ("Hosed while obtaining audio mode page\n");
279 return result;
280 }
281
282 sr_cmd[0] = MODE_SENSE;
283 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
284 sr_cmd[2] = 0x4e;
285 sr_cmd[3] = 0;
286 sr_cmd[4] = 28;
287 sr_cmd[5] = 0;
288
289 if ((result = do_ioctl (target, sr_cmd, mask, sizeof (mask)))) {
290 printk ("Hosed while obtaining mask for audio mode page\n");
291 return result;
292 }
293
294
295
296 buffer[21] = volctrl.channel0 & mask[21];
297 buffer[23] = volctrl.channel1 & mask[23];
298 buffer[25] = volctrl.channel2 & mask[25];
299 buffer[27] = volctrl.channel3 & mask[27];
300
301 sr_cmd[0] = MODE_SELECT;
302 sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10;
303 sr_cmd[2] = sr_cmd[3] = 0;
304 sr_cmd[4] = 28;
305 sr_cmd[5] = 0;
306
307 result = do_ioctl (target, sr_cmd, buffer, sizeof (buffer));
308 return result;
309 }
310
311 case CDROMSUBCHNL:
312 {
313 struct cdrom_subchnl subchnl;
314 char buffer[16];
315
316 sr_cmd[0] = SCMD_READ_SUBCHANNEL;
317 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
318 sr_cmd[2] = 0x40;
319 sr_cmd[3] = 0x01;
320 sr_cmd[4] = sr_cmd[5] = 0;
321 sr_cmd[6] = 0;
322 sr_cmd[7] = 0;
323 sr_cmd[8] = 16;
324 sr_cmd[9] = 0;
325
326 result = do_ioctl(target, sr_cmd, buffer, sizeof (buffer));
327
328 subchnl.cdsc_audiostatus = buffer[1];
329 subchnl.cdsc_format = CDROM_MSF;
330 subchnl.cdsc_ctrl = buffer[5] & 0xf;
331 subchnl.cdsc_trk = buffer[6];
332 subchnl.cdsc_ind = buffer[7];
333
334 subchnl.cdsc_reladdr.msf.minute = buffer[13];
335 subchnl.cdsc_reladdr.msf.second = buffer[14];
336 subchnl.cdsc_reladdr.msf.frame = buffer[15];
337 subchnl.cdsc_absaddr.msf.minute = buffer[9];
338 subchnl.cdsc_absaddr.msf.second = buffer[10];
339 subchnl.cdsc_absaddr.msf.frame = buffer[11];
340
341 verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));
342 memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
343 return result;
344 }
345
346 case CDROMREADMODE2:
347 return -EINVAL;
348 case CDROMREADMODE1:
349 return -EINVAL;
350
351 RO_IOCTLS(dev,arg);
352 default:
353 return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
354 }
355 }