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