TaiyoYuden.cc
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:7k
- /* cdrdao - write audio CD-Rs in disc-at-once mode
- *
- * Copyright (C) 1998, 1999 Andreas Mueller <mueller@daneb.ping.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /*
- * $Log: TaiyoYuden.cc,v $
- * Revision 1.4 1999/04/05 11:04:10 mueller
- * Added driver option flags.
- *
- * Revision 1.3 1999/03/27 20:50:04 mueller
- * Adapted to changed writing interface.
- *
- * Revision 1.2 1999/02/06 20:42:44 mueller
- * Added member function 'checkToc()'.
- *
- * Revision 1.1 1999/02/04 21:05:47 mueller
- * Initial revision
- *
- */
- /* Driver for the TaiyoYuden drive created by Henk-Jan Slotboom.
- * Very similar to the Philips CDD2x00 drives.
- */
- static char rcsid[] = "$Id: TaiyoYuden.cc,v 1.4 1999/04/05 11:04:10 mueller Exp mueller $";
- #include <config.h>
- #include <string.h>
- #include <assert.h>
- #include "TaiyoYuden.h"
- #include "SubChannel.h"
- #include "Toc.h"
- #include "util.h"
- TaiyoYuden::TaiyoYuden(ScsiIf *scsiIf, unsigned long options)
- : PlextorReader(scsiIf, options), CDD2600Base(this)
- {
- driverName_ = "Taiyo-Yuden - Version 0.1(alpha)";
-
- leadInLength_ = leadOutLength_ = 0;
- speed_ = 2;
- simulate_ = 1;
- encodingMode_ = 0;
- audioDataByteOrder_ = 0; // little endian
- memset(&diskInfo_, 0, sizeof(DiskInfo));
- }
- TaiyoYuden::~TaiyoYuden()
- {
- }
- // static constructor
- CdrDriver *TaiyoYuden::instance(ScsiIf *scsiIf, unsigned long options)
- {
- return new TaiyoYuden(scsiIf, options);
- }
- // sets speed
- // return: 0: OK
- // 1: illegal speed
- int TaiyoYuden::speed(int s)
- {
- if (s >= 0 && s <= 2) {
- speed_ = s;
- return 0;
- }
- else if (s > 2) {
- speed_ = 2;
- return 0;
- }
- else {
- return 1;
- }
- }
- // loads ('unload' == 0) or ejects ('unload' == 1) tray
- // return: 0: OK
- // 1: scsi command failed
- int TaiyoYuden::loadUnload(int unload) const
- {
- unsigned char cmd[10];
- memset(cmd, 0, 10);
- cmd[0] = 0xe7; // MEDIUM LOAD/UNLOAD
- if (unload) {
- cmd[8] |= 0x01;
- }
- if (sendCmd(cmd, 10, NULL, 0, NULL, 0) != 0) {
- message(-2, "Cannot load/unload medium.");
- return 1;
- }
- return 0;
- };
- int TaiyoYuden::initDao(const Toc *toc)
- {
- long n;
- toc_ = toc;
- blockLength_ = AUDIO_BLOCK_LEN;
- blocksPerWrite_ = scsiIf_->maxDataLen() / blockLength_;
- assert(blocksPerWrite_ > 0);
- if (modeSelectBlockSize(blockLength_, 1) != 0 ||
- modeSelectSpeed(-1, speed_, simulate_, 1) != 0 ||
- modeSelectCatalog(toc_) != 0 ||
- readSessionInfo(&leadInLength_, &leadOutLength_, 1) != 0) {
- return 1;
- }
- // allocate buffer for write zeros
- n = blocksPerWrite_ * blockLength_;
- delete[] zeroBuffer_;
- zeroBuffer_ = new char[n];
- memset(zeroBuffer_, 0, n);
- return 0;
- }
- int TaiyoYuden::startDao()
- {
- long lba = -leadInLength_ - 150; // Value is not really important since the
- // LBA is not used by 'writeData'.
-
- if (writeSession(toc_, multiSession_) != 0) {
- return 1;
- }
- message(1, "Writing lead-in and gap...");
- // write lead-in
- if (writeZeros(toc_->leadInMode(), lba, 0, leadInLength_) != 0) {
- flushCache();
- return 1;
- }
- // write gap (2 seconds)
- if (writeZeros(toc_->leadInMode(), lba, 0, 150) != 0) {
- flushCache();
- return 1;
- }
- message(1, "");
- return 0;
- }
- int TaiyoYuden::finishDao()
- {
- long lba = toc_->length().lba();
- message(1, "Writing lead-out...");
- // write lead-out
- if (writeZeros(toc_->leadOutMode(), lba, lba + 150, leadOutLength_) != 0) {
- flushCache();
- return 1;
- }
- message(1, "nFlushing cache...");
-
- if (flushCache() != 0) {
- return 1;
- }
- message(1, "");
- delete[] zeroBuffer_, zeroBuffer_ = NULL;
- return 0;
- }
- void TaiyoYuden::abortDao()
- {
- flushCache();
- }
- // Writes data to target, the block length depends on the actual writing mode
- // and is stored internally. 'len' is number of blocks to write.
- // 'lba' specifies the next logical block address for writing and is updated
- // by this function but not used for writing
- // return: 0: OK
- // 1: scsi command failed
- int TaiyoYuden::writeData(TrackData::Mode mode, long &lba, const char *buf,
- long len)
- {
- assert(blocksPerWrite_ > 0);
- assert(blockLength_ > 0);
- assert(mode == TrackData::AUDIO);
- int nwritten = 0;
- int writeLen = 0;
- unsigned char cmd[10];
- memset(cmd, 0, 10);
- cmd[0] = 0x2a; // WRITE1
-
- while (len > 0) {
- writeLen = (len > blocksPerWrite_ ? blocksPerWrite_ : len);
- cmd[7] = writeLen >> 8;
- cmd[8] = writeLen & 0xff;
- if (sendCmd(cmd, 10, (unsigned char *)(buf + (nwritten * blockLength_)),
- writeLen * blockLength_, NULL, 0) != 0) {
- message(-2, "Write data failed.");
- return 1;
- }
- lba += writeLen;
- len -= writeLen;
- nwritten += writeLen;
- }
-
- return 0;
- }
- // Retrieve disk information.
- // return: DiskInfo structure or 'NULL' on error
- DiskInfo *TaiyoYuden::diskInfo()
- {
- unsigned char cmd[10];
- unsigned long dataLen = 34;
- unsigned char data[34];
-
- memset(&diskInfo_, 0, sizeof(DiskInfo));
-
- if (readCapacity(&(diskInfo_.capacity), 0) == 0) {
- diskInfo_.valid.capacity = 1;
- }
-
- if (readSessionInfo(&leadInLength_, &leadOutLength_, 0) == 0) {
- diskInfo_.valid.manufacturerId = 1;
- // start time of lead-in
- diskInfo_.manufacturerId = Msf(450150 - leadInLength_ - 150 );
- diskInfo_.empty = 1;
- }
- else {
- diskInfo_.empty = 0;
- }
- diskInfo_.valid.empty = 0; // does not work for this drive
-
- memset(cmd, 0, 10);
- memset(data, 0, dataLen);
-
- cmd[0] = 0x51; // READ DISK INFORMATION
- cmd[7] = dataLen >> 8;
- cmd[8] = dataLen;
-
- if (sendCmd(cmd, 10, NULL, 0, data, dataLen, 0) == 0) {
- diskInfo_.empty = (data[2] & 0x03) == 0 ? 1 : 0;
- diskInfo_.cdrw = (data[2] & 0x10) != 0 ? 1 : 0;
- diskInfo_.valid.cdrw = 1;
- }
- return &diskInfo_;
- }
- // Special toc check for Taiyo-Yuden drives. Every track must have a pre-gap
- // to create a correct disk. The pre-gap length may be only 1 block.
- // Only warnings are created.
- // Return: 0: OK
- // 1: at least one warning was given
- // 2: at least on error was given
- int TaiyoYuden::checkToc(const Toc *toc)
- {
- int err = PlextorReader::checkToc(toc);
- int trackNr;
- Msf start, end;
- const Track *t;
- int warningGiven = 0;
- TrackIterator itr(toc);
- for (t = itr.first(start, end), trackNr = 1;
- t != NULL;
- t = itr.next(start, end), trackNr++) {
- if (t->start().lba() == 0 && trackNr > 1) {
- if (!warningGiven) {
- warningGiven = 1;
- message(-1, "Each track must have a minimal pre-gap to create a useful disk.");
- message(-1, "This is not fulfilled for following track(s):");
- }
- message(-1, "Track %d", trackNr);
- }
- }
- if (warningGiven) {
- message(0,"");
- if (err < 1)
- err = 1;
- }
- return err;
- }