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