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

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: CDD2600Base.cc,v $
  21.  * Revision 1.2  1999/03/27 20:52:02  mueller
  22.  * Adapted to changed writing interface.
  23.  *
  24.  * Revision 1.1  1998/10/03 15:03:59  mueller
  25.  * Initial revision
  26.  *
  27.  */
  28. static char rcsid[] = "$Id: CDD2600Base.cc,v 1.2 1999/03/27 20:52:02 mueller Exp mueller $";
  29. #include <config.h>
  30. #include <string.h>
  31. #include <assert.h>
  32. #include "CDD2600Base.h"
  33. #include "SubChannel.h"
  34. #include "Toc.h"
  35. #include "util.h"
  36. CDD2600Base::CDD2600Base(CdrDriver *driver)
  37. {
  38.   driver_ = driver;
  39. }
  40. CDD2600Base::~CDD2600Base()
  41. {
  42.   driver_ = NULL;
  43. }
  44. // sets the block length
  45. // return: 0: OK
  46. //         1: scsi command failed
  47. int CDD2600Base::modeSelectBlockSize(int blockSize, int showMsg)
  48. {
  49.   unsigned char cmd[6];
  50.   unsigned char data[12];
  51.   memset(cmd, 0, 6);
  52.   memset(data, 0, 12);
  53.   cmd[0] = 0x15; // MODE SELECT
  54.   cmd[4] = 12;
  55.   data[3] = 8;
  56.   data[9] = blockSize >> 16;
  57.   data[10] = blockSize >> 8;
  58.   data[11] = blockSize;
  59.   if (driver_->sendCmd(cmd, 6, data, 12, NULL, 0, showMsg) != 0) {
  60.     if (showMsg)
  61.       message(-2, "Cannot set block size to %d.", blockSize);
  62.     return 1;
  63.   }
  64.   return 0;
  65. }
  66. // sets read/write speed and simulation mode
  67. // return: 0: OK
  68. //         1: scsi command failed
  69. int CDD2600Base::modeSelectSpeed(int readSpeed, int writeSpeed, int simulate,
  70.  int showMessage)
  71. {
  72.   unsigned char mp[8];
  73.   memset(mp, 0, 8);
  74.   mp[0] = 0x23;
  75.   mp[1] = 0x06;
  76.   if (writeSpeed >= 0) {
  77.     mp[2] = writeSpeed;
  78.   }
  79.   mp[3] = (simulate != 0 ? 1 : 0);
  80.   if (readSpeed >= 0) {
  81.     mp[4] = readSpeed;
  82.   }
  83.   if (driver_->setModePage(mp, NULL, NULL, showMessage) != 0) {
  84.     if (showMessage) {
  85.       message(-2, "Cannot set speed/simulation mode.");
  86.     }
  87.     return 1;
  88.   }
  89.   return 0;
  90. }
  91. // Sets catalog number if valid in given TOC.
  92. // return: 0: OK
  93. //         1: scsi command failed
  94. int CDD2600Base::modeSelectCatalog(const Toc *toc)
  95. {
  96.   unsigned char mp[10];
  97.   memset(mp, 0, 10);
  98.   mp[0] = 0x22;
  99.   mp[1] = 0x08;
  100.   if (toc->catalogValid()) {
  101.     mp[2] = 0x01;
  102.     mp[3] = (toc->catalog(0) << 4) | toc->catalog(1);
  103.     mp[4] = (toc->catalog(2) << 4) | toc->catalog(3);
  104.     mp[5] = (toc->catalog(4) << 4) | toc->catalog(5);
  105.     mp[6] = (toc->catalog(6) << 4) | toc->catalog(7);
  106.     mp[7] = (toc->catalog(8) << 4) | toc->catalog(9);
  107.     mp[8] = (toc->catalog(10) << 4) | toc->catalog(11);
  108.     mp[9] = (toc->catalog(12) << 4);
  109.   }
  110.   if (driver_->setModePage(mp, NULL, NULL, 1) != 0) {
  111.     message(-2, "Cannot set catalog number.");
  112.     return 1;
  113.   }
  114.   return 0;
  115. }
  116. // Requests length of lead-in and lead-out.
  117. // return: 0: OK
  118. //         1: scsi command failed
  119. int CDD2600Base::readSessionInfo(long *leadInLen, long *leadOutLen,
  120.  int showMessage)
  121. {
  122.   unsigned char cmd[10];
  123.   unsigned char data[4];
  124.   memset(cmd, 0, 10);
  125.   memset(data, 0, 4);
  126.   cmd[0] = 0xee; // READ SESSION INFO
  127.   cmd[8] = 4;
  128.   if (driver_->sendCmd(cmd, 10, NULL, 0, data, 4, showMessage) != 0) {
  129.     if (showMessage)
  130.       message(-2, "Cannot read session info.");
  131.     return 1;
  132.   }
  133.   *leadInLen = (data[0] << 8) | data[1];
  134.   *leadOutLen = (data[2] << 8) | data[3];
  135.   message(3, "Lead-in length: %ld, lead-out length: %ld", *leadInLen,
  136.   *leadOutLen);
  137.   return 0;
  138. }
  139. // Sends initiating write session command for disk at once writing. This
  140. // includes the complete table of contents with all related data.
  141. // return: 0: OK
  142. //         1: scsi command failed
  143. int CDD2600Base::writeSession(const Toc *toc, int multiSession)
  144. {
  145.   unsigned char cmd[10];
  146.   unsigned char *data = NULL;
  147.   unsigned int dataLen = 0;
  148.   unsigned char *tp = NULL;
  149.   unsigned int tdl = 0; // track descriptor length
  150.   int cdromMode = 0;
  151.   int indexCount = 0;
  152.   int i;
  153.   int n;
  154.   const Track *t;
  155.   Msf start, end, index;
  156.   TrackIterator itr(toc);
  157.   // count total number of index increments
  158.   for (t = itr.first(start, end); t != NULL; t = itr.next(start, end)) {
  159.     indexCount += t->nofIndices();
  160.   }
  161.   dataLen = toc->nofTracks() * 20 + indexCount * 4;
  162.   /*
  163.   message(0, "%d tracks, %d indexes -> dataLen %u", toc->nofTracks(),
  164.   indexCount, dataLen);
  165.   */
  166.   data = new (unsigned char)[dataLen];
  167.   memset(data, 0, dataLen);
  168.   tp = data;
  169.   memset(cmd, 0, 10);
  170.   cmd[0] = 0xed; // write session
  171.   cmd[7] = dataLen >> 8;
  172.   cmd[8] = dataLen;
  173.   // setup toc-type, lead-out type and multi session flag
  174.   cmd[6] = 0;
  175.   switch (toc->tocType()) {
  176.   case Toc::CD_DA:
  177.   case Toc::CD_ROM:
  178.     cmd[6] = 0;
  179.     break;
  180.   case Toc::CD_ROM_XA:
  181.     cmd[6] = 2;
  182.     break;
  183.   case Toc::CD_I:
  184.     cmd[6] = 4;
  185.     break;
  186.   }
  187.   if (cdromMode) {
  188.     // Programming manual says that lead-out fixation parameter is only
  189.     // valid if the toc-type is CD-ROM. Unfortunately it does not tell
  190.     // which values to set.
  191. #if 0
  192.     switch (toc->leadOutMode()) {
  193.     case TrackData::MODE1:
  194.       cmd[6] |= 1 << 4;
  195.       break;
  196.     case TrackData::MODE2:
  197.     case TrackData::MODE2_FORM1:
  198.     case TrackData::MODE2_FORM2:
  199.     case TrackData::MODE2_FORM_MIX:
  200.       cmd[6] |= 2 << 4;
  201.       break;
  202.     default:
  203.       break;
  204.     }
  205. #endif
  206.   }
  207.   if (multiSession != 0) 
  208.     cmd[6] |= 1 << 3; // open next session
  209.   
  210.   for (t = itr.first(start, end); t != NULL; t = itr.next(start, end)) {
  211.     n = t->nofIndices();
  212.     tdl = 20 + n * 4;
  213.     tp[0] = tdl >> 8;
  214.     tp[1] = tdl;
  215.     tp[2] = 0;
  216.     if (t->copyPermitted()) {
  217.       tp[2] |= 0x02;
  218.     }
  219.     if (t->type() == TrackData::AUDIO) {
  220.       // audio track
  221.       if (t->preEmphasis()) {
  222. tp[2] |= 0x01;
  223.       }
  224.       if (t->audioType() == 1) {
  225. tp[2] |= 0x08;
  226.       }
  227.       
  228.       if (t->isrcValid()) {
  229. tp[2] |= 0x80;
  230.       
  231. tp[3] = SubChannel::ascii2Isrc(t->isrcCountry(0));
  232. tp[4] = SubChannel::ascii2Isrc(t->isrcCountry(1));
  233. tp[5] = SubChannel::ascii2Isrc(t->isrcOwner(0));
  234. tp[6] = SubChannel::ascii2Isrc(t->isrcOwner(1));
  235. tp[7] = SubChannel::ascii2Isrc(t->isrcOwner(2));
  236. tp[8] = (t->isrcYear(0) << 4) | t->isrcYear(1);
  237. tp[9] = (t->isrcSerial(0) << 4) | t->isrcSerial(1);
  238. tp[10] = (t->isrcSerial(2) << 4) | t->isrcSerial(3);
  239. tp[11] = (t->isrcSerial(4) << 4);
  240.       }
  241.     }
  242.     else {
  243.       // data track
  244.       tp[2] |= 0x04;
  245.     }
  246.     //message(0, "Track start: %s(0x%06lx)", start.str(), start.lba());
  247.     tp[12] = start.lba() >> 24;
  248.     tp[13] = start.lba() >> 16;
  249.     tp[14] = start.lba() >> 8;
  250.     tp[15] = start.lba();
  251.     for (i = 0; i < n; i++) {
  252.       index = start + t->getIndex(i);
  253.       //message(0, "      index: %s(0x%06lx)", index.str(), index.lba());
  254.       
  255.       tp[16 + i * 4] = index.lba() >> 24;
  256.       tp[17 + i * 4] = index.lba() >> 16;
  257.       tp[18 + i * 4] = index.lba() >> 8;
  258.       tp[19 + i * 4] = index.lba();
  259.     }
  260.     //message(0, "      end  : %s(0x%06lx)", end.str(), end.lba());
  261.     
  262.     tp[16 + n * 4] = end.lba() >> 24;
  263.     tp[17 + n * 4] = end.lba() >> 16;
  264.     tp[18 + n * 4] = end.lba() >> 8;
  265.     tp[19 + n * 4] = end.lba();
  266.     tp += tdl;
  267.   }
  268.   //message(0, "tp: %d", tp - data);
  269.   if (driver_->sendCmd(cmd, 10, data, dataLen, NULL, 0) != 0) {
  270.     message(-2, "Cannot write disk toc.");
  271.     delete[] data;
  272.     return 1;
  273.   }
  274.   delete[] data;
  275.   return 0;
  276. }