1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2
3 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
4 Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
5 Provided under GPL version 2 or later.
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include "../config.h"
10 #endif
11
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <signal.h>
15
16 /* ts A61007 */
17 /* #include <a ssert.h> */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <fcntl.h>
23 #include <errno.h>
24
25 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
26 #ifndef O_BINARY
27 #define O_BINARY 0
28 #endif
29
30 #include "sector.h"
31 #include "libburn.h"
32 #include "drive.h"
33 #include "transport.h"
34
35 /* ts A60925 : obsoleted by libdax_msgs.h
36 #include "message.h"
37 */
38
39 #include "crc.h"
40 #include "debug.h"
41 #include "init.h"
42 #include "toc.h"
43 #include "util.h"
44 #include "mmc.h"
45 #include "sg.h"
46 #include "read.h"
47 #include "options.h"
48
49 /* ts A70812 */
50 #include "error.h"
51 #include "libdax_msgs.h"
52 extern struct libdax_msgs *libdax_messenger;
53
54
burn_disc_read(struct burn_drive * d,const struct burn_read_opts * o)55 void burn_disc_read(struct burn_drive *d, const struct burn_read_opts *o)
56 {
57 #if 0
58 int i, end, maxsects, finish;
59 int seclen;
60 int drive_lba;
61 unsigned short crc;
62 unsigned char fakesub[96];
63 struct buffer page; <- needs to become dynamic memory
64 int speed;
65
66 /* ts A61007 : if this function gets revived, then these
67 tests have to be done more graceful */
68 a ssert((o->version & 0xfffff000) == (OPTIONS_VERSION & 0xfffff000));
69 a ssert(!d->busy);
70 a ssert(d->toc->valid);
71 a ssert(o->datafd != -1);
72
73 /* moved up from spc_select_error_params alias d->send_parameters() */
74 a ssert(d->mdata->valid);
75
76 /* XXX not sure this is a good idea. copy it? */
77 /* XXX also, we have duplicated data now, do we remove the fds from struct
78 drive, or only store a subset of the _opts structs in drives */
79
80 /* set the speed on the drive */
81 speed = o->speed > 0 ? o->speed : d->mdata->max_read_speed;
82 d->set_speed(d, speed, 0);
83
84 d->params.retries = o->hardware_error_retries;
85
86 d->send_parameters(d, o);
87
88 d->cancel = 0;
89 d->busy = BURN_DRIVE_READING;
90 d->currsession = 0;
91 /* drive_lba = 232000;
92 d->currtrack = 18;
93 */
94 d->currtrack = 0;
95 drive_lba = 0;
96 /* XXX removal of this line obviously breaks *
97 d->track_end = burn_track_end(d, d->currsession, d->currtrack);*/
98 printf("track ends at %d\n", d->track_end);
99 page.sectors = 0;
100 page.bytes = 0;
101
102 if (o->subfd != -1) {
103 memset(fakesub, 0xFF, 12);
104 memset(fakesub + 12, 0, 84);
105 fakesub[13] = 1;
106 fakesub[14] = 1;
107 fakesub[20] = 2;
108 fakesub[12] = (d->toc->toc_entry[0].control << 4) +
109 d->toc->toc_entry[0].adr;
110
111 #ifdef Libburn_no_crc_C
112 crc = 0; /* dummy */
113 #else
114 crc = crc_ccitt(fakesub + 12, 10);
115 #endif
116
117 fakesub[22] = crc >> 8;
118 fakesub[23] = crc & 0xFF;
119 write(o->subfd, fakesub, 96);
120 }
121 while (1) {
122 seclen = burn_sector_length_read(d, o);
123
124 for (i = 0; i < page.sectors; i++) {
125 burn_packet_process(d, page.data + seclen * i, o);
126 d->track_end--;
127 drive_lba++;
128 }
129
130 if ((d->cancel) || (drive_lba == LAST_SESSION_END(d))) {
131 d->busy = BURN_DRIVE_IDLE;
132 if (!d->cancel)
133 d->toc->complete = 1;
134 return;
135 }
136 /* XXX: removal of this line obviously breaks *
137 end = burn_track_end(d, d->currsession, d->currtrack); */
138
139 if (drive_lba == end) {
140 d->currtrack++;
141 if (d->currtrack >
142 d->toc->session[d->currsession].lasttrack) {
143 d->currsession++;
144 /* session switch to d->currsession */
145 /* skipping a lead out */
146 drive_lba = CURRENT_SESSION_START(d);
147 /* XXX more of the same
148 end = burn_track_end(d, d->currsession,
149 d->currtrack);
150 */
151 }
152 }
153
154 page.sectors = 0;
155 page.bytes = 0;
156
157 maxsects = BUFFER_SIZE / seclen;
158 finish = end - drive_lba;
159
160 d->track_end = finish;
161
162 page.sectors = (finish < maxsects) ? finish : maxsects;
163 printf("reading %d sectors from %d\n", page.sectors,
164 drive_lba);
165
166 /* >>> ts A61009 : ensure page.sectors >= 0 before calling */
167 /* >>> ts B21123 : Would now be d->read_cd() with
168 with sectype = 0 , mainch = 0xf8 */
169 d->r ead_sectors(d, drive_lba, page.sectors, o, &page);
170
171 printf("Read %d\n", page.sectors);
172 }
173 #endif
174 }
burn_sector_length_read(struct burn_drive * d,const struct burn_read_opts * o)175 int burn_sector_length_read(struct burn_drive *d,
176 const struct burn_read_opts *o)
177 {
178 int dlen = 2352;
179 int data;
180
181 /*XXX how do we handle this crap now?*/
182 /* data = d->toc->track[d->currtrack].toc_entry->control & 4;*/
183 data = 1;
184 if (o->report_recovered_errors)
185 dlen += 294;
186 if ((o->subcodes_data) && data)
187 dlen += 96;
188 if ((o->subcodes_audio) && !data)
189 dlen += 96;
190 return dlen;
191 }
192
bitcount(unsigned char * data,int n)193 static int bitcount(unsigned char *data, int n)
194 {
195 int i, j, count = 0;
196 unsigned char tem;
197
198 for (i = 0; i < n; i++) {
199 tem = data[i];
200 for (j = 0; j < 8; j++) {
201 count += tem & 1;
202 tem >>= 1;
203 }
204 }
205 return count;
206 }
207
208
burn_packet_process(struct burn_drive * d,unsigned char * data,const struct burn_read_opts * o)209 void burn_packet_process(struct burn_drive *d, unsigned char *data,
210 const struct burn_read_opts *o)
211 {
212 unsigned char sub[96];
213 int ptr = 2352, i, j, code, fb;
214 int audio = 1;
215 #ifndef Libburn_no_crc_C
216 unsigned short crc;
217 #endif
218
219 if (o->c2errors) {
220 fb = bitcount(data + ptr, 294);
221 if (fb) {
222 /* bitcount(data + ptr, 294) damaged bits */;
223 }
224 ptr += 294;
225 }
226 /*
227 if (d->toc->track[d->currtrack].mode == BURN_MODE_UNINITIALIZED) {
228 if ((d->toc->track[d->currtrack].toc_entry->control & 4) == 0)
229 d->toc->track[d->currtrack].mode = BURN_MODE_AUDIO;
230 else
231 switch (data[15]) {
232 case 0:
233 d->toc->track[d->currtrack].mode = BURN_MODE0;
234 break;
235 case 1:
236 d->toc->track[d->currtrack].mode = BURN_MODE1;
237 break;
238 case 2:
239 d->toc->track[d->currtrack].mode =
240 BURN_MODE2_FORMLESS;
241 break;
242 }
243 }
244 */
245 if ((audio && o->subcodes_audio)
246 || (!audio && o->subcodes_data)) {
247 memset(sub, 0, sizeof(sub));
248 for (i = 0; i < 12; i++) {
249 for (j = 0; j < 8; j++) {
250 for (code = 0; code < 8; code++) {
251 sub[code * 12 + i] <<= 1;
252 if (data[ptr + j + i * 8] &
253 (1 << (7 - code)))
254 sub[code * 12 + i]++;
255 }
256 }
257 }
258
259 #ifndef Libburn_no_crc_C
260 crc = (*(sub + 22) << 8) + *(sub + 23);
261 if (crc != crc_ccitt(sub + 12, 10)) {
262 /*
263 burn_print(1, "sending error on %s %s\n",
264 d->idata->vendor, d->idata->product);
265 e = burn_error();
266 e->drive = d;
267 burn_print(1, "crc mismatch in Q\n");
268 */;
269 }
270 #endif
271
272 /* else process_q(d, sub + 12); */
273 /*
274 if (o->subfd != -1) write(o->subfd, sub, 96); */
275 }
276 /*
277 if ((d->track_end <= 150)
278 && (drive_lba + 150 < CURRENT_SESSION_END(d))
279 && (TOC_ENTRY(d->toc, d->currtrack).control == 4)
280 && (TOC_ENTRY(d->toc, d->currtrack + 1).control == 0)) {
281 burn_print(12, "pregap : %d\n", d->track_end);
282 write(o->binfd, zeros, 2352);
283
284 #warning XXX WHERE ARE MY SUBCODES
285 } else
286 *//* write(o->datafd, data, 2352); */
287 }
288
289 /* so yeah, when you uncomment these, make them write zeros instead of crap
290 static void write_empty_sector(int fd)
291 {
292 static char sec[2352], initialized = 0;
293
294 if (!initialized) {
295 memset(sec, 0, 2352);
296 initialized = 1;
297 }
298 burn_print(1, "writing an 'empty' sector\n");
299 write(fd, sec, 2352);
300 }
301
302 static void write_empty_subcode(int fd)
303 {
304 char sub[96];
305
306 write(fd, sub, 96);
307 }
308
309 static void flipq(unsigned char *sub)
310 {
311 *(sub + 12 + 10) = ~*(sub + 12 + 10);
312 *(sub + 12 + 11) = ~*(sub + 12 + 11);
313 }
314 */
315
316
317 /** @param flag bit1= be silent on failure
318 bit5= report failure with severity DEBUG
319 */
burn_stdio_seek(int fd,off_t byte_address,struct burn_drive * d,int flag)320 static int burn_stdio_seek(int fd, off_t byte_address, struct burn_drive *d,
321 int flag)
322 {
323 char msg[80];
324
325 if (lseek(fd, byte_address, SEEK_SET) != -1)
326 return 1;
327 if (!(flag & 2)) {
328 sprintf(msg, "Cannot address start byte %.f",
329 (double) byte_address);
330 libdax_msgs_submit(libdax_messenger,
331 d->global_index, 0x00020147,
332 (flag & 32) ?
333 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
334 LIBDAX_MSGS_PRIO_HIGH, msg, errno, 0);
335 }
336 return 0;
337 }
338
339
340 /* ts A70904 */
341 /** @param flag bit0= be silent on data shortage
342 bit5= report data shortage with severity DEBUG
343 */
burn_stdio_read(int fd,char * buf,int bufsize,struct burn_drive * d,int flag)344 int burn_stdio_read(int fd, char *buf, int bufsize, struct burn_drive *d,
345 int flag)
346 {
347 int todo, count = 0;
348
349 for(todo = bufsize; todo > 0; ) {
350 count = read(fd, buf + (bufsize - todo), todo);
351 if(count <= 0)
352 break;
353 todo -= count;
354 }
355 if(todo > 0 && !(flag & 1)) {
356 libdax_msgs_submit(libdax_messenger, d->global_index,
357 0x0002014a,
358 (flag & 32) ?
359 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
360 LIBDAX_MSGS_PRIO_HIGH,
361 "Cannot read desired amount of data", errno, 0);
362 }
363 if (count < 0)
364 return -1;
365 return (bufsize - todo);
366 }
367
368
369 /* With DVD and BD media, the minimum ECC entity is read instead of single
370 blocks.
371 @param flag see burn_read_data() in libburn.h
372 */
retry_mmc_read(struct burn_drive * d,int chunksize,int sose_mem,int start,char ** wpt,off_t * data_count,int flag)373 static int retry_mmc_read(struct burn_drive *d, int chunksize, int sose_mem,
374 int start, char **wpt, off_t *data_count,
375 int flag)
376 {
377 int i, err, todo;
378 int retry_at, retry_size;
379
380 retry_at = start;
381 retry_size = chunksize;
382 todo = chunksize;
383 retry_size = 16; /* DVD ECC block size */
384 if (d->current_is_cd_profile) {
385 retry_size = 1; /* CD block size */
386 } else if (d->current_profile >= 0x40 && d->current_profile <= 0x43) {
387 retry_size = 32; /* BD cluster size */
388 }
389 for (i = 0; todo > 0; i++) {
390 if (flag & 2)
391 d->silent_on_scsi_error = 1;
392 else if (flag & 32)
393 d->silent_on_scsi_error = 3;
394 retry_at = start + i * retry_size;
395 if (retry_size > todo)
396 retry_size = todo;
397 err = d->read_10(d, retry_at, retry_size, d->buffer);
398 if (flag & (2 | 32))
399 d->silent_on_scsi_error = sose_mem;
400 if (err == BE_CANCELLED)
401 return 0;
402 memcpy(*wpt, d->buffer->data, retry_size * 2048);
403 *wpt += retry_size * 2048;
404 *data_count += retry_size * 2048;
405 todo -= retry_size;
406 }
407 return 1;
408 }
409
410
411 /* @param flag see burn_read_data() in libburn.h
412 */
retry_stdio_read(struct burn_drive * d,int fd,int chunksize,int start,char ** wpt,off_t * data_count,int flag)413 static int retry_stdio_read(struct burn_drive *d, int fd, int chunksize,
414 int start, char **wpt, off_t *data_count,
415 int flag)
416 {
417 int i, ret, to_read, todo;
418
419 ret = burn_stdio_seek(fd, ((off_t) start) * 2048, d, flag & 2);
420 if (ret <= 0)
421 return ret;
422 todo = chunksize * 2048;
423 for (i = 0; todo > 0; i += 2048) {
424 to_read = todo;
425 if (to_read > 2048)
426 to_read = 2048;
427 ret = burn_stdio_read(fd, (char *) d->buffer->data, to_read,
428 d, 1);
429 if (ret <= 0)
430 return 0;
431 memcpy(*wpt, d->buffer->data, to_read);
432 *wpt += to_read;
433 *data_count += to_read;
434 todo -= to_read;
435 }
436 return 1;
437 }
438
439
440 /* ts A70812 : API function */
burn_read_data(struct burn_drive * d,off_t byte_address,char data[],off_t data_size,off_t * data_count,int flag)441 int burn_read_data(struct burn_drive *d, off_t byte_address,
442 char data[], off_t data_size, off_t *data_count, int flag)
443 {
444 int alignment = 2048, start, upto, chunksize = 1, err, cpy_size;
445 int sose_mem = 0, fd = -1, ret;
446 char msg[81], *wpt;
447 struct buffer *buf = NULL, *buffer_mem = d->buffer;
448
449 /*
450 #define Libburn_read_data_adr_logginG 1
451 */
452 #ifdef Libburn_read_data_adr_logginG
453 static FILE *log_fp= NULL;
454
455 if(log_fp == NULL)
456 log_fp = fopen("/tmp/burn_read_data_log", "a");
457 if(log_fp!=NULL)
458 fprintf(log_fp, "%d\n", (int) (byte_address / 2048));
459 #endif /* Libburn_read_data_logginG */
460
461 BURN_ALLOC_MEM(buf, struct buffer, 1);
462 *data_count = 0;
463 sose_mem = d->silent_on_scsi_error;
464
465 if (d->released) {
466 libdax_msgs_submit(libdax_messenger,
467 d->global_index, 0x00020142,
468 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
469 "Drive is not grabbed on random access read", 0, 0);
470 {ret = 0; goto ex;}
471 }
472 if (d->drive_role == 0) {
473 libdax_msgs_submit(libdax_messenger, d->global_index,
474 0x00020146,
475 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
476 "Drive is a virtual placeholder (null-drive)", 0, 0);
477 {ret = 0; goto ex;}
478 } else if (d->drive_role == 3) {
479 libdax_msgs_submit(libdax_messenger, d->global_index,
480 0x00020151,
481 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
482 "Read attempt on write-only drive", 0, 0);
483 {ret = 0; goto ex;}
484 }
485 if ((byte_address % alignment) != 0) {
486 sprintf(msg,
487 "Read start address not properly aligned (%d bytes)",
488 alignment);
489 libdax_msgs_submit(libdax_messenger, d->global_index,
490 0x00020143,
491 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
492 msg, 0, 0);
493 {ret = 0; goto ex;}
494 }
495 if (d->media_read_capacity != 0x7fffffff && byte_address >=
496 ((off_t) d->media_read_capacity + (off_t) 1) * (off_t) 2048) {
497 if (!(flag & 2)) {
498 sprintf(msg,
499 "Read start address %ds larger than number of readable blocks %d",
500 (int) (byte_address / 2048 + !!(byte_address % 2048)),
501 d->media_read_capacity + 1);
502 libdax_msgs_submit(libdax_messenger, d->global_index,
503 0x00020172, (flag & 32) ?
504 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
505 LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
506 }
507 {ret = 0; goto ex;}
508 }
509
510 if (d->busy != BURN_DRIVE_IDLE) {
511 libdax_msgs_submit(libdax_messenger,
512 d->global_index, 0x00020145,
513 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
514 "Drive is busy on attempt to read data", 0, 0);
515 {ret = 0; goto ex;}
516 }
517
518 if (d->drive_role != 1) {
519
520 /* <<< We need _LARGEFILE64_SOURCE defined by the build system.
521 */
522 #ifndef O_LARGEFILE
523 #define O_LARGEFILE 0
524 #endif
525
526 fd = d->stdio_fd;
527 if (fd < 0)
528 d->stdio_fd = fd =
529 open(d->devname,
530 O_RDONLY | O_LARGEFILE | O_BINARY);
531 if (fd == -1) {
532 if (errno == EACCES && (flag & 2)) {
533 if (!(flag & 8))
534 libdax_msgs_submit(libdax_messenger,
535 d->global_index, 0x00020183,
536 LIBDAX_MSGS_SEV_WARNING,
537 LIBDAX_MSGS_PRIO_HIGH,
538 "Failed to open device (a pseudo-drive) for reading",
539 errno, 0);
540 } else if (errno != ENOENT || !(flag & 2))
541 libdax_msgs_submit(libdax_messenger,
542 d->global_index, 0x00020005,
543 (flag & 32) && errno == ENOENT ?
544 LIBDAX_MSGS_SEV_DEBUG :
545 LIBDAX_MSGS_SEV_SORRY,
546 LIBDAX_MSGS_PRIO_HIGH,
547 "Failed to open device (a pseudo-drive) for reading",
548 errno, 0);
549 ret = 0;
550 if (errno == EACCES && (flag & 8))
551 ret= -2;
552 goto ex;
553 }
554 ret = burn_stdio_seek(fd, byte_address, d, flag & (2 | 32));
555 if (ret <= 0)
556 goto ex;
557 }
558
559 d->busy = BURN_DRIVE_READING_SYNC;
560 d->buffer = buf;
561
562 start = byte_address / 2048;
563 upto = start + data_size / 2048;
564 if (data_size % 2048)
565 upto++;
566 wpt = data;
567 for (; start < upto; start += chunksize) {
568 chunksize = upto - start;
569 if (chunksize > (BUFFER_SIZE / 2048)) {
570 chunksize = (BUFFER_SIZE / 2048);
571 cpy_size = BUFFER_SIZE;
572 } else
573 cpy_size = data_size - *data_count;
574 if (flag & 2)
575 d->silent_on_scsi_error = 1;
576 else if (flag & 32)
577 d->silent_on_scsi_error = 3;
578 if (flag & 16) {
579 d->had_particular_error &= ~1;
580 if (!d->silent_on_scsi_error)
581 d->silent_on_scsi_error = 2;
582 }
583 if (d->drive_role == 1) {
584 err = d->read_10(d, start, chunksize, d->buffer);
585 } else {
586 ret = burn_stdio_read(fd, (char *) d->buffer->data,
587 cpy_size, d,
588 (flag & 32) | !!(flag & 2));
589 err = 0;
590 if (ret <= 0)
591 err = BE_CANCELLED;
592 }
593 if (flag & (2 | 16 | 32))
594 d->silent_on_scsi_error = sose_mem;
595 if (err == BE_CANCELLED) {
596 if ((flag & 16) && (d->had_particular_error & 1))
597 {ret = -3; goto ex;}
598 /* Retry: with CD read by single blocks
599 with other media: retry in full chunks
600 */
601 if(flag & 4)
602 goto bad_read;
603 if (d->drive_role == 1) {
604 ret = retry_mmc_read(d, chunksize, sose_mem,
605 start, &wpt, data_count, flag);
606 } else {
607 ret = retry_stdio_read(d, fd, chunksize,
608 start, &wpt, data_count, flag);
609 }
610 if (ret <= 0)
611 goto bad_read;
612 } else {
613 memcpy(wpt, d->buffer->data, cpy_size);
614 wpt += cpy_size;
615 *data_count += cpy_size;
616 }
617 }
618
619 ret = 1;
620 ex:;
621 BURN_FREE_MEM(buf);
622 d->buffer = buffer_mem;
623 d->busy = BURN_DRIVE_IDLE;
624 return ret;
625
626 bad_read:;
627 if (!(flag & 2))
628 libdax_msgs_submit(libdax_messenger, d->global_index,
629 0x00020000,
630 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
631 "burn_read_data() returns 0", 0, 0);
632 ret = 0; goto ex;
633 }
634
635
636 /* ts B21119 : API function*/
burn_read_audio(struct burn_drive * d,int sector_no,char data[],off_t data_size,off_t * data_count,int flag)637 int burn_read_audio(struct burn_drive *d, int sector_no,
638 char data[], off_t data_size, off_t *data_count, int flag)
639 {
640 int alignment = 2352, start, upto, chunksize = 1, err, cpy_size, i;
641 int sose_mem = 0, ret;
642 char msg[81], *wpt;
643 struct buffer *buf = NULL, *buffer_mem = d->buffer;
644
645 BURN_ALLOC_MEM(buf, struct buffer, 1);
646 *data_count = 0;
647 sose_mem = d->silent_on_scsi_error;
648
649 if (d->released) {
650 libdax_msgs_submit(libdax_messenger,
651 d->global_index, 0x00020142,
652 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
653 "Drive is not grabbed on random access read", 0, 0);
654 {ret = 0; goto ex;}
655 }
656 if (d->drive_role != 1) {
657 libdax_msgs_submit(libdax_messenger, d->global_index,
658 0x00020146,
659 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
660 "Drive is a virtual placeholder (stdio-drive or null-drive)",
661 0, 0);
662 {ret = 0; goto ex;}
663 }
664 if ((data_size % alignment) != 0) {
665 sprintf(msg,
666 "Audio read size not properly aligned (%d bytes)",
667 alignment);
668 libdax_msgs_submit(libdax_messenger, d->global_index,
669 0x0002019d,
670 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
671 msg, 0, 0);
672 {ret = 0; goto ex;}
673 }
674 if (d->busy != BURN_DRIVE_IDLE) {
675 libdax_msgs_submit(libdax_messenger,
676 d->global_index, 0x00020145,
677 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
678 "Drive is busy on attempt to read audio", 0, 0);
679 {ret = 0; goto ex;}
680 }
681
682 d->busy = BURN_DRIVE_READING_SYNC;
683 d->buffer = buf;
684
685 start = sector_no;
686 upto = start + data_size / alignment;
687 wpt = data;
688 for (; start < upto; start += chunksize) {
689 chunksize = upto - start;
690 if (chunksize > (BUFFER_SIZE / alignment))
691 chunksize = (BUFFER_SIZE / alignment);
692 cpy_size = chunksize * alignment;
693 if (flag & 2)
694 d->silent_on_scsi_error = 1;
695 else if (flag & 32)
696 d->silent_on_scsi_error = 3;
697 if (flag & 16) {
698 d->had_particular_error &= ~1;
699 if (!d->silent_on_scsi_error)
700 d->silent_on_scsi_error = 2;
701 }
702 err = d->read_cd(d, start, chunksize, 1, 0x10, NULL, d->buffer,
703 (flag & 8) >> 3);
704 if (flag & (2 | 16 | 32))
705 d->silent_on_scsi_error = sose_mem;
706 if (err == BE_CANCELLED) {
707 if ((flag & 16) && (d->had_particular_error & 1))
708 {ret = -3; goto ex;}
709 if(!(flag & 4))
710 for (i = 0; i < chunksize - 1; i++) {
711 if (flag & 2)
712 d->silent_on_scsi_error = 1;
713 else if (flag & 32)
714 d->silent_on_scsi_error = 3;
715 err = d->read_cd(d, start + i, 1, 1, 0x10,
716 NULL, d->buffer, (flag & 8) >> 3);
717 if (flag & (2 | 32))
718 d->silent_on_scsi_error = sose_mem;
719 if (err == BE_CANCELLED)
720 break;
721 memcpy(wpt, d->buffer->data, alignment);
722 wpt += alignment;
723 *data_count += alignment;
724 }
725
726 ret = 0; goto ex;
727 }
728 memcpy(wpt, d->buffer->data, cpy_size);
729 wpt += cpy_size;
730 *data_count += cpy_size;
731 }
732
733 ret = 1;
734 ex:
735 BURN_FREE_MEM(buf);
736 d->buffer = buffer_mem;
737 d->busy = BURN_DRIVE_IDLE;
738 return ret;
739 }
740
741
742 #ifdef Libburn_develop_quality_scaN
743
744 /* B21108 ts */
burn_nec_optiarc_rep_err_rate(struct burn_drive * d,int start_lba,int rate_period,int flag)745 int burn_nec_optiarc_rep_err_rate(struct burn_drive *d,
746 int start_lba, int rate_period, int flag)
747 {
748 int ret, lba = 0, error_rate1 = 0, error_rate2 = 0, enabled = 0, dret;
749
750 /* Sub Operation Code 1 : Enable Error Rate reporting function */
751 ret = mmc_nec_optiarc_f3(d, 1, start_lba, rate_period,
752 &lba, &error_rate1, &error_rate2);
753 if (ret <= 0)
754 goto ex;
755 enabled = 1;
756
757 /* >>> Sub Operation Code 2 : Seek to starting address
758 start_lba , rate_period
759 */;
760
761 /* >>> Loop with Sub Operation Code 3 : Send Error Rate information
762 reply: 4-byte LBA , 2-byte C1/PIE , 2-byte C2/PIF
763 */;
764
765 ret = 1;
766 ex:;
767 if (enabled) {
768 /* Code F : Disable Error Rate reporting function */
769 dret = mmc_nec_optiarc_f3(d, 0xf, 0, 0,
770 &lba, &error_rate1, &error_rate2);
771 if (dret < ret)
772 ret = dret;
773 }
774 return ret;
775 }
776
777 #endif /* Libburn_develop_quality_scaN */
778
779