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