This source file includes following definitions.
- sr_ioctl_done
- do_ioctl
- sr_ioctl
1 #ifdef MODULE
2 #include <linux/autoconf.h>
3 #include <linux/module.h>
4 #include <linux/version.h>
5 #endif
6
7 #include <linux/kernel.h>
8 #include <linux/sched.h>
9 #include <linux/mm.h>
10 #include <linux/fs.h>
11 #include <asm/segment.h>
12 #include <linux/errno.h>
13
14 #include "../block/blk.h"
15 #include "scsi.h"
16 #include "hosts.h"
17 #include "sr.h"
18 #include "scsi_ioctl.h"
19
20 #include <linux/cdrom.h>
21
22 #define IOCTL_RETRIES 3
23
24
25 #define IOCTL_TIMEOUT 3000
26
27 static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
28 {
29 struct request * req;
30
31 req = &SCpnt->request;
32 req->rq_status = RQ_SCSI_DONE;
33
34 if (req->sem != NULL) {
35 up(req->sem);
36 }
37 }
38
39
40
41
42
43 static int do_ioctl(int target, unsigned char * sr_cmd, void * buffer, unsigned buflength)
44 {
45 Scsi_Cmnd * SCpnt;
46 int result;
47
48 SCpnt = allocate_device(NULL, scsi_CDs[target].device, 1);
49 scsi_do_cmd(SCpnt,
50 (void *) sr_cmd, buffer, buflength, sr_ioctl_done,
51 IOCTL_TIMEOUT, IOCTL_RETRIES);
52
53
54 if (SCpnt->request.rq_status != RQ_SCSI_DONE){
55 struct semaphore sem = MUTEX_LOCKED;
56 SCpnt->request.sem = &sem;
57 down(&sem);
58
59 while (SCpnt->request.rq_status != RQ_SCSI_DONE)
60 schedule();
61 };
62
63 result = SCpnt->result;
64
65
66 if(driver_byte(result) != 0)
67 switch(SCpnt->sense_buffer[2] & 0xf) {
68 case UNIT_ATTENTION:
69 scsi_CDs[target].device->changed = 1;
70 printk("Disc change detected.\n");
71 break;
72 case NOT_READY:
73 printk("CDROM not ready. Make sure there is a disc in the drive.\n");
74 break;
75 case ILLEGAL_REQUEST:
76 printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");
77 break;
78 default:
79 printk("SCSI CD error: host %d id %d lun %d return code = %03x\n",
80 scsi_CDs[target].device->host->host_no,
81 scsi_CDs[target].device->id,
82 scsi_CDs[target].device->lun,
83 result);
84 printk("\tSense class %x, sense error %x, extended sense %x\n",
85 sense_class(SCpnt->sense_buffer[0]),
86 sense_error(SCpnt->sense_buffer[0]),
87 SCpnt->sense_buffer[2] & 0xf);
88
89 };
90
91 result = SCpnt->result;
92 SCpnt->request.rq_status = RQ_INACTIVE;
93 wake_up(&SCpnt->device->device_wait);
94
95 return result;
96 }
97
98 int sr_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
99 {
100 u_char sr_cmd[10];
101
102 kdev_t dev = inode->i_rdev;
103 int result, target, err;
104
105 target = MINOR(dev);
106
107 if (target >= sr_template.nr_dev ||
108 !scsi_CDs[target].device) return -ENXIO;
109
110 switch (cmd)
111 {
112
113 case CDROMPAUSE:
114
115 sr_cmd[0] = SCMD_PAUSE_RESUME;
116 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
117 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
118 sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
119 sr_cmd[8] = 0;
120 sr_cmd[9] = 0;
121
122 result = do_ioctl(target, sr_cmd, NULL, 255);
123 return result;
124
125 case CDROMRESUME:
126
127 sr_cmd[0] = SCMD_PAUSE_RESUME;
128 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
129 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
130 sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
131 sr_cmd[8] = 1;
132 sr_cmd[9] = 0;
133
134 result = do_ioctl(target, sr_cmd, NULL, 255);
135
136 return result;
137
138 case CDROMPLAYMSF:
139 {
140 struct cdrom_msf msf;
141
142 err = verify_area (VERIFY_READ, (void *) arg, sizeof (msf));
143 if (err) return err;
144
145 memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
146
147 sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
148 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
149 sr_cmd[2] = 0;
150 sr_cmd[3] = msf.cdmsf_min0;
151 sr_cmd[4] = msf.cdmsf_sec0;
152 sr_cmd[5] = msf.cdmsf_frame0;
153 sr_cmd[6] = msf.cdmsf_min1;
154 sr_cmd[7] = msf.cdmsf_sec1;
155 sr_cmd[8] = msf.cdmsf_frame1;
156 sr_cmd[9] = 0;
157
158 result = do_ioctl(target, sr_cmd, NULL, 255);
159 return result;
160 }
161
162 case CDROMPLAYTRKIND:
163 {
164 struct cdrom_ti ti;
165
166 err = verify_area (VERIFY_READ, (void *) arg, sizeof (ti));
167 if (err) return err;
168
169 memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
170
171 sr_cmd[0] = SCMD_PLAYAUDIO_TI;
172 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
173 sr_cmd[2] = 0;
174 sr_cmd[3] = 0;
175 sr_cmd[4] = ti.cdti_trk0;
176 sr_cmd[5] = ti.cdti_ind0;
177 sr_cmd[6] = 0;
178 sr_cmd[7] = ti.cdti_trk1;
179 sr_cmd[8] = ti.cdti_ind1;
180 sr_cmd[9] = 0;
181
182 result = do_ioctl(target, sr_cmd, NULL, 255);
183
184 return result;
185 }
186
187 case CDROMREADTOCHDR:
188 {
189 struct cdrom_tochdr tochdr;
190 char * buffer;
191
192 sr_cmd[0] = SCMD_READ_TOC;
193 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
194 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
195 sr_cmd[6] = 0;
196 sr_cmd[7] = 0;
197 sr_cmd[8] = 12;
198 sr_cmd[9] = 0;
199
200 buffer = (unsigned char *) scsi_malloc(512);
201 if(!buffer) return -ENOMEM;
202
203 result = do_ioctl(target, sr_cmd, buffer, 12);
204
205 tochdr.cdth_trk0 = buffer[2];
206 tochdr.cdth_trk1 = buffer[3];
207
208 scsi_free(buffer, 512);
209
210 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));
211 if (err)
212 return err;
213 memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));
214
215 return result;
216 }
217
218 case CDROMREADTOCENTRY:
219 {
220 struct cdrom_tocentry tocentry;
221 char * buffer;
222
223 err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry));
224 if (err) return err;
225
226 memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));
227
228 sr_cmd[0] = SCMD_READ_TOC;
229 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
230 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
231 sr_cmd[6] = tocentry.cdte_track;
232 sr_cmd[7] = 0;
233 sr_cmd[8] = 12;
234 sr_cmd[9] = 0;
235
236 buffer = (unsigned char *) scsi_malloc(512);
237 if(!buffer) return -ENOMEM;
238
239 result = do_ioctl (target, sr_cmd, buffer, 12);
240
241 if (tocentry.cdte_format == CDROM_MSF) {
242 tocentry.cdte_addr.msf.minute = buffer[9];
243 tocentry.cdte_addr.msf.second = buffer[10];
244 tocentry.cdte_addr.msf.frame = buffer[11];
245 tocentry.cdte_ctrl = buffer[5] & 0xf;
246 }
247 else
248 tocentry.cdte_addr.lba = (int) buffer[0];
249
250 scsi_free(buffer, 512);
251
252 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry));
253 if (err)
254 return err;
255 memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));
256
257 return result;
258 }
259
260 case CDROMSTOP:
261 sr_cmd[0] = START_STOP;
262 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
263 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
264 sr_cmd[4] = 0;
265
266 result = do_ioctl(target, sr_cmd, NULL, 255);
267 return result;
268
269 case CDROMSTART:
270 sr_cmd[0] = START_STOP;
271 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
272 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
273 sr_cmd[4] = 1;
274
275 result = do_ioctl(target, sr_cmd, NULL, 255);
276 return result;
277
278 case CDROMEJECT:
279
280
281
282 if (scsi_CDs[target].device -> access_count > 1)
283 return -EBUSY;
284
285 sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
286 sr_cmd[0] = START_STOP;
287 sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1;
288 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
289 sr_cmd[4] = 0x02;
290
291 if (!(result = do_ioctl(target, sr_cmd, NULL, 255)))
292 scsi_CDs[target].device -> changed = 1;
293
294 return result;
295
296 case CDROMEJECT_SW:
297 scsi_CDs[target].auto_eject = !!arg;
298 return 0;
299
300 case CDROMVOLCTRL:
301 {
302 char * buffer, * mask;
303 struct cdrom_volctrl volctrl;
304
305 err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl));
306 if (err) return err;
307
308 memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));
309
310
311
312 sr_cmd[0] = MODE_SENSE;
313 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
314 sr_cmd[2] = 0xe;
315 sr_cmd[3] = 0;
316 sr_cmd[4] = 28;
317 sr_cmd[5] = 0;
318
319 buffer = (unsigned char *) scsi_malloc(512);
320 if(!buffer) return -ENOMEM;
321
322 if ((result = do_ioctl (target, sr_cmd, buffer, 28))) {
323 printk ("Hosed while obtaining audio mode page\n");
324 scsi_free(buffer, 512);
325 return result;
326 }
327
328 sr_cmd[0] = MODE_SENSE;
329 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
330 sr_cmd[2] = 0x4e;
331 sr_cmd[3] = 0;
332 sr_cmd[4] = 28;
333 sr_cmd[5] = 0;
334
335 mask = (unsigned char *) scsi_malloc(512);
336 if(!mask) {
337 scsi_free(buffer, 512);
338 return -ENOMEM;
339 };
340
341 if ((result = do_ioctl (target, sr_cmd, mask, 28))) {
342 printk ("Hosed while obtaining mask for audio mode page\n");
343 scsi_free(buffer, 512);
344 scsi_free(mask, 512);
345 return result;
346 }
347
348
349 buffer[0] = 0;
350
351 buffer[21] = volctrl.channel0 & mask[21];
352 buffer[23] = volctrl.channel1 & mask[23];
353 buffer[25] = volctrl.channel2 & mask[25];
354 buffer[27] = volctrl.channel3 & mask[27];
355
356 sr_cmd[0] = MODE_SELECT;
357 sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10;
358 sr_cmd[2] = sr_cmd[3] = 0;
359 sr_cmd[4] = 28;
360 sr_cmd[5] = 0;
361
362 result = do_ioctl (target, sr_cmd, buffer, 28);
363 scsi_free(buffer, 512);
364 scsi_free(mask, 512);
365 return result;
366 }
367
368 case CDROMSUBCHNL:
369 {
370 struct cdrom_subchnl subchnl;
371 char * buffer;
372
373 sr_cmd[0] = SCMD_READ_SUBCHANNEL;
374 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
375 sr_cmd[2] = 0x40;
376 sr_cmd[3] = 0x01;
377 sr_cmd[4] = sr_cmd[5] = 0;
378 sr_cmd[6] = 0;
379 sr_cmd[7] = 0;
380 sr_cmd[8] = 16;
381 sr_cmd[9] = 0;
382
383 buffer = (unsigned char*) scsi_malloc(512);
384 if(!buffer) return -ENOMEM;
385
386 result = do_ioctl(target, sr_cmd, buffer, 16);
387
388 subchnl.cdsc_audiostatus = buffer[1];
389 subchnl.cdsc_format = CDROM_MSF;
390 subchnl.cdsc_ctrl = buffer[5] & 0xf;
391 subchnl.cdsc_trk = buffer[6];
392 subchnl.cdsc_ind = buffer[7];
393
394 subchnl.cdsc_reladdr.msf.minute = buffer[13];
395 subchnl.cdsc_reladdr.msf.second = buffer[14];
396 subchnl.cdsc_reladdr.msf.frame = buffer[15];
397 subchnl.cdsc_absaddr.msf.minute = buffer[9];
398 subchnl.cdsc_absaddr.msf.second = buffer[10];
399 subchnl.cdsc_absaddr.msf.frame = buffer[11];
400
401 scsi_free(buffer, 512);
402
403 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));
404 if (err)
405 return err;
406 memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
407 return result;
408 }
409
410 case CDROMREADMODE2:
411 return -EINVAL;
412 case CDROMREADMODE1:
413 return -EINVAL;
414
415
416 case CDROMMULTISESSION:
417 {
418 struct cdrom_multisession ms_info;
419 long lba;
420
421 err = verify_area(VERIFY_READ, (void *) arg,
422 sizeof(struct cdrom_multisession));
423 if (err) return (err);
424
425 memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
426
427 if (ms_info.addr_format==CDROM_MSF) {
428 lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET;
429 ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES);
430 lba %= CD_SECS*CD_FRAMES;
431 ms_info.addr.msf.second = lba / CD_FRAMES;
432 ms_info.addr.msf.frame = lba % CD_FRAMES;
433 } else if (ms_info.addr_format==CDROM_LBA)
434 ms_info.addr.lba=scsi_CDs[target].mpcd_sector;
435 else return (-EINVAL);
436
437 ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01;
438
439 err=verify_area(VERIFY_WRITE,(void *) arg,
440 sizeof(struct cdrom_multisession));
441 if (err) return (err);
442
443 memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
444 return (0);
445 }
446
447 case BLKRASET:
448 if(!suser()) return -EACCES;
449 if(!(inode->i_rdev)) return -EINVAL;
450 if(arg > 0xff) return -EINVAL;
451 read_ahead[MAJOR(inode->i_rdev)] = arg;
452 return 0;
453 RO_IOCTLS(dev,arg);
454 default:
455 return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
456 }
457 }
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476