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