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