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 CDROMSUBCHNL:
382 {
383 struct cdrom_subchnl subchnl;
384 char * buffer;
385
386 sr_cmd[0] = SCMD_READ_SUBCHANNEL;
387 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
388 sr_cmd[2] = 0x40;
389 sr_cmd[3] = 0x01;
390 sr_cmd[4] = sr_cmd[5] = 0;
391 sr_cmd[6] = 0;
392 sr_cmd[7] = 0;
393 sr_cmd[8] = 16;
394 sr_cmd[9] = 0;
395
396 buffer = (unsigned char*) scsi_malloc(512);
397 if(!buffer) return -ENOMEM;
398
399 result = do_ioctl(target, sr_cmd, buffer, 16);
400
401 subchnl.cdsc_audiostatus = buffer[1];
402 subchnl.cdsc_format = CDROM_MSF;
403 subchnl.cdsc_ctrl = buffer[5] & 0xf;
404 subchnl.cdsc_trk = buffer[6];
405 subchnl.cdsc_ind = buffer[7];
406
407 subchnl.cdsc_reladdr.msf.minute = buffer[13];
408 subchnl.cdsc_reladdr.msf.second = buffer[14];
409 subchnl.cdsc_reladdr.msf.frame = buffer[15];
410 subchnl.cdsc_absaddr.msf.minute = buffer[9];
411 subchnl.cdsc_absaddr.msf.second = buffer[10];
412 subchnl.cdsc_absaddr.msf.frame = buffer[11];
413
414 scsi_free(buffer, 512);
415
416 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));
417 if (err)
418 return err;
419 memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
420 return result;
421 }
422
423 case CDROMREADMODE2:
424 return -EINVAL;
425 case CDROMREADMODE1:
426 return -EINVAL;
427
428
429 case CDROMMULTISESSION:
430 {
431 struct cdrom_multisession ms_info;
432 long lba;
433
434 err = verify_area(VERIFY_READ, (void *) arg,
435 sizeof(struct cdrom_multisession));
436 if (err) return (err);
437
438 memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
439
440 if (ms_info.addr_format==CDROM_MSF) {
441 lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET;
442 ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES);
443 lba %= CD_SECS*CD_FRAMES;
444 ms_info.addr.msf.second = lba / CD_FRAMES;
445 ms_info.addr.msf.frame = lba % CD_FRAMES;
446 } else if (ms_info.addr_format==CDROM_LBA)
447 ms_info.addr.lba=scsi_CDs[target].mpcd_sector;
448 else return (-EINVAL);
449
450 ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01;
451
452 err=verify_area(VERIFY_WRITE,(void *) arg,
453 sizeof(struct cdrom_multisession));
454 if (err) return (err);
455
456 memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
457 return (0);
458 }
459
460 case BLKRASET:
461 if(!suser()) return -EACCES;
462 if(!(inode->i_rdev)) return -EINVAL;
463 if(arg > 0xff) return -EINVAL;
464 read_ahead[MAJOR(inode->i_rdev)] = arg;
465 return 0;
466 RO_IOCTLS(dev,arg);
467 default:
468 return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
469 }
470 }
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489