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