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 CDROMPLAYBLK:
163 {
164 struct cdrom_blk blk;
165
166 err = verify_area (VERIFY_READ, (void *) arg, sizeof (blk));
167 if (err) return err;
168
169 memcpy_fromfs(&blk, (void *) arg, sizeof(blk));
170
171 sr_cmd[0] = SCMD_PLAYAUDIO10;
172 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
173 sr_cmd[2] = blk.from >> 24;
174 sr_cmd[3] = blk.from >> 16;
175 sr_cmd[4] = blk.from >> 8;
176 sr_cmd[5] = blk.from;
177 sr_cmd[6] = 0;
178 sr_cmd[7] = blk.len >> 8;
179 sr_cmd[8] = blk.len;
180 sr_cmd[9] = 0;
181
182 result = do_ioctl(target, sr_cmd, NULL, 255);
183 return result;
184 }
185
186 case CDROMPLAYTRKIND:
187 {
188 struct cdrom_ti ti;
189
190 err = verify_area (VERIFY_READ, (void *) arg, sizeof (ti));
191 if (err) return err;
192
193 memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
194
195 sr_cmd[0] = SCMD_PLAYAUDIO_TI;
196 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
197 sr_cmd[2] = 0;
198 sr_cmd[3] = 0;
199 sr_cmd[4] = ti.cdti_trk0;
200 sr_cmd[5] = ti.cdti_ind0;
201 sr_cmd[6] = 0;
202 sr_cmd[7] = ti.cdti_trk1;
203 sr_cmd[8] = ti.cdti_ind1;
204 sr_cmd[9] = 0;
205
206 result = do_ioctl(target, sr_cmd, NULL, 255);
207
208 return result;
209 }
210
211 case CDROMREADTOCHDR:
212 {
213 struct cdrom_tochdr tochdr;
214 char * buffer;
215
216 sr_cmd[0] = SCMD_READ_TOC;
217 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
218 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
219 sr_cmd[6] = 0;
220 sr_cmd[7] = 0;
221 sr_cmd[8] = 12;
222 sr_cmd[9] = 0;
223
224 buffer = (unsigned char *) scsi_malloc(512);
225 if(!buffer) return -ENOMEM;
226
227 result = do_ioctl(target, sr_cmd, buffer, 12);
228
229 tochdr.cdth_trk0 = buffer[2];
230 tochdr.cdth_trk1 = buffer[3];
231
232 scsi_free(buffer, 512);
233
234 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));
235 if (err)
236 return err;
237 memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));
238
239 return result;
240 }
241
242 case CDROMREADTOCENTRY:
243 {
244 struct cdrom_tocentry tocentry;
245 char * buffer;
246
247 err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry));
248 if (err) return err;
249
250 memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));
251
252 sr_cmd[0] = SCMD_READ_TOC;
253 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
254 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
255 sr_cmd[6] = tocentry.cdte_track;
256 sr_cmd[7] = 0;
257 sr_cmd[8] = 12;
258 sr_cmd[9] = 0;
259
260 buffer = (unsigned char *) scsi_malloc(512);
261 if(!buffer) return -ENOMEM;
262
263 result = do_ioctl (target, sr_cmd, buffer, 12);
264
265 if (tocentry.cdte_format == CDROM_MSF) {
266 tocentry.cdte_addr.msf.minute = buffer[9];
267 tocentry.cdte_addr.msf.second = buffer[10];
268 tocentry.cdte_addr.msf.frame = buffer[11];
269 tocentry.cdte_ctrl = buffer[5] & 0xf;
270 }
271 else
272 tocentry.cdte_addr.lba = (int) buffer[0];
273
274 scsi_free(buffer, 512);
275
276 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry));
277 if (err)
278 return err;
279 memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));
280
281 return result;
282 }
283
284 case CDROMSTOP:
285 sr_cmd[0] = START_STOP;
286 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
287 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
288 sr_cmd[4] = 0;
289
290 result = do_ioctl(target, sr_cmd, NULL, 255);
291 return result;
292
293 case CDROMSTART:
294 sr_cmd[0] = START_STOP;
295 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
296 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
297 sr_cmd[4] = 1;
298
299 result = do_ioctl(target, sr_cmd, NULL, 255);
300 return result;
301
302 case CDROMEJECT:
303
304
305
306 if (scsi_CDs[target].device -> access_count > 1)
307 return -EBUSY;
308
309 sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
310 sr_cmd[0] = START_STOP;
311 sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 1;
312 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
313 sr_cmd[4] = 0x02;
314
315 if (!(result = do_ioctl(target, sr_cmd, NULL, 255)))
316 scsi_CDs[target].device -> changed = 1;
317
318 return result;
319
320 case CDROMEJECT_SW:
321 scsi_CDs[target].auto_eject = !!arg;
322 return 0;
323
324 case CDROMVOLCTRL:
325 {
326 char * buffer, * mask;
327 struct cdrom_volctrl volctrl;
328
329 err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl));
330 if (err) return err;
331
332 memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));
333
334
335
336 sr_cmd[0] = MODE_SENSE;
337 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
338 sr_cmd[2] = 0xe;
339 sr_cmd[3] = 0;
340 sr_cmd[4] = 28;
341 sr_cmd[5] = 0;
342
343 buffer = (unsigned char *) scsi_malloc(512);
344 if(!buffer) return -ENOMEM;
345
346 if ((result = do_ioctl (target, sr_cmd, buffer, 28))) {
347 printk ("Hosed while obtaining audio mode page\n");
348 scsi_free(buffer, 512);
349 return result;
350 }
351
352 sr_cmd[0] = MODE_SENSE;
353 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
354 sr_cmd[2] = 0x4e;
355 sr_cmd[3] = 0;
356 sr_cmd[4] = 28;
357 sr_cmd[5] = 0;
358
359 mask = (unsigned char *) scsi_malloc(512);
360 if(!mask) {
361 scsi_free(buffer, 512);
362 return -ENOMEM;
363 };
364
365 if ((result = do_ioctl (target, sr_cmd, mask, 28))) {
366 printk ("Hosed while obtaining mask for audio mode page\n");
367 scsi_free(buffer, 512);
368 scsi_free(mask, 512);
369 return result;
370 }
371
372
373 buffer[0] = 0;
374
375 buffer[21] = volctrl.channel0 & mask[21];
376 buffer[23] = volctrl.channel1 & mask[23];
377 buffer[25] = volctrl.channel2 & mask[25];
378 buffer[27] = volctrl.channel3 & mask[27];
379
380 sr_cmd[0] = MODE_SELECT;
381 sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10;
382 sr_cmd[2] = sr_cmd[3] = 0;
383 sr_cmd[4] = 28;
384 sr_cmd[5] = 0;
385
386 result = do_ioctl (target, sr_cmd, buffer, 28);
387 scsi_free(buffer, 512);
388 scsi_free(mask, 512);
389 return result;
390 }
391
392 case CDROMSUBCHNL:
393 {
394 struct cdrom_subchnl subchnl;
395 char * buffer;
396
397 sr_cmd[0] = SCMD_READ_SUBCHANNEL;
398 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
399 sr_cmd[2] = 0x40;
400 sr_cmd[3] = 0x01;
401 sr_cmd[4] = sr_cmd[5] = 0;
402 sr_cmd[6] = 0;
403 sr_cmd[7] = 0;
404 sr_cmd[8] = 16;
405 sr_cmd[9] = 0;
406
407 buffer = (unsigned char*) scsi_malloc(512);
408 if(!buffer) return -ENOMEM;
409
410 result = do_ioctl(target, sr_cmd, buffer, 16);
411
412 subchnl.cdsc_audiostatus = buffer[1];
413 subchnl.cdsc_format = CDROM_MSF;
414 subchnl.cdsc_ctrl = buffer[5] & 0xf;
415 subchnl.cdsc_trk = buffer[6];
416 subchnl.cdsc_ind = buffer[7];
417
418 subchnl.cdsc_reladdr.msf.minute = buffer[13];
419 subchnl.cdsc_reladdr.msf.second = buffer[14];
420 subchnl.cdsc_reladdr.msf.frame = buffer[15];
421 subchnl.cdsc_absaddr.msf.minute = buffer[9];
422 subchnl.cdsc_absaddr.msf.second = buffer[10];
423 subchnl.cdsc_absaddr.msf.frame = buffer[11];
424
425 scsi_free(buffer, 512);
426
427 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));
428 if (err)
429 return err;
430 memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
431 return result;
432 }
433
434 case CDROMREADMODE2:
435 return -EINVAL;
436 case CDROMREADMODE1:
437 return -EINVAL;
438
439
440 case CDROMMULTISESSION:
441 {
442 struct cdrom_multisession ms_info;
443 long lba;
444
445 err = verify_area(VERIFY_READ, (void *) arg,
446 sizeof(struct cdrom_multisession));
447 if (err) return (err);
448
449 memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
450
451 if (ms_info.addr_format==CDROM_MSF) {
452 lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET;
453 ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES);
454 lba %= CD_SECS*CD_FRAMES;
455 ms_info.addr.msf.second = lba / CD_FRAMES;
456 ms_info.addr.msf.frame = lba % CD_FRAMES;
457 } else if (ms_info.addr_format==CDROM_LBA)
458 ms_info.addr.lba=scsi_CDs[target].mpcd_sector;
459 else return (-EINVAL);
460
461 ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01;
462
463 err=verify_area(VERIFY_WRITE,(void *) arg,
464 sizeof(struct cdrom_multisession));
465 if (err) return (err);
466
467 memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
468 return (0);
469 }
470
471 case BLKRASET:
472 if(!suser()) return -EACCES;
473 if(!(inode->i_rdev)) return -EINVAL;
474 if(arg > 0xff) return -EINVAL;
475 read_ahead[MAJOR(inode->i_rdev)] = arg;
476 return 0;
477 RO_IOCTLS(dev,arg);
478 default:
479 return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
480 }
481 }
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500