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