Import 2.1.34
[davej-history.git] / drivers / scsi / sr_ioctl.c
bloba10e9545d4ec0c6a4da57cebfbc305b2385bfac5
1 #include <linux/kernel.h>
2 #include <linux/sched.h>
3 #include <linux/mm.h>
4 #include <linux/fs.h>
5 #include <asm/uaccess.h>
6 #include <linux/errno.h>
7 #include <linux/string.h>
9 #include <linux/blk.h>
10 #include"scsi.h"
11 #include"hosts.h"
12 #include <scsi/scsi_ioctl.h>
14 #include <linux/cdrom.h>
15 #include <linux/ucdrom.h>
16 #include"sr.h"
18 externvoidget_sectorsize(int);
20 #define IOCTL_RETRIES 3
21 /* The CDROM is fairly slow, so we need a little extra time */
22 /* In fact, it is very slow if it has to spin up first */
23 #define IOCTL_TIMEOUT 3000
25 static voidsr_ioctl_done(Scsi_Cmnd * SCpnt)
27 struct request * req;
29 req = &SCpnt->request;
30 req->rq_status = RQ_SCSI_DONE;/* Busy, but indicate request done */
32 if(req->sem != NULL) {
33 up(req->sem);
37 /* We do our own retries because we want to know what the specific
38 error code is. Normally the UNIT_ATTENTION code will automatically
39 clear after one error */
41 intsr_do_ioctl(int target,unsigned char* sr_cmd,void* buffer,unsigned buflength)
43 Scsi_Cmnd * SCpnt;
44 int result;
46 SCpnt =allocate_device(NULL, scsi_CDs[target].device,1);
48 struct semaphore sem = MUTEX_LOCKED;
49 SCpnt->request.sem = &sem;
50 scsi_do_cmd(SCpnt,
51 (void*) sr_cmd, buffer, buflength, sr_ioctl_done,
52 IOCTL_TIMEOUT, IOCTL_RETRIES);
53 down(&sem);
56 result = SCpnt->result;
58 /* Minimal error checking. Ignore cases we know about, and report the rest. */
59 if(driver_byte(result) !=0)
60 switch(SCpnt->sense_buffer[2] &0xf) {
61 case UNIT_ATTENTION:
62 scsi_CDs[target].device->changed =1;
63 printk("Disc change detected.\n");
64 break;
65 case NOT_READY:/* This happens if there is no disc in drive */
66 printk(KERN_INFO "CDROM not ready. Make sure there is a disc in the drive.\n");
67 break;
68 case ILLEGAL_REQUEST:
69 printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");
70 break;
71 default:
72 print_sense("sr", SCpnt);
75 result = SCpnt->result;
76 SCpnt->request.rq_status = RQ_INACTIVE;/* Deallocate */
77 wake_up(&SCpnt->device->device_wait);
78 /* Wake up a process waiting for device*/
79 return result;
82 /* ---------------------------------------------------------------------- */
83 /* interface to cdrom.c */
85 intsr_tray_move(struct cdrom_device_info *cdi,int pos)
87 u_char sr_cmd[10];
89 sr_cmd[0] = START_STOP;
90 sr_cmd[1] = ((scsi_CDs[MINOR(cdi->dev)].device -> lun) <<5);
91 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] =0;
92 sr_cmd[4] = (pos ==0) ?0x03/* close */:0x02/* eject */;
94 returnsr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL,255);
97 intsr_lock_door(struct cdrom_device_info *cdi,int lock)
99 returnscsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
100 lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK,
104 intsr_drive_status(struct cdrom_device_info *cdi,int slot)
106 if(CDSL_CURRENT != slot) {
107 /* we have no changer support */
108 return-EINVAL;
111 if(!scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
112 SCSI_IOCTL_TEST_UNIT_READY,0))
113 return CDS_DISC_OK;
115 #if 1
116 /* Tell tray is open if the drive is not ready. Seems there is
117 * no way to check whenever the tray is really open, but this way
118 * we get auto-close-on-open work. And it seems to have no ill
119 * effects with caddy drives... */
120 return CDS_TRAY_OPEN;
121 #else
122 return CDS_NO_DISC;
123 #endif
126 intsr_disk_status(struct cdrom_device_info *cdi)
128 struct cdrom_tochdr toc_h;
129 struct cdrom_tocentry toc_e;
130 int i;
132 if(scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,SCSI_IOCTL_TEST_UNIT_READY,0))
133 return CDS_NO_DISC;
135 /* if the xa-bit is on, we tell it is XA... */
136 if(scsi_CDs[MINOR(cdi->dev)].xa_flag)
137 return CDS_XA_2_1;
139 /* ...else we look for data tracks */
140 if(sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h))
141 return CDS_NO_INFO;
142 for(i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
143 toc_e.cdte_track = i;
144 toc_e.cdte_format = CDROM_LBA;
145 if(sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e))
146 return CDS_NO_INFO;
147 if(toc_e.cdte_ctrl & CDROM_DATA_TRACK)
148 return CDS_DATA_1;
149 #if 0
150 if(i == toc_h.cdth_trk0 && toc_e.cdte_addr.lba >100)
151 /* guess: looks like a "hidden track" CD */
152 return CDS_DATA_1;
153 #endif
155 return CDS_AUDIO;
158 intsr_get_last_session(struct cdrom_device_info *cdi,
159 struct cdrom_multisession* ms_info)
161 ms_info->addr.lba=scsi_CDs[MINOR(cdi->dev)].ms_offset;
162 ms_info->xa_flag=scsi_CDs[MINOR(cdi->dev)].xa_flag ||
163 scsi_CDs[MINOR(cdi->dev)].ms_offset >0;
165 return0;
168 intsr_get_mcn(struct cdrom_device_info *cdi,struct cdrom_mcn *mcn)
170 u_char sr_cmd[10];
171 char* buffer;
172 int result;
174 sr_cmd[0] = SCMD_READ_SUBCHANNEL;
175 sr_cmd[1] = ((scsi_CDs[MINOR(cdi->dev)].device->lun) <<5);
176 sr_cmd[2] =0x40;/* I do want the subchannel info */
177 sr_cmd[3] =0x02;/* Give me medium catalog number info */
178 sr_cmd[4] = sr_cmd[5] =0;
179 sr_cmd[6] =0;
180 sr_cmd[7] =0;
181 sr_cmd[8] =24;
182 sr_cmd[9] =0;
184 buffer = (unsigned char*)scsi_malloc(512);
185 if(!buffer)return-ENOMEM;
187 result =sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer,24);
189 memcpy(mcn->medium_catalog_number, buffer +9,13);
190 mcn->medium_catalog_number[13] =0;
192 scsi_free(buffer,512);
194 return result;
197 intsr_reset(struct cdrom_device_info *cdi)
199 invalidate_buffers(cdi->dev);
200 return0;
203 /* ----------------------------------------------------------------------- */
204 /* this is called by the generic cdrom driver. arg is a _kernel_ pointer, */
205 /* becauce the generic cdrom driver does the user access stuff for us. */
207 intsr_audio_ioctl(struct cdrom_device_info *cdi,unsigned int cmd,void* arg)
209 u_char sr_cmd[10];
210 int result, target;
212 target =MINOR(cdi->dev);
214 switch(cmd)
216 /* Sun-compatible */
217 case CDROMPAUSE:
219 sr_cmd[0] = SCMD_PAUSE_RESUME;
220 sr_cmd[1] = scsi_CDs[target].device->lun <<5;
221 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] =0;
222 sr_cmd[5] = sr_cmd[6] = sr_cmd[7] =0;
223 sr_cmd[8] =0;
224 sr_cmd[9] =0;
226 result =sr_do_ioctl(target, sr_cmd, NULL,255);
227 break;
229 case CDROMRESUME:
231 sr_cmd[0] = SCMD_PAUSE_RESUME;
232 sr_cmd[1] = scsi_CDs[target].device->lun <<5;
233 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] =0;
234 sr_cmd[5] = sr_cmd[6] = sr_cmd[7] =0;
235 sr_cmd[8] =1;
236 sr_cmd[9] =0;
238 result =sr_do_ioctl(target, sr_cmd, NULL,255);
239 break;
241 case CDROMPLAYMSF:
243 struct cdrom_msf* msf = (struct cdrom_msf*)arg;
245 sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
246 sr_cmd[1] = scsi_CDs[target].device->lun <<5;
247 sr_cmd[2] =0;
248 sr_cmd[3] = msf->cdmsf_min0;
249 sr_cmd[4] = msf->cdmsf_sec0;
250 sr_cmd[5] = msf->cdmsf_frame0;
251 sr_cmd[6] = msf->cdmsf_min1;
252 sr_cmd[7] = msf->cdmsf_sec1;
253 sr_cmd[8] = msf->cdmsf_frame1;
254 sr_cmd[9] =0;
256 result =sr_do_ioctl(target, sr_cmd, NULL,255);
257 break;
260 case CDROMPLAYBLK:
262 struct cdrom_blk* blk = (struct cdrom_blk*)arg;
264 sr_cmd[0] = SCMD_PLAYAUDIO10;
265 sr_cmd[1] = scsi_CDs[target].device->lun <<5;
266 sr_cmd[2] = blk->from >>24;
267 sr_cmd[3] = blk->from >>16;
268 sr_cmd[4] = blk->from >>8;
269 sr_cmd[5] = blk->from;
270 sr_cmd[6] =0;
271 sr_cmd[7] = blk->len >>8;
272 sr_cmd[8] = blk->len;
273 sr_cmd[9] =0;
275 result =sr_do_ioctl(target, sr_cmd, NULL,255);
276 break;
279 case CDROMPLAYTRKIND:
281 struct cdrom_ti* ti = (struct cdrom_ti*)arg;
283 sr_cmd[0] = SCMD_PLAYAUDIO_TI;
284 sr_cmd[1] = scsi_CDs[target].device->lun <<5;
285 sr_cmd[2] =0;
286 sr_cmd[3] =0;
287 sr_cmd[4] = ti->cdti_trk0;
288 sr_cmd[5] = ti->cdti_ind0;
289 sr_cmd[6] =0;
290 sr_cmd[7] = ti->cdti_trk1;
291 sr_cmd[8] = ti->cdti_ind1;
292 sr_cmd[9] =0;
294 result =sr_do_ioctl(target, sr_cmd, NULL,255);
295 break;
298 case CDROMREADTOCHDR:
300 struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
301 char* buffer;
303 sr_cmd[0] = SCMD_READ_TOC;
304 sr_cmd[1] = ((scsi_CDs[target].device->lun) <<5);
305 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] =0;
306 sr_cmd[6] =0;
307 sr_cmd[7] =0;/* MSB of length (12) */
308 sr_cmd[8] =12;/* LSB of length */
309 sr_cmd[9] =0;
311 buffer = (unsigned char*)scsi_malloc(512);
312 if(!buffer)return-ENOMEM;
314 result =sr_do_ioctl(target, sr_cmd, buffer,12);
316 tochdr->cdth_trk0 = buffer[2];
317 tochdr->cdth_trk1 = buffer[3];
319 scsi_free(buffer,512);
320 break;
323 case CDROMREADTOCENTRY:
325 struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
326 unsigned char* buffer;
328 sr_cmd[0] = SCMD_READ_TOC;
329 sr_cmd[1] = ((scsi_CDs[target].device->lun) <<5) |
330 (tocentry->cdte_format == CDROM_MSF ?0x02:0);
331 sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] =0;
332 sr_cmd[6] = tocentry->cdte_track;
333 sr_cmd[7] =0;/* MSB of length (12) */
334 sr_cmd[8] =12;/* LSB of length */
335 sr_cmd[9] =0;
337 buffer = (unsigned char*)scsi_malloc(512);
338 if(!buffer)return-ENOMEM;
340 result =sr_do_ioctl(target, sr_cmd, buffer,12);
342 tocentry->cdte_ctrl = buffer[5] &0xf;
343 tocentry->cdte_adr = buffer[5] >>4;
344 tocentry->cdte_datamode = (tocentry->cdte_ctrl &0x04) ?1:0;
345 if(tocentry->cdte_format == CDROM_MSF) {
346 tocentry->cdte_addr.msf.minute = buffer[9];
347 tocentry->cdte_addr.msf.second = buffer[10];
348 tocentry->cdte_addr.msf.frame = buffer[11];
349 }else
350 tocentry->cdte_addr.lba = (((((buffer[8] <<8) + buffer[9]) <<8)
351 + buffer[10]) <<8) + buffer[11];
353 scsi_free(buffer,512);
354 break;
357 case CDROMSTOP:
358 sr_cmd[0] = START_STOP;
359 sr_cmd[1] = ((scsi_CDs[target].device->lun) <<5) |1;
360 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] =0;
361 sr_cmd[4] =0;
363 result =sr_do_ioctl(target, sr_cmd, NULL,255);
364 break;
366 case CDROMSTART:
367 sr_cmd[0] = START_STOP;
368 sr_cmd[1] = ((scsi_CDs[target].device->lun) <<5) |1;
369 sr_cmd[2] = sr_cmd[3] = sr_cmd[5] =0;
370 sr_cmd[4] =1;
372 result =sr_do_ioctl(target, sr_cmd, NULL,255);
373 break;
375 case CDROMVOLCTRL:
377 char* buffer, * mask;
378 struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
380 /* First we get the current params so we can just twiddle the volume */
382 sr_cmd[0] = MODE_SENSE;
383 sr_cmd[1] = (scsi_CDs[target].device -> lun) <<5;
384 sr_cmd[2] =0xe;/* Want mode page 0xe, CDROM audio params */
385 sr_cmd[3] =0;
386 sr_cmd[4] =28;
387 sr_cmd[5] =0;
389 buffer = (unsigned char*)scsi_malloc(512);
390 if(!buffer)return-ENOMEM;
392 if((result =sr_do_ioctl(target, sr_cmd, buffer,28))) {
393 printk("Hosed while obtaining audio mode page\n");
394 scsi_free(buffer,512);
395 break;
398 sr_cmd[0] = MODE_SENSE;
399 sr_cmd[1] = (scsi_CDs[target].device -> lun) <<5;
400 sr_cmd[2] =0x4e;/* Want the mask for mode page 0xe */
401 sr_cmd[3] =0;
402 sr_cmd[4] =28;
403 sr_cmd[5] =0;
405 mask = (unsigned char*)scsi_malloc(512);
406 if(!mask) {
407 scsi_free(buffer,512);
408 result = -ENOMEM;
409 break;
412 if((result =sr_do_ioctl(target, sr_cmd, mask,28))) {
413 printk("Hosed while obtaining mask for audio mode page\n");
414 scsi_free(buffer,512);
415 scsi_free(mask,512);
416 break;
419 /* Now mask and substitute our own volume and reuse the rest */
420 buffer[0] =0;/* Clear reserved field */
422 buffer[21] = volctrl->channel0 & mask[21];
423 buffer[23] = volctrl->channel1 & mask[23];
424 buffer[25] = volctrl->channel2 & mask[25];
425 buffer[27] = volctrl->channel3 & mask[27];
427 sr_cmd[0] = MODE_SELECT;
428 sr_cmd[1] = ((scsi_CDs[target].device -> lun) <<5) |0x10;/* Params are SCSI-2 */
429 sr_cmd[2] = sr_cmd[3] =0;
430 sr_cmd[4] =28;
431 sr_cmd[5] =0;
433 result =sr_do_ioctl(target, sr_cmd, buffer,28);
434 scsi_free(buffer,512);
435 scsi_free(mask,512);
436 break;
439 case CDROMVOLREAD:
441 char* buffer;
442 struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
444 /* Get the current params */
446 sr_cmd[0] = MODE_SENSE;
447 sr_cmd[1] = (scsi_CDs[target].device -> lun) <<5;
448 sr_cmd[2] =0xe;/* Want mode page 0xe, CDROM audio params */
449 sr_cmd[3] =0;
450 sr_cmd[4] =28;
451 sr_cmd[5] =0;
453 buffer = (unsigned char*)scsi_malloc(512);
454 if(!buffer)return-ENOMEM;
456 if((result =sr_do_ioctl(target, sr_cmd, buffer,28))) {
457 printk("(CDROMVOLREAD) Hosed while obtaining audio mode page\n");
458 scsi_free(buffer,512);
459 break;
462 volctrl->channel0 = buffer[21];
463 volctrl->channel1 = buffer[23];
464 volctrl->channel2 = buffer[25];
465 volctrl->channel3 = buffer[27];
467 scsi_free(buffer,512);
468 break;
471 case CDROMSUBCHNL:
473 struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
474 char* buffer;
476 sr_cmd[0] = SCMD_READ_SUBCHANNEL;
477 sr_cmd[1] = ((scsi_CDs[target].device->lun) <<5) |0x02;/* MSF format */
478 sr_cmd[2] =0x40;/* I do want the subchannel info */
479 sr_cmd[3] =0x01;/* Give me current position info */
480 sr_cmd[4] = sr_cmd[5] =0;
481 sr_cmd[6] =0;
482 sr_cmd[7] =0;
483 sr_cmd[8] =16;
484 sr_cmd[9] =0;
486 buffer = (unsigned char*)scsi_malloc(512);
487 if(!buffer)return-ENOMEM;
489 result =sr_do_ioctl(target, sr_cmd, buffer,16);
491 subchnl->cdsc_audiostatus = buffer[1];
492 subchnl->cdsc_format = CDROM_MSF;
493 subchnl->cdsc_ctrl = buffer[5] &0xf;
494 subchnl->cdsc_trk = buffer[6];
495 subchnl->cdsc_ind = buffer[7];
497 subchnl->cdsc_reladdr.msf.minute = buffer[13];
498 subchnl->cdsc_reladdr.msf.second = buffer[14];
499 subchnl->cdsc_reladdr.msf.frame = buffer[15];
500 subchnl->cdsc_absaddr.msf.minute = buffer[9];
501 subchnl->cdsc_absaddr.msf.second = buffer[10];
502 subchnl->cdsc_absaddr.msf.frame = buffer[11];
504 scsi_free(buffer,512);
505 break;
507 default:
508 return-EINVAL;
511 #if 0
512 if(result)
513 printk("DEBUG: sr_audio: result for ioctl %x: %x\n",cmd,result);
514 #endif
516 return result;
519 intsr_dev_ioctl(struct cdrom_device_info *cdi,
520 unsigned int cmd,unsigned long arg)
522 int target, err;
524 target =MINOR(cdi->dev);
526 switch(cmd) {
527 /* these are compatible with the ide-cd driver */
528 case CDROMREADRAW:
529 case CDROMREADMODE1:
530 case CDROMREADMODE2:
532 #if CONFIG_BLK_DEV_SR_VENDOR
534 unsigned char*raw;
535 struct cdrom_msf msf;
536 int blocksize, lba, rc;
538 if(cmd == CDROMREADMODE1)
539 blocksize = CD_FRAMESIZE;/* 2048 */
540 else if(cmd == CDROMREADMODE2)
541 blocksize = CD_FRAMESIZE_RAW0;/* 2336 */
542 else
543 /* some SCSI drives do not allow this one */
544 blocksize = CD_FRAMESIZE_RAW;/* 2352 */
546 if(copy_from_user(&msf,(void*)arg,sizeof(msf)))
547 return-EFAULT;
548 if(!(raw =scsi_malloc(2048+512)))
549 return-ENOMEM;
551 lba = (((msf.cdmsf_min0 * CD_SECS) + msf.cdmsf_sec0)
552 * CD_FRAMES + msf.cdmsf_frame0) - CD_BLOCK_OFFSET;
553 rc =sr_read_sector(target, lba, blocksize, raw);
554 if(!rc)
555 if(copy_to_user((void*)arg, raw, blocksize))
556 rc = -EFAULT;
558 scsi_free(raw,2048+512);
559 return rc;
561 #else
562 return-EINVAL;
563 #endif
566 case BLKRAGET:
567 if(!arg)
568 return-EINVAL;
569 err =verify_area(VERIFY_WRITE, (long*) arg,sizeof(long));
570 if(err)
571 return err;
572 put_user(read_ahead[MAJOR(cdi->dev)], (long*) arg);
573 return0;
575 case BLKRASET:
576 if(!suser())
577 return-EACCES;
578 if(!(cdi->dev))
579 return-EINVAL;
580 if(arg >0xff)
581 return-EINVAL;
582 read_ahead[MAJOR(cdi->dev)] = arg;
583 return0;
585 RO_IOCTLS(cdi->dev,arg);
587 default:
588 returnscsi_ioctl(scsi_CDs[target].device,cmd,(void*) arg);
593 * Overrides for Emacs so that we follow Linus's tabbing style.
594 * Emacs will notice this stuff at the end of the file and automatically
595 * adjust the settings for this buffer only. This must remain at the end
596 * of the file.
597 * ---------------------------------------------------------------------------
598 * Local variables:
599 * c-indent-level: 4
600 * c-brace-imaginary-offset: 0
601 * c-brace-offset: -4
602 * c-argdecl-indent: 4
603 * c-label-offset: -4
604 * c-continued-statement-offset: 4
605 * c-continued-brace-offset: 0
606 * indent-tabs-mode: nil
607 * tab-width: 8
608 * End:
close