1 /* cdrdao - write audio CD-Rs in disc-at-once mode
2 *
3 * Copyright (C) 1998-2001 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 #include <config.h>
21
22 #include <string.h>
23 #include <assert.h>
24
25 #include "CDD2600.h"
26 #include "SubChannel.h"
27 #include "PQSubChannel16.h"
28
29 #include "Toc.h"
30 #include "log.h"
31
CDD2600(ScsiIf * scsiIf,unsigned long options)32 CDD2600::CDD2600(ScsiIf *scsiIf, unsigned long options)
33 : CdrDriver(scsiIf, options|OPT_DRV_NO_PREGAP_READ), CDD2600Base(this)
34 {
35 driverName_ = "CDD2600 - Version 1.1";
36
37 leadInLength_ = leadOutLength_ = 0;
38 speed_ = 2;
39 simulate_ = true;
40 encodingMode_ = 0;
41
42 // reads big endian samples
43 audioDataByteOrder_ = 1;
44
45 memset(&diskInfo_, 0, sizeof(DiskInfo));
46 }
47
~CDD2600()48 CDD2600::~CDD2600()
49 {
50 }
51
52 // static constructor
instance(ScsiIf * scsiIf,unsigned long options)53 CdrDriver *CDD2600::instance(ScsiIf *scsiIf, unsigned long options)
54 {
55 return new CDD2600(scsiIf, options);
56 }
57
58 // sets speed
59 // return: 0: OK
60 // 1: illegal speed
speed(int s)61 int CDD2600::speed(int s)
62 {
63 if (s >= 0 && s <= 2) {
64 speed_ = s;
65 return 0;
66 }
67 else if (s > 2) {
68 speed_ = 2;
69 return 0;
70 }
71 else {
72 return 1;
73 }
74 }
75
76 // loads ('unload' == 0) or ejects ('unload' == 1) tray
77 // return: 0: OK
78 // 1: scsi command failed
79
loadUnload(int unload) const80 int CDD2600::loadUnload(int unload) const
81 {
82 unsigned char cmd[10];
83
84 memset(cmd, 0, 10);
85
86 cmd[0] = 0xe7; // MEDIUM LOAD/UNLOAD
87 if (unload) {
88 cmd[8] |= 0x01;
89 }
90
91 if (sendCmd(cmd, 10, NULL, 0, NULL, 0) != 0) {
92 log_message(-2, "Cannot load/unload medium.");
93 return 1;
94 }
95
96 return 0;
97 }
98
99 // sets various audio play parameters, output channels are set to stereo mode
100 // and given volume
101 // immediate: 0: wait until audio play command finished
102 // 1: command finishs immediately after playback has started
103 // sotc: 0: play across track boundaries
104 // 1: stop playing at track boundaries
modeSelectPlay(int immediate,int sotc,unsigned char volume)105 int CDD2600::modeSelectPlay(int immediate, int sotc, unsigned char volume)
106 {
107 unsigned char mp[16];
108
109 memset(mp, 0, 16);
110
111 mp[0] = 0x0e; // PLAY page code
112 mp[1] = 14; // parameter length
113 if (immediate != 0) {
114 mp[2] |= 0x04;
115 }
116 if (sotc != 0) {
117 mp[2] |= 0x02;
118 }
119 mp[8] = 1;
120 mp[9] = volume;
121 mp[10] = 2;
122 mp[11] = volume;
123
124 if (setModePage(mp, NULL, NULL, 1) != 0) {
125 log_message(-2, "Cannot set play parameters.");
126 return 1;
127 }
128
129 return 0;
130 }
131
initDao(const Toc * toc)132 int CDD2600::initDao(const Toc *toc)
133 {
134 long n;
135 blockLength_ = AUDIO_BLOCK_LEN;
136 blocksPerWrite_ = scsiIf_->maxDataLen() / blockLength_;
137
138 assert(blocksPerWrite_ > 0);
139
140 toc_ = toc;
141
142 diskInfo();
143
144 if (!diskInfo_.valid.empty || !diskInfo_.valid.append) {
145 log_message(-2, "Cannot determine status of inserted medium.");
146 return 1;
147 }
148
149 if (!diskInfo_.append) {
150 log_message(-2, "Inserted medium is not appendable.");
151 return 1;
152 }
153
154 if (modeSelectBlockSize(blockLength_, 1) != 0 ||
155 modeSelectSpeed(-1, speed_, simulate_, 1) != 0 ||
156 modeSelectCatalog(toc_) != 0 ||
157 readSessionInfo(&leadInLength_, &leadOutLength_, 1) != 0) {
158 return 1;
159 }
160
161 // allocate buffer for write zeros
162 n = blocksPerWrite_ * blockLength_;
163 delete[] zeroBuffer_;
164 zeroBuffer_ = new char[n];
165 memset(zeroBuffer_, 0, n);
166
167 return 0;
168 }
169
startDao()170 int CDD2600::startDao()
171 {
172 long lba;
173
174 if (writeSession(toc_, multiSession_, diskInfo_.thisSessionLba) != 0) {
175 return 1;
176 }
177
178 log_message(2, "Writing lead-in and gap...");
179
180 lba = diskInfo_.thisSessionLba - 150 - leadInLength_;
181
182 // write lead-in
183 if (writeZeros(toc_->leadInMode(), TrackData::SUBCHAN_NONE, lba, lba + 150,
184 leadInLength_) != 0) {
185 flushCache();
186 return 1;
187 }
188
189 log_message(5, "Lba after lead-in: %ld", lba);
190
191 // write gap (2 seconds)
192 if (writeZeros(toc_->leadInMode(), TrackData::SUBCHAN_NONE,
193 lba, lba + 150, 150) != 0) {
194 flushCache();
195 return 1;
196 }
197
198 log_message(2, "");
199
200 return 0;
201 }
202
finishDao()203 int CDD2600::finishDao()
204 {
205 long lba = diskInfo_.thisSessionLba + toc_->length().lba();
206
207 log_message(2, "Writing lead-out...");
208
209 // write lead-out
210 if (writeZeros(toc_->leadOutMode(), TrackData::SUBCHAN_NONE, lba, lba + 150,
211 leadOutLength_) != 0) {
212 flushCache();
213 return 1;
214 }
215
216 log_message(2, "\nFlushing cache...");
217
218 if (flushCache() != 0) {
219 return 1;
220 }
221
222 log_message(2, "");
223
224 blockLength_ = MODE1_BLOCK_LEN;
225 modeSelectBlockSize(blockLength_, 1);
226
227 delete[] zeroBuffer_, zeroBuffer_ = NULL;
228
229 return 0;
230 }
231
abortDao()232 void CDD2600::abortDao()
233 {
234 flushCache();
235
236 blockLength_ = MODE1_BLOCK_LEN;
237 modeSelectBlockSize(blockLength_, 1);
238 }
239
240 // Writes data to target, the block length depends on the actual writing mode
241 // and is stored internally. 'len' is number of blocks to write.
242 // 'lba' specifies the next logical block address for writing and is updated
243 // by this function but not used for writing
244 // return: 0: OK
245 // 1: scsi command failed
writeData(TrackData::Mode mode,TrackData::SubChannelMode sm,long & lba,const char * buf,long len)246 int CDD2600::writeData(TrackData::Mode mode, TrackData::SubChannelMode sm,
247 long &lba, const char *buf, long len)
248 {
249 assert(blocksPerWrite_ > 0);
250 assert(blockLength_ > 0);
251 assert(mode == TrackData::AUDIO);
252 int nwritten = 0;
253 int writeLen = 0;
254 unsigned char cmd[10];
255
256 memset(cmd, 0, 10);
257 cmd[0] = 0x2a; // WRITE1
258
259 while (len > 0) {
260 writeLen = (len > blocksPerWrite_ ? blocksPerWrite_ : len);
261
262 cmd[7] = writeLen >> 8;
263 cmd[8] = writeLen & 0xff;
264
265 if (sendCmd(cmd, 10, (unsigned char *)(buf + (nwritten * blockLength_)),
266 writeLen * blockLength_, NULL, 0) != 0) {
267 log_message(-2, "Write data failed.");
268 return 1;
269 }
270
271 lba += writeLen;
272
273 len -= writeLen;
274 nwritten += writeLen;
275 }
276
277 return 0;
278 }
279
readDiskToc(int session,const char * audioFilename)280 Toc *CDD2600::readDiskToc(int session, const char *audioFilename)
281 {
282
283 blockLength_ = AUDIO_BLOCK_LEN;
284 if (modeSelectBlockSize(blockLength_, 1) != 0) {
285 return NULL;
286 }
287
288 modeSelectSpeed(2, -1, 1, 0);
289
290 Toc *toc = CdrDriver::readDiskToc(session, audioFilename);
291
292 setBlockSize(MODE1_BLOCK_LEN);
293
294 return toc;
295 }
296
readDisk(int session,const char * fname)297 Toc *CDD2600::readDisk(int session, const char *fname)
298 {
299 Toc *toc = CdrDriver::readDisk(session, fname);
300
301 setBlockSize(MODE1_BLOCK_LEN);
302
303 return toc;
304 }
305
readIsrc(int trackNr,char * buf)306 int CDD2600::readIsrc(int trackNr, char *buf)
307 {
308 unsigned char cmd[10];
309 unsigned short dataLen = 0x30;
310 unsigned char data[0x30];
311 int i;
312
313 memset(cmd, 0, 10);
314 cmd[0] = 0x42; // READ SUB CHANNEL
315 cmd[2] = 0x40; // get sub channel data
316 cmd[3] = 0x03; // get ISRC code
317 cmd[6] = trackNr;
318 cmd[7] = dataLen >> 8;
319 cmd[8] = dataLen;
320
321 if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
322 log_message(-1, "Cannot read ISRC code.");
323 return 1;
324 }
325 else {
326 if (data[0x08] & 0x80) {
327 for (i = 0; i < 12; i++) {
328 buf[i] = data[0x09 + i];
329 }
330 buf[12] = 0;
331 }
332 }
333
334 return 0;
335 }
336
337 // tries to read catalog number from disk and adds it to 'toc'
338 // return: 1 if valid catalog number was found, else 0
339
readCatalog(Toc * toc,long startLba,long endLba)340 int CDD2600::readCatalog(Toc *toc, long startLba, long endLba)
341 {
342 unsigned char cmd[10];
343 unsigned short dataLen = 0x30;
344 unsigned char data[0x30];
345 char catalog[14];
346 int i;
347
348 // read sub channel information
349 memset(cmd, 0, 10);
350 cmd[0] = 0x42; // READ SUB CHANNEL
351 cmd[2] = 0x40; // get sub channel data
352 cmd[3] = 0x02; // get media catalog number
353 cmd[7] = dataLen >> 8;
354 cmd[8] = dataLen;
355
356 if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
357 log_message(-2, "Cannot read sub channel data.");
358 return 0;
359 }
360
361 if (data[0x08] & 0x80) {
362 for (i = 0; i < 13; i++) {
363 catalog[i] = data[0x09 + i];
364 }
365 catalog[13] = 0;
366
367 if (toc->catalog(catalog) == 0) {
368 return 1;
369 }
370 }
371
372 return 0;
373 }
374
analyzeTrack(TrackData::Mode mode,int trackNr,long startLba,long endLba,Msf * index,int * indexCnt,long * pregap,char * isrcCode,unsigned char * ctl)375 int CDD2600::analyzeTrack(TrackData::Mode mode, int trackNr, long startLba,
376 long endLba,
377 Msf *index, int *indexCnt, long *pregap,
378 char *isrcCode, unsigned char *ctl)
379 {
380 blockLength_ = AUDIO_BLOCK_LEN;
381 modeSelectBlockSize(blockLength_, 1);
382
383 int ret = analyzeTrackSearch(mode, trackNr, startLba, endLba,
384 index, indexCnt, pregap, isrcCode, ctl);
385
386 *isrcCode = 0;
387
388 if (mode == TrackData::AUDIO) {
389 // read ISRC code from sub channel
390 readIsrc(trackNr, isrcCode);
391 }
392
393 return ret;
394 }
395
getTrackIndex(long lba,int * trackNr,int * indexNr,unsigned char * ctl)396 int CDD2600::getTrackIndex(long lba, int *trackNr, int *indexNr,
397 unsigned char *ctl)
398 {
399 long relPos;
400
401 readBlock(lba);
402
403 return readSubChannelData(trackNr, indexNr, &relPos, ctl);
404 }
405
readSubChannelData(int * trackNr,int * indexNr,long * relPos,unsigned char * ctl)406 int CDD2600::readSubChannelData(int *trackNr, int *indexNr, long *relPos,
407 unsigned char *ctl)
408 {
409 unsigned char cmd[10];
410 unsigned short dataLen = 0x30;
411 unsigned char data[0x30];
412
413 // read sub channel information
414 memset(cmd, 0, 10);
415 cmd[0] = 0x42; // READ SUB CHANNEL
416 cmd[2] = 0x40; // get sub channel data
417 cmd[3] = 0x00; // get sub Q channel data
418 cmd[6] = 0;
419 cmd[7] = dataLen >> 8;
420 cmd[8] = dataLen;
421
422 if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
423 log_message(-2, "Cannot read sub Q channel data.");
424 return 1;
425 }
426
427 *trackNr = data[6];
428 *indexNr = data[7];
429 *relPos = 0;
430 *relPos |= data[0x0c] << 24;
431 *relPos |= data[0x0d] << 16;
432 *relPos |= data[0x0e] << 8;
433 *relPos |= data[0x0f];
434
435 if (ctl != NULL) {
436 *ctl = data[5] & 0x0f;
437 }
438
439 return 0;
440 }
441
442 // reads a single block of length 'blockLength_' from given sector
443 // return: 0: OK
444 // 1: error occured
readBlock(unsigned long sector)445 void CDD2600::readBlock(unsigned long sector)
446 {
447 unsigned char cmd[10];
448 unsigned long dataLen = 2 * blockLength_;
449 unsigned char *data = new unsigned char[dataLen];
450
451
452 // read sub channel information
453 memset(cmd, 0, 10);
454 cmd[0] = 0x28; // READ10
455 cmd[2] = sector >> 24;
456 cmd[3] = sector >> 16;
457 cmd[4] = sector >> 8;
458 cmd[5] = sector;
459 cmd[7] = 0;
460 cmd[8] = 2;
461
462 if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
463 log_message(-2, "Cannot read block - ignored.");
464 }
465
466 delete[] data;
467 }
468
nextWritableAddress(long * lba,int showError)469 int CDD2600::nextWritableAddress(long *lba, int showError)
470 {
471 unsigned char cmd[10];
472 unsigned char data[6];
473
474 memset(data, 0, 6);
475 memset(cmd, 0, 10);
476
477 cmd[0] = 0xe2; // FIRST WRITABLE ADDRESS
478 cmd[3] = 1 /*<< 2*/; // AUDIO
479 // cmd[7] = 1; // NPA
480 cmd[8] = 6; // allocation length
481
482 if (sendCmd(cmd, 10, NULL, 0, data, 6, showError) != 0) {
483 if (showError)
484 log_message(-2, "Cannot retrieve next writable address.");
485 return 1;
486 }
487
488 *lba = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
489
490 return 0;
491 }
492
493 // Retrieve disk information.
494 // return: DiskInfo structure or 'NULL' on error
diskInfo()495 DiskInfo *CDD2600::diskInfo()
496 {
497 unsigned char cmd[10];
498 unsigned char data[34];
499 long nwa;
500 int i;
501
502 memset(&diskInfo_, 0, sizeof(DiskInfo));
503
504 if (readCapacity(&(diskInfo_.capacity), 0) == 0) {
505 diskInfo_.valid.capacity = 1;
506 }
507
508 if (readSessionInfo(&leadInLength_, &leadOutLength_, 0) == 0) {
509 diskInfo_.valid.manufacturerId = 1;
510
511 // start time of lead-in
512 diskInfo_.manufacturerId = Msf(450150 - leadInLength_ - 150 );
513 diskInfo_.append = 1; // this is for the CDD2000 which does not support
514 // READ DISK INFORMATION
515 }
516 else {
517 diskInfo_.append = 0; // this is for the CDD2000 which does not support
518 // READ DISK INFORMATION
519 }
520 diskInfo_.valid.empty = 1;
521 diskInfo_.valid.append = 1;
522
523 memset(cmd, 0, 10);
524 memset(data, 0, 4);
525
526 cmd[0] = 0x43; // READ TOC
527 cmd[6] = 0;
528 cmd[8] = 4;
529
530 if (sendCmd(cmd, 10, NULL, 0, data, 4, 0) == 0) {
531 log_message(5, "First track %u, last track %u", data[2], data[3]);
532 diskInfo_.lastTrackNr = data[3];
533 }
534 else {
535 log_message(5, "READ TOC (format 0) failed.");
536 }
537
538 if (diskInfo_.lastTrackNr > 0) {
539 // the lead-in length does not specify the manufacturer ID anymore
540 diskInfo_.valid.manufacturerId = 0;
541
542 diskInfo_.empty = 0; // CD-R is not empty
543 diskInfo_.diskTocType = 0xff; // undefined
544
545 if (diskInfo_.lastTrackNr < 99 && nextWritableAddress(&nwa, 0) == 0) {
546 log_message(5, "NWA: %ld", nwa);
547 diskInfo_.thisSessionLba = nwa;
548 diskInfo_.append = 1;
549 }
550 else {
551 diskInfo_.append = 0;
552 }
553
554
555 memset(cmd, 0, 10);
556 memset(data, 0, 12);
557
558 cmd[0] = 0x43; // READ TOC
559 cmd[6] = 0;
560 cmd[8] = 12;
561 cmd[9] = 1 << 6;
562
563 if (sendCmd(cmd, 10, NULL, 0, data, 12) == 0) {
564 diskInfo_.sessionCnt = data[3];
565 diskInfo_.lastSessionLba = (data[8] << 24) | (data[9] << 16) |
566 (data[10] << 8) | data[11];
567
568 log_message(5, "First session %u, last session %u, last session start %ld",
569 data[2], data[3], diskInfo_.lastSessionLba);
570 }
571 else {
572 log_message(5, "READ TOC (format 1) failed.");
573 }
574
575 if (diskInfo_.sessionCnt > 0) {
576 int len;
577 CdRawToc *toc = getRawToc(diskInfo_.sessionCnt, &len);
578
579 if (toc != NULL) {
580 for (i = 0; i < len; i++) {
581 if (toc[i].sessionNr == diskInfo_.sessionCnt) {
582 #if 0
583 if (toc[i].point == 0xb0 && toc[i].min != 0xff &&
584 toc[i].sec != 0xff && toc[i].frame != 0xff) {
585 int m = toc[i].min;
586 int s = toc[i].sec;
587 int f = toc[i].frame;
588
589 if (m < 90 && s < 60 && f < 75) {
590 diskInfo_.thisSessionLba = Msf(m, s, f).lba(); // + 150 - 150
591 diskInfo_.thisSessionLba += leadInLength_;
592 }
593 }
594 #endif
595 if (toc[i].point == 0xa0) {
596 diskInfo_.diskTocType = toc[i].psec;
597 }
598 }
599
600 // The point C0 entry may be only stored in the first session's
601 // lead-in
602 if (toc[i].point == 0xc0 && toc[i].pmin <= 99 &&
603 toc[i].psec < 60 && toc[i].pframe < 75) {
604 diskInfo_.manufacturerId =
605 Msf(toc[i].pmin, toc[i].psec, toc[i].pframe);
606 diskInfo_.valid.manufacturerId = 1;
607 }
608 }
609
610 #if 0
611 if (diskInfo_.thisSessionLba > 0) {
612 if (diskInfo_.lastTrackNr < 99)
613 diskInfo_.append = 1;
614 }
615 else {
616 log_message(4, "Did not find BO pointer in session %d.",
617 diskInfo_.sessionCnt);
618
619 }
620 #endif
621
622 delete[] toc;
623 }
624 else {
625 log_message(5, "getRawToc failed.");
626 }
627 }
628 }
629 else {
630 // disk is empty and appendable
631 diskInfo_.empty = 1;
632 }
633
634 if (diskInfo_.append == 0)
635 diskInfo_.empty = 0;
636
637 return &diskInfo_;
638 }
639
getRawToc(int sessionNr,int * len)640 CdRawToc *CDD2600::getRawToc(int sessionNr, int *len)
641 {
642 unsigned char cmd[10];
643 unsigned short dataLen;
644 unsigned char *data = NULL;;
645 unsigned char reqData[4]; // buffer for requestion the actual length
646 unsigned char *p = NULL;
647 int i;
648 CdRawToc *rawToc;
649 int entries;
650
651 assert(sessionNr >= 1);
652
653 // read disk toc length
654 memset(cmd, 0, 10);
655 cmd[0] = 0x43; // READ TOC
656 cmd[6] = sessionNr;
657 cmd[8] = 4;
658 cmd[9] |= 2 << 6; // get Q subcodes
659
660 if (sendCmd(cmd, 10, NULL, 0, reqData, 4) != 0) {
661 log_message(-2, "Cannot read raw disk toc.");
662 return NULL;
663 }
664
665 dataLen = ((reqData[0] << 8) | reqData[1]) + 2;
666
667 log_message(5, "Raw toc data len: %d", dataLen);
668
669 data = new unsigned char[dataLen];
670
671 // read disk toc
672 cmd[7] = dataLen >> 8;
673 cmd[8] = dataLen;
674
675 if (sendCmd(cmd, 10, NULL, 0, data, dataLen) != 0) {
676 log_message(-2, "Cannot read raw disk toc.");
677 delete[] data;
678 return NULL;
679 }
680
681 entries = (((data[0] << 8) | data[1]) - 2) / 11;
682
683
684 rawToc = new CdRawToc[entries];
685
686 for (i = 0, p = data + 4; i < entries; i++, p += 11 ) {
687 #if 0
688 log_message(0, "%d %02x %02d %2x %02d:%02d:%02d %02x %02d:%02d:%02d",
689 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10]);
690 #endif
691 rawToc[i].sessionNr = p[0];
692 rawToc[i].adrCtl = p[1];
693 rawToc[i].point = p[3];
694 rawToc[i].min = p[4];
695 rawToc[i].sec = p[5];
696 rawToc[i].frame = p[6];
697 rawToc[i].pmin = p[8];
698 rawToc[i].psec = p[9];
699 rawToc[i].pframe = p[10];
700 }
701
702 delete[] data;
703
704 *len = entries;
705
706 return rawToc;
707 }
708
readTrackData(TrackData::Mode mode,TrackData::SubChannelMode,long lba,long len,unsigned char * buf)709 long CDD2600::readTrackData(TrackData::Mode mode, TrackData::SubChannelMode,
710 long lba, long len, unsigned char *buf)
711 {
712 unsigned char cmd[10];
713 long blockLen = 2340;
714 long i;
715 TrackData::Mode actMode;
716 int ok = 0;
717 const unsigned char *sense;
718 int senseLen;
719 int softError;
720
721 if (setBlockSize(blockLen) != 0)
722 return 0;
723
724 memset(cmd, 0, 10);
725
726 cmd[0] = 0x28; // READ10
727 cmd[2] = lba >> 24;
728 cmd[3] = lba >> 16;
729 cmd[4] = lba >> 8;
730 cmd[5] = lba;
731
732 /*
733 if (mode == TrackData::MODE2_FORM1 || mode == TrackData::MODE2_FORM2)
734 cmd[9] = 1 << 6; // MIX flag
735 */
736
737 while (len > 0 && !ok) {
738 cmd[7] = len >> 8;
739 cmd[8] = len;
740
741 memset(transferBuffer_, 0, len * blockLen);
742 switch (sendCmd(cmd, 10, NULL, 0, transferBuffer_, len * blockLen, 0)) {
743 case 0:
744 ok = 1;
745 break;
746
747 case 2:
748 softError = 0;
749 sense = scsiIf_->getSense(senseLen);
750
751 if (senseLen > 0x0c) {
752 if ((sense[2] &0x0f) == 5) {
753 switch (sense[12]) {
754 case 0x64: // Illegal mode for this track
755 softError = 1;
756 break;
757 }
758 }
759 else if ((sense[2] & 0x0f) == 3) { // Medium error
760 switch (sense[12]) {
761 case 0x02: // No seek complete, sector not found
762 case 0x11: // L-EC error
763 return -2;
764 break;
765 }
766 }
767 }
768
769 if (!softError) {
770 scsiIf_->printError();
771 return -1;
772 }
773 break;
774
775 default:
776 log_message(-2, "Read error at LBA %ld, len %ld", lba, len);
777 return -1;
778 break;
779 }
780
781 if (!ok) {
782 len--;
783 }
784 }
785
786 unsigned char *sector = transferBuffer_;
787 for (i = 0; i < len; i++) {
788 actMode = determineSectorMode(sector);
789
790 if (!(actMode == mode ||
791 (mode == TrackData::MODE2_FORM_MIX &&
792 (actMode == TrackData::MODE2_FORM1 ||
793 actMode == TrackData::MODE2_FORM2)) ||
794
795 (mode == TrackData::MODE1_RAW && actMode == TrackData::MODE1) ||
796
797 (mode == TrackData::MODE2_RAW &&
798 (actMode == TrackData::MODE2 ||
799 actMode == TrackData::MODE2_FORM1 ||
800 actMode == TrackData::MODE2_FORM2)))) {
801 return i;
802 }
803
804 if (buf != NULL) {
805 switch (mode) {
806 case TrackData::MODE1:
807 memcpy(buf, sector + 4, MODE1_BLOCK_LEN);
808 buf += MODE1_BLOCK_LEN;
809 break;
810 case TrackData::MODE2:
811 case TrackData::MODE2_FORM_MIX:
812 memcpy(buf, sector + 4, MODE2_BLOCK_LEN);
813 buf += MODE2_BLOCK_LEN;
814 break;
815 case TrackData::MODE2_FORM1:
816 memcpy(buf, sector + 12, MODE2_FORM1_DATA_LEN);
817 buf += MODE2_FORM1_DATA_LEN;
818 break;
819 case TrackData::MODE2_FORM2:
820 memcpy(buf, sector + 12, MODE2_FORM2_DATA_LEN);
821 buf += MODE2_FORM2_DATA_LEN;
822 break;
823 case TrackData::MODE1_RAW:
824 case TrackData::MODE2_RAW:
825 memcpy(buf, syncPattern, 12);
826 memcpy(buf + 12, sector, 2340);
827 buf += AUDIO_BLOCK_LEN;
828 break;
829 case TrackData::MODE0:
830 case TrackData::AUDIO:
831 log_message(-3, "CDD2600::readTrackData: Illegal mode.");
832 return 0;
833 break;
834 }
835 }
836
837 sector += blockLen;
838 }
839
840 return len;
841 }
842
readSubChannels(TrackData::SubChannelMode,long lba,long len,SubChannel *** chans,Sample * audioData)843 int CDD2600::readSubChannels(TrackData::SubChannelMode, long lba, long len,
844 SubChannel ***chans, Sample *audioData)
845 {
846 unsigned char cmd[10];
847 int tries = 5;
848 int ret;
849
850 if (setBlockSize(AUDIO_BLOCK_LEN) != 0)
851 return 1;
852
853 memset(cmd, 0, 10);
854
855 cmd[0] = 0x28; // READ10
856 cmd[2] = lba >> 24;
857 cmd[3] = lba >> 16;
858 cmd[4] = lba >> 8;
859 cmd[5] = lba;
860 cmd[7] = len >> 8;
861 cmd[8] = len;
862
863 do {
864 ret = sendCmd(cmd, 10, NULL, 0,
865 (unsigned char*)audioData, len * AUDIO_BLOCK_LEN,
866 (tries == 1) ? 1 : 0);
867
868 if (ret != 0 && tries == 1) {
869 log_message(-2, "Reading of audio data failed at sector %ld.", lba);
870 return 1;
871 }
872
873 tries--;
874 } while (ret != 0 && tries > 0);
875
876 *chans = NULL;
877 return 0;
878 }
879
readAudioRange(ReadDiskInfo * rinfo,int fd,long start,long end,int startTrack,int endTrack,TrackInfo * info)880 int CDD2600::readAudioRange(ReadDiskInfo *rinfo, int fd, long start, long end,
881 int startTrack, int endTrack,
882 TrackInfo *info)
883 {
884 if (!onTheFly_) {
885 int t;
886
887 log_message(1, "Analyzing...");
888
889 for (t = startTrack; t <= endTrack; t++) {
890 long totalProgress;
891
892 totalProgress = t * 1000;
893 totalProgress /= rinfo->tracks;
894
895 sendReadCdProgressMsg(RCD_ANALYZING, rinfo->tracks, t + 1, 0,
896 totalProgress);
897
898 log_message(2, "Track %d...", t + 1);
899 info[t].isrcCode[0] = 0;
900 readIsrc(t + 1, info[t].isrcCode);
901
902 if (info[t].isrcCode[0] != 0)
903 log_message(2, "Found ISRC code.");
904
905 totalProgress = (t + 1) * 1000;
906 totalProgress /= rinfo->tracks;
907
908 sendReadCdProgressMsg(RCD_ANALYZING, rinfo->tracks, t + 1, 1000,
909 totalProgress);
910 }
911
912 log_message(1, "Reading...");
913 }
914
915 return CdrDriver::readAudioRangeParanoia(rinfo, fd, start, end, startTrack,
916 endTrack, info);
917 }
918