linux/drivers/scsi/sr_vendor.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* -*-linux-c-*-
   3
   4 * vendor-specific code for SCSI CD-ROM's goes here.
   5 *
   6 * This is needed becauce most of the new features (multisession and
   7 * the like) are too new to be included into the SCSI-II standard (to
   8 * be exact: there is'nt anything in my draft copy).
   9 *
  10 * Aug 1997: Ha! Got a SCSI-3 cdrom spec across my fingers. SCSI-3 does
  11 *           multisession using the READ TOC command (like SONY).
  12 *
  13 *           Rearranged stuff here: SCSI-3 is included allways, support
  14 *           for NEC/TOSHIBA/HP commands is optional.
  15 *
  16 *   Gerd Knorr <kraxel@cs.tu-berlin.de> 
  17 *
  18 * --------------------------------------------------------------------------
  19 *
  20 * support for XA/multisession-CD's
  21 * 
  22 *   - NEC:     Detection and support of multisession CD's.
  23 *     
  24 *   - TOSHIBA: Detection and support of multisession CD's.
  25 *              Some XA-Sector tweaking, required for older drives.
  26 *
  27 *   - SONY:    Detection and support of multisession CD's.
  28 *              added by Thomas Quinot <thomas@cuivre.freenix.fr>
  29 *
  30 *   - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS: known to
  31 *              work with SONY (SCSI3 now)  code.
  32 *
  33 *   - HP:      Much like SONY, but a little different... (Thomas)
  34 *              HP-Writers only ??? Maybe other CD-Writers work with this too ?
  35 *              HP 6020 writers now supported.
  36 */
  37
  38#include <linux/cdrom.h>
  39#include <linux/errno.h>
  40#include <linux/string.h>
  41#include <linux/bcd.h>
  42#include <linux/blkdev.h>
  43#include <linux/slab.h>
  44
  45#include <scsi/scsi.h>
  46#include <scsi/scsi_cmnd.h>
  47#include <scsi/scsi_device.h>
  48#include <scsi/scsi_host.h>
  49#include <scsi/scsi_ioctl.h>
  50
  51#include "sr.h"
  52
  53#if 0
  54#define DEBUG
  55#endif
  56
  57/* here are some constants to sort the vendors into groups */
  58
  59#define VENDOR_SCSI3           1        /* default: scsi-3 mmc */
  60
  61#define VENDOR_NEC             2
  62#define VENDOR_TOSHIBA         3
  63#define VENDOR_WRITER          4        /* pre-scsi3 writers */
  64#define VENDOR_CYGNAL_85ED     5        /* CD-on-a-chip */
  65
  66#define VENDOR_TIMEOUT  30*HZ
  67
  68void sr_vendor_init(Scsi_CD *cd)
  69{
  70        const char *vendor = cd->device->vendor;
  71        const char *model = cd->device->model;
  72        
  73        /* default */
  74        cd->vendor = VENDOR_SCSI3;
  75        if (cd->readcd_known)
  76                /* this is true for scsi3/mmc drives - no more checks */
  77                return;
  78
  79        if (cd->device->type == TYPE_WORM) {
  80                cd->vendor = VENDOR_WRITER;
  81
  82        } else if (!strncmp(vendor, "NEC", 3)) {
  83                cd->vendor = VENDOR_NEC;
  84                if (!strncmp(model, "CD-ROM DRIVE:25", 15) ||
  85                    !strncmp(model, "CD-ROM DRIVE:36", 15) ||
  86                    !strncmp(model, "CD-ROM DRIVE:83", 15) ||
  87                    !strncmp(model, "CD-ROM DRIVE:84 ", 16)
  88#if 0
  89                /* my NEC 3x returns the read-raw data if a read-raw
  90                   is followed by a read for the same sector - aeb */
  91                    || !strncmp(model, "CD-ROM DRIVE:500", 16)
  92#endif
  93                    )
  94                        /* these can't handle multisession, may hang */
  95                        cd->cdi.mask |= CDC_MULTI_SESSION;
  96
  97        } else if (!strncmp(vendor, "TOSHIBA", 7)) {
  98                cd->vendor = VENDOR_TOSHIBA;
  99
 100        } else if (!strncmp(vendor, "Beurer", 6) &&
 101                   !strncmp(model, "Gluco Memory", 12)) {
 102                /* The Beurer GL50 evo uses a Cygnal-manufactured CD-on-a-chip
 103                   that only accepts a subset of SCSI commands.  Most of the
 104                   not-implemented commands are fine to fail, but a few,
 105                   particularly around the MMC or Audio commands, will put the
 106                   device into an unrecoverable state, so they need to be
 107                   avoided at all costs.
 108                */
 109                cd->vendor = VENDOR_CYGNAL_85ED;
 110                cd->cdi.mask |= (
 111                        CDC_MULTI_SESSION |
 112                        CDC_CLOSE_TRAY | CDC_OPEN_TRAY |
 113                        CDC_LOCK |
 114                        CDC_GENERIC_PACKET |
 115                        CDC_PLAY_AUDIO
 116                        );
 117        }
 118}
 119
 120
 121/* small handy function for switching block length using MODE SELECT,
 122 * used by sr_read_sector() */
 123
 124int sr_set_blocklength(Scsi_CD *cd, int blocklength)
 125{
 126        unsigned char *buffer;  /* the buffer for the ioctl */
 127        struct packet_command cgc;
 128        struct ccs_modesel_head *modesel;
 129        int rc, density = 0;
 130
 131        if (cd->vendor == VENDOR_TOSHIBA)
 132                density = (blocklength > 2048) ? 0x81 : 0x83;
 133
 134        buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 135        if (!buffer)
 136                return -ENOMEM;
 137
 138#ifdef DEBUG
 139        sr_printk(KERN_INFO, cd, "MODE SELECT 0x%x/%d\n", density, blocklength);
 140#endif
 141        memset(&cgc, 0, sizeof(struct packet_command));
 142        cgc.cmd[0] = MODE_SELECT;
 143        cgc.cmd[1] = (1 << 4);
 144        cgc.cmd[4] = 12;
 145        modesel = (struct ccs_modesel_head *) buffer;
 146        memset(modesel, 0, sizeof(*modesel));
 147        modesel->block_desc_length = 0x08;
 148        modesel->density = density;
 149        modesel->block_length_med = (blocklength >> 8) & 0xff;
 150        modesel->block_length_lo = blocklength & 0xff;
 151        cgc.buffer = buffer;
 152        cgc.buflen = sizeof(*modesel);
 153        cgc.data_direction = DMA_TO_DEVICE;
 154        cgc.timeout = VENDOR_TIMEOUT;
 155        if (0 == (rc = sr_do_ioctl(cd, &cgc))) {
 156                cd->device->sector_size = blocklength;
 157        }
 158#ifdef DEBUG
 159        else
 160                sr_printk(KERN_INFO, cd,
 161                          "switching blocklength to %d bytes failed\n",
 162                          blocklength);
 163#endif
 164        kfree(buffer);
 165        return rc;
 166}
 167
 168/* This function gets called after a media change. Checks if the CD is
 169   multisession, asks for offset etc. */
 170
 171int sr_cd_check(struct cdrom_device_info *cdi)
 172{
 173        Scsi_CD *cd = cdi->handle;
 174        unsigned long sector;
 175        unsigned char *buffer;  /* the buffer for the ioctl */
 176        struct packet_command cgc;
 177        int rc, no_multi;
 178
 179        if (cd->cdi.mask & CDC_MULTI_SESSION)
 180                return 0;
 181
 182        buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 183        if (!buffer)
 184                return -ENOMEM;
 185
 186        sector = 0;             /* the multisession sector offset goes here  */
 187        no_multi = 0;           /* flag: the drive can't handle multisession */
 188        rc = 0;
 189
 190        memset(&cgc, 0, sizeof(struct packet_command));
 191
 192        switch (cd->vendor) {
 193
 194        case VENDOR_SCSI3:
 195                cgc.cmd[0] = READ_TOC;
 196                cgc.cmd[8] = 12;
 197                cgc.cmd[9] = 0x40;
 198                cgc.buffer = buffer;
 199                cgc.buflen = 12;
 200                cgc.quiet = 1;
 201                cgc.data_direction = DMA_FROM_DEVICE;
 202                cgc.timeout = VENDOR_TIMEOUT;
 203                rc = sr_do_ioctl(cd, &cgc);
 204                if (rc != 0)
 205                        break;
 206                if ((buffer[0] << 8) + buffer[1] < 0x0a) {
 207                        sr_printk(KERN_INFO, cd, "Hmm, seems the drive "
 208                           "doesn't support multisession CD's\n");
 209                        no_multi = 1;
 210                        break;
 211                }
 212                sector = buffer[11] + (buffer[10] << 8) +
 213                    (buffer[9] << 16) + (buffer[8] << 24);
 214                if (buffer[6] <= 1) {
 215                        /* ignore sector offsets from first track */
 216                        sector = 0;
 217                }
 218                break;
 219
 220        case VENDOR_NEC:{
 221                        unsigned long min, sec, frame;
 222                        cgc.cmd[0] = 0xde;
 223                        cgc.cmd[1] = 0x03;
 224                        cgc.cmd[2] = 0xb0;
 225                        cgc.buffer = buffer;
 226                        cgc.buflen = 0x16;
 227                        cgc.quiet = 1;
 228                        cgc.data_direction = DMA_FROM_DEVICE;
 229                        cgc.timeout = VENDOR_TIMEOUT;
 230                        rc = sr_do_ioctl(cd, &cgc);
 231                        if (rc != 0)
 232                                break;
 233                        if (buffer[14] != 0 && buffer[14] != 0xb0) {
 234                                sr_printk(KERN_INFO, cd, "Hmm, seems the cdrom "
 235                                          "doesn't support multisession CD's\n");
 236
 237                                no_multi = 1;
 238                                break;
 239                        }
 240                        min = bcd2bin(buffer[15]);
 241                        sec = bcd2bin(buffer[16]);
 242                        frame = bcd2bin(buffer[17]);
 243                        sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
 244                        break;
 245                }
 246
 247        case VENDOR_TOSHIBA:{
 248                        unsigned long min, sec, frame;
 249
 250                        /* we request some disc information (is it a XA-CD ?,
 251                         * where starts the last session ?) */
 252                        cgc.cmd[0] = 0xc7;
 253                        cgc.cmd[1] = 0x03;
 254                        cgc.buffer = buffer;
 255                        cgc.buflen = 4;
 256                        cgc.quiet = 1;
 257                        cgc.data_direction = DMA_FROM_DEVICE;
 258                        cgc.timeout = VENDOR_TIMEOUT;
 259                        rc = sr_do_ioctl(cd, &cgc);
 260                        if (rc == -EINVAL) {
 261                                sr_printk(KERN_INFO, cd, "Hmm, seems the drive "
 262                                          "doesn't support multisession CD's\n");
 263                                no_multi = 1;
 264                                break;
 265                        }
 266                        if (rc != 0)
 267                                break;
 268                        min = bcd2bin(buffer[1]);
 269                        sec = bcd2bin(buffer[2]);
 270                        frame = bcd2bin(buffer[3]);
 271                        sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
 272                        if (sector)
 273                                sector -= CD_MSF_OFFSET;
 274                        sr_set_blocklength(cd, 2048);
 275                        break;
 276                }
 277
 278        case VENDOR_WRITER:
 279                cgc.cmd[0] = READ_TOC;
 280                cgc.cmd[8] = 0x04;
 281                cgc.cmd[9] = 0x40;
 282                cgc.buffer = buffer;
 283                cgc.buflen = 0x04;
 284                cgc.quiet = 1;
 285                cgc.data_direction = DMA_FROM_DEVICE;
 286                cgc.timeout = VENDOR_TIMEOUT;
 287                rc = sr_do_ioctl(cd, &cgc);
 288                if (rc != 0) {
 289                        break;
 290                }
 291                if ((rc = buffer[2]) == 0) {
 292                        sr_printk(KERN_WARNING, cd,
 293                                  "No finished session\n");
 294                        break;
 295                }
 296                cgc.cmd[0] = READ_TOC;  /* Read TOC */
 297                cgc.cmd[6] = rc & 0x7f; /* number of last session */
 298                cgc.cmd[8] = 0x0c;
 299                cgc.cmd[9] = 0x40;
 300                cgc.buffer = buffer;
 301                cgc.buflen = 12;
 302                cgc.quiet = 1;
 303                cgc.data_direction = DMA_FROM_DEVICE;
 304                cgc.timeout = VENDOR_TIMEOUT;
 305                rc = sr_do_ioctl(cd, &cgc);
 306                if (rc != 0) {
 307                        break;
 308                }
 309                sector = buffer[11] + (buffer[10] << 8) +
 310                    (buffer[9] << 16) + (buffer[8] << 24);
 311                break;
 312
 313        default:
 314                /* should not happen */
 315                sr_printk(KERN_WARNING, cd,
 316                          "unknown vendor code (%i), not initialized ?\n",
 317                          cd->vendor);
 318                sector = 0;
 319                no_multi = 1;
 320                break;
 321        }
 322        cd->ms_offset = sector;
 323        cd->xa_flag = 0;
 324        if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(cd))
 325                cd->xa_flag = 1;
 326
 327        if (2048 != cd->device->sector_size) {
 328                sr_set_blocklength(cd, 2048);
 329        }
 330        if (no_multi)
 331                cdi->mask |= CDC_MULTI_SESSION;
 332
 333#ifdef DEBUG
 334        if (sector)
 335                sr_printk(KERN_DEBUG, cd, "multisession offset=%lu\n",
 336                          sector);
 337#endif
 338        kfree(buffer);
 339        return rc;
 340}
 341