CDD2600.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:17k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998  Andreas Mueller <mueller@daneb.ping.de>
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19. /*
  20.  * $Log: CDD2600.cc,v $
  21.  * Revision 1.14  1999/04/05 11:04:10  mueller
  22.  * Added driver option flags.
  23.  *
  24.  * Revision 1.13  1999/03/27 20:52:02  mueller
  25.  * Adapted to changed writing interface.
  26.  *
  27.  * Revision 1.12  1998/10/24 14:30:40  mueller
  28.  * Changed prototype of 'readDiskToc()'.
  29.  *
  30.  * Revision 1.11  1998/10/03 15:11:05  mueller
  31.  * Moved basic writing methods to class 'CDD2600Base'.
  32.  *
  33.  * Revision 1.10  1998/09/27 19:17:46  mueller
  34.  * Fixed 'disc-info' for CDD2000.
  35.  * Added retrieval of control nibbles for track with 'analyzeTrack()'.
  36.  *
  37.  * Revision 1.9  1998/09/22 19:15:13  mueller
  38.  * Removed memory allocations during write process.
  39.  *
  40.  * Revision 1.8  1998/09/08 11:54:22  mueller
  41.  * Extended disk info structure because CDD2000 does not support the
  42.  * 'READ DISK INFO' command.
  43.  *
  44.  * Revision 1.7  1998/09/07 15:20:20  mueller
  45.  * Reorganized read-toc related code.
  46.  *
  47.  * Revision 1.6  1998/09/06 13:34:22  mueller
  48.  * Use 'message()' for printing messages.
  49.  *
  50.  * Revision 1.5  1998/08/25 19:23:46  mueller
  51.  * Added index extraction for 'read-toc'.
  52.  * Added disk info code.
  53.  *
  54.  * Revision 1.4  1998/08/07 12:44:30  mueller
  55.  * Changed group 1 mode select commands to group 0 mode select commands.
  56.  * Implement pre-gap detection in 'readDiscToc()'.
  57.  *
  58.  */
  59. static char rcsid[] = "$Id: CDD2600.cc,v 1.14 1999/04/05 11:04:10 mueller Exp mueller $";
  60. #include <config.h>
  61. #include <string.h>
  62. #include <assert.h>
  63. #include "CDD2600.h"
  64. #include "SubChannel.h"
  65. #include "PQSubChannel16.h"
  66. #include "Toc.h"
  67. #include "util.h"
  68. CDD2600::CDD2600(ScsiIf *scsiIf, unsigned long options)
  69.   : CdrDriver(scsiIf, options|OPT_DRV_NO_PREGAP_READ), CDD2600Base(this)
  70. {
  71.   driverName_ = "CDD2600 - Version 1.1";
  72.   
  73.   leadInLength_ = leadOutLength_ = 0;
  74.   speed_ = 2;
  75.   simulate_ = 1;
  76.   encodingMode_ = 0;
  77.   // reads big endian samples
  78.   audioDataByteOrder_ = 1;
  79.   memset(&diskInfo_, 0, sizeof(DiskInfo));
  80. }
  81. CDD2600::~CDD2600()
  82. {
  83. }
  84. // static constructor
  85. CdrDriver *CDD2600::instance(ScsiIf *scsiIf, unsigned long options)
  86. {
  87.   return new CDD2600(scsiIf, options);
  88. }
  89. // sets speed
  90. // return: 0: OK
  91. //         1: illegal speed
  92. int CDD2600::speed(int s)
  93. {
  94.   if (s >= 0 && s <= 2) {
  95.     speed_ = s;
  96.     return 0;
  97.   }
  98.   else if (s > 2) {
  99.     speed_ = 2;
  100.     return 0;
  101.   }
  102.   else {
  103.     return 1;
  104.   }
  105. }
  106. // loads ('unload' == 0) or ejects ('unload' == 1) tray
  107. // return: 0: OK
  108. //         1: scsi command failed
  109. int CDD2600::loadUnload(int unload) const
  110. {
  111.   unsigned char cmd[10];
  112.   memset(cmd, 0, 10);
  113.   cmd[0] = 0xe7; // MEDIUM LOAD/UNLOAD
  114.   if (unload) {
  115.     cmd[8] |= 0x01;
  116.   }
  117.   
  118.   if (sendCmd(cmd, 10, NULL, 0, NULL, 0) != 0) {
  119.     message(-2, "Cannot load/unload medium.");
  120.     return 1;
  121.   }
  122.   return 0;
  123. }
  124. // sets various audio play parameters, output channels are set to stereo mode
  125. // and given volume
  126. // immediate: 0: wait until audio play command finished
  127. //            1: command finishs immediately after playback has started
  128. // sotc:      0: play across track boundaries
  129. //            1: stop playing at track boundaries
  130. int CDD2600::modeSelectPlay(int immediate, int sotc, unsigned char volume)
  131. {
  132.   unsigned char mp[16];
  133.   memset(mp, 0, 16);
  134.   mp[0] = 0x0e; // PLAY page code
  135.   mp[1] = 14; // parameter length
  136.   if (immediate != 0) {
  137.     mp[2] |= 0x04;
  138.   }
  139.   if (sotc != 0) {
  140.     mp[2] |= 0x02;
  141.   }
  142.   mp[8]  = 1;
  143.   mp[9]  = volume;
  144.   mp[10] = 2;
  145.   mp[11] = volume;
  146.   if (setModePage(mp, NULL, NULL, 1) != 0) {
  147.     message(-2, "Cannot set play parameters.");
  148.     return 1;
  149.   }
  150.   return 0;
  151. }
  152. int CDD2600::initDao(const Toc *toc)
  153. {
  154.   long n;
  155.   blockLength_ = AUDIO_BLOCK_LEN;
  156.   blocksPerWrite_ = scsiIf_->maxDataLen() / blockLength_;
  157.   assert(blocksPerWrite_ > 0);
  158.   toc_ = toc;
  159.   if (modeSelectBlockSize(blockLength_, 1) != 0 ||
  160.       modeSelectSpeed(-1, speed_, simulate_, 1) != 0 ||
  161.       modeSelectCatalog(toc_) != 0 ||
  162.       readSessionInfo(&leadInLength_, &leadOutLength_, 1) != 0) {
  163.     return 1;
  164.   }
  165.   // allocate buffer for write zeros
  166.   n = blocksPerWrite_ * blockLength_;
  167.   delete[] zeroBuffer_;
  168.   zeroBuffer_ = new char[n];
  169.   memset(zeroBuffer_, 0, n);
  170.   return 0;
  171. }
  172. int CDD2600::startDao()
  173. {
  174.   long lba = -leadInLength_ - 150; // Value is not really important since the
  175.                                    // LBA is not used by 'writeData'.
  176.   if (writeSession(toc_, multiSession_) != 0) {
  177.     return 1;
  178.   }
  179.   message(1, "Writing lead-in and gap...");
  180.   // write lead-in
  181.   if (writeZeros(toc_->leadInMode(), lba, 0, leadInLength_) != 0) {
  182.     flushCache();
  183.     return 1;
  184.   }
  185.   // write gap (2 seconds)
  186.   if (writeZeros(toc_->leadInMode(), lba, 0, 150) != 0) {
  187.     flushCache();
  188.     return 1;
  189.   }
  190.   message(1, "");
  191.   return 0;
  192. }
  193. int CDD2600::finishDao()
  194. {
  195.   long lba = toc_->length().lba();
  196.   message(1, "Writing lead-out...");
  197.   // write lead-out
  198.   if (writeZeros(toc_->leadOutMode(), lba, lba + 150, leadOutLength_) != 0) {
  199.     flushCache();
  200.     return 1;
  201.   }
  202.   message(1, "nFlushing cache...");
  203.   
  204.   if (flushCache() != 0) {
  205.     return 1;
  206.   }
  207.   message(1, "");
  208.   delete[] zeroBuffer_, zeroBuffer_ = NULL;
  209.   return 0;
  210. }
  211. void CDD2600::abortDao()
  212. {
  213.   flushCache();
  214. }
  215. // Writes data to target, the block length depends on the actual writing mode
  216. // and is stored internally. 'len' is number of blocks to write.
  217. // 'lba' specifies the next logical block address for writing and is updated
  218. // by this function but not used for writing
  219. // return: 0: OK
  220. //         1: scsi command failed
  221. int CDD2600::writeData(TrackData::Mode mode, long &lba, const char *buf,
  222.        long len)
  223. {
  224.   assert(blocksPerWrite_ > 0);
  225.   assert(blockLength_ > 0);
  226.   assert(mode == TrackData::AUDIO);
  227.   int nwritten = 0;
  228.   int writeLen = 0;
  229.   unsigned char cmd[10];
  230.   memset(cmd, 0, 10);
  231.   cmd[0] = 0x2a; // WRITE1
  232.   
  233.   while (len > 0) {
  234.     writeLen = (len > blocksPerWrite_ ? blocksPerWrite_ : len);
  235.     cmd[7] = writeLen >> 8;
  236.     cmd[8] = writeLen & 0xff;
  237.     if (sendCmd(cmd, 10, (unsigned char *)(buf + (nwritten * blockLength_)),
  238. writeLen * blockLength_, NULL, 0) != 0) {
  239.       message(-2, "Write data failed.");
  240.       return 1;
  241.     }
  242.     lba += writeLen;
  243.     len -= writeLen;
  244.     nwritten += writeLen;
  245.   }
  246.       
  247.   return 0;
  248. }
  249. Toc *CDD2600::readDiskToc(int session, const char *audioFilename)
  250. {
  251.   blockLength_ = AUDIO_BLOCK_LEN;
  252.   if (modeSelectBlockSize(blockLength_, 1) != 0) {
  253.     return NULL;
  254.   }
  255.   modeSelectSpeed(2, -1, 1, 0);
  256.   Toc *toc = CdrDriver::readDiskToc(session, audioFilename);
  257.   setBlockSize(MODE1_BLOCK_LEN);
  258.   
  259.   return toc;
  260. }
  261. Toc *CDD2600::readDisk(int session, const char *fname)
  262. {
  263.   Toc *toc = CdrDriver::readDisk(session, fname);
  264.   setBlockSize(MODE1_BLOCK_LEN);
  265.   return toc;
  266. }
  267. int CDD2600::readIsrc(int trackNr, char *buf)
  268. {
  269.   unsigned char cmd[10];
  270.   unsigned short dataLen = 0x30;
  271.   unsigned char data[0x30];
  272.   int i;
  273.   memset(cmd, 0, 10);
  274.   cmd[0] = 0x42; // READ SUB CHANNEL
  275.   cmd[2] = 0x40; // get sub channel data
  276.   cmd[3] = 0x03; // get ISRC code
  277.   cmd[6] = trackNr;
  278.   cmd[7] = dataLen >> 8;
  279.   cmd[8] = dataLen;
  280.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
  281.     message(-1, "Cannot read ISRC code.");
  282.     return 1;
  283.   }
  284.   else {
  285.     if (data[0x08] & 0x80) {
  286.       for (i = 0; i < 12; i++) {
  287. buf[i] = data[0x09 + i];
  288.       }
  289.       buf[12] = 0;
  290.     }
  291.   }
  292.   return 0;
  293. }
  294. // tries to read catalog number from disk and adds it to 'toc'
  295. // return: 1 if valid catalog number was found, else 0
  296. int CDD2600::readCatalog(Toc *toc, long startLba, long endLba)
  297. {
  298.   unsigned char cmd[10];
  299.   unsigned short dataLen = 0x30;
  300.   unsigned char data[0x30];
  301.   char catalog[14];
  302.   int i;
  303.   // read sub channel information
  304.   memset(cmd, 0, 10);
  305.   cmd[0] = 0x42; // READ SUB CHANNEL
  306.   cmd[2] = 0x40; // get sub channel data
  307.   cmd[3] = 0x02; // get media catalog number
  308.   cmd[7] = dataLen >> 8;
  309.   cmd[8] = dataLen;
  310.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
  311.     message(-2, "Cannot read sub channel data.");
  312.     return 0;
  313.   }
  314.   if (data[0x08] & 0x80) {
  315.     for (i = 0; i < 13; i++) {
  316.       catalog[i] = data[0x09 + i];
  317.     }
  318.     catalog[13] = 0;
  319.     if (toc->catalog(catalog) == 0) {
  320.       return 1;
  321.     }
  322.   }
  323.   return 0;
  324. }
  325. int CDD2600::analyzeTrack(TrackData::Mode mode, int trackNr, long startLba,
  326.   long endLba,
  327.   Msf *index, int *indexCnt, long *pregap,
  328.   char *isrcCode, unsigned char *ctl)
  329. {
  330.   blockLength_ = AUDIO_BLOCK_LEN;
  331.   modeSelectBlockSize(blockLength_, 1);
  332.   int ret = analyzeTrackSearch(mode, trackNr, startLba, endLba,
  333.        index, indexCnt, pregap, isrcCode, ctl);
  334.   *isrcCode = 0;
  335.   if (mode == TrackData::AUDIO) {
  336.     // read ISRC code from sub channel
  337.     readIsrc(trackNr, isrcCode);
  338.   }
  339.   return ret;
  340. }
  341. int CDD2600::getTrackIndex(long lba, int *trackNr, int *indexNr, 
  342.    unsigned char *ctl)
  343. {
  344.   long relPos;
  345.   readBlock(lba);
  346.   return readSubChannelData(trackNr, indexNr, &relPos, ctl);
  347. }
  348. int CDD2600::readSubChannelData(int *trackNr, int *indexNr, long *relPos,
  349. unsigned char *ctl)
  350. {
  351.   unsigned char cmd[10];
  352.   unsigned short dataLen = 0x30;
  353.   unsigned char data[0x30];
  354.   // read sub channel information
  355.   memset(cmd, 0, 10);
  356.   cmd[0] = 0x42; // READ SUB CHANNEL
  357.   cmd[2] = 0x40; // get sub channel data
  358.   cmd[3] = 0x00; // get sub Q channel data
  359.   cmd[6] = 0;
  360.   cmd[7] = dataLen >> 8;
  361.   cmd[8] = dataLen;
  362.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
  363.     message(-2, "Cannot read sub Q channel data.");
  364.     return 1;
  365.   }
  366.   *trackNr = data[6];
  367.   *indexNr = data[7];
  368.   *relPos = 0;
  369.   *relPos |= data[0x0c] << 24;
  370.   *relPos |= data[0x0d] << 16;
  371.   *relPos |= data[0x0e] << 8;
  372.   *relPos |= data[0x0f];
  373.   if (ctl != NULL) {
  374.     *ctl = data[5] & 0x0f;
  375.   }
  376.   return 0;
  377. }
  378. // reads a single block of length 'blockLength_' from given sector
  379. // return: 0: OK
  380. //         1: error occured
  381. void CDD2600::readBlock(unsigned long sector)
  382. {
  383.   unsigned char cmd[10];
  384.   unsigned long dataLen = 2 * blockLength_;
  385.   unsigned char *data = new (unsigned char)[dataLen];
  386.   // read sub channel information
  387.   memset(cmd, 0, 10);
  388.   cmd[0] = 0x28; // READ10
  389.   cmd[2] = sector >> 24;
  390.   cmd[3] = sector >> 16;
  391.   cmd[4] = sector >> 8;
  392.   cmd[5] = sector;
  393.   cmd[7] = 0;
  394.   cmd[8] = 2;
  395.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
  396.     message(-2, "Cannot read block - ignored.");
  397.   }
  398.   delete[] data;
  399. }
  400. // Retrieve disk information.
  401. // return: DiskInfo structure or 'NULL' on error
  402. DiskInfo *CDD2600::diskInfo()
  403. {
  404.   unsigned char cmd[10];
  405.   unsigned long dataLen = 34;
  406.   unsigned char data[34];
  407.   memset(&diskInfo_, 0, sizeof(DiskInfo));
  408.   if (readCapacity(&(diskInfo_.capacity), 0) == 0) {
  409.     diskInfo_.valid.capacity = 1;
  410.   }
  411.   
  412.   if (readSessionInfo(&leadInLength_, &leadOutLength_, 0) == 0) {
  413.     diskInfo_.valid.manufacturerId = 1;
  414.     
  415.     // start time of lead-in
  416.     diskInfo_.manufacturerId = Msf(450150 - leadInLength_ - 150 );
  417.     diskInfo_.empty = 1; // this is for the CDD2000 which does not support
  418.                          // READ DISK INFORMATION
  419.   }
  420.   else {
  421.     diskInfo_.empty = 0; // this is for the CDD2000 which does not support
  422.                          // READ DISK INFORMATION
  423.   }
  424.   diskInfo_.valid.empty = 1;
  425.   memset(cmd, 0, 10);
  426.   memset(data, 0, dataLen);
  427.   cmd[0] = 0x51; // READ DISK INFORMATION
  428.   cmd[7] = dataLen >> 8;
  429.   cmd[8] = dataLen;
  430.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen, 0) == 0) {
  431.     diskInfo_.empty = (data[2] & 0x03) == 0 ? 1 : 0;
  432.     diskInfo_.cdrw = (data[2] & 0x10) != 0 ? 1 : 0;
  433.     diskInfo_.valid.cdrw = 1;
  434.   }
  435.   return &diskInfo_;
  436. }
  437. CdRawToc *CDD2600::getRawToc(int sessionNr, int *len)
  438. {
  439.   unsigned char cmd[10];
  440.   unsigned short dataLen;
  441.   unsigned char *data = NULL;;
  442.   unsigned char reqData[4]; // buffer for requestion the actual length
  443.   unsigned char *p = NULL;
  444.   int i;
  445.   CdRawToc *rawToc;
  446.   int entries;
  447.   assert(sessionNr >= 1);
  448.   // read disk toc length
  449.   memset(cmd, 0, 10);
  450.   cmd[0] = 0x43; // READ TOC
  451.   cmd[6] = sessionNr;
  452.   cmd[8] = 4;
  453.   cmd[9] |= 2 << 6; // get Q subcodes
  454.   if (sendCmd(cmd, 10, NULL, 0, reqData, 4) != 0) {
  455.     message(-2, "Cannot read raw disk toc.");
  456.     return NULL;
  457.   }
  458.   dataLen = ((reqData[0] << 8) | reqData[1]) + 2;
  459.   message(3, "Raw toc data len: %d", dataLen);
  460.   data = new (unsigned char)[dataLen];
  461.   
  462.   // read disk toc
  463.   cmd[7] = dataLen >> 8;
  464.   cmd[8] = dataLen;
  465.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
  466.     message(-2, "Cannot read raw disk toc.");
  467.     delete[] data;
  468.     return NULL;
  469.   }
  470.   entries = (((data[0] << 8) | data[1]) - 2) / 11;
  471.   rawToc = new CdRawToc[entries];
  472.   for (i = 0, p = data + 4; i < entries; i++, p += 11 ) {
  473. #if 0
  474.     message(0, "%d %02x %02d %2x %02x:%02x:%02x %02x %02x:%02x:%02x",
  475.     p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10]);
  476. #endif
  477.     rawToc[i].sessionNr = p[0];
  478.     rawToc[i].adrCtl = p[1];
  479.     rawToc[i].point = p[3];
  480.     rawToc[i].pmin = p[8];
  481.     rawToc[i].psec = p[9];
  482.     rawToc[i].pframe = p[10];
  483.   }
  484.   delete[] data;
  485.   *len = entries;
  486.   return rawToc;
  487. }
  488. long CDD2600::readTrackData(TrackData::Mode mode, long lba, long len,
  489.     unsigned char *buf)
  490. {
  491.   unsigned char cmd[10];
  492.   long blockLen = 2340;
  493.   long i;
  494.   TrackData::Mode actMode;
  495.   int ok = 0;
  496.   const unsigned char *sense;
  497.   int senseLen;
  498.   int softError;
  499.   if (setBlockSize(blockLen) != 0)
  500.     return 0;
  501.   memset(cmd, 0, 10);
  502.   cmd[0] = 0x28; // READ10
  503.   cmd[2] = lba >> 24;
  504.   cmd[3] = lba >> 16;
  505.   cmd[4] = lba >> 8;
  506.   cmd[5] = lba;
  507.   /*  
  508.   if (mode == TrackData::MODE2_FORM1 || mode == TrackData::MODE2_FORM2)
  509.     cmd[9] = 1 << 6; // MIX flag
  510.     */
  511.   while (len > 0 && !ok) {
  512.     cmd[7] = len >> 8;
  513.     cmd[8] = len;
  514.     memset(transferBuffer_, 0, len * blockLen);
  515.     switch (sendCmd(cmd, 10, NULL, 0, transferBuffer_, len * blockLen, 0)) {
  516.     case 0:
  517.       ok = 1;
  518.       break;
  519.     case 2:
  520.       softError = 0;
  521.       sense = scsiIf_->getSense(senseLen);
  522.       if (senseLen > 0x0c) {
  523. if ((sense[2] &0x0f) == 5) {
  524.   switch (sense[12]) {
  525.   case 0x64: // Illegal mode for this track
  526.     softError = 1;
  527.     break;
  528.   }
  529. }
  530. else if ((sense[2] & 0x0f) == 3) { // Medium error
  531.   switch (sense[12]) {
  532.   case 0x02: // No seek complete, sector not found
  533.   case 0x11: // L-EC error
  534.     return -2;
  535.     break;
  536.   }
  537. }
  538.       }
  539.       if (!softError) {
  540. scsiIf_->printError();
  541. return -1;
  542.       }
  543.       break;
  544.     default:
  545.       message(-2, "Read error at LBA %ld, len %ld", lba, len);
  546.       return -1;
  547.       break;
  548.     }
  549.     if (!ok) {
  550.       len--;
  551.     }
  552.   }
  553.   unsigned char *sector = transferBuffer_;
  554.   for (i = 0; i < len; i++) {
  555.     actMode = determineSectorMode(sector);
  556.     if (!(actMode == mode ||
  557.   (mode == TrackData::MODE2_FORM_MIX &&
  558.    (actMode == TrackData::MODE2_FORM1 ||
  559.     actMode == TrackData::MODE2_FORM2)) ||
  560.   (mode == TrackData::MODE1_RAW && actMode == TrackData::MODE1) ||
  561.   (mode == TrackData::MODE2_RAW &&
  562.    (actMode == TrackData::MODE2 ||
  563.     actMode == TrackData::MODE2_FORM1 ||
  564.     actMode == TrackData::MODE2_FORM2)))) {
  565.       return i;
  566.     }
  567.     if (buf != NULL) {
  568.       switch (mode) {
  569.       case TrackData::MODE1:
  570. memcpy(buf, sector + 4, MODE1_BLOCK_LEN);
  571. buf += MODE1_BLOCK_LEN;
  572. break;
  573.       case TrackData::MODE2:
  574.       case TrackData::MODE2_FORM_MIX:
  575. memcpy(buf, sector + 4, MODE2_BLOCK_LEN);
  576. buf += MODE2_BLOCK_LEN;
  577. break;
  578.       case TrackData::MODE2_FORM1:
  579. memcpy(buf, sector + 12, MODE2_FORM1_DATA_LEN);
  580. buf += MODE2_FORM1_DATA_LEN;
  581. break;
  582.       case TrackData::MODE2_FORM2:
  583. memcpy(buf, sector + 12, MODE2_FORM2_DATA_LEN);
  584. buf += MODE2_FORM2_DATA_LEN;
  585. break;
  586.       case TrackData::MODE1_RAW:
  587.       case TrackData::MODE2_RAW:
  588. memcpy(buf, syncPattern, 12);
  589. memcpy(buf + 12, sector, 2340);
  590. buf += AUDIO_BLOCK_LEN;
  591. break;
  592.       case TrackData::MODE0:
  593.       case TrackData::AUDIO:
  594. message(-3, "CDD2600::readTrackData: Illegal mode.");
  595. return 0;
  596. break;
  597.       }
  598.     }
  599.     sector += blockLen;
  600.   }
  601.   return len;
  602. }
  603. int CDD2600::readSubChannels(long lba, long len, SubChannel ***chans,
  604.      Sample *audioData)
  605. {
  606.   unsigned char cmd[10];
  607.   int tries = 5;
  608.   int ret;
  609.   if (setBlockSize(AUDIO_BLOCK_LEN) != 0)
  610.     return 1;
  611.   memset(cmd, 0, 10);
  612.   cmd[0] = 0x28; // READ10
  613.   cmd[2] = lba >> 24;
  614.   cmd[3] = lba >> 16;
  615.   cmd[4] = lba >> 8;
  616.   cmd[5] = lba;
  617.   cmd[7] = len >> 8;
  618.   cmd[8] = len;
  619.   do {
  620.     ret = sendCmd(cmd, 10, NULL, 0, 
  621.   (unsigned char*)audioData, len * AUDIO_BLOCK_LEN,
  622.   (tries == 1) ? 1 : 0);
  623.     if (ret != 0 && tries == 1) {
  624.       message(-2, "Reading of audio data failed at sector %ld.", lba);
  625.       return 1;
  626.     }
  627.     
  628.     tries--;
  629.   } while (ret != 0 && tries > 0);
  630.   *chans = NULL;
  631.   return 0;
  632. }
  633. int CDD2600::readAudioRange(int fd, long start, long end,
  634.     int startTrack, int endTrack,
  635.     TrackInfo *info)
  636. {
  637.   if (!onTheFly_) {
  638.     int t;
  639.     message(1, "Analyzing...");
  640.     for (t = startTrack; t <= endTrack; t++) {
  641.       message(1, "Track %d...", t + 1);
  642.       info[t].isrcCode[0] = 0;
  643.       readIsrc(t + 1, info[t].isrcCode);
  644.     if (info[t].isrcCode[0] != 0)
  645.       message(1, "Found ISRC code.");
  646.     }
  647.     message(1, "Reading...");
  648.   }
  649.   return CdrDriver::readAudioRangeParanoia(fd, start, end, startTrack,
  650.    endTrack, info);
  651. }