"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/libburn/read.c" (30 Jan 2021, 19860 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "read.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
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
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 }
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
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
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 */
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 */
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 */
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 */
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 */
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*/
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 */
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