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 memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
143
144 sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
145 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
146 sr_cmd[2] = 0;
147 sr_cmd[3] = msf.cdmsf_min0;
148 sr_cmd[4] = msf.cdmsf_sec0;
149 sr_cmd[5] = msf.cdmsf_frame0;
150 sr_cmd[6] = msf.cdmsf_min1;
151 sr_cmd[7] = msf.cdmsf_sec1;
152 sr_cmd[8] = msf.cdmsf_frame1;
153 sr_cmd[9] = 0;
154
155 result = do_ioctl(target, sr_cmd, NULL, 255);
156 return result;
157 }
158
159 case CDROMPLAYTRKIND:
160 {
161 struct cdrom_ti ti;
162 memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
163
164 sr_cmd[0] = SCMD_PLAYAUDIO_TI;
165 sr_cmd[1] = scsi_CDs[target].device->lun << 5;
166 sr_cmd[2] = 0;
167 sr_cmd[3] = 0;
168 sr_cmd[4] = ti.cdti_trk0;
169 sr_cmd[5] = ti.cdti_ind0;
170 sr_cmd[6] = 0;
171 sr_cmd[7] = ti.cdti_trk1;
172 sr_cmd[8] = ti.cdti_ind1;
173 sr_cmd[9] = 0;
174
175 result = do_ioctl(target, sr_cmd, NULL, 255);
176
177 return result;
178 }
179
180 case CDROMREADTOCHDR:
181 {
182 struct cdrom_tochdr tochdr;
183 char * buffer;
184
185 sr_cmd[0] = SCMD_READ_TOC;
186 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
187 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
188 sr_cmd[6] = 0;
189 sr_cmd[7] = 0;
190 sr_cmd[8] = 12;
191 sr_cmd[9] = 0;
192
193 buffer = (unsigned char *) scsi_malloc(512);
194 if(!buffer) return -ENOMEM;
195
196 result = do_ioctl(target, sr_cmd, buffer, 12);
197
198 tochdr.cdth_trk0 = buffer[2];
199 tochdr.cdth_trk1 = buffer[3];
200
201 scsi_free(buffer, 512);
202
203 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));
204 if (err)
205 return err;
206 memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));
207
208 return result;
209 }
210
211 case CDROMREADTOCENTRY:
212 {
213 struct cdrom_tocentry tocentry;
214 char * buffer;
215
216 verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry));
217 memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));
218
219 sr_cmd[0] = SCMD_READ_TOC;
220 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
221 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
222 sr_cmd[6] = tocentry.cdte_track;
223 sr_cmd[7] = 0;
224 sr_cmd[8] = 12;
225 sr_cmd[9] = 0;
226
227 buffer = (unsigned char *) scsi_malloc(512);
228 if(!buffer) return -ENOMEM;
229
230 result = do_ioctl (target, sr_cmd, buffer, 12);
231
232 if (tocentry.cdte_format == CDROM_MSF) {
233 tocentry.cdte_addr.msf.minute = buffer[9];
234 tocentry.cdte_addr.msf.second = buffer[10];
235 tocentry.cdte_addr.msf.frame = buffer[11];
236 tocentry.cdte_ctrl = buffer[5] & 0xf;
237 }
238 else
239 tocentry.cdte_addr.lba = (int) buffer[0];
240
241 scsi_free(buffer, 512);
242
243 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry));
244 if (err)
245 return err;
246 memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));
247
248 return result;
249 }
250
251 case CDROMSTOP:
252 sr_cmd[0] = START_STOP;
253 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
254 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
255 sr_cmd[4] = 0;
256
257 result = do_ioctl(target, sr_cmd, NULL, 255);
258 return result;
259
260 case CDROMSTART:
261 sr_cmd[0] = START_STOP;
262 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
263 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
264 sr_cmd[4] = 1;
265
266 result = do_ioctl(target, sr_cmd, NULL, 255);
267 return result;
268
269 case CDROMEJECT:
270 if (scsi_CDs[target].device -> access_count != 1)
271 return -EBUSY;
272
273 sr_ioctl (inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
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] = 0x02;
278
279 if (!(result = do_ioctl(target, sr_cmd, NULL, 255)))
280 scsi_CDs[target].device -> changed = 1;
281
282 return result;
283
284 case CDROMVOLCTRL:
285 {
286 char * buffer, * mask;
287 struct cdrom_volctrl volctrl;
288
289 verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl));
290 memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));
291
292
293
294 sr_cmd[0] = MODE_SENSE;
295 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
296 sr_cmd[2] = 0xe;
297 sr_cmd[3] = 0;
298 sr_cmd[4] = 28;
299 sr_cmd[5] = 0;
300
301 buffer = (unsigned char *) scsi_malloc(512);
302 if(!buffer) return -ENOMEM;
303
304 if ((result = do_ioctl (target, sr_cmd, buffer, 28))) {
305 printk ("Hosed while obtaining audio mode page\n");
306 scsi_free(buffer, 512);
307 return result;
308 }
309
310 sr_cmd[0] = MODE_SENSE;
311 sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5;
312 sr_cmd[2] = 0x4e;
313 sr_cmd[3] = 0;
314 sr_cmd[4] = 28;
315 sr_cmd[5] = 0;
316
317 mask = (unsigned char *) scsi_malloc(512);
318 if(!mask) {
319 scsi_free(buffer, 512);
320 return -ENOMEM;
321 };
322
323 if ((result = do_ioctl (target, sr_cmd, mask, 28))) {
324 printk ("Hosed while obtaining mask for audio mode page\n");
325 scsi_free(buffer, 512);
326 scsi_free(mask, 512);
327 return result;
328 }
329
330
331 buffer[0] = 0;
332
333 buffer[21] = volctrl.channel0 & mask[21];
334 buffer[23] = volctrl.channel1 & mask[23];
335 buffer[25] = volctrl.channel2 & mask[25];
336 buffer[27] = volctrl.channel3 & mask[27];
337
338 sr_cmd[0] = MODE_SELECT;
339 sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10;
340 sr_cmd[2] = sr_cmd[3] = 0;
341 sr_cmd[4] = 28;
342 sr_cmd[5] = 0;
343
344 result = do_ioctl (target, sr_cmd, buffer, 28);
345 scsi_free(buffer, 512);
346 scsi_free(mask, 512);
347 return result;
348 }
349
350 case CDROMSUBCHNL:
351 {
352 struct cdrom_subchnl subchnl;
353 char * buffer;
354
355 sr_cmd[0] = SCMD_READ_SUBCHANNEL;
356 sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;
357 sr_cmd[2] = 0x40;
358 sr_cmd[3] = 0x01;
359 sr_cmd[4] = sr_cmd[5] = 0;
360 sr_cmd[6] = 0;
361 sr_cmd[7] = 0;
362 sr_cmd[8] = 16;
363 sr_cmd[9] = 0;
364
365 buffer = (unsigned char*) scsi_malloc(512);
366 if(!buffer) return -ENOMEM;
367
368 result = do_ioctl(target, sr_cmd, buffer, 16);
369
370 subchnl.cdsc_audiostatus = buffer[1];
371 subchnl.cdsc_format = CDROM_MSF;
372 subchnl.cdsc_ctrl = buffer[5] & 0xf;
373 subchnl.cdsc_trk = buffer[6];
374 subchnl.cdsc_ind = buffer[7];
375
376 subchnl.cdsc_reladdr.msf.minute = buffer[13];
377 subchnl.cdsc_reladdr.msf.second = buffer[14];
378 subchnl.cdsc_reladdr.msf.frame = buffer[15];
379 subchnl.cdsc_absaddr.msf.minute = buffer[9];
380 subchnl.cdsc_absaddr.msf.second = buffer[10];
381 subchnl.cdsc_absaddr.msf.frame = buffer[11];
382
383 scsi_free(buffer, 512);
384
385 err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));
386 if (err)
387 return err;
388 memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
389 return result;
390 }
391
392 case CDROMREADMODE2:
393 return -EINVAL;
394 case CDROMREADMODE1:
395 return -EINVAL;
396
397
398 case CDROMMULTISESSION:
399 {
400 struct cdrom_multisession ms_info;
401 long lba;
402
403 err = verify_area(VERIFY_READ, (void *) arg,
404 sizeof(struct cdrom_multisession));
405 if (err) return (err);
406
407 memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
408
409 if (ms_info.addr_format==CDROM_MSF) {
410 lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET;
411 ms_info.addr.msf.minute = lba / (CD_SECS*CD_FRAMES);
412 lba %= CD_SECS*CD_FRAMES;
413 ms_info.addr.msf.second = lba / CD_FRAMES;
414 ms_info.addr.msf.frame = lba % CD_FRAMES;
415 } else if (ms_info.addr_format==CDROM_LBA)
416 ms_info.addr.lba=scsi_CDs[target].mpcd_sector;
417 else return (-EINVAL);
418
419 ms_info.xa_flag=scsi_CDs[target].xa_flags & 0x01;
420
421 err=verify_area(VERIFY_WRITE,(void *) arg,
422 sizeof(struct cdrom_multisession));
423 if (err) return (err);
424
425 memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
426 return (0);
427 }
428
429 case BLKRASET:
430 if(!suser()) return -EACCES;
431 if(!inode->i_rdev) return -EINVAL;
432 if(arg > 0xff) return -EINVAL;
433 read_ahead[MAJOR(inode->i_rdev)] = arg;
434 return 0;
435 RO_IOCTLS(dev,arg);
436 default:
437 return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
438 }
439 }
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458