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