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