]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/ide/ide-cd_ioctl.c
tegra: Make tegra_vi01_device accessible
[linux-2.6.git] / drivers / ide / ide-cd_ioctl.c
1 /*
2  * cdrom.c IOCTLs handling for ide-cd driver.
3  *
4  * Copyright (C) 1994-1996  Scott Snyder <snyder@fnald0.fnal.gov>
5  * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
6  * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/cdrom.h>
11 #include <linux/gfp.h>
12 #include <linux/ide.h>
13 #include <scsi/scsi.h>
14
15 #include "ide-cd.h"
16
17 /****************************************************************************
18  * Other driver requests (open, close, check media change).
19  */
20 int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
21 {
22         return 0;
23 }
24
25 /*
26  * Close down the device.  Invalidate all cached blocks.
27  */
28 void ide_cdrom_release_real(struct cdrom_device_info *cdi)
29 {
30         ide_drive_t *drive = cdi->handle;
31
32         if (!cdi->use_count)
33                 drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
34 }
35
36 /*
37  * add logic to try GET_EVENT command first to check for media and tray
38  * status. this should be supported by newer cd-r/w and all DVD etc
39  * drives
40  */
41 int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr)
42 {
43         ide_drive_t *drive = cdi->handle;
44         struct media_event_desc med;
45         struct request_sense sense;
46         int stat;
47
48         if (slot_nr != CDSL_CURRENT)
49                 return -EINVAL;
50
51         stat = cdrom_check_status(drive, &sense);
52         if (!stat || sense.sense_key == UNIT_ATTENTION)
53                 return CDS_DISC_OK;
54
55         if (!cdrom_get_media_event(cdi, &med)) {
56                 if (med.media_present)
57                         return CDS_DISC_OK;
58                 else if (med.door_open)
59                         return CDS_TRAY_OPEN;
60                 else
61                         return CDS_NO_DISC;
62         }
63
64         if (sense.sense_key == NOT_READY && sense.asc == 0x04
65                         && sense.ascq == 0x04)
66                 return CDS_DISC_OK;
67
68         /*
69          * If not using Mt Fuji extended media tray reports,
70          * just return TRAY_OPEN since ATAPI doesn't provide
71          * any other way to detect this...
72          */
73         if (sense.sense_key == NOT_READY) {
74                 if (sense.asc == 0x3a && sense.ascq == 1)
75                         return CDS_NO_DISC;
76                 else
77                         return CDS_TRAY_OPEN;
78         }
79         return CDS_DRIVE_NOT_READY;
80 }
81
82 /*
83  * ide-cd always generates media changed event if media is missing, which
84  * makes it impossible to use for proper event reporting, so disk->events
85  * is cleared to 0 and the following function is used only to trigger
86  * revalidation and never propagated to userland.
87  */
88 unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *cdi,
89                                          unsigned int clearing, int slot_nr)
90 {
91         ide_drive_t *drive = cdi->handle;
92         int retval;
93
94         if (slot_nr == CDSL_CURRENT) {
95                 (void) cdrom_check_status(drive, NULL);
96                 retval = (drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED) ? 1 : 0;
97                 drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
98                 return retval ? DISK_EVENT_MEDIA_CHANGE : 0;
99         } else {
100                 return 0;
101         }
102 }
103
104 /* Eject the disk if EJECTFLAG is 0.
105    If EJECTFLAG is 1, try to reload the disk. */
106 static
107 int cdrom_eject(ide_drive_t *drive, int ejectflag,
108                 struct request_sense *sense)
109 {
110         struct cdrom_info *cd = drive->driver_data;
111         struct cdrom_device_info *cdi = &cd->devinfo;
112         char loej = 0x02;
113         unsigned char cmd[BLK_MAX_CDB];
114
115         if ((drive->atapi_flags & IDE_AFLAG_NO_EJECT) && !ejectflag)
116                 return -EDRIVE_CANT_DO_THIS;
117
118         /* reload fails on some drives, if the tray is locked */
119         if ((drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED) && ejectflag)
120                 return 0;
121
122         /* only tell drive to close tray if open, if it can do that */
123         if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY))
124                 loej = 0;
125
126         memset(cmd, 0, BLK_MAX_CDB);
127
128         cmd[0] = GPCMD_START_STOP_UNIT;
129         cmd[4] = loej | (ejectflag != 0);
130
131         return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, 0);
132 }
133
134 /* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
135 static
136 int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
137                     struct request_sense *sense)
138 {
139         struct request_sense my_sense;
140         int stat;
141
142         if (sense == NULL)
143                 sense = &my_sense;
144
145         /* If the drive cannot lock the door, just pretend. */
146         if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) {
147                 stat = 0;
148         } else {
149                 unsigned char cmd[BLK_MAX_CDB];
150
151                 memset(cmd, 0, BLK_MAX_CDB);
152
153                 cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
154                 cmd[4] = lockflag ? 1 : 0;
155
156                 stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL,
157                                        sense, 0, 0);
158         }
159
160         /* If we got an illegal field error, the drive
161            probably cannot lock the door. */
162         if (stat != 0 &&
163             sense->sense_key == ILLEGAL_REQUEST &&
164             (sense->asc == 0x24 || sense->asc == 0x20)) {
165                 printk(KERN_ERR "%s: door locking not supported\n",
166                         drive->name);
167                 drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
168                 stat = 0;
169         }
170
171         /* no medium, that's alright. */
172         if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
173                 stat = 0;
174
175         if (stat == 0) {
176                 if (lockflag)
177                         drive->atapi_flags |= IDE_AFLAG_DOOR_LOCKED;
178                 else
179                         drive->atapi_flags &= ~IDE_AFLAG_DOOR_LOCKED;
180         }
181
182         return stat;
183 }
184
185 int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position)
186 {
187         ide_drive_t *drive = cdi->handle;
188         struct request_sense sense;
189
190         if (position) {
191                 int stat = ide_cd_lockdoor(drive, 0, &sense);
192
193                 if (stat)
194                         return stat;
195         }
196
197         return cdrom_eject(drive, !position, &sense);
198 }
199
200 int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock)
201 {
202         ide_drive_t *drive = cdi->handle;
203
204         return ide_cd_lockdoor(drive, lock, NULL);
205 }
206
207 /*
208  * ATAPI devices are free to select the speed you request or any slower
209  * rate. :-(  Requesting too fast a speed will _not_ produce an error.
210  */
211 int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
212 {
213         ide_drive_t *drive = cdi->handle;
214         struct cdrom_info *cd = drive->driver_data;
215         struct request_sense sense;
216         u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
217         int stat;
218         unsigned char cmd[BLK_MAX_CDB];
219
220         if (speed == 0)
221                 speed = 0xffff; /* set to max */
222         else
223                 speed *= 177;   /* Nx to kbytes/s */
224
225         memset(cmd, 0, BLK_MAX_CDB);
226
227         cmd[0] = GPCMD_SET_SPEED;
228         /* Read Drive speed in kbytes/second MSB/LSB */
229         cmd[2] = (speed >> 8) & 0xff;
230         cmd[3] = speed & 0xff;
231         if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
232             (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
233                 /* Write Drive speed in kbytes/second MSB/LSB */
234                 cmd[4] = (speed >> 8) & 0xff;
235                 cmd[5] = speed & 0xff;
236         }
237
238         stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
239
240         if (!ide_cdrom_get_capabilities(drive, buf)) {
241                 ide_cdrom_update_speed(drive, buf);
242                 cdi->speed = cd->current_speed;
243         }
244
245         return 0;
246 }
247
248 int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
249                                struct cdrom_multisession *ms_info)
250 {
251         struct atapi_toc *toc;
252         ide_drive_t *drive = cdi->handle;
253         struct cdrom_info *info = drive->driver_data;
254         struct request_sense sense;
255         int ret;
256
257         if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0 || !info->toc) {
258                 ret = ide_cd_read_toc(drive, &sense);
259                 if (ret)
260                         return ret;
261         }
262
263         toc = info->toc;
264         ms_info->addr.lba = toc->last_session_lba;
265         ms_info->xa_flag = toc->xa_flag;
266
267         return 0;
268 }
269
270 int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
271                       struct cdrom_mcn *mcn_info)
272 {
273         ide_drive_t *drive = cdi->handle;
274         int stat, mcnlen;
275         char buf[24];
276         unsigned char cmd[BLK_MAX_CDB];
277         unsigned len = sizeof(buf);
278
279         memset(cmd, 0, BLK_MAX_CDB);
280
281         cmd[0] = GPCMD_READ_SUBCHANNEL;
282         cmd[1] = 2;             /* MSF addressing */
283         cmd[2] = 0x40;  /* request subQ data */
284         cmd[3] = 2;             /* format */
285         cmd[8] = len;
286
287         stat = ide_cd_queue_pc(drive, cmd, 0, buf, &len, NULL, 0, 0);
288         if (stat)
289                 return stat;
290
291         mcnlen = sizeof(mcn_info->medium_catalog_number) - 1;
292         memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen);
293         mcn_info->medium_catalog_number[mcnlen] = '\0';
294
295         return 0;
296 }
297
298 int ide_cdrom_reset(struct cdrom_device_info *cdi)
299 {
300         ide_drive_t *drive = cdi->handle;
301         struct cdrom_info *cd = drive->driver_data;
302         struct request_sense sense;
303         struct request *rq;
304         int ret;
305
306         rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
307         rq->cmd_type = REQ_TYPE_SPECIAL;
308         rq->cmd_flags = REQ_QUIET;
309         ret = blk_execute_rq(drive->queue, cd->disk, rq, 0);
310         blk_put_request(rq);
311         /*
312          * A reset will unlock the door. If it was previously locked,
313          * lock it again.
314          */
315         if (drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED)
316                 (void)ide_cd_lockdoor(drive, 1, &sense);
317
318         return ret;
319 }
320
321 static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
322                                 struct atapi_toc_entry **ent)
323 {
324         struct cdrom_info *info = drive->driver_data;
325         struct atapi_toc *toc = info->toc;
326         int ntracks;
327
328         /*
329          * don't serve cached data, if the toc isn't valid
330          */
331         if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0)
332                 return -EINVAL;
333
334         /* Check validity of requested track number. */
335         ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
336
337         if (toc->hdr.first_track == CDROM_LEADOUT)
338                 ntracks = 0;
339
340         if (track == CDROM_LEADOUT)
341                 *ent = &toc->ent[ntracks];
342         else if (track < toc->hdr.first_track || track > toc->hdr.last_track)
343                 return -EINVAL;
344         else
345                 *ent = &toc->ent[track - toc->hdr.first_track];
346
347         return 0;
348 }
349
350 static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
351 {
352         struct cdrom_ti *ti = arg;
353         struct atapi_toc_entry *first_toc, *last_toc;
354         unsigned long lba_start, lba_end;
355         int stat;
356         struct request_sense sense;
357         unsigned char cmd[BLK_MAX_CDB];
358
359         stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
360         if (stat)
361                 return stat;
362
363         stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
364         if (stat)
365                 return stat;
366
367         if (ti->cdti_trk1 != CDROM_LEADOUT)
368                 ++last_toc;
369         lba_start = first_toc->addr.lba;
370         lba_end   = last_toc->addr.lba;
371
372         if (lba_end <= lba_start)
373                 return -EINVAL;
374
375         memset(cmd, 0, BLK_MAX_CDB);
376
377         cmd[0] = GPCMD_PLAY_AUDIO_MSF;
378         lba_to_msf(lba_start,   &cmd[3], &cmd[4], &cmd[5]);
379         lba_to_msf(lba_end - 1, &cmd[6], &cmd[7], &cmd[8]);
380
381         return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
382 }
383
384 static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
385 {
386         struct cdrom_info *cd = drive->driver_data;
387         struct cdrom_tochdr *tochdr = arg;
388         struct atapi_toc *toc;
389         int stat;
390
391         /* Make sure our saved TOC is valid. */
392         stat = ide_cd_read_toc(drive, NULL);
393         if (stat)
394                 return stat;
395
396         toc = cd->toc;
397         tochdr->cdth_trk0 = toc->hdr.first_track;
398         tochdr->cdth_trk1 = toc->hdr.last_track;
399
400         return 0;
401 }
402
403 static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg)
404 {
405         struct cdrom_tocentry *tocentry = arg;
406         struct atapi_toc_entry *toce;
407         int stat;
408
409         stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce);
410         if (stat)
411                 return stat;
412
413         tocentry->cdte_ctrl = toce->control;
414         tocentry->cdte_adr  = toce->adr;
415         if (tocentry->cdte_format == CDROM_MSF) {
416                 lba_to_msf(toce->addr.lba,
417                            &tocentry->cdte_addr.msf.minute,
418                            &tocentry->cdte_addr.msf.second,
419                            &tocentry->cdte_addr.msf.frame);
420         } else
421                 tocentry->cdte_addr.lba = toce->addr.lba;
422
423         return 0;
424 }
425
426 int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
427                           unsigned int cmd, void *arg)
428 {
429         ide_drive_t *drive = cdi->handle;
430
431         switch (cmd) {
432         /*
433          * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
434          * atapi doesn't support it
435          */
436         case CDROMPLAYTRKIND:
437                 return ide_cd_fake_play_trkind(drive, arg);
438         case CDROMREADTOCHDR:
439                 return ide_cd_read_tochdr(drive, arg);
440         case CDROMREADTOCENTRY:
441                 return ide_cd_read_tocentry(drive, arg);
442         default:
443                 return -EINVAL;
444         }
445 }
446
447 /* the generic packet interface to cdrom.c */
448 int ide_cdrom_packet(struct cdrom_device_info *cdi,
449                             struct packet_command *cgc)
450 {
451         ide_drive_t *drive = cdi->handle;
452         unsigned int flags = 0;
453         unsigned len = cgc->buflen;
454
455         if (cgc->timeout <= 0)
456                 cgc->timeout = ATAPI_WAIT_PC;
457
458         /* here we queue the commands from the uniform CD-ROM
459            layer. the packet must be complete, as we do not
460            touch it at all. */
461
462         if (cgc->data_direction == CGC_DATA_WRITE)
463                 flags |= REQ_WRITE;
464
465         if (cgc->sense)
466                 memset(cgc->sense, 0, sizeof(struct request_sense));
467
468         if (cgc->quiet)
469                 flags |= REQ_QUIET;
470
471         cgc->stat = ide_cd_queue_pc(drive, cgc->cmd,
472                                     cgc->data_direction == CGC_DATA_WRITE,
473                                     cgc->buffer, &len,
474                                     cgc->sense, cgc->timeout, flags);
475         if (!cgc->stat)
476                 cgc->buflen -= len;
477         return cgc->stat;
478 }