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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*  cdrdao - write audio CD-Rs in disc-at-once mode
  2.  *
  3.  *  Copyright (C) 1998, 1999 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: TaiyoYuden.cc,v $
  21.  * Revision 1.4  1999/04/05 11:04:10  mueller
  22.  * Added driver option flags.
  23.  *
  24.  * Revision 1.3  1999/03/27 20:50:04  mueller
  25.  * Adapted to changed writing interface.
  26.  *
  27.  * Revision 1.2  1999/02/06 20:42:44  mueller
  28.  * Added member function 'checkToc()'.
  29.  *
  30.  * Revision 1.1  1999/02/04 21:05:47  mueller
  31.  * Initial revision
  32.  *
  33.  */
  34. /* Driver for the TaiyoYuden drive created by Henk-Jan Slotboom.
  35.  * Very similar to the Philips CDD2x00 drives.
  36.  */
  37. static char rcsid[] = "$Id: TaiyoYuden.cc,v 1.4 1999/04/05 11:04:10 mueller Exp mueller $";
  38. #include <config.h>
  39. #include <string.h>
  40. #include <assert.h>
  41. #include "TaiyoYuden.h"
  42. #include "SubChannel.h"
  43. #include "Toc.h"
  44. #include "util.h"
  45. TaiyoYuden::TaiyoYuden(ScsiIf *scsiIf, unsigned long options)
  46.   : PlextorReader(scsiIf, options), CDD2600Base(this)
  47. {
  48.   driverName_ = "Taiyo-Yuden - Version 0.1(alpha)";
  49.   
  50.   leadInLength_ = leadOutLength_ = 0;
  51.   speed_ = 2;
  52.   simulate_ = 1;
  53.   encodingMode_ = 0;
  54.   audioDataByteOrder_ = 0; // little endian
  55.   memset(&diskInfo_, 0, sizeof(DiskInfo));
  56. }
  57. TaiyoYuden::~TaiyoYuden()
  58. {
  59. }
  60. // static constructor
  61. CdrDriver *TaiyoYuden::instance(ScsiIf *scsiIf, unsigned long options)
  62. {
  63.   return new TaiyoYuden(scsiIf, options);
  64. }
  65. // sets speed
  66. // return: 0: OK
  67. //         1: illegal speed
  68. int TaiyoYuden::speed(int s)
  69. {
  70.   if (s >= 0 && s <= 2) {
  71.     speed_ = s;
  72.     return 0;
  73.   }
  74.   else if (s > 2) {
  75.     speed_ = 2;
  76.     return 0;
  77.   }
  78.   else {
  79.     return 1;
  80.   }
  81. }
  82. // loads ('unload' == 0) or ejects ('unload' == 1) tray
  83. // return: 0: OK
  84. //         1: scsi command failed
  85. int TaiyoYuden::loadUnload(int unload) const
  86. {
  87.   unsigned char cmd[10];
  88.   memset(cmd, 0, 10);
  89.   cmd[0] = 0xe7; // MEDIUM LOAD/UNLOAD
  90.   if (unload) {
  91.     cmd[8] |= 0x01;
  92.   }
  93.   if (sendCmd(cmd, 10, NULL, 0, NULL, 0) != 0) {
  94.     message(-2, "Cannot load/unload medium.");
  95.     return 1;
  96.   }
  97.   return 0;
  98. };
  99. int TaiyoYuden::initDao(const Toc *toc)
  100. {
  101.   long n;
  102.   toc_ = toc;
  103.   blockLength_ = AUDIO_BLOCK_LEN;
  104.   blocksPerWrite_ = scsiIf_->maxDataLen() / blockLength_;
  105.   assert(blocksPerWrite_ > 0);
  106.   if (modeSelectBlockSize(blockLength_, 1) != 0 ||
  107.       modeSelectSpeed(-1, speed_, simulate_, 1) != 0 ||
  108.       modeSelectCatalog(toc_) != 0 ||
  109.       readSessionInfo(&leadInLength_, &leadOutLength_, 1) != 0) {
  110.     return 1;
  111.   }
  112.   // allocate buffer for write zeros
  113.   n = blocksPerWrite_ * blockLength_;
  114.   delete[] zeroBuffer_;
  115.   zeroBuffer_ = new char[n];
  116.   memset(zeroBuffer_, 0, n);
  117.   return 0;
  118. }
  119. int TaiyoYuden::startDao()
  120. {
  121.   long lba = -leadInLength_ - 150; // Value is not really important since the
  122.                                    // LBA is not used by 'writeData'.
  123.  
  124.   if (writeSession(toc_, multiSession_) != 0) {
  125.     return 1;
  126.   }
  127.   message(1, "Writing lead-in and gap...");
  128.   // write lead-in
  129.   if (writeZeros(toc_->leadInMode(), lba, 0, leadInLength_) != 0) {
  130.     flushCache();
  131.     return 1;
  132.   }
  133.   // write gap (2 seconds)
  134.   if (writeZeros(toc_->leadInMode(), lba, 0, 150) != 0) {
  135.     flushCache();
  136.     return 1;
  137.   }
  138.   message(1, "");
  139.   return 0;
  140. }
  141. int TaiyoYuden::finishDao()
  142. {
  143.   long lba = toc_->length().lba();
  144.   message(1, "Writing lead-out...");
  145.   // write lead-out
  146.   if (writeZeros(toc_->leadOutMode(), lba, lba + 150, leadOutLength_) != 0) {
  147.     flushCache();
  148.     return 1;
  149.   }
  150.   message(1, "nFlushing cache...");
  151.   
  152.   if (flushCache() != 0) {
  153.     return 1;
  154.   }
  155.   message(1, "");
  156.   delete[] zeroBuffer_, zeroBuffer_ = NULL;
  157.   return 0;
  158. }
  159. void TaiyoYuden::abortDao()
  160. {
  161.   flushCache();
  162. }
  163. // Writes data to target, the block length depends on the actual writing mode
  164. // and is stored internally. 'len' is number of blocks to write.
  165. // 'lba' specifies the next logical block address for writing and is updated
  166. // by this function but not used for writing
  167. // return: 0: OK
  168. //         1: scsi command failed
  169. int TaiyoYuden::writeData(TrackData::Mode mode, long &lba, const char *buf,
  170.   long len)
  171. {
  172.   assert(blocksPerWrite_ > 0);
  173.   assert(blockLength_ > 0);
  174.   assert(mode == TrackData::AUDIO);
  175.   int nwritten = 0;
  176.   int writeLen = 0;
  177.   unsigned char cmd[10];
  178.   memset(cmd, 0, 10);
  179.   cmd[0] = 0x2a; // WRITE1
  180.   
  181.   while (len > 0) {
  182.     writeLen = (len > blocksPerWrite_ ? blocksPerWrite_ : len);
  183.     cmd[7] = writeLen >> 8;
  184.     cmd[8] = writeLen & 0xff;
  185.     if (sendCmd(cmd, 10, (unsigned char *)(buf + (nwritten * blockLength_)),
  186. writeLen * blockLength_, NULL, 0) != 0) {
  187.       message(-2, "Write data failed.");
  188.       return 1;
  189.     }
  190.     lba += writeLen;
  191.     len -= writeLen;
  192.     nwritten += writeLen;
  193.   }
  194.       
  195.   return 0;
  196. }
  197. // Retrieve disk information.
  198. // return: DiskInfo structure or 'NULL' on error
  199. DiskInfo *TaiyoYuden::diskInfo()
  200. {
  201.   unsigned char cmd[10];
  202.   unsigned long dataLen = 34;
  203.   unsigned char data[34];
  204.   
  205.   memset(&diskInfo_, 0, sizeof(DiskInfo));
  206.   
  207.   if (readCapacity(&(diskInfo_.capacity), 0) == 0) {
  208.     diskInfo_.valid.capacity = 1;
  209.   }
  210.   
  211.   if (readSessionInfo(&leadInLength_, &leadOutLength_, 0) == 0) {
  212.     diskInfo_.valid.manufacturerId = 1;
  213.            // start time of lead-in
  214.     diskInfo_.manufacturerId = Msf(450150 - leadInLength_ - 150 );
  215.     diskInfo_.empty = 1;
  216.   }
  217.   else {
  218.     diskInfo_.empty = 0;
  219.   }
  220.   diskInfo_.valid.empty = 0; // does not work for this drive
  221.   
  222.   memset(cmd, 0, 10);
  223.   memset(data, 0, dataLen);
  224.   
  225.   cmd[0] = 0x51; // READ DISK INFORMATION
  226.   cmd[7] = dataLen >> 8;
  227.   cmd[8] = dataLen;
  228.    
  229.   if (sendCmd(cmd, 10, NULL, 0, data, dataLen, 0) == 0) {
  230.     diskInfo_.empty = (data[2] & 0x03) == 0 ? 1 : 0;
  231.     diskInfo_.cdrw = (data[2] & 0x10) != 0 ? 1 : 0;
  232.     diskInfo_.valid.cdrw = 1;
  233.   }
  234.   return &diskInfo_;
  235. }
  236. // Special toc check for Taiyo-Yuden drives. Every track must have a pre-gap
  237. // to create a correct disk. The pre-gap length may be only 1 block.
  238. // Only warnings are created.
  239. // Return: 0: OK
  240. //         1: at least one warning was given
  241. //         2: at least on error was given
  242. int TaiyoYuden::checkToc(const Toc *toc)
  243. {
  244.   int err = PlextorReader::checkToc(toc);
  245.   int trackNr;
  246.   Msf start, end;
  247.   const Track *t;
  248.   int warningGiven = 0;
  249.   TrackIterator itr(toc);
  250.   for (t = itr.first(start, end), trackNr = 1;
  251.        t != NULL;
  252.        t = itr.next(start, end), trackNr++) {
  253.     if (t->start().lba() == 0 && trackNr > 1) {
  254.       if (!warningGiven) {
  255. warningGiven = 1;
  256. message(-1, "Each track must have a minimal pre-gap to create a useful disk.");
  257. message(-1, "This is not fulfilled for following track(s):");
  258.       }
  259.       message(-1, "Track %d", trackNr);
  260.     }
  261.   }
  262.   if (warningGiven) {
  263.     message(0,"");
  264.     if (err < 1)
  265.       err = 1;
  266.   }
  267.   return err;
  268. }